Index: vendor/bind/8.3.4/contrib/bind/bin/named/db_defs.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/db_defs.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/db_defs.h (revision 109985) @@ -0,0 +1,341 @@ +/* + * from db.h 4.16 (Berkeley) 6/1/90 + * $Id: db_defs.h,v 8.47.4.1 2002/11/14 13:22:24 marka Exp $ + */ + +/* + * Copyright (c) 1985, 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * Global definitions for data base routines. + */ + + /* max length of data in RR data field */ +#define MAXDATA (3*MAXDNAME + 5*INT32SZ) + + /* max length of data in a TXT RR segment */ +#define MAXCHARSTRING 255 + +#define DB_ROOT_TIMBUF 3600 +#define TIMBUF 300 + +#define DICT_INDEXBITS 24 +#define DICT_MAXLENGTH 127 +#define DICT_INSERT_P 0x0001 + +/* Average hash chain depths. */ +#define AVGCH_MARSHAL 5 +#define AVGCH_NLOOKUP 3 + +/* Nonstandard maximum class to force better packing. */ +#define ZONE_BITS 24 +#define CLASS_BITS 8 +#define ZONE_MAX ((1<> ((sizeof(v) * 8) - HASHSHIFT))) +#define HASHLOWER(c) ((isascii(c) && isupper(c)) ? tolower(c) : (c)) +#define HASHIMILATE(v,c) ((v) = (HASHROTATE(v)) + (HASHLOWER(c) & HASHMASK)) + +#define TSIG_BUF_SIZE 640 +#define TSIG_SIG_SIZE 20 + +struct tsig_record { + u_int8_t sig[TSIG_SIG_SIZE]; + struct dst_key *key; + int siglen; + int tsig_size; +}; + +struct sig_record { + u_int16_t sig_type_n; + u_int8_t sig_alg_n, sig_labels_n; + u_int32_t sig_ottl_n, sig_exp_n, sig_time_n; + u_int16_t sig_keyid_n; +}; + +/* This is the wire format size of "struct sig_record", i.e., no padding. */ +#define SIG_HDR_SIZE 18 + +struct dnode { + struct databuf *dp; + struct dnode *dn_next; + int line; + const char *file; +}; + +typedef struct dnode * dlist; + +struct db_rrset { + dlist rr_list; + dlist rr_sigs; + char *rr_name; + int16_t rr_class; + int16_t rr_type; + struct db_rrset *rr_next; +}; +#define DBHASHSIZE(s) (sizeof(struct hashbuf) + \ + (s-1) * sizeof(struct db_rrset *)) + +#define SIG_COVERS(dp) (ns_get16(dp->d_data)) + +/* + * Flags to updatedb + */ +#define DB_NODATA 0x01 /* data should not exist */ +#define DB_MEXIST 0x02 /* data must exist */ +#define DB_DELETE 0x04 /* delete data if it exists */ +#define DB_NOTAUTH 0x08 /* must not update authoritative data */ +#define DB_NOHINTS 0x10 /* don't reflect update in fcachetab */ +#define DB_PRIMING 0x20 /* is this update the result of priming? */ +#define DB_MERGE 0x40 /* make no control on rr in db_update (for ixfr) */ +#define DB_REPLACE 0x80 /* replace data if it exists */ + +#define DB_Z_CACHE 0 /* cache-zone-only db_dump() */ +#define DB_Z_ALL 65535 /* normal db_dump() */ +#define DB_Z_SPECIAL(z) ((z) == DB_Z_CACHE || (z) == DB_Z_ALL) + +/* + * Error return codes + */ +#define OK 0 +#define NONAME (-1) +#define NOCLASS (-2) +#define NOTYPE (-3) +#define NODATA (-4) +#define DATAEXISTS (-5) +#define NODBFILE (-6) +#define TOOMANYZONES (-7) +#define GOODDB (-8) +#define NEWDB (-9) +#define AUTH (-10) +#ifdef BIND_UPDATE +#define SERIAL (-11) +#endif +#define CNAMEANDOTHER (-12) +#define DNSSECFAIL (-13) /* db_set_update */ +#define NONGLUE (-14) + +/* + * getnum() options + */ +#define GETNUM_NONE 0x00 /* placeholder */ +#define GETNUM_SERIAL 0x01 /* treat as serial number */ +#define GETNUM_SCALED 0x02 /* permit "k", "m" suffixes, scale result */ + +/* + * db_load() options + */ +#define ISNOTIXFR 0 +#define ISIXFR 1 +#define ISAXFRIXFR 2 + +/* + * Database access abstractions. + */ +#define foreach_rr(dp, np, ty, cl, zn) \ + for ((dp) = (np)->n_data; (dp) != NULL; (dp) = (dp)->d_next) \ + if (!match(dp, (cl), (ty))) \ + continue; \ + else if (((zn) == DB_Z_CACHE) \ + ? stale(dp) \ + : (zn) != (dp)->d_zone) \ + continue; \ + else if ((dp)->d_rcode) \ + continue; \ + else \ + /* Caller code follows in sequence. */ + +#define DRCNTINC(x) \ + do { \ + if (++((x)->d_rcnt) == 0) \ + ns_panic(ns_log_db, 1, "++d_rcnt == 0"); \ + } while (0) + +#define DRCNTDEC(x) \ + do { \ + if (((x)->d_rcnt)-- == 0) \ + ns_panic(ns_log_db, 1, "d_rcnt-- == 0"); \ + } while (0) + +#define ISVALIDGLUE(xdp) ((xdp)->d_type == T_NS || (xdp)->d_type == T_A \ + || (xdp)->d_type == T_AAAA || (xdp)->d_type == ns_t_a6) + Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/db_defs.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/db_sec.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/db_sec.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/db_sec.c (revision 109985) @@ -0,0 +1,1081 @@ + +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: db_sec.c,v 8.35.4.2 2002/11/14 13:24:44 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986, 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "port_after.h" + +#include "named.h" + +struct zpubkey { + struct dst_key *zpk_key; /* Should be DST_KEY */ + char *zpk_name; + struct zpubkey *zpk_next; +}; + +typedef struct zpubkey *zpubkey_list; + +static int nxt_match_rrset(struct databuf *dp, struct db_rrset *rrset); + +/* + * A converted databuf is a stripped down databuf after converting the + * data to wire format. + */ +struct converted_databuf { + struct converted_databuf *cd_next; + u_char *cd_data; + int cd_size, cd_alloc; +}; + +/* All of the trusted keys and zone keys */ +static tree *trusted_keys = NULL; + +static int +compare_pubkey (struct zpubkey *zpk1, struct zpubkey *zpk2) { + char ta[NS_MAXDNAME], tb[NS_MAXDNAME]; + + if (ns_makecanon(zpk1->zpk_name, ta, sizeof ta) < 0 || + ns_makecanon(zpk2->zpk_name, tb, sizeof tb) < 0) + return (-1); + return (strcasecmp(ta, tb)); +} + +static struct zpubkey * +tree_srch_pubkey (const char *name) { + struct zpubkey tkey, *key; + + DE_CONST(name, tkey.zpk_name); + if (trusted_keys == NULL) { + tree_init(&trusted_keys); + return (NULL); + } + key = (struct zpubkey *)tree_srch(&trusted_keys, compare_pubkey, + &tkey); + return (key); +} + +static DST_KEY * +find_public_key (const char *name, u_int16_t key_id) { + struct namebuf *knp; + struct hashbuf *htp; + struct databuf *dp; + const char *fname; + DST_KEY *key; + + ns_debug(ns_log_default, 5, "find_public_key(%s, %d)", name, key_id); + + htp = hashtab; + knp = nlookup (name, &htp, &fname, 0); + if (fname != name) + /* The name doesn't exist, so there's no key */ + return (NULL); + + for (dp = knp->n_data; dp != NULL; dp = dp->d_next) { + if (dp->d_type != ns_t_key || dp->d_secure < DB_S_SECURE) + continue; + key = dst_dnskey_to_key(name, dp->d_data, dp->d_size); + /* XXX what about multiple keys with same footprint? */ + if (key) { + if (key->dk_id == ntohs(key_id)) + return (key); + else + dst_free_key(key); + } + } + return (NULL); +} + + +static DST_KEY * +find_trusted_key (const char *name, u_int16_t key_id) { + struct zpubkey *zpk; + zpubkey_list keylist = tree_srch_pubkey (name); + + ns_debug(ns_log_default, 5, "find_trusted_key(%s, %d)", name, key_id); + + for (zpk = keylist; zpk; zpk = zpk->zpk_next) + if (zpk->zpk_key->dk_id == ntohs(key_id)) + return (zpk->zpk_key); + + return (NULL); +} + +int +add_trusted_key (const char *name, const int flags, const int proto, + const int alg, const char *str) +{ + zpubkey_list keylist; + struct zpubkey *zpk; + u_char buf[1024]; + int n; + + keylist = tree_srch_pubkey (name); + + zpk = (struct zpubkey *) memget (sizeof (struct zpubkey)); + if (zpk == NULL) + ns_panic(ns_log_default, 1, + "add_trusted_key: memget failed(%s)", name); + n = b64_pton(str, buf, sizeof(buf)); + if (n < 0) + goto failure; + zpk->zpk_key = dst_buffer_to_key(name, alg, flags, proto, buf, n); + if (zpk->zpk_key == NULL) { + ns_warning(ns_log_default, + "add_trusted_key: dst_buffer_to_key(%s) failed", + name); + goto failure; + } + zpk->zpk_name = zpk->zpk_key->dk_key_name; + zpk->zpk_next = NULL; + + if (keylist == NULL) { + if (tree_add (&trusted_keys, compare_pubkey, zpk, NULL) == NULL) + goto failure; + } + else { + struct zpubkey *tkey = keylist; + while (tkey->zpk_next) + tkey = tkey->zpk_next; + tkey->zpk_next = zpk; + } + + return (1); + failure: + memput(zpk, sizeof (struct zpubkey)); + return (0); +} + +/* Can the signer sign records for this name? This is a heuristic. */ +static int +can_sign(const char *name, const char *signer) { + return (ns_samedomain(name, signer) && + dn_count_labels(name) - dn_count_labels(signer) <= 2); +} + +static int +rrset_set_security(struct db_rrset *rrset, int slev) { + struct dnode *dnp; + + for (dnp = rrset->rr_list; dnp != NULL; dnp = dnp->dn_next) + dnp->dp->d_secure = slev; + for (dnp = rrset->rr_sigs; dnp != NULL; dnp = dnp->dn_next) + dnp->dp->d_secure = slev; + return (slev); +} + +static int +convert_databuf(struct databuf *dp, struct converted_databuf *cdp) { + u_char *bp = cdp->cd_data; + u_char *cp = dp->d_data; + u_char *eob = cdp->cd_data + cdp->cd_alloc; + int len; + u_char buf[MAXDNAME]; + + switch (dp->d_type) { + case ns_t_soa: + case ns_t_minfo: + case ns_t_rp: + if (eob - bp < (int)strlen((char *)cp) + 1) + return (-1); + if (ns_name_pton((char *)cp, buf, sizeof buf) < 0) + return (-1); + len = ns_name_ntol(buf, bp, eob - bp); + if (len < 0) + return (-1); + bp += len; + cp += strlen((char *)cp) + 1; + + if (eob - bp < (int)strlen((char *)cp) + 1) + return (-1); + if (ns_name_pton((char *)cp, buf, sizeof buf) < 0) + return (-1); + len = ns_name_ntol(buf, bp, eob - bp); + if (len < 0) + return (-1); + bp += len; + cp += strlen((char *)cp) + 1; + + if (dp->d_type == ns_t_soa) { + if (eob - bp < 5 * INT32SZ) + return (-1); + memcpy(bp, cp, 5 * INT32SZ); + bp += (5 * INT32SZ); + cp += (5 * INT32SZ); + } + + break; + + case ns_t_ns: + case ns_t_cname: + case ns_t_mb: + case ns_t_mg: + case ns_t_mr: + case ns_t_ptr: + case ns_t_nxt: + if (eob - bp < (int)strlen((char *)cp) + 1) + return (-1); + if (ns_name_pton((char *)cp, buf, sizeof buf) < 0) + return (-1); + len = ns_name_ntol(buf, bp, eob - bp); + if (len < 0) + return (-1); + bp += len; + cp += (len = strlen((char *)cp) + 1); + + if (dp->d_type == ns_t_nxt) { + if (eob - bp < dp->d_size - len) + return (-1); + memcpy(bp, cp, dp->d_size - len); + bp += (dp->d_size - len); + cp += (dp->d_size - len); + } + break; + + case ns_t_srv: + if (eob - bp < 2 * INT16SZ) + return (-1); + memcpy(bp, cp, 2 * INT16SZ); + bp += (2 * INT16SZ); + cp += (2 * INT16SZ); + /* no break */ + case ns_t_rt: + case ns_t_mx: + case ns_t_afsdb: + case ns_t_px: + if (eob - bp < INT16SZ) + return (-1); + memcpy (bp, cp, INT16SZ); + bp += INT16SZ; + cp += INT16SZ; + + if (eob - bp < (int)strlen((char *)cp) + 1) + return (-1); + if (ns_name_pton((char *)cp, buf, sizeof buf) < 0) + return (-1); + len = ns_name_ntol(buf, bp, eob - bp); + if (len < 0) + return (-1); + bp += len; + cp += strlen((char *)cp) + 1; + + if (dp->d_type == ns_t_px) { + if (eob - bp < (int)strlen((char *)cp) + 1) + return (-1); + if (ns_name_pton((char *)cp, buf, sizeof buf) < 0) + return (-1); + len = ns_name_ntol(buf, bp, eob - bp); + if (len < 0) + return (-1); + bp += len; + cp += strlen((char *)cp) + 1; + } + break; + + default: + if (eob - bp < dp->d_size) + return (-1); + memcpy(bp, cp, dp->d_size); + bp += dp->d_size; + } + cdp->cd_size = bp - cdp->cd_data; + return (cdp->cd_size); +} + +static int +digest_rr(char *envelope, int elen, struct converted_databuf *cdp, + char *buffer, int blen) +{ + char *bp = buffer, *eob = buffer + blen; + + if (eob - bp < elen) + return (-1); + memcpy (bp, envelope, elen); + bp += elen; + + if (eob - bp < INT16SZ) + return (-1); + PUTSHORT(cdp->cd_size, bp); + + if (eob - bp < cdp->cd_size) + return (-1); + memcpy (bp, cdp->cd_data, cdp->cd_size); + bp += cdp->cd_size; + + return (bp - buffer); +} + +/* Sorts the converted databuf in the list */ +static void +insert_converted_databuf(struct converted_databuf *cdp, + struct converted_databuf **clist) +{ + struct converted_databuf *tcdp, *next; + int t; + +#define compare_cdatabuf(c1, c2, t) \ + (t = memcmp(c1->cd_data, c2->cd_data, MIN(c1->cd_size, c2->cd_size)), \ + t == 0 ? c1->cd_size - c2->cd_size : t) + + if (*clist == NULL) { + *clist = cdp; + return; + } + + tcdp = *clist; + if (compare_cdatabuf(cdp, tcdp, t) < 0) { + cdp->cd_next = tcdp; + *clist = cdp; + return; + } + + next = tcdp->cd_next; + while (next) { + if (compare_cdatabuf(cdp, next, t) < 0) { + cdp->cd_next = next; + tcdp->cd_next = cdp; + return; + } + tcdp = next; + next = next->cd_next; + } + tcdp->cd_next = cdp; +#undef compare_cdatabuf +} + +static void +free_clist(struct converted_databuf *clist) { + struct converted_databuf *cdp; + + while (clist != NULL) { + cdp = clist; + clist = clist->cd_next; + memput(cdp->cd_data, cdp->cd_alloc); + memput(cdp, sizeof(struct converted_databuf)); + } +} + +/* Removes all empty nodes from an rrset's SIG list. */ +static void +rrset_trim_sigs(struct db_rrset *rrset) { + struct dnode *dnp, *odnp, *ndnp; + + odnp = NULL; + dnp = rrset->rr_sigs; + while (dnp != NULL) { + if (dnp->dp != NULL) { + odnp = dnp; + dnp = dnp->dn_next; + } + else { + if (odnp != NULL) + odnp->dn_next = dnp->dn_next; + else + rrset->rr_sigs = dnp->dn_next; + ndnp = dnp->dn_next; + memput(dnp, sizeof(struct dnode)); + dnp = ndnp; + } + } +} + +static int +verify_set(struct db_rrset *rrset) { + DST_KEY *key = NULL; + struct sig_record *sigdata; + struct dnode *sigdn; + struct databuf *sigdp; + u_int32_t now; + u_int32_t exptime; + u_int32_t signtime; + char *signer; + u_char name_n[MAXDNAME]; + u_char *sig, *eom; + int trustedkey = 0, siglen, labels, len = 0, ret; + u_char *buffer = NULL, *bp; + u_char envelope[MAXDNAME+32], *ep; + struct dnode *dnp; + int bufsize = 2048; /* Large enough for MAXDNAME + SIG_HDR_SIZE */ + struct converted_databuf *clist = NULL, *cdp; + int dnssec_failed = 0, dnssec_succeeded = 0; + int return_value; + int i; + int expired = 0; + + if (rrset == NULL || rrset->rr_name == NULL) { + ns_warning (ns_log_default, "verify_set: missing rrset/name"); + return (rrset_set_security(rrset, DB_S_FAILED)); + } + + if (rrset->rr_sigs == NULL) + return (rrset_set_security(rrset, DB_S_INSECURE)); + + ns_debug(ns_log_default, 5, "verify_set(%s, %s, %s)", rrset->rr_name, + p_type(rrset->rr_type), p_class(rrset->rr_class)); + + now = time(NULL); + + for (sigdn = rrset->rr_sigs; sigdn != NULL; sigdn = sigdn->dn_next) { + u_int32_t namefield; + struct sig_record sigrec; + + sigdp = sigdn->dp; + + eom = sigdp->d_data + sigdp->d_size; + if (sigdp->d_size < SIG_HDR_SIZE) { + return_value = DB_S_FAILED; + goto end; + } + memcpy(&sigrec, sigdp->d_data, SIG_HDR_SIZE); + sigdata = &sigrec; + signer = (char *)sigdp->d_data + SIG_HDR_SIZE; + sig = (u_char *)signer + strlen(signer) + 1; + siglen = eom - sig; + + /* + * Don't verify a set if the SIG inception time is in + * the future. This should be fixed before 2038 (BEW) + */ + signtime = ntohl(sigdata->sig_time_n); + if (SEQ_GT(signtime, now)) + continue; + + /* An expired set is dropped, but the data is not. */ + exptime = ntohl(sigdata->sig_exp_n); + if (SEQ_GT(now, exptime)) { + expired++; + db_detach(&sigdn->dp); + sigdp = NULL; + continue; + } + + /* Cleanup from the last iteration if we continue'd */ + if (trustedkey == 0 && key != NULL) + dst_free_key(key); + + key = find_trusted_key(signer, sigdata->sig_keyid_n); + + if (key == NULL) { + trustedkey = 0; + key = find_public_key(signer, sigdata->sig_keyid_n); + } + else + trustedkey = 1; + + /* if we don't have the key, either + * - the data should be considered insecure + * - the sig is not a dnssec signature + */ + if (key == NULL) + continue; + + /* Can a key with this name sign the data? */ + if (!can_sign(rrset->rr_name, signer)) + continue; + + /* Check the protocol and flags of the key */ + if (key->dk_proto != NS_KEY_PROT_DNSSEC && + key->dk_proto != NS_KEY_PROT_ANY) + continue; + if (key->dk_flags & NS_KEY_NO_AUTH) + continue; + namefield = key->dk_flags & NS_KEY_NAME_TYPE; + if (namefield == NS_KEY_NAME_USER || + namefield == NS_KEY_NAME_RESERVED) + continue; + if (namefield == NS_KEY_NAME_ENTITY && + (key->dk_flags & NS_KEY_SIGNATORYMASK) == 0) + continue; + + /* + * If we're still here, we have a non-null key that's either + * a zone key or an entity key with signing authority. + */ + + if (buffer == NULL) { + bp = buffer = memget(bufsize); + if (bp == NULL) { + return_value = DB_S_FAILED; + goto end; + } + } + else + bp = buffer; + + + /* Digest the fixed portion of the SIG record */ + memcpy(bp, (char *) sigdata, SIG_HDR_SIZE); + bp += SIG_HDR_SIZE; + + /* Digest the signer's name, canonicalized */ + if (ns_name_pton(signer, name_n, sizeof name_n) < 0) { + return_value = DB_S_FAILED; + goto end; + } + i = ns_name_ntol(name_n, (u_char *)bp, bufsize - SIG_HDR_SIZE); + if (i < 0) { + return_value = DB_S_FAILED; + goto end; + } + bp += i; + + /* create the dns record envelope: + * + */ + if (ns_name_pton(rrset->rr_name, name_n, sizeof name_n) < 0 || + ns_name_ntol(name_n, (u_char *)envelope, sizeof envelope) < 0) { + return_value = DB_S_FAILED; + goto end; + } + + labels = dn_count_labels(rrset->rr_name); + if (labels > sigdata->sig_labels_n) { + ep = envelope; + for (i=0; i < (labels - 1 - sigdata->sig_labels_n); i++) + ep += (*ep+1); + i = dn_skipname(ep, envelope + sizeof envelope); + if (i < 0) { + return_value = DB_S_FAILED; + goto end; + } + envelope[0] = '\001'; + envelope[1] = '*'; + memmove(envelope + 2, ep, i); + } + i = dn_skipname(envelope, envelope + sizeof envelope); + if (i < 0) { + return_value = DB_S_FAILED; + goto end; + } + ep = envelope + i; + PUTSHORT (rrset->rr_type, ep); + PUTSHORT (rrset->rr_class, ep); + if (envelope + sizeof(envelope) - ep < INT32SZ) { + return_value = DB_S_FAILED; + goto end; + } + memcpy (ep, &sigdata->sig_ottl_n, INT32SZ); + ep += INT32SZ; + + if (clist == NULL) { + for (dnp = rrset->rr_list; + dnp != NULL; + dnp = dnp->dn_next) + { + struct databuf *dp = dnp->dp; + + cdp = memget(sizeof(struct converted_databuf)); + if (cdp == NULL) { + return_value = DB_S_FAILED; + goto end; + } + memset(cdp, 0, sizeof(*cdp)); + /* Should be large enough... */ + cdp->cd_alloc = dp->d_size + 8; + cdp->cd_data = memget(cdp->cd_alloc); + if (cdp->cd_data == NULL) { + memput(cdp, sizeof(*cdp)); + return_value = DB_S_FAILED; + goto end; + } + while (convert_databuf(dp, cdp) < 0) { + memput(cdp->cd_data, cdp->cd_alloc); + cdp->cd_alloc *= 2; + cdp->cd_data = memget(cdp->cd_alloc); + if (cdp->cd_data == NULL) { + memput(cdp, sizeof(*cdp)); + return_value = DB_S_FAILED; + goto end; + } + } + insert_converted_databuf(cdp, &clist); + } + } + + for (cdp = clist; cdp != NULL; cdp = cdp->cd_next) { + len = digest_rr((char *)envelope, ep-envelope, cdp, + (char *)bp, bufsize - (bp - buffer)); + while (len < 0) { + u_char *newbuf; + + /* Double the buffer size */ + newbuf = memget(bufsize*2); + if (newbuf == NULL) { + return_value = DB_S_FAILED; + goto end; + } + memcpy(newbuf, buffer, bp - buffer); + bp = (bp - buffer) + newbuf; + memput(buffer, bufsize); + buffer = newbuf; + bufsize *= 2; + + len = digest_rr((char *)envelope, ep-envelope, + cdp, (char *)bp, + bufsize - (bp - buffer)); + } + bp += len; + } + + if (len < 0) { + return_value = DB_S_FAILED; + goto end; + } + + ret = dst_verify_data(SIG_MODE_ALL, key, NULL, buffer, + bp - buffer, sig, siglen); + + if (ret < 0) { + dnssec_failed++; + db_detach(&sigdn->dp); + sigdp = NULL; + } + else + dnssec_succeeded++; + } + +end: + if (dnssec_failed > 0 || expired > 0) + rrset_trim_sigs(rrset); + if (trustedkey == 0 && key != NULL) + dst_free_key(key); + + if (dnssec_failed > 0 && dnssec_succeeded == 0) { + ns_warning (ns_log_default, + "verify_set(%s, %s, %s) failed", + rrset->rr_name, p_type(rrset->rr_type), + p_class(rrset->rr_class)); + return_value = DB_S_FAILED; + } + else if (dnssec_succeeded > 0) + return_value = DB_S_SECURE; + else + return_value = DB_S_INSECURE; + free_clist(clist); + if (buffer != NULL) + memput(buffer, bufsize); + return (rrset_set_security(rrset, return_value)); +} + +static void +rrset_free(struct db_rrset *rrset) { + struct dnode *dnp; + + ns_debug(ns_log_default, 5, "rrset_free(%s)", rrset->rr_name); + + while (rrset->rr_list) { + dnp = rrset->rr_list; + rrset->rr_list = rrset->rr_list->dn_next; + if (dnp->dp != NULL) + db_detach(&dnp->dp); + memput(dnp, sizeof(struct dnode)); + } + while (rrset->rr_sigs) { + dnp = rrset->rr_sigs; + rrset->rr_sigs = rrset->rr_sigs->dn_next; + if (dnp->dp != NULL) + db_detach(&dnp->dp); + memput(dnp, sizeof(struct dnode)); + } +} + +/* + * This is called when we have an rrset with SIGs and no other data. + * Returns 1 if we either found the necessary data or if the SIG can be added + * with no other data. 0 indicates that the SIG cannot be added. + */ +static int +attach_data(struct db_rrset *rrset) { + int type, class; + struct databuf *dp, *newdp, *sigdp; + struct dnode *dnp; + struct namebuf *np; + struct hashbuf *htp; + char *signer; + const char *fname; + char *name = rrset->rr_name; + + sigdp = rrset->rr_sigs->dp; + + type = SIG_COVERS(sigdp); + class = sigdp->d_class; + signer = (char *)(sigdp + SIG_HDR_SIZE); + + /* First, see if the signer can sign data for the name. If not, + * it's not a DNSSEC signature, so we can insert it with no + * corresponding data. + */ + if (!can_sign(name, signer)) + return (1); + + htp = hashtab; + np = nlookup (name, &htp, &fname, 0); + if (fname != name) + return (0); + + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (dp->d_type == type && dp->d_class == class) { + newdp = savedata(class, type, dp->d_ttl, dp->d_data, + dp->d_size); + dnp = (struct dnode *) memget (sizeof (struct dnode)); + if (dnp == NULL) + ns_panic(ns_log_default, 1, + "attach_data: memget failed"); + dnp->dp = newdp; + dnp->dn_next = rrset->rr_list; + rrset->rr_list = dnp; + } + } + if (rrset->rr_list != NULL) + return (1); + else + return (0); +} + +static int +rrset_db_update(struct db_rrset *rrset, int flags, struct hashbuf **htpp, + struct sockaddr_in from, int *rrcount) +{ + struct dnode *dnp; + int ret; + + /* If we have any unattached SIG records that are DNSSEC signatures, + * don't cache them unless we already have the corresponding data. + * If we do cache unattached SIGs, we run into problems later if we + * have a SIG X and get a query for type X. + */ + if (rrset->rr_list == NULL) { + if (attach_data(rrset) == 0) { + rrset_free(rrset); + return (OK); + } + + if (rrset->rr_list != NULL && + verify_set(rrset) == DB_S_FAILED) + { + rrset_free(rrset); + return (OK); + } + } + + for (dnp = rrset->rr_list; dnp != NULL; dnp = dnp->dn_next) { + ret = db_update(rrset->rr_name, dnp->dp, dnp->dp, NULL, + flags, (*htpp), from); + if (ret != OK) { + /* XXX Probably should do rollback. */ + db_err(ret, rrset->rr_name, dnp->dp->d_type, + dnp->file, dnp->line); + if (ret != DATAEXISTS) { + rrset_free(rrset); + return (ret); + } + } + if (rrcount != NULL) + (*rrcount)++; + } + for (dnp = rrset->rr_sigs; dnp != NULL; dnp = dnp->dn_next) { + if (dnp->dp == NULL) /* verifyset() can remove sigs */ + continue; + ret = db_update(rrset->rr_name, dnp->dp, dnp->dp, NULL, + flags, (*htpp), from); + if (ret != OK) { + /* XXX Probably should do rollback. */ + db_err(ret, rrset->rr_name, dnp->dp->d_type, + dnp->file, dnp->line); + if (ret != DATAEXISTS) { + rrset_free(rrset); + return (ret); + } + } + if (rrcount != NULL) + (*rrcount)++; + } + rrset_free(rrset); + return (OK); +} + +static int +rr_in_set(struct databuf *rr, struct dnode *set) { + struct dnode *dnp; + + if (set == NULL) + return (0); + + for(dnp = set; dnp != NULL; dnp = dnp->dn_next) { + if (dnp->dp->d_size == rr->d_size && + memcmp(dnp->dp->d_data, rr->d_data, dnp->dp->d_size) == 0) + return (1); + } + return (0); +} + +static int +add_to_rrset_list(struct db_rrset **rrsets, char *name, struct databuf *dp, + int line, const char *file) +{ + struct db_rrset *rrset = *rrsets; + struct dnode *dnp; + + while (rrset != NULL) { + if (rrset->rr_type != ns_t_nxt || dp->d_type != ns_t_nxt) { + if (dp->d_type == ns_t_sig) { + if ((int)SIG_COVERS(dp) == rrset->rr_type) + break; + } else { + if (dp->d_type == rrset->rr_type) + break; + } + } + else if (nxt_match_rrset(dp, rrset)) + break; + rrset = rrset->rr_next; + } + + if (rrset != NULL) { + if ((dp->d_type == ns_t_sig && rr_in_set(dp, rrset->rr_sigs)) || + (dp->d_type != ns_t_sig && rr_in_set(dp, rrset->rr_list))) + return (DATAEXISTS); + } else { + rrset = (struct db_rrset *) memget(sizeof(struct db_rrset)); + if (rrset == NULL) + ns_panic(ns_log_default, 1, + "add_to_rrset_list: memget failed(%s)", name); + memset(rrset, 0, sizeof(struct db_rrset)); + rrset->rr_name = savestr(name, 1); + rrset->rr_class = dp->d_class; + if (dp->d_type == ns_t_sig) + rrset->rr_type = SIG_COVERS(dp); + else + rrset->rr_type = dp->d_type; + rrset->rr_next = *rrsets; + *rrsets = rrset; + } + + dnp = (struct dnode *) memget(sizeof(struct dnode)); + if (dnp == NULL) + ns_panic(ns_log_default, 1, + "add_to_rrset_list: memget failed(%s)", name); + memset(dnp, 0, sizeof(struct dnode)); + dnp->dp = dp; + DRCNTINC(dnp->dp); + if (dp->d_type == ns_t_sig) { + if (rrset->rr_sigs != NULL) { + struct dnode *fdnp; + + /* Preserve the order of the RRs */ + /* Add this one to the end of the list */ + for (fdnp = rrset->rr_sigs; + fdnp->dn_next != NULL; + fdnp = fdnp->dn_next) + /* NULL */ ; + fdnp->dn_next = dnp; + } else + rrset->rr_sigs = dnp; + } else { + if (rrset->rr_list != NULL) { + struct dnode *fdnp; + + /* Preserve the order of the RRs */ + /* Add this one to the end of the list */ + for (fdnp = rrset->rr_list; + fdnp->dn_next != NULL; + fdnp = fdnp->dn_next) + /* NULL */ ; + fdnp->dn_next = dnp; + } else + rrset->rr_list = dnp; + } + dnp->file = file; + dnp->line = line; + return (0); +} + +static int +update_rrset_list(struct db_rrset **rrsets, int flags, struct hashbuf **htpp, + struct sockaddr_in from, int *rrcount) +{ + struct db_rrset *rrset = *rrsets, *next = NULL, *last = NULL; + int result = 0, tresult, cnameandother = 0; + + while (rrset != NULL) { + if (rrset->rr_type == ns_t_key) + break; + last = rrset; + rrset = rrset->rr_next; + } + + if (rrset != NULL && last != NULL) { + last->rr_next = rrset->rr_next; + rrset->rr_next = *rrsets; + *rrsets = rrset; + } + + rrset = *rrsets; + + while (rrset != NULL) { + if (verify_set(rrset) > DB_S_FAILED) { + ns_debug(ns_log_default, 10, + "update_rrset_list(%s, %s): set verified", + rrset->rr_name, p_type(rrset->rr_type)); + tresult = rrset_db_update(rrset, flags, htpp, + from, rrcount); + if (tresult == CNAMEANDOTHER) + cnameandother++; + if (tresult != OK) + result = tresult; + } + else { + rrset_free(rrset); + result = DNSSECFAIL; + } + rrset->rr_name = freestr(rrset->rr_name); + next = rrset->rr_next; + memput(rrset, sizeof(struct db_rrset)); + rrset = next; + } + *rrsets = NULL; + if (cnameandother != 0) + return (CNAMEANDOTHER); + return (result); +} + +int +db_set_update(char *name, struct databuf *dp, void **state, + int flags, struct hashbuf **htpp, struct sockaddr_in from, + int *rrcount, int line, const char *file) +{ + struct db_rrset **rrsets; + struct db_rrset *rrset; + int result = 0; + + ns_debug(ns_log_default, 5, "db_set_update(%s)", + (name == NULL) ? "" : (*name == 0) ? "." : name); + + if (state == NULL) + ns_panic(ns_log_default, 1, + "Called db_set_update with state == NULL"); + + rrsets = (struct db_rrset **) state; + + if (*rrsets != NULL) { + rrset = *rrsets; + if (rrset->rr_name != NULL && dp != NULL && + name != NULL && ns_samename(name, rrset->rr_name) == 1 && + dp->d_class == rrset->rr_class) + return (add_to_rrset_list(rrsets, name, dp, + line, file)); + } + + if (*rrsets != NULL) + result = update_rrset_list(rrsets, flags, htpp, from, rrcount); + + if (dp != NULL) { + ns_debug(ns_log_default, 10, + "db_set_update(%s), creating new list", name); + + (void) add_to_rrset_list(rrsets, name, dp, line, file); + } + return (result); +} + +static int +nxt_match_rrset(struct databuf *dp, struct db_rrset *rrset) { + if (rrset->rr_list != NULL) + return (nxtmatch(rrset->rr_name, dp, rrset->rr_list->dp)); + else + return (nxtmatch(rrset->rr_name, dp, rrset->rr_sigs->dp)); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/db_sec.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_defs.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_defs.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_defs.h (revision 109985) @@ -0,0 +1,932 @@ +/* + * from ns.h 4.33 (Berkeley) 8/23/90 + * $Id: ns_defs.h,v 8.121.2.1 2002/11/14 13:28:12 marka Exp $ + */ + +/* + * Copyright (c) 1986 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1999 by Check Point Software Technologies, Inc. + * + * 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 Check Point Software Technologies Incorporated 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 CHECK POINT SOFTWARE TECHNOLOGIES + * INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL CHECK POINT SOFTWARE TECHNOLOGIES INCORPRATED + * 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 SOFTWARE. + */ + +/* + * Global definitions for the name server. + */ + +/* + * Effort has been expended here to make all structure members 32 bits or + * larger land on 32-bit boundaries; smaller structure members have been + * deliberately shuffled and smaller integer sizes chosen where possible + * to make sure this happens. This is all meant to avoid structure member + * padding which can cost a _lot_ of memory when you have hundreds of + * thousands of entries in your cache. + */ + +/* + * Timeout time should be around 1 minute or so. Using the + * the current simplistic backoff strategy, the sequence + * retrys after 4, 8, and 16 seconds. With 3 servers, this + * dies out in a little more than a minute. + * (sequence RETRYBASE, 2*RETRYBASE, 4*RETRYBASE... for MAXRETRY) + */ +#define NEWZONES 64 /* how many zones to grow the zone table by */ +#define INITIALZONES NEWZONES /* how many zones are allocated initially */ +#define MINROOTS 2 /* min number of root hints */ +#define NSMAX 16 /* max number of NS addrs to try ([0..255]) */ +#define RETRYBASE 4 /* base time between retries */ +#define MAXCLASS 255 /* XXX - may belong elsewhere */ +#define MAXRETRY 3 /* max number of retries per addr */ +#define MAXCNAMES 8 /* max # of CNAMES tried per addr */ +#define MAXQUERIES 20 /* max # of queries to be made */ +#define MAXQSERIAL 4 /* max # of outstanding QSERIAL's */ + /* (prevent "recursive" loops) */ +#define INIT_REFRESH 600 /* retry time for initial slave */ + /* contact (10 minutes) */ +#define MIN_REFRESH 2 /* never refresh more frequently than once */ + /* every MIN_REFRESH seconds */ +#define MIN_RETRY 1 /* never retry more frequently than once */ + /* every MIN_RETRY seconds */ +#define MAX_REFRESH 2419200 /* perform a refresh query at least */ + /* every 4 weeks*/ +#define MAX_RETRY 1209600 /* perform a retry after no more than 2 weeks */ +#define MAX_EXPIRE 31536000 /* expire a zone if we have not talked to */ + /* the primary in 1 year */ +#define NADDRECS 20 /* max addt'l rr's per resp */ + +#define XFER_TIMER 120 /* named-xfer's connect timeout */ +#define MAX_XFER_TIME 60*60*2 /* default max seconds for an xfer */ +#define XFER_TIME_FUDGE 10 /* MAX_XFER_TIME fudge */ +#define MAX_XFERS_RUNNING 20 /* max value of transfers_in */ +#define DEFAULT_XFERS_RUNNING 10 /* default value of transfers_in */ +#define DEFAULT_XFERS_PER_NS 2 /* default # of xfers per peer nameserver */ +#define XFER_BUFSIZE (16*1024) /* arbitrary but bigger than most MTU's */ +#define MAX_SYNCDELAY 3 /* Presumed timeout in use by our clients. */ +#define MAX_SYNCDRAIN 100000 /* How long we'll spin in drain_all_rcvbuf. */ +#define MAX_SYNCSTORE 500 +#define NS_MAX_DISTANCE 3 /* maximum nameserver chaining before failure */ + + /* maximum time to cache negative answers */ +#define DEFAULT_MAX_NCACHE_TTL (3*60*60) + +#define ALPHA 0.7 /* How much to preserve of old response time */ +#define BETA 1.2 /* How much to penalize response time on failure */ +#define GAMMA 0.98 /* How much to decay unused response times */ + + /* What maintainance operations need to be performed sometime soon? */ +typedef enum need { + main_need_zreload = 0, /* ns_zreload() needed. */ + main_need_reload, /* ns_reload() needed. */ + main_need_reconfig, /* ns_reconfig() needed. */ + main_need_endxfer, /* endxfer() needed. */ + main_need_zoneload, /* loadxfer() needed. */ + main_need_dump, /* doadump() needed. */ + main_need_statsdump, /* ns_stats() needed. */ + main_need_statsdumpandclear, /* ns_stats() needed. */ + main_need_exit, /* exit() needed. */ + main_need_qrylog, /* toggle_qrylog() needed. */ + main_need_debug, /* use_desired_debug() needed. */ + main_need_restart, /* exec() needed. */ + main_need_reap, /* need to reap dead children. */ + main_need_noexpired, /* ns_reconfig() needed w/ noexpired set. */ + main_need_tryxfer, /* attemt to start a zone transfer. */ + main_need_num /* MUST BE LAST. */ +} main_need; + + /* What global options are set? */ +#define OPTION_NORECURSE 0x00000001 /* Don't recurse even if asked. */ +#define OPTION_NOFETCHGLUE 0x00000002 /* Don't fetch missing glue. */ +#define OPTION_FORWARD_ONLY 0x00000004 /* Don't use NS RR's, just forward. */ +#define OPTION_FAKE_IQUERY 0x00000008 /* Fake up bogus response to IQUERY. */ +#ifdef BIND_NOTIFY +/* #define OPTION_NONOTIFY 0x00000010 */ /* Turn off notify */ +#define OPTION_SUPNOTIFY_INITIAL 0x00000020 /* Supress initial notify */ +#endif +#define OPTION_NONAUTH_NXDOMAIN 0x00000040 /* Generate non-auth NXDOMAINs? */ +#define OPTION_MULTIPLE_CNAMES 0x00000080 /* Allow a name to have multiple + * CNAME RRs */ +#define OPTION_HOSTSTATS 0x00000100 /* Maintain per-host statistics? */ +#define OPTION_DEALLOC_ON_EXIT 0x00000200 /* Deallocate everything on exit? */ +#define OPTION_NODIALUP 0x00000400 /* Turn off dialup support */ +#define OPTION_NORFC2308_TYPE1 0x00000800 /* Prevent type1 respones (RFC 2308) + * to cached negative respones */ +#define OPTION_USE_ID_POOL 0x00001000 /* Use the memory hogging query ID */ +#define OPTION_TREAT_CR_AS_SPACE 0x00002000 /* Treat CR in zone files as + * space */ +#define OPTION_USE_IXFR 0x00004000 /* Use by default ixfr in zone + * transfer */ +#define OPTION_MAINTAIN_IXFR_BASE 0x00008000 /* Part of IXFR file name logic. */ +#define OPTION_HITCOUNT 0x00010000 /* Keep track of each time an + * RR gets hit in the database */ + +#define DEFAULT_OPTION_FLAGS (OPTION_NODIALUP|OPTION_NONAUTH_NXDOMAIN|\ + OPTION_USE_ID_POOL|OPTION_NORFC2308_TYPE1) + +#ifdef BIND_UPDATE +#define SOAINCRINTVL 300 /* default value for the time after which + * the zone serial number must be incremented + * after a successful update has occurred */ +#define DUMPINTVL 3600 /* default interval at which to dump changed zones + * randomized, not exact */ +#define DEFERUPDCNT 100 /* default number of updates that can happen + * before the zone serial number will be + * incremented */ +#define UPDATE_TIMER XFER_TIMER +#endif /* BIND_UPDATE */ + +#define USE_MINIMUM 0xffffffff +#define MAXIMUM_TTL 0x7fffffff + +#define CLEAN_TIMER 0x01 +#define INTERFACE_TIMER 0x02 +#define STATS_TIMER 0x04 +#define HEARTBEAT_TIMER 0x08 + + /* IP address accessor, network byte order. */ +#define ina_ulong(ina) (ina.s_addr) + + /* IP address accessor, host byte order, read only. */ +#define ina_hlong(ina) ntohl(ina.s_addr) + + /* IP address equality. */ + /* XXX: assumes that network byte order won't affect equality. */ +#define ina_equal(a, b) (ina_ulong(a) == ina_ulong(b)) + + /* IP address equality with a mask. */ +#define ina_onnet(h, n, m) ((ina_ulong(h) & ina_ulong(m)) == ina_ulong(n)) + + /* Sequence space arithmetic. */ +#define SEQ_GT(a,b) ((int32_t)((a)-(b)) > 0) +#define SEQ_LT(a,b) ((int32_t)((a)-(b)) < 0) + +#define NS_OPTION_P(option) ((server_options == NULL) ? \ + (panic(panic_msg_no_options, NULL), 0) : \ + ((server_options->flags & option) != 0)) + +#define NS_ZOPTION_P(zp, option) \ + (((zp) != NULL && (((zp)->z_optset & option) != 0)) ? \ + (((zp)->z_options & option) != 0) : NS_OPTION_P(option)) + +#define NS_ZFWDTAB(zp) (((zp) == NULL) ? \ + server_options->fwdtab : (zp)->z_fwdtab) + +#define NS_INCRSTAT(addr, which) \ + do { \ + if ((int)which >= (int)nssLast) \ + ns_panic(ns_log_insist, 1, panic_msg_bad_which, \ + __FILE__, __LINE__, #which); \ + else { \ + if (NS_OPTION_P(OPTION_HOSTSTATS)) { \ + struct nameser *ns = \ + nameserFind(addr, NS_F_INSERT); \ + if (ns != NULL) \ + ns->stats[(int)which]++; \ + } \ + globalStats[(int)which]++; \ + } \ + } while (0) + +enum severity { ignore, warn, fail, not_set }; + +#ifdef BIND_NOTIFY +enum notify { notify_use_default=0, notify_yes, notify_no, notify_explicit }; +#endif + +enum zdialup { zdialup_use_default=0, zdialup_yes, zdialup_no }; + +enum axfr_format { axfr_use_default=0, axfr_one_answer, axfr_many_answers }; + +struct ip_match_direct { + struct in_addr address; + struct in_addr mask; +}; + +struct ip_match_indirect { + struct ip_match_list *list; +}; + +struct ip_match_key { + struct dst_key *key; +}; + +typedef enum { ip_match_pattern, ip_match_indirect, ip_match_localhost, + ip_match_localnets, ip_match_key } ip_match_type; + +typedef struct ip_match_element { + ip_match_type type; + u_int flags; + union { + struct ip_match_direct direct; + struct ip_match_indirect indirect; + struct ip_match_key key; + } u; + struct ip_match_element *next; +} *ip_match_element; + +/* Flags for ip_match_element */ +#define IP_MATCH_NEGATE 0x01 /* match means deny access */ + +typedef struct ip_match_list { + ip_match_element first; + ip_match_element last; +} *ip_match_list; + +typedef struct ztimer_info { + char *name; + int class; + int type; +} *ztimer_info; + +/* + * These fields are ordered to maintain word-alignment; + * be careful about changing them. + */ +struct zoneinfo { + char *z_origin; /* root domain name of zone */ + time_t z_time; /* time for next refresh */ + time_t z_lastupdate; /* time of last soa serial increment */ + u_int32_t z_refresh; /* refresh interval */ + u_int32_t z_retry; /* refresh retry interval */ + u_int32_t z_expire; /* expiration time for cached info */ + u_int32_t z_minimum; /* minimum TTL value */ + u_int32_t z_serial; /* changes if zone modified */ + char *z_source; /* source location of data */ + time_t z_ftime; /* modification time of source file */ + struct in_addr z_axfr_src; /* bind() the axfr socket to this */ + struct in_addr z_addr[NSMAX]; /* list of master servers for zone */ + struct dst_key * z_keys[NSMAX]; /* tsig key associated with master */ + u_char z_addrcnt; /* number of entries in z_addr[] */ + struct in_addr z_xaddr[NSMAX]; /* list of master servers for xfer */ + u_char z_xaddrcnt; /* number of entries in z_xaddr[] */ + u_char z_type; /* type of zone; see below */ + u_int32_t z_flags; /* state bits; see below */ + pid_t z_xferpid; /* xfer child pid */ + u_int z_options; /* options set specific to this zone */ + u_int z_optset; /* which opts override global opts */ + int z_class; /* class of zone */ + int z_numxfrs; /* Ref count of concurrent xfrs. */ + enum severity z_checknames; /* How to handle non-RFC-compliant names */ +#ifdef BIND_UPDATE + time_t z_dumptime; /* randomized time for next zone dump + * if Z_NEED_DUMP is set */ + u_int32_t z_dumpintvl; /* time interval between zone dumps */ + time_t z_soaincrintvl; /* interval for updating soa serial */ + time_t z_soaincrtime; /* time for soa increment */ + u_int32_t z_deferupdcnt; /* max number of updates before SOA + * serial number incremented */ + u_int32_t z_updatecnt; /* number of update requests processed + * since the last SOA serial update */ + char *z_updatelog; /* log file for updates */ +#endif + ip_match_list z_update_acl; /* list of who can issue dynamic + updates */ + ip_match_list z_query_acl; /* sites we'll answer questions for */ + ip_match_list z_transfer_acl; /* sites that may get a zone transfer + from us */ + long z_max_transfer_time_in; /* max num seconds for AXFR */ +#ifdef BIND_NOTIFY + enum notify z_notify; /* Notify mode */ + struct in_addr *z_also_notify; /* More nameservers to notify */ + int z_notify_count; +#endif + enum zdialup z_dialup; /* secondaries over a dialup link */ + char *z_ixfr_base; /* where to find the history of the zone */ + char *z_ixfr_tmp; /* tmp file for the ixfr */ + int z_maintain_ixfr_base; + long z_max_log_size_ixfr; + u_int32_t z_serial_ixfr_start; + evTimerID z_timer; /* maintenance timer */ + ztimer_info z_timerinfo; /* UAP associated with timer */ + time_t z_nextmaint; /* time of next maintenance */ + u_int16_t z_port; /* perform AXFR to this port */ + struct fwdinfo *z_fwdtab; /* zone-specific forwarders */ + LINK(struct zoneinfo) z_freelink; /* if it's on the free list. */ + LINK(struct zoneinfo) z_reloadlink; /* if it's on the reload list. */ +}; + + /* zone types (z_type) */ +enum zonetype { z_nil, z_master, z_slave, z_hint, z_stub, z_forward, + z_cache, z_any }; +#define Z_NIL z_nil /* XXX */ +#define Z_MASTER z_master /* XXX */ +#define Z_PRIMARY z_master /* XXX */ +#define Z_SLAVE z_slave /* XXX */ +#define Z_SECONDARY z_slave /* XXX */ +#define Z_HINT z_hint /* XXX */ +#define Z_CACHE z_cache /* XXX */ +#define Z_STUB z_stub /* XXX */ +#define Z_FORWARD z_forward /* XXX */ +#define Z_ANY z_any /* XXX*2 */ + + /* zone state bits (32 bits) */ +#define Z_AUTH 0x00000001 /* zone is authoritative */ +#define Z_NEED_XFER 0x00000002 /* waiting to do xfer */ +#define Z_XFER_RUNNING 0x00000004 /* asynch. xfer is running */ +#define Z_NEED_RELOAD 0x00000008 /* waiting to do reload */ +#define Z_SYSLOGGED 0x00000010 /* have logged timeout */ +#define Z_QSERIAL 0x00000020 /* sysquery()'ing for serial number */ +#define Z_FOUND 0x00000040 /* found in boot file when reloading */ +#define Z_INCLUDE 0x00000080 /* set if include used in file */ +#define Z_DB_BAD 0x00000100 /* errors when loading file */ +#define Z_TMP_FILE 0x00000200 /* backup file for xfer is temporary */ +#ifdef BIND_UPDATE +#define Z_DYNAMIC 0x00000400 /* allow dynamic updates */ +#define Z_NEED_DUMP 0x00000800 /* zone has changed, needs a dump */ +#define Z_NEED_SOAUPDATE 0x00001000 /* soa serial number needs increment */ +#endif /* BIND_UPDATE */ +#define Z_XFER_ABORTED 0x00002000 /* zone transfer has been aborted */ +#define Z_XFER_GONE 0x00004000 /* zone transfer process is gone */ +#define Z_TIMER_SET 0x00008000 /* z_timer contains a valid id */ +#ifdef BIND_NOTIFY +#define Z_NOTIFY 0x00010000 /* has an outbound notify executing */ +#endif +#define Z_NEED_QSERIAL 0x00020000 /* we need to re-call qserial() */ +#define Z_PARENT_RELOAD 0x00040000 /* we need to reload this as parent */ +#define Z_FORWARD_SET 0x00080000 /* has forwarders been set */ +#define Z_EXPIRED 0x00100000 /* expire timer has gone off */ +#define Z_NEEDREFRESH 0x00200000 /* need to perform a refresh check */ + + /* named_xfer exit codes */ +#define XFER_UPTODATE 0 /* zone is up-to-date */ +#define XFER_SUCCESS 1 /* performed transfer successfully */ +#define XFER_TIMEOUT 2 /* no server reachable/xfer timeout */ +#define XFER_FAIL 3 /* other failure, has been logged */ +#define XFER_SUCCESSAXFR 4 /* named-xfr recived a xfr */ +#define XFER_SUCCESSIXFR 5 /* named-xfr recived a ixfr */ +#define XFER_SUCCESSAXFRIXFRFILE 6 /* named-xfr received AXFR for IXFR */ +#define XFER_REFUSED 7 /* one master returned REFUSED */ +#define XFER_ISAXFR -1 /* the last XFR is AXFR */ +#define XFER_ISIXFR -2 /* the last XFR is IXFR */ +#define XFER_ISAXFRIXFR -3 /* the last XFR is AXFR but we must create IXFR base */ + +struct qserv { + struct sockaddr_in + ns_addr; /* address of NS */ + struct databuf *ns; /* databuf for NS record */ + struct databuf *nsdata; /* databuf for server address */ + struct timeval stime; /* time first query started */ + unsigned int forwarder:1; /* this entry is for a forwarder */ + unsigned int noedns:1; /* don't try edns */ + unsigned int nretry:30; /* # of times addr retried */ + u_int32_t serial; /* valid if Q_ZSERIAL */ +}; + +/* + * Structure for recording info on forwarded or generated queries. + */ +struct qinfo { + u_int16_t q_id; /* id of query */ + u_int16_t q_nsid; /* id of forwarded query */ + struct sockaddr_in + q_from; /* requestor's address */ + u_char *q_msg, /* the message */ + *q_cmsg; /* the cname message */ + int16_t q_msglen, /* len of message */ + q_msgsize, /* allocated size of message */ + q_cmsglen, /* len of cname message */ + q_cmsgsize; /* allocated size of cname message */ + int16_t q_dfd; /* UDP file descriptor */ + u_int16_t q_udpsize; /* UDP message size */ + int q_distance; /* distance this query is from the + * original query that the server + * received. */ + time_t q_time; /* time to retry */ + time_t q_expire; /* time to expire */ + struct qinfo *q_next; /* rexmit list (sorted by time) */ + struct qinfo *q_link; /* storage list (random order) */ + struct databuf *q_usedns[NSMAX]; /* databuf for NS that we've tried */ + struct qserv q_addr[NSMAX]; /* addresses of NS's */ +#ifdef notyet + struct nameser *q_ns[NSMAX]; /* name servers */ +#endif + struct dst_key *q_keys[NSMAX]; /* keys to use with this address */ + u_char q_naddr; /* number of addr's in q_addr */ + u_char q_curaddr; /* last addr sent to */ + u_char q_nusedns; /* number of elements in q_usedns[] */ + u_int8_t q_flags; /* see below */ + int16_t q_cname; /* # of cnames found */ + int16_t q_nqueries; /* # of queries required */ + struct qstream *q_stream; /* TCP stream, null if UDP */ + struct zoneinfo *q_zquery; /* Zone query is about (Q_ZSERIAL) */ + struct zoneinfo *q_fzone; /* Forwarding zone, if any */ + char *q_domain; /* domain of most enclosing zone cut */ + char *q_name; /* domain of query */ + u_int16_t q_class; /* class of query */ + u_int16_t q_type; /* type of query */ +#ifdef BIND_NOTIFY + int q_notifyzone; /* zone which needs another notify() + * when the reply to this comes in. + */ +#endif + struct tsig_record *q_tsig; /* forwarded query's TSIG record */ + struct tsig_record *q_nstsig; /* forwarded query's TSIG record */ +}; + + /* q_flags bits (8 bits) */ +#define Q_SYSTEM 0x01 /* is a system query */ +#define Q_PRIMING 0x02 /* generated during priming phase */ +#define Q_ZSERIAL 0x04 /* getting zone serial for xfer test */ +#define Q_USEVC 0x08 /* forward using tcp not udp */ +#define Q_EDNS 0x10 /* add edns opt record to answer */ + +#define Q_NEXTADDR(qp,n) (&(qp)->q_addr[n].ns_addr) + +#define RETRY_TIMEOUT 45 + +/* + * Return codes from ns_forw: + */ +#define FW_OK 0 +#define FW_DUP 1 +#define FW_NOSERVER 2 +#define FW_SERVFAIL 3 + +typedef void (*sq_closure)(struct qstream *qs); + +#ifdef BIND_UPDATE +struct fdlist { + int fd; + struct fdlist *next; +}; +#endif + + +typedef struct ns_delta { + LINK(struct ns_delta) d_link; + ns_updque d_changes; +} ns_delta; + +typedef LIST(ns_delta) ns_deltalist; + +typedef struct _interface { + int dfd, /* Datagram file descriptor */ + sfd; /* Stream file descriptor. */ + time_t gen; /* Generation number. */ + struct in_addr addr; /* Interface address. */ + u_int16_t port; /* Interface port. */ + u_int16_t flags; /* Valid bits for evXXXXID. */ + evFileID evID_d; /* Datagram read-event. */ + evConnID evID_s; /* Stream listen-event. */ + LINK(struct _interface) link; +} interface; + +#define INTERFACE_FILE_VALID 0x01 +#define INTERFACE_CONN_VALID 0x02 +#define INTERFACE_FORWARDING 0x04 + +struct qstream { + int s_rfd; /* stream file descriptor */ + int s_size; /* expected amount of data to rcv */ + int s_bufsize; /* amount of data received in s_buf */ + u_char *s_buf; /* buffer of received data */ + u_char *s_wbuf; /* send buffer */ + u_char *s_wbuf_send; /* next sendable byte of send buffer */ + u_char *s_wbuf_free; /* next free byte of send buffer */ + u_char *s_wbuf_end; /* byte after end of send buffer */ + sq_closure s_wbuf_closure; /* callback for writable descriptor */ + struct qstream *s_next; /* next stream */ + struct sockaddr_in + s_from; /* address query came from */ + interface *s_ifp; /* interface query came from */ + time_t s_time; /* time stamp of last transaction */ + int s_refcnt; /* number of outstanding queries */ + u_char s_temp[HFIXEDSZ]; +#ifdef BIND_UPDATE + int s_opcode; /* type of request */ + int s_linkcnt; /* number of client connections using + * this connection to forward updates + * to the primary */ + struct fdlist *s_fds; /* linked list of connections to the + * primaries that have been used by + * the server to forward this client's + * update requests */ +#endif + evStreamID evID_r; /* read event. */ + evFileID evID_w; /* writable event handle. */ + evConnID evID_c; /* connect event handle */ + u_int flags; /* see below */ + struct qstream_xfr { + enum { s_x_base, s_x_firstsoa, s_x_zone, + s_x_lastsoa, s_x_done, s_x_adding, + s_x_deleting, s_x_addsoa, s_x_deletesoa } + state; /* state of transfer. */ + u_char *msg, /* current assembly message. */ + *cp, /* where are we in msg? */ + *eom, /* end of msg. */ + *ptrs[128]; /* ptrs for dn_comp(). */ + int class, /* class of an XFR. */ + type, /* type of XFR. */ + id, /* id of an XFR. */ + opcode; /* opcode of an XFR. */ + u_int zone; /* zone being XFR'd. */ + union { + struct namebuf *axfr; /* top np of an AXFR. */ + ns_deltalist *ixfr; /* top udp of an IXFR. */ + } top; + int ixfr_zone; + u_int32_t serial; /* serial number requested in IXFR */ + ns_tcp_tsig_state *tsig_state; /* used by ns_sign_tcp */ + int tsig_skip; /* skip calling ns_sign_tcp + * during the next flush */ + int tsig_size; /* need to reserve this space + * for the tsig. */ + struct qs_x_lev { /* decompose the recursion. */ + enum {sxl_ns, sxl_all, sxl_sub} + state; /* what's this level doing? */ + int flags; /* see below (SXL_*). */ + char dname[MAXDNAME]; + struct namebuf *np, /* this node. */ + *nnp, /* next node to process. */ + **npp, /* subs. */ + **npe; /* end of subs. */ + struct databuf *dp; /* current rr. */ + struct qs_x_lev *next; /* link. */ + } *lev; /* LIFO. */ + enum axfr_format transfer_format; + } xfr; +}; +#define SXL_GLUING 0x01 +#define SXL_ZONECUT 0x02 + + /* flags */ +#define STREAM_MALLOC 0x01 +#define STREAM_WRITE_EV 0x02 +#define STREAM_READ_EV 0x04 +#define STREAM_CONNECT_EV 0x08 +#define STREAM_DONE_CLOSE 0x10 +#define STREAM_AXFR 0x20 +#define STREAM_AXFRIXFR 0x40 + +#define ALLOW_NETS 0x0001 +#define ALLOW_HOSTS 0x0002 +#define ALLOW_ALL (ALLOW_NETS | ALLOW_HOSTS) + +struct fwddata { + struct sockaddr_in + fwdaddr; /* address of NS */ + struct databuf *ns; /* databuf for NS record */ + struct databuf *nsdata; /* databuf for server address */ + int ref_count; /* how many users of this */ +}; + +struct fwdinfo { + struct fwdinfo *next; + struct fwddata *fwddata; +}; + +enum nameserStats { nssRcvdR, /* sent us an answer */ + nssRcvdNXD, /* sent us a negative response */ + nssRcvdFwdR, /* sent us a response we had to fwd */ + nssRcvdDupR, /* sent us an extra answer */ + nssRcvdFail, /* sent us a SERVFAIL */ + nssRcvdFErr, /* sent us a FORMERR */ + nssRcvdErr, /* sent us some other error */ + nssRcvdAXFR, /* sent us an AXFR */ + nssRcvdLDel, /* sent us a lame delegation */ + nssRcvdOpts, /* sent us some IP options */ + nssSentSysQ, /* sent them a sysquery */ + nssSentAns, /* sent them an answer */ + nssSentFwdQ, /* fwdd a query to them */ + nssSentDupQ, /* sent them a retry */ + nssSendtoErr, /* error in sendto */ + nssRcvdQ, /* sent us a query */ + nssRcvdIQ, /* sent us an inverse query */ + nssRcvdFwdQ, /* sent us a query we had to fwd */ + nssRcvdDupQ, /* sent us a retry */ + nssRcvdTCP, /* sent us a query using TCP */ + nssSentFwdR, /* fwdd a response to them */ + nssSentFail, /* sent them a SERVFAIL */ + nssSentFErr, /* sent them a FORMERR */ + nssSentNaAns, /* sent them a non autoritative answer */ + nssSentNXD, /* sent them a negative response */ + nssRcvdUQ, /* sent us an unapproved query */ + nssRcvdURQ, /* sent us an unapproved recursive query */ + nssRcvdUXFR, /* sent us an unapproved AXFR or IXFR */ + nssRcvdUUpd, /* sent us an unapproved update */ + nssLast }; + +struct nameser { + struct in_addr addr; /* key */ + u_long stats[nssLast]; /* statistics */ +#ifdef notyet + u_int32_t rtt; /* round trip time */ + /* XXX - need to add more stuff from "struct qserv", and use our rtt */ + u_int16_t flags; /* see below */ + u_int8_t xfers; /* #/xfers running right now */ +#endif +}; + +enum transport { primary_trans, secondary_trans, response_trans, update_trans, + num_trans }; + +/* types used by the parser or config routines */ + +typedef struct zone_config { + void *opaque; +} zone_config; + +typedef struct listen_info { + u_short port; + ip_match_list list; + struct listen_info *next; +} *listen_info; + +typedef struct listen_info_list { + listen_info first; + listen_info last; +} *listen_info_list; + +#ifndef RLIMIT_TYPE +#define RLIMIT_TYPE u_long +#endif +typedef RLIMIT_TYPE rlimit_type; + +struct control; +typedef struct control *control; +typedef LIST(struct control) controls; + +enum ordering { unknown_order, fixed_order, cyclic_order, random_order }; + +#define DEFAULT_ORDERING cyclic_order + +typedef struct rrset_order_element { + int class; + int type; + char *name; + enum ordering order; + struct rrset_order_element *next; +} *rrset_order_element ; + +typedef struct rrset_order_list { + rrset_order_element first; + rrset_order_element last; +} *rrset_order_list; + + +typedef struct options { + u_int32_t flags; + char *hostname; + char *version; + char *directory; + char *dump_filename; + char *pid_filename; + char *stats_filename; + char *memstats_filename; + char *named_xfer; + int transfers_in; + int transfers_per_ns; + int transfers_out; + int serial_queries; + int max_log_size_ixfr; + enum axfr_format transfer_format; + long max_transfer_time_in; + struct sockaddr_in query_source; + struct in_addr axfr_src; +#ifdef BIND_NOTIFY + int notify_count; + struct in_addr *also_notify; +#endif + ip_match_list query_acl; + ip_match_list recursion_acl; + ip_match_list transfer_acl; + ip_match_list blackhole_acl; + ip_match_list topology; + ip_match_list sortlist; + enum severity check_names[num_trans]; + u_long data_size; + u_long stack_size; + u_long core_size; + u_long files; + listen_info_list listen_list; + struct fwdinfo *fwdtab; + /* XXX need to add forward option */ + int clean_interval; + int interface_interval; + int stats_interval; + rrset_order_list ordering; + int heartbeat_interval; + u_int max_ncache_ttl; + u_int max_host_stats; + u_int lame_ttl; + int minroots; + u_int16_t preferred_glue; + enum notify notify; +} *options; + +typedef struct key_list_element { + struct dst_key *key; + struct key_list_element *next; +} *key_list_element; + +typedef struct key_info_list { + key_list_element first; + key_list_element last; +} *key_info_list; + +typedef struct topology_config { + void *opaque; +} topology_config; + +#define UNKNOWN_TOPOLOGY_DISTANCE 9998 +#define MAX_TOPOLOGY_DISTANCE 9999 + +typedef struct topology_distance { + ip_match_list patterns; + struct topology_distance *next; +} *topology_distance; + +typedef struct topology_context { + topology_distance first; + topology_distance last; +} *topology_context; + +typedef struct acl_table_entry { + char *name; + ip_match_list list; + struct acl_table_entry *next; +} *acl_table_entry; + +typedef struct server_config { + void *opaque; +} server_config; + +#define SERVER_INFO_BOGUS 0x01 +#define SERVER_INFO_SUPPORT_IXFR 0x02 +#define SERVER_INFO_EDNS 0x04 + +typedef struct server_info { + struct in_addr address; + u_int flags; + int transfers; + enum axfr_format transfer_format; + key_info_list key_list; + /* could move statistics to here, too */ + struct server_info *next; +} *server_info; + +/* + * enum <--> name translation + */ + +struct ns_sym { + int number; /* Identifying number, like ns_log_default */ + const char * name; /* Its symbolic name, like "default" */ +}; + +/* + * Logging options + */ + +typedef enum ns_logging_categories { + ns_log_default = 0, + ns_log_config, + ns_log_parser, + ns_log_queries, + ns_log_lame_servers, + ns_log_statistics, + ns_log_panic, + ns_log_update, + ns_log_ncache, + ns_log_xfer_in, + ns_log_xfer_out, + ns_log_db, + ns_log_eventlib, + ns_log_packet, +#ifdef BIND_NOTIFY + ns_log_notify, +#endif + ns_log_cname, + ns_log_security, + ns_log_os, + ns_log_insist, + ns_log_maint, + ns_log_load, + ns_log_resp_checks, + ns_log_control, + ns_log_max_category +} ns_logging_categories; + +typedef struct log_config { + log_context log_ctx; + log_channel eventlib_channel; + log_channel packet_channel; + int default_debug_active; +} *log_config; + +struct map { + const char * token; + int val; +}; + +#define NOERROR_NODATA 15 /* only used internally by the server, used for + * -ve $ing non-existence of records. 15 is not + * a code used as yet anyway. + */ + +#define NTTL 600 /* ttl for negative data: 10 minutes? */ + +#define VQEXPIRY 900 /* a VQ entry expires in 15*60 = 900 seconds */ + +#ifdef BIND_UPDATE +enum req_action { Finish, Refuse, Return }; +#endif + +#ifdef INIT + error "INIT already defined, check system include files" +#endif +#ifdef DECL + error "DECL already defined, check system include files" +#endif + +#ifdef MAIN_PROGRAM +#define INIT(x) = x +#define DECL +#else +#define INIT(x) +#define DECL extern +#endif + +#define EDNS_MESSAGE_SZ 4096 Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_defs.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_ncache.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_ncache.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_ncache.c (revision 109985) @@ -0,0 +1,269 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_ncache.c,v 8.29.4.1 2002/11/14 13:41:31 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "named.h" + +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eom) { \ + return; \ + } \ + } while (0) + +void +cache_n_resp(u_char *msg, int msglen, struct sockaddr_in from, + const char *qname, int qclass, int qtype) +{ + struct databuf *dp; + HEADER *hp; + u_char *cp, *eom, *rdatap; + char dname[MAXDNAME]; + int n, type, class, flags; + u_int ancount, nscount, dlen; +#ifdef RETURNSOA + u_int32_t ttl; + u_int16_t atype; + u_char *sp, *cp1; + u_char data[MAXDATA]; + u_char *eod = data + sizeof(data); +#endif + + nameserIncr(from.sin_addr, nssRcvdNXD); + + hp = (HEADER *)msg; + cp = msg + HFIXEDSZ; + eom = msg + msglen; + + switch (ntohs(hp->qdcount)) { + case 0: + dname[sizeof dname - 1] = '\0'; + strncpy(dname, qname, sizeof dname); + if (dname[sizeof dname - 1] != '\0') { + ns_debug(ns_log_ncache, 1, + "qp->qname too long (%d)", strlen(qname)); + hp->rcode = FORMERR; + return; + } + class = qclass; + type = qtype; + break; + case 1: + n = dn_expand(msg, eom, cp, dname, sizeof dname); + if (n < 0) { + ns_debug(ns_log_ncache, 1, + "Query expand name failed: cache_n_resp"); + hp->rcode = FORMERR; + return; + } + cp += n; + BOUNDS_CHECK(cp, 2 * INT16SZ); + GETSHORT(type, cp); + GETSHORT(class, cp); + if (class > CLASS_MAX) { + ns_debug(ns_log_ncache, 1, + "bad class in cache_n_resp"); + hp->rcode = FORMERR; + return; + } + break; + default: + ns_debug(ns_log_ncache, 1, + "QDCOUNT>1 (%d) in cache_n_resp", ntohs(hp->qdcount)); + hp->rcode = FORMERR; + return; + } + ns_debug(ns_log_ncache, 1, "ncache: dname %s, type %d, class %d", + dname, type, class); + + ancount = ntohs(hp->ancount); + nscount = ntohs(hp->nscount); + + while (ancount--) { + u_int32_t ttl; + int atype, aclass; + + n = dn_skipname(cp, eom); + if (n < 0) { + ns_debug(ns_log_ncache, 3, "ncache: form error"); + return; + } + cp += n; + BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); + GETSHORT(atype, cp); + GETSHORT(aclass, cp); + if (atype != T_CNAME || aclass != class) { + ns_debug(ns_log_ncache, 3, + "ncache: not CNAME (%s) or wrong class (%s)", + p_type(atype), p_class(aclass)); + return; + } + GETLONG(ttl, cp); + GETSHORT(dlen, cp); + BOUNDS_CHECK(cp, dlen); + rdatap = cp; + n = dn_expand(msg, msg + msglen, cp, dname, sizeof dname); + if (n < 0) { + ns_debug(ns_log_ncache, 3, "ncache: bad cname target"); + return; + } + cp += n; + if (cp != rdatap + dlen) { + ns_debug(ns_log_ncache, 3, "ncache: bad cname rdata"); + return; + } + } + + dp = NULL; +#ifdef RETURNSOA + while (nscount--) { + sp = cp; + + /* we store NXDOMAIN as T_SOA regardless of the query type */ + if (hp->rcode == NXDOMAIN) + type = T_SOA; + + /* store ther SOA record */ + n = dn_skipname(cp, msg + msglen); + if (n < 0) { + ns_debug(ns_log_ncache, 3, "ncache: form error"); + return; + } + cp += n; + + BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); + GETSHORT(atype, cp); /* type */ + cp += INT16SZ; /* class */ + GETLONG(ttl, cp); /* ttl */ + GETSHORT(dlen, cp); /* dlen */ + BOUNDS_CHECK(cp, dlen); + if (atype != T_SOA) { + ns_debug(ns_log_ncache, 3, + "ncache: type (%d) != T_SOA", atype); + cp += dlen; + continue; + } + rdatap = cp; + + /* origin */ + n = dn_expand(msg, msg + msglen, cp, (char*)data, eod - data); + if (n < 0) { + ns_debug(ns_log_ncache, 3, + "ncache: origin form error"); + return; + } + cp += n; + n = strlen((char*)data) + 1; + cp1 = data + n; + /* mail */ + n = dn_expand(msg, msg + msglen, cp, (char*)cp1, eod - cp1); + if (n < 0) { + ns_debug(ns_log_ncache, 3, "ncache: mail form error"); + return; + } + cp += n; + n = strlen((char*)cp1) + 1; + cp1 += n; + n = 5 * INT32SZ; + if (n > (eod - cp1)) /* Can't happen. See MAXDATA. */ + return; + BOUNDS_CHECK(cp, n); + memcpy(cp1, cp, n); + /* serial, refresh, retry, expire, min */ + cp1 += n; + cp += n; + if (cp != rdatap + dlen) { + ns_debug(ns_log_ncache, 3, "ncache: form error"); + return; + } + /* store the zone of the soa record */ + n = dn_expand(msg, msg + msglen, sp, (char*)cp1, eod - cp1); + if (n < 0) { + ns_debug(ns_log_ncache, 3, "ncache: form error 2"); + return; + } + n = strlen((char*)cp1) + 1; + cp1 += n; + + /* + * we only want to store these long enough so that + * ns_resp can find it. + */ + if (qtype == T_SOA && hp->rcode == NXDOMAIN) + ttl = 0; + dp = savedata(class, type, + MIN(ttl, server_options->max_ncache_ttl) + + tt.tv_sec, data, + cp1 - data); + break; + } +#endif + if (dp == NULL) +#ifdef STRICT_RFC2308 + dp = savedata(class, type, tt.tv_sec, NULL, 0); +#else + dp = savedata(class, type, NTTL + tt.tv_sec, NULL, 0); +#endif + dp->d_zone = DB_Z_CACHE; + dp->d_cred = hp->aa ? DB_C_AUTH : DB_C_ANSWER; + dp->d_secure = DB_S_INSECURE; /* BEW - should be UNCHECKED */ + dp->d_clev = 0; + if(hp->rcode == NXDOMAIN) { + dp->d_rcode = NXDOMAIN; + flags = DB_NODATA|DB_NOTAUTH|DB_NOHINTS; + } else { + dp->d_rcode = NOERROR_NODATA; + flags = DB_NOTAUTH|DB_NOHINTS; + } + + n = db_update(dname, dp, dp, NULL, flags, hashtab, from); + if (n != OK) + ns_debug(ns_log_ncache, 1, + "db_update failed (%d), cache_n_resp()", n); + else + ns_debug(ns_log_ncache, 4, + "ncache succeeded: [%s %s %s] rcode:%d ttl:%ld", + dname, p_type(type), p_class(class), + dp->d_rcode, (long)(dp->d_ttl - tt.tv_sec)); + db_detach(&dp); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_ncache.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_req.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_req.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_req.c (revision 109985) @@ -0,0 +1,2545 @@ +#if !defined(lint) && !defined(SABER) +static const char sccsid[] = "@(#)ns_req.c 4.47 (Berkeley) 7/1/91"; +static const char rcsid[] = "$Id: ns_req.c,v 8.169.2.1 2002/11/14 13:02:48 marka Exp $"; +#endif /* not lint */ + +/* + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "port_after.h" + +#include "named.h" + +struct addinfo { + char *a_dname; /* domain name */ + char *a_rname; /* referred by */ + u_int16_t a_rtype; /* referred by */ + u_int16_t a_type; /* type for data */ + u_int16_t a_class; /* class for data */ +}; + + +#ifndef BIND_UPDATE +enum req_action { Finish, Refuse, Return }; +#endif + +static struct addinfo addinfo[NADDRECS]; +static void addname(const char *, const char *, + u_int16_t, u_int16_t, u_int16_t); +static void copyCharString(u_char **, const char *); + +static enum req_action req_query(HEADER *hp, u_char **cpp, u_char *eom, + struct qstream *qsp, + int *buflenp, int *msglenp, + u_char *msg, int dfd, int *ra, + struct sockaddr_in from, + struct tsig_record *in_tsig, + u_int16_t udpsize); + +static enum req_action req_iquery(HEADER *hp, u_char **cpp, u_char *eom, + int *buflenp, struct sockaddr_in from); + +#ifdef BIND_NOTIFY +static enum req_action req_notify(HEADER *hp, u_char **cpp, u_char *eom, + u_char *msg,struct sockaddr_in from); +#endif + +/* + * See if there is a OPT record at the end of the message. + * + * Results: + * -1 FORMERR + * 0 last RR is not a OPT record + * n>0 lenght of OPT record + */ +int +ns_get_opt(u_char *msg, u_char *eom, + u_int8_t *versionp, u_int16_t *rcodep, u_int16_t *flagp, + u_int16_t *bufsizep, u_char **optionsp, size_t *optsizep) +{ + HEADER *hp = (HEADER *) msg; + u_char *start, *options, *cp; + u_int8_t version; + u_int16_t rdlen, type, bufsize, flags, optsize, rcode; + int i, n, root; + + if (msg == NULL || eom == NULL || (msg + HFIXEDSZ) > eom) + return (-1); + + if (ntohs(hp->arcount) == 0) + return (0); + + cp = msg + HFIXEDSZ; + n = ns_skiprr(cp, eom, ns_s_qd, ntohs(hp->qdcount)); + if (n < 0) + return (-1); + cp += n; + n = ns_skiprr(cp, eom, ns_s_an, ntohs(hp->ancount)); + if (n < 0) + return (-1); + cp += n; + n = ns_skiprr(cp, eom, ns_s_ns, ntohs(hp->nscount)); + if (n < 0) + return (-1); + cp += n; + i = ntohs(hp->arcount); + while (i-- > 0) { + start = cp; + if (cp >= eom) + return (-1); + root = (*cp == 0); + n = dn_skipname(cp, eom); + if (n < 0) + return (-1); + cp += n; + if (cp + (2 + 2 + 4 + 2) > eom) + return (-1); + GETSHORT(type, cp); + if (type != ns_t_opt) { + cp += INT16SZ + INT32SZ; /* class, ttl */ + GETSHORT(rdlen, cp); + if (cp + rdlen > eom) + return (-1); + cp += rdlen; + continue; + } + /* We have the OPT record. Check it out in detail. */ + if (!root) + return (-1); + GETSHORT(bufsize, cp); + rcode = (*cp++ <<4) + hp->rcode ; + version = *cp++; + GETSHORT(flags, cp); + GETSHORT(rdlen, cp); + if (cp + rdlen > eom) + return (-1); + options = cp; + optsize = rdlen; + if (versionp != NULL) + *versionp = version; + if (rcodep != NULL) + *rcodep = rcode; + if (flagp != NULL) + *flagp = flags; + if (bufsizep != NULL) + *bufsizep = bufsize; + if (optionsp != NULL) + *optionsp = options; + if (optsizep != NULL) + *optsizep = optsize; + return (cp - start); + } + /* OPT not found */ + return (0); +} + +int +ns_add_opt(u_char *msg, u_char *cp, size_t buflen, u_int8_t version, + u_int16_t rcode, u_int16_t size, u_int16_t flags, + u_char *options, size_t optlen) +{ + HEADER *hp = (HEADER *) msg; + + if ((cp + 1 + 2 + 2 + 4 + 2 + optlen) > (msg + buflen)) + return (-1); + + *cp++ = 0; /* "." */ + PUTSHORT(ns_t_opt, cp); /* type */ + PUTSHORT(size, cp); /* class (udp size) */ + *cp++ = (rcode >> 4) & 0xff; /* ttl (rcode + version + flags) */ + hp->rcode = rcode & 0xf; + *cp++ = version; + PUTSHORT(flags, cp); + PUTSHORT(optlen, cp); /* rdlen */ + memcpy(cp, options, optlen); /* options */ + hp->arcount = htons(ntohs(hp->arcount) + 1); + return (1 + 2 + 2 + 4 + 2 + optlen); +} + +/* + * Process request using database; assemble and send response. + */ +void +ns_req(u_char *msg, int msglen, int buflen, struct qstream *qsp, + struct sockaddr_in from, int dfd) +{ + HEADER *hp = (HEADER *) msg; + u_char *cp, *eom; + enum req_action action = Return; + int n, ra, has_tsig, tsig_size = 0, opt_size = 0, sig2len; + u_char *tsigstart; + u_char sig[TSIG_SIG_SIZE], sig2[TSIG_SIG_SIZE]; + struct tsig_record *in_tsig = NULL; + int error = NOERROR; + int msglen_orig = msglen; + int buflen_orig = buflen; + int siglen = sizeof sig; + DST_KEY *key = NULL; + time_t tsig_time; + int opt = 0; + u_int8_t version = 0; + u_int16_t rcode = ns_r_noerror; + u_int16_t udpsize = 0; + int drop; + int tsig_adjust = 0; + +#ifdef DEBUG + if (debug > 3) { + ns_debug(ns_log_packet, 3, "ns_req(from %s)", sin_ntoa(from)); + fp_nquery(msg, msglen, log_get_stream(packet_channel)); + } +#endif + + drop = drop_port(ntohs(from.sin_port)); + if (qsp == NULL && drop == 1) + return; + + tsigstart = ns_find_tsig(msg, msg + msglen); + if (tsigstart == NULL) + has_tsig = 0; + else { + char buf[MAXDNAME]; + u_char tmp[NS_MAXCDNAME]; + + has_tsig = 1; + n = ns_name_unpack(msg, msg + msglen, tsigstart, + tmp, sizeof tmp); + if (n > 0) { + tsig_adjust = dn_skipname(tmp, tmp + sizeof(tmp)) - n; + if (ns_name_ntop(tmp, buf, sizeof buf) == -1) + n = -1; + else if (buf[0] == '.') + buf[0] = '\0'; + } + if (n < 0) { + ns_debug(ns_log_default, 1, + "ns_req: bad TSIG key name"); + error = ns_r_formerr; + hp->rcode = ns_r_formerr; + key = NULL; + } else if ((key = find_key(buf, NULL)) == NULL) { + error = ns_r_badkey; + hp->rcode = ns_r_notauth; + ns_debug(ns_log_default, 1, + "ns_req: TSIG verify failed - unknown key %s", + buf); + } +#ifdef LOG_TSIG_BUG + if (n < 0 || key == NULL) + ns_error(ns_log_security, + "SECURITY: POSSIBLE ATTEMPT TO EXERCISE \"TSIG BUG\" FROM %s: %s%s%s", + sin_ntoa(from), + (n < 0) ? "bad key (formerr)" : + "unknown key (", + (n < 0) ? "" : (buf[0] != '\0' ? buf : "."), + (n < 0) ? "" : ")"); +#endif + } + if (has_tsig && key != NULL) { + n = ns_verify(msg, &msglen, key, NULL, 0, sig, &siglen, + &tsig_time, 0); + if (n != 0) { + hp->rcode = ns_r_notauth; + /* A query should never have an error code set */ + if (n == ns_r_badsig || n == ns_r_badkey || + n == ns_r_badtime) { + ns_debug(ns_log_default, 1, + "ns_req: TSIG verify failed - query had error %s (%d) set", + p_rcode(n), n); + error = n; + action = Return; + } + /* If there's a processing error just respond */ + else if (n == -ns_r_badsig || n == -ns_r_badkey || + n == -ns_r_badtime) { + n = -n; + ns_debug(ns_log_default, 1, + "ns_req: TSIG verify failed - %s (%d)", + p_rcode(n), n); + error = n; + } else { + ns_debug(ns_log_default, 1, + "ns_req: TSIG verify failed - FORMERR"); + error = ns_r_formerr; + } + action = Finish; + } + in_tsig = memget(sizeof(struct tsig_record)); + if (in_tsig == NULL) + ns_panic(ns_log_default, 1, "memget failed"); + in_tsig->key = key; + in_tsig->siglen = siglen; + memcpy(in_tsig->sig, sig, siglen); + tsig_size = msglen_orig - msglen; + /* AXFR/IXFR need the uncompressed tsig size. */ + in_tsig->tsig_size = tsig_size + tsig_adjust; + } else if (has_tsig) { + action = Finish; + in_tsig = memget(sizeof(struct tsig_record)); + if (in_tsig == NULL) + ns_panic(ns_log_default, 1, "memget failed"); + in_tsig->key = NULL; + in_tsig->siglen = 0; + tsig_size = msg + msglen - tsigstart; + in_tsig->tsig_size = tsig_size; + msglen = tsigstart - msg; + } + + /* Hash some stuff so it's nice and random */ + nsid_hash((u_char *)&tt, sizeof(tt)); + nsid_hash(msg, (msglen > 512) ? 512 : msglen); + + if (error == NOERROR) { + + opt = ns_get_opt(msg, msg + msglen, &version, + NULL, NULL, &udpsize, NULL, NULL); + if (opt < 0) { + rcode = ns_r_formerr; + action = Finish; + } else if (opt == 0) { + if (qsp == NULL && buflen > PACKETSZ) + buflen_orig = buflen = PACKETSZ; + } else if (opt > 0) { + if (version != 0) { + rcode = ns_r_badvers; + action = Finish; + } + opt_size = 11; + if (udpsize < 512) + udpsize = 512; + if (qsp == NULL && buflen > udpsize) + buflen_orig = buflen = udpsize; + } + } else if (qsp == NULL && buflen > PACKETSZ) + buflen_orig = buflen = PACKETSZ; + + /* + * It's not a response so these bits have no business + * being set. will later simplify work if we can + * safely assume these are always 0 when a query + * comes in. + */ +#ifdef BIND_NOTIFY + if (hp->opcode != ns_o_notify) +#endif + hp->aa = 0; + hp->ra = 0; + ra = (NS_OPTION_P(OPTION_NORECURSE) == 0); + + if (error == NOERROR) + hp->rcode = ns_r_noerror; + if (rcode == ns_r_noerror) + rcode = hp->rcode; + cp = msg + HFIXEDSZ; + eom = msg + msglen; + buflen -= HFIXEDSZ; + + free_addinfo(); /* sets addcount to zero */ + dnptrs[0] = NULL; + + if (error == NOERROR && rcode == ns_r_noerror) { + switch (hp->opcode) { + case ns_o_query: + action = req_query(hp, &cp, eom, qsp, + &buflen, &msglen, + msg, dfd, &ra, from, + in_tsig, udpsize); + break; + + case ns_o_iquery: + action = req_iquery(hp, &cp, eom, &buflen, from); + break; + +#ifdef BIND_NOTIFY + case ns_o_notify: + action = req_notify(hp, &cp, eom, msg, from); + break; +#endif + +#ifdef BIND_UPDATE + case ns_o_update: + action = req_update(hp, cp, eom, msg, from, in_tsig); + break; +#endif /* BIND_UPDATE */ + + default: + ns_debug(ns_log_default, 1, + "ns_req: Opcode %d not implemented", + hp->opcode); + /* XXX - should syslog, limited by haveComplained */ + hp->qdcount = htons(0); + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); + hp->rcode = ns_r_notimpl; + action = Finish; + } + rcode = hp->rcode; + } + + if (in_tsig != NULL) { + memput(in_tsig, sizeof(struct tsig_record)); + in_tsig = NULL; + } + + /* + * Loop advoidance. + */ + if (qsp == NULL && drop == 2 && + (hp->rcode == FORMERR || hp->rcode == NOTIMP)) + action = Return; + + /* + * Vector via internal opcode. + */ + switch (action) { + case Return: + return; + case Refuse: + rcode = hp->rcode = ns_r_refused; + cp = eom; + /*FALLTHROUGH*/ + case Finish: + /* rest of the function handles this case */ + break; + default: + panic("ns_req: bad action variable", NULL); + /*NOTREACHED*/ + } + + /* + * Apply final polish. + */ + hp->qr = 1; /* set Response flag */ + hp->ra = ra; /* init above, may be modified by req_query */ + + if (!hp->tc && (has_tsig > 0 || opt > 0) && + buflen < (tsig_size + opt_size)) + hp->tc = 1; + + /* + * If there was a format error, then we don't know what the msg has. + */ + if (hp->rcode == ns_r_formerr || rcode == ns_r_badvers) { + hp->qdcount = htons(0); + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); + cp = msg + HFIXEDSZ; + } + + /* + * If the query had a TSIG / OPT and the message is truncated or + * there was a TSIG error, build a new message with no data and a + * TSIG / OPT. + */ + if ((hp->tc || error != NOERROR) && (has_tsig > 0 || opt > 0)) { + sign_again: + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); + cp = msg + HFIXEDSZ; + cp += ns_skiprr(cp, msg + msglen, ns_s_qd, ntohs(hp->qdcount)); + ns_name_rollback(cp, (const u_char **)dnptrs, + (const u_char **)dnptrs_end); + if (opt > 0) { + n = ns_add_opt(msg, cp, buflen_orig, 0, + rcode, EDNS_MESSAGE_SZ, 0, NULL, 0); + if (n < 0) { + hp->qdcount = htons(0); + goto sign_again; + } + cp += n; + } + if (has_tsig > 0) { + sig2len = sizeof sig2; + msglen = cp - msg; + buflen = buflen_orig - msglen; + n = ns_sign2(msg, &msglen, msglen + buflen, error, key, + sig, siglen, sig2, &sig2len, tsig_time, + dnptrs, dnptrs_end); + if (n == NS_TSIG_ERROR_NO_SPACE && + ntohs(hp->qdcount) != 0) { + hp->qdcount = htons(0); + goto sign_again; + } + if (n != 0) + ns_info(ns_log_default, + "ns_req: unable to sign response"); + cp = msg + msglen; + } + } + /* Either the message is not truncated or there was no TSIG & OPT */ + else { + /* + * Reserve space for tsig if required. + */ + if (has_tsig > 0 || opt_size != 0) + buflen -= tsig_size + opt_size; + INSIST(buflen >= 0); + msglen = cp - msg; + n = doaddinfo(hp, cp, buflen); + cp += n; + buflen -= n; + msglen += n; + if (opt > 0) { + buflen += opt_size; + n = ns_add_opt(msg, cp, msglen + buflen, 0, + rcode, EDNS_MESSAGE_SZ, 0, NULL, 0); + INSIST(n > 0); + cp += n; + buflen -= n; + msglen += n; + } + if (has_tsig > 0) { + buflen += tsig_size; + sig2len = sizeof sig2; + n = ns_sign2(msg, &msglen, msglen + buflen, error, key, + sig, siglen, sig2, &sig2len, tsig_time, + dnptrs, dnptrs_end); + if (n != 0) { + INSIST(0); + } + cp = msg + msglen; + } + } + +#ifdef DEBUG + if (ns_wouldlog(ns_log_default, 1)) { + ns_debug(ns_log_default, 1, + "ns_req: answer -> %s fd=%d id=%d size=%d rc=%d", + sin_ntoa(from), (qsp == NULL) ? dfd : qsp->s_rfd, + ntohs(hp->id), cp - msg, hp->rcode); + } + if (debug >= 10) + res_pquery(&res, msg, cp - msg, + log_get_stream(packet_channel)); +#endif /*DEBUG*/ + if (qsp == NULL) { + if (sendto(dfd, (char*)msg, cp - msg, 0, + (struct sockaddr *)&from, + sizeof from) < 0) { + if (!haveComplained(ina_ulong(from.sin_addr), + (u_long)sendtoStr)) + ns_info(ns_log_default, + "ns_req: sendto(%s): %s", + sin_ntoa(from), strerror(errno)); + nameserIncr(from.sin_addr, nssSendtoErr); + } + nameserIncr(from.sin_addr, nssSentAns); + if (hp->rcode == ns_r_nxdomain) + nameserIncr(from.sin_addr, nssSentNXD); + if (!hp->aa) + nameserIncr(from.sin_addr, nssSentNaAns); + } else + writestream(qsp, msg, cp - msg); + + /* Is now a safe time? */ + if (needs_prime_cache) + prime_cache(); +} + +#ifdef BIND_NOTIFY +int +findZonePri(const struct zoneinfo *zp, const struct sockaddr_in from) { + struct in_addr ina; + int i; + + ina = from.sin_addr; + for (i = 0; (u_int)i < zp->z_addrcnt; i++) + if (ina_equal(zp->z_addr[i], ina)) + return (i); + return (-1); +} + +static enum req_action +req_notify(HEADER *hp, u_char **cpp, u_char *eom, u_char *msg, + struct sockaddr_in from) +{ + int n, type, class; + char dnbuf[MAXDNAME]; + struct zoneinfo *zp; + + /* valid notify's are authoritative */ + if (!hp->aa) { + ns_debug(ns_log_notify, 1, + "FORMERR Notify request without AA"); +#ifdef not_yet + hp->rcode = ns_r_formerr; + return (Finish); +#endif + } + hp->aa = 0; + + /* valid notify's have one question */ + if (ntohs(hp->qdcount) != 1) { + ns_debug(ns_log_notify, 1, + "FORMERR Notify header counts wrong"); + hp->rcode = ns_r_formerr; + return (Finish); + } + + n = dn_expand(msg, eom, *cpp, dnbuf, sizeof dnbuf); + if (n < 0) { + ns_debug(ns_log_notify, 1, + "FORMERR Query expand name failed"); + hp->rcode = ns_r_formerr; + return (Finish); + } + *cpp += n; + if (*cpp + 2 * INT16SZ > eom) { + ns_debug(ns_log_notify, 1, + "FORMERR notify too short"); + hp->rcode = ns_r_formerr; + return (Finish); + } + GETSHORT(type, *cpp); + GETSHORT(class, *cpp); + ns_info(ns_log_notify, "rcvd NOTIFY(%s, %s, %s) from %s", + dnbuf, p_class(class), p_type(type), sin_ntoa(from)); + /* XXX - when answers are allowed, we'll need to do compression + * correctly here, and we will need to check for packet underflow. + */ + /* + * We are ignoring the other field, make sure the header reflects + * *cpp. + */ + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); + /* Find the zone this NOTIFY refers to. */ + zp = find_auth_zone(dnbuf, class); + if (zp == NULL) { + ns_info(ns_log_notify, + "rcvd NOTIFY for \"%s\", name not one of our zones", + dnbuf); + hp->rcode = ns_r_servfail; + return (Finish); + } + /* Access control. */ + switch (type) { + case T_SOA: + if (zp->z_type != z_slave) { + /* + * This can come if a user did an AXFR of some zone + * somewhere and that zone's server now wants to + * tell us that the SOA has changed. AXFR's always + * come from nonpriv ports so it isn't possible to + * know whether it was the server or just "dig". + * This condition can be avoided by using secure + * zones since that way only real secondaries can + * AXFR from you. + */ + ns_info(ns_log_notify, + "NOTIFY(SOA) for non-slave zone (%s), from %s", + dnbuf, sin_ntoa(from)); + goto refuse; + } + if (ns_samename(dnbuf, zp->z_origin) != 1) { + ns_info(ns_log_notify, + "NOTIFY(SOA) for non-origin (%s), from %s", + dnbuf, sin_ntoa(from)); + goto refuse; + } + if (findZonePri(zp, from) == -1) { + ns_debug(ns_log_notify, 1, + "NOTIFY(SOA) from non-master server (zone %s), from %s", + zp->z_origin, sin_ntoa(from)); + goto refuse; + } + break; + default: + /* No access requirements defined for other types. */ + break; + } + /* The work occurs here. */ + switch (type) { + case T_SOA: + if (zp->z_flags & + (Z_NEED_RELOAD|Z_NEED_XFER|Z_QSERIAL|Z_XFER_RUNNING)) { + ns_info(ns_log_notify, + "NOTIFY(SOA) for zone already xferring (%s)", + dnbuf); + zp->z_flags |= Z_NEEDREFRESH; + goto noerror; + } + zp->z_time = tt.tv_sec; + qserial_query(zp); + sched_zone_maint(zp); + break; + default: + /* + * Unimplemented, but it's not a protocol error, just + * something to be ignored. + */ + hp->rcode = ns_r_notimpl; + return (Finish); + } + noerror: + hp->rcode = ns_r_noerror; + hp->aa = 1; + return (Finish); + refuse: + hp->rcode = ns_r_refused; + return (Finish); +} +#endif /*BIND_NOTIFY*/ + +static int +add_bind(HEADER *hp, u_char **cpp, u_char *msg, int *msglenp, + const char *label, const char *data) +{ + u_char *tp; + + hp->ancount = htons(1); + hp->nscount = htons(0); + hp->arcount = htons(0); + hp->rcode = ns_r_noerror; + hp->aa = 1; + hp->ra = 0; + copyCharString(cpp, label); /* Name */ + copyCharString(cpp, "BIND"); + *(*cpp)++ = 0x00; + PUTSHORT(T_TXT, *cpp); /* Type */ + PUTSHORT(C_CHAOS, *cpp); /* Class */ + PUTLONG(0, *cpp); /* TTL */ + tp = *cpp; /* Temp RdLength */ + PUTSHORT(0, *cpp); + copyCharString(cpp, data); + PUTSHORT((*cpp) - (tp + INT16SZ), tp); /* Real RdLength */ + *msglenp = *cpp - msg; /* Total message length */ + return (Finish); +} + +static enum req_action +req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp, + int *buflenp, int *msglenp, u_char *msg, int dfd, int *ra, + struct sockaddr_in from, struct tsig_record *in_tsig, + u_int16_t udpsize) +{ + int n, class, type, count, zone, foundname, founddata, omsglen, cname; + int recursion_blocked_by_acl; + u_int16_t id; + u_int32_t serial_ixfr = 0; + int ixfr_found; + int ixfr_error = 0; + char dnbuf2[MAXDNAME]; + u_char **dpp, *omsg, *answers, *afterq; + char dnbuf[MAXDNAME], *dname; + const char *fname; + struct hashbuf *htp; + struct databuf *nsp[NSMAX]; + struct namebuf *np, *anp; + struct qinfo *qp; + struct zoneinfo *zp; + struct databuf *dp; + DST_KEY *in_key = (in_tsig != NULL) ? in_tsig->key : NULL; + int access_class; + int adjustlen = 0; + + nameserIncr(from.sin_addr, nssRcvdQ); + + nsp[0] = NULL; + dpp = dnptrs; + *dpp++ = msg; + *dpp = NULL; + /* + * Make gcc happy. + */ + omsglen = 0; + omsg = NULL; + id = 0; + recursion_blocked_by_acl = 0; + + /* valid queries have one question and zero answers */ + if ((ntohs(hp->qdcount) != 1) + || ntohs(hp->ancount) != 0) { + ns_debug(ns_log_default, 1, + "FORMERR Query header counts wrong"); + hp->rcode = ns_r_formerr; + return (Finish); + } + + if (ntohs(hp->arcount) != 0) { + ns_debug(ns_log_default, 1, "Ignoring addition section"); + hp->arcount = htons(0); + adjustlen = 1; + } + + /* + * Get domain name, class, and type. + */ + if ((**cpp & INDIR_MASK) == 0) + *dpp++ = *cpp; /* remember name for compression */ + *dpp = NULL; + n = dn_expand(msg, eom, *cpp, dnbuf, sizeof dnbuf); + if (n < 0) { + ns_debug(ns_log_default, 1, + "FORMERR Query expand name failed"); + hp->rcode = ns_r_formerr; + return (Finish); + } + *cpp += n; + answers = *cpp; + if (*cpp + 2 * INT16SZ > eom) { + ns_debug(ns_log_default, 1, + "FORMERR Query message length short"); + hp->rcode = ns_r_formerr; + return (Finish); + } + GETSHORT(type, *cpp); + GETSHORT(class, *cpp); + if (*cpp < eom && type != ns_t_ixfr) { + if (!adjustlen) + ns_debug(ns_log_default, 6, + "message length > received message"); + *msglenp = *cpp - msg; + } + + if (((ntohs(hp->nscount) != 0) && (type != ns_t_ixfr)) || + ((ntohs(hp->nscount) != 1) && (type == ns_t_ixfr))) + { + ns_debug(ns_log_default, 1, "FORMERR Query nscount wrong"); + hp->rcode = ns_r_formerr; + return (Finish); + } + + afterq = *cpp; + qtypeIncr(type); + + /* + * Process query. + */ + if (type == ns_t_ixfr) { + ns_info(ns_log_security, "Request %s from %s", + p_type(type), sin_ntoa(from)); + hp->nscount = htons(0); + hp->rd = 0; /* Force IXFR queries to be non recursive. */ + n = dn_expand(msg, eom, *cpp, dnbuf2, sizeof dnbuf2); + if (n < 0) { + ns_debug(ns_log_default, 1, + "FORMERR Query expand name failed"); + hp->rcode = ns_r_formerr; + return (Finish); + } + *cpp += n; + if (*cpp + 3 * INT16SZ + INT32SZ > eom) { + ns_debug(ns_log_default, 1, + "ran out of data in IXFR query"); + hp->rcode = ns_r_formerr; + return (Finish); + } + GETSHORT(n, *cpp); + if (n != ns_t_soa || ns_samename(dnbuf, dnbuf2) != 1) { + ns_debug(ns_log_default, 1, + "FORMERR SOA record expected"); + hp->rcode = ns_r_formerr; + return (Finish); + } + *cpp += INT32SZ + INT16SZ * 2; /* skip class, ttl, dlen */ + if (0 >= (n = dn_skipname(*cpp, eom))) { + ns_debug(ns_log_default, 1, + "FORMERR Query expand name failed"); + hp->rcode = ns_r_formerr; + return (Finish); + } + *cpp += n; /* mname */ + if (0 >= (n = dn_skipname(*cpp, eom))) { + ns_debug(ns_log_default, 1, + "FORMERR Query expand name failed"); + hp->rcode = ns_r_formerr; + return (Finish); + } + *cpp += n; /* rname */ + if (*cpp + 5 * INT32SZ > eom) { + ns_debug(ns_log_default, 1, + "ran out of data in IXFR query"); + hp->rcode = ns_r_formerr; + return (Finish); + } + GETLONG(serial_ixfr, *cpp); + /* ignore other soa counters */ + if ((*cpp + (4 * INT32SZ)) < eom && !adjustlen) + ns_debug(ns_log_default, 6, + "ixfr: message length > received message"); + /* Reset msglenp to cover just the question. */ + *msglenp = afterq - msg; + } + *cpp = afterq; + + if (!ns_t_udp_p(type)) { + /* Refuse request if not a TCP connection. */ + if (qsp == NULL) { + ns_info(ns_log_default, + "rejected UDP %s from %s for \"%s\"", + p_type(type), sin_ntoa(from), + *dnbuf ? dnbuf : "."); + return (Refuse); + } + /* The position of this is subtle. */ + nameserIncr(from.sin_addr, nssRcvdAXFR); + hp->rd = 0; /* Recursion not possible. */ + } + *buflenp -= (*msglenp - HFIXEDSZ); + count = 0; + founddata = 0; + dname = dnbuf; + cname = 0; + +#ifdef QRYLOG + if (qrylog) { + ns_info(ns_log_queries, "%s/%s/%s/%s/%s", + (hp->rd) ? "XX+" : "XX ", + inet_ntoa(from.sin_addr), + (dname[0] == '\0') ? "." : dname, + p_type(type), p_class(class)); + } +#endif /*QRYLOG*/ + + try_again: + foundname = 0; + ns_debug(ns_log_default, 1, "req: nlookup(%s) id %d type=%d class=%d", + dname, ntohs(hp->id), type, class); + htp = hashtab; /* lookup relative to root */ + if ((anp = np = nlookup(dname, &htp, &fname, 0)) == NULL) + fname = ""; + ns_debug(ns_log_default, 1, "req: %s '%s' as '%s' (cname=%d)", + np == NULL ? "missed" : "found", + dname, fname, cname); + +#ifdef YPKLUDGE + /* Some braindamaged resolver software will not + recognize internet addresses in dot notation and + send out address queries for "names" such as + 128.93.8.1. This kludge will prevent those + from flooding higher level servers. + We simply claim to be authoritative and that + the domain doesn't exist. + Note that we could return the address but we + don't do that in order to encourage that broken + software is fixed. + */ + + if (!np && type == T_A && class == C_IN && dname) { + struct in_addr ina; + + if (inet_aton(dname, &ina)) { + hp->rcode = ns_r_nxdomain; + hp->aa = 1; + ns_debug(ns_log_default, 3, + "ypkludge: hit as '%s'", dname); + return (Finish); + } + } +#endif /*YPKLUDGE*/ + + /* + * Don't accept in a query names which would be rejected in responses. + * (This is primarily in case we have to forward it, but it's also a + * matter of architectural symmetry.) + */ + if (!ns_nameok(NULL, dname, class, NULL, response_trans, + ns_ownercontext(type, response_trans), + dname, from.sin_addr)) { + ns_debug(ns_log_default, 1, "bad name in query"); + hp->rcode = ns_r_formerr; + return (Refuse); + } + + /* + * Begin Access Control Point + */ + zone = DB_Z_CACHE; + + /* + * Map class ANY to to class IN for the purpose of access control. + */ + access_class = (class == C_ANY && !ns_t_xfr_p(type)) ? C_IN : class; + + if (np) { +#ifndef FORWARD_ALLOWS + struct namebuf *access_np; + + /* + * Find out which zone this will be answered from. Note + * that we look for a zone with the same class as ours. + * The np that we found in the database might not be the + * one we asked for (i.e. dname might not equal fname). This + * is OK, since if a name doesn't exist, we need to go up + * the tree until we find the closest enclosing zone that + * is of the same class. + */ + for (access_np = np; access_np != NULL; + access_np = np_parent(access_np)) { + dp = access_np->n_data; + while (dp && dp->d_class != access_class) + dp = dp->d_next; + if (dp != NULL) { + zone = dp->d_zone; + break; + } + } +#else + /* + * Try looking for forward zone. It can be deeper than + * any entry in the cache. + */ + if (zone == DB_Z_CACHE) { + char *s = dname; + int escape = 0; + while ((zp = find_zone(s, access_class)) == NULL) { + if (*s == '\0') + break; + while (*s != '\0' && (escape || *s != '.')) { + escape = escape ? 0 : (*s == '\\'); + s++; + } + if (*s == '.') + s++; + } + if (zp != NULL) + zone = zp - zones; + } +#endif + } + + zp = &zones[zone]; + + ixfr_found = 0; + if (type == ns_t_ixfr && zone != DB_Z_CACHE) { + if (SEQ_GT(serial_ixfr, zp->z_serial)) + ixfr_found = 0; + else { + ixfr_error = ixfr_have_log(zp, serial_ixfr, + zp->z_serial); + if (ixfr_error < 0) { + ns_info(ns_log_security, "No %s log from %d for \"%s\"", + p_type(type), serial_ixfr, *dname ? dname : "."); + ns_debug(ns_log_default, + 1, "ixfr_have_log(%d %d) failed %d", + serial_ixfr, zp->z_serial, ixfr_error); + ixfr_found = 0; /* Refuse IXFR and send AXFR */ + } else if (ixfr_error == 1) { + ixfr_found = 1; + } + } + ns_debug(ns_log_default, 1, "IXFR log lowest serial: %d", + zp->z_serial_ixfr_start); + } + /* + * If recursion is turned on, we need to check recursion ACL + * if it exists - and return result to caller. + */ + { + ip_match_list recursion_acl; + + recursion_acl = server_options->recursion_acl; + if (!NS_OPTION_P(OPTION_NORECURSE) && recursion_acl != NULL + && !ip_address_allowed(recursion_acl, from.sin_addr)) { + recursion_blocked_by_acl = 1; + *ra = 0; + } + } + + /* + * Are queries allowed from this host? + */ + if (!ns_t_xfr_p(type)) { + ip_match_list query_acl; + + if (zp->z_query_acl != NULL) + query_acl = zp->z_query_acl; + else + query_acl = server_options->query_acl; + + if (query_acl != NULL + && !ip_addr_or_key_allowed(query_acl, from.sin_addr, + in_key)) + { + /* + * If this is *not* a zone acl and we would not + * have recursed and we have some answer return + * what we have with a referral. + */ + if ((zp->z_query_acl == NULL) && + (!hp->rd || NS_OPTION_P(OPTION_NORECURSE) || + recursion_blocked_by_acl) && + (ntohs(hp->ancount) != 0)) { + goto fetchns; + } + + /* + * See if we would have made a referral from + * an enclosing zone if we are actually in the + * cache. + */ + if (zp->z_type == z_cache && np != NULL) { + struct namebuf *access_np; + + zone = DB_Z_CACHE; + for (access_np = np; access_np != NULL; + access_np = np_parent(access_np)) { + dp = access_np->n_data; + while (dp && + (dp->d_class != access_class || + dp->d_zone == DB_Z_CACHE)) + dp = dp->d_next; + if (dp != NULL) { + zone = dp->d_zone; + np = access_np; + break; + } + } + zp = &zones[zone]; + if (zp->z_type != z_cache && + zp->z_query_acl != NULL && + ip_addr_or_key_allowed(zp->z_query_acl, + from.sin_addr, in_key) && + (!hp->rd || recursion_blocked_by_acl || + NS_OPTION_P(OPTION_NORECURSE))) { + goto fetchns; + } + } +#ifdef NXDOMAIN_ON_DENIAL + hp->rcode = ns_r_nxdomain; + return (Finish); +#else + ns_notice(ns_log_security, + "denied query from %s for \"%s\" %s/%s", + sin_ntoa(from), *dname ? dname : ".", + p_type(type), p_class(class)); + nameserIncr(from.sin_addr, nssRcvdUQ); + return (Refuse); +#endif + } + } else { + ip_match_list transfer_acl; + + /* Do they have permission to do a zone transfer? */ + + if (zp->z_transfer_acl != NULL) + transfer_acl = zp->z_transfer_acl; + else + transfer_acl = server_options->transfer_acl; + + if (transfer_acl != NULL + && !ip_addr_or_key_allowed(transfer_acl, from.sin_addr, + in_key)) + { + ns_notice(ns_log_security, + "denied %s from %s for \"%s\" %s (acl)", + p_type(type), sin_ntoa(from), + *dname ? dname : ".", p_class(class)); + nameserIncr(from.sin_addr, nssRcvdUXFR); + if (type == ns_t_ixfr) { + hp->rcode = ns_r_refused; + return (Finish); + } + return (Refuse); + } + + /* Are we master or slave? */ + + if (zp->z_type != z_master && zp->z_type != z_slave) { + ns_notice(ns_log_security, + "denied %s from %s for \"%s\" (not master/slave)", + p_type(type), sin_ntoa(from), + *dname ? dname : "."); + nameserIncr(from.sin_addr, nssRcvdUXFR); + if (type == ns_t_ixfr) { + hp->rcode = ns_r_refused; + return (Finish); + } + return (Refuse); + } + + /* Are we authoritative? */ + + if ((zp->z_flags & Z_AUTH) == 0) { + ns_notice(ns_log_security, + "denied %s from %s for \"%s\" %s (not authoritative)", + p_type(type), sin_ntoa(from), + *dname ? dname : ".", p_class(class)); + nameserIncr(from.sin_addr, nssRcvdUXFR); + if (type == ns_t_ixfr) { + hp->rcode = ns_r_refused; + return (Finish); + } + return (Refuse); + } + + /* Is the name at a zone cut? */ + + if (ns_samename(zp->z_origin, dname) != 1) { + ns_notice(ns_log_security, + "denied %s from %s for \"%s\" %s (not zone top)", + p_type(type), sin_ntoa(from), + *dname ? dname : ".", p_class(class)); + nameserIncr(from.sin_addr, nssRcvdUXFR); + if (type == ns_t_ixfr) { + hp->rcode = ns_r_refused; + return (Finish); + } + return (Refuse); + } + + if (type == ns_t_ixfr) { + ns_info(ns_log_security, "approved %s from %s for \"%s\"", + (ixfr_found) ? p_type(type) : "IXFR/AXFR", + sin_ntoa(from), *dname ? dname : "."); + } else + ns_info(ns_log_security, "approved %s from %s for \"%s\"", + p_type(type), sin_ntoa(from), *dname ? dname : "."); + } + + /* + * End Access Control Point + */ + /* + * Yow! + */ + if (class == ns_c_chaos && type == ns_t_txt && + ns_samename(dnbuf, "VERSION.BIND") == 1 && + server_options->version != NULL && + server_options->version[0] != '\0') + return (add_bind(hp, cpp, msg, msglenp, + "VERSION", server_options->version)); + + if (class == ns_c_chaos && type == ns_t_txt && + ns_samename(dnbuf, "HOSTNAME.BIND") == 1 && + server_options->hostname != NULL && + server_options->hostname[0] != '\0') + return (add_bind(hp, cpp, msg, msglenp, + "HOSTNAME", server_options->hostname)); + + /* + * If we don't know anything about the requested name, + * go look for nameservers. + */ + if (!np || fname != dname) + goto fetchns; + + foundname++; + answers = *cpp; + count = *cpp - msg; + + /* The response is authoritative until we add insecure data */ + hp->ad = 1; + + /* Look for NXDOMAIN record with appropriate class + * if found return immediately + */ + for (dp = np->n_data; dp; dp = dp->d_next) { + if (!stale(dp) && (dp->d_rcode == ns_r_nxdomain) && + (dp->d_class == class)) { +#ifdef RETURNSOA + n = finddata(np, class, T_SOA, hp, &dname, + buflenp, &count); + if (n != 0) { + if (count) { + *cpp += n; + *buflenp -= n; + *msglenp += n; + hp->nscount = htons((u_int16_t)count); + } + if (hp->rcode == NOERROR_NODATA) { + /* this should not occur */ + hp->rcode = ns_r_noerror; + return (Finish); + } + } +#else + count = 0; +#endif + hp->rcode = ns_r_nxdomain; + /* + * XXX forcing AA all the time isn't right, but + * we have to work that way by default + * for compatibility with older servers. + */ + if (!NS_OPTION_P(OPTION_NONAUTH_NXDOMAIN)) + hp->aa = 1; + ns_debug(ns_log_default, 3, "NXDOMAIN aa = %d", + hp->aa); + if ((count == 0) || NS_OPTION_P(OPTION_NORFC2308_TYPE1)) + return (Finish); + founddata = 1; + goto fetchns; + } + } + + /* + * If not NXDOMAIN, the NOERROR_NODATA record might be + * anywhere in the chain. Have to go through the grind. + */ + + n = finddata(np, class, type, hp, &dname, buflenp, &count); + if (n == 0) { + /* + * NO data available. Refuse transfer requests, or + * look for better servers for other requests. + */ + if (ns_t_xfr_p(type)) { + ns_debug(ns_log_default, 1, + "transfer refused: no data"); + return (Refuse); + } + goto fetchns; + } + + if (hp->rcode == NOERROR_NODATA) { + hp->rcode = ns_r_noerror; +#ifdef RETURNSOA + if (count) { + *cpp += n; + *buflenp -= n; + *msglenp += n; + hp->nscount = htons(count); + } +#endif + founddata = 1; + ns_debug(ns_log_default, 1, "count = %d", count); + if ((count == 0) || NS_OPTION_P(OPTION_NORFC2308_TYPE1)) + return (Finish); + goto fetchns; + } + + *cpp += n; + *buflenp -= n; + *msglenp += n; + hp->ancount = htons(ntohs(hp->ancount) + (u_int16_t)count); + if (fname != dname && type != T_CNAME && type != T_ANY) { + if (cname++ >= MAXCNAMES) { + ns_debug(ns_log_default, 3, + "resp: leaving, MAXCNAMES exceeded"); + hp->rcode = ns_r_servfail; + return (Finish); + } + goto try_again; + } + founddata = 1; + ns_debug(ns_log_default, 3, + "req: foundname=%d, count=%d, founddata=%d, cname=%d", + foundname, count, founddata, cname); + + if (ns_t_xfr_p(type)) { +#ifdef BIND_UPDATE + if ((zp->z_flags & Z_NEED_SOAUPDATE) != 0) + if (incr_serial(zp) < 0) + ns_error(ns_log_default, + "error updating serial number for %s from %d", + zp->z_origin, zp->z_serial); +#endif + /* + * Just return SOA if "up to date". + */ + if (type == ns_t_ixfr) { + hp->aa = 1; + if ((SEQ_GT(serial_ixfr, zp->z_serial) || + serial_ixfr == zp->z_serial)) { + return (Finish); + } + } + + /* + * We don't handle UDP based IXFR queries (yet). + * Tell client to retry with TCP by returning SOA. + */ + if (qsp == NULL) + return (Finish); + else { + if (!ixfr_found && type == ns_t_ixfr) { + qsp->flags |= STREAM_AXFRIXFR; + hp->qdcount = htons(1); + } + ns_xfr(qsp, np, zone, class, type, + hp->opcode, ntohs(hp->id), + serial_ixfr, in_tsig); + } + return (Return); + } + + if (count > 1 && type == T_A && !NS_OPTION_P(OPTION_NORECURSE) && + hp->rd) + sort_response(answers, *cpp, count, &from); + + fetchns: + /* + * If we're already out of room in the response, we're done. + */ + if (hp->tc) + return (Finish); + + if (hp->ancount == 0) + hp->ad = 0; + + /* + * Look for name servers to refer to and fill in the authority + * section or record the address for forwarding the query + * (recursion desired). + */ + free_nsp(nsp); + nsp[0] = NULL; + count = 0; + switch (findns(&np, class, nsp, &count, 0)) { + case NXDOMAIN: + /* We are authoritative for this np. */ + if (!foundname) + hp->rcode = ns_r_nxdomain; + ns_debug(ns_log_default, 3, "req: leaving (%s, rcode %d)", + dname, hp->rcode); + if (class != C_ANY) { + hp->aa = 1; + if (np && (!foundname || !founddata)) { + n = doaddauth(hp, *cpp, *buflenp, np, nsp[0]); + *cpp += n; + *buflenp -= n; +#ifdef ADDAUTH + } else if (ntohs(hp->ancount) != 0) { + /* don't add NS records for NOERROR NODATA + as some servers can get confused */ + free_nsp(nsp); + switch (findns(&np, class, nsp, &count, 1)) { + case NXDOMAIN: + case SERVFAIL: + break; + default: + if (np && + (type != T_NS || np != anp) + ) { + n = add_data(np, nsp, *cpp, + *buflenp, &count); + if (n < 0) { + hp->tc = 1; + n = (-n); + } + *cpp += n; + *buflenp -= n; + hp->nscount = + htons((u_int16_t) + count); + } + } +#endif /*ADDAUTH*/ + } + } + free_nsp(nsp); + return (Finish); + + case SERVFAIL: + /* We're authoritative but the zone isn't loaded. */ + if (!founddata && + !(NS_ZOPTION_P(zp, OPTION_FORWARD_ONLY) && + NS_ZFWDTAB(zp))) { + hp->rcode = ns_r_servfail; + free_nsp(nsp); + return (Finish); + } + } + + if (!founddata && hp->rd && recursion_blocked_by_acl) { + ns_notice(ns_log_security, + "denied recursion for query from %s for %s %s", + sin_ntoa(from), *dname ? dname : ".", p_class(class)); + nameserIncr(from.sin_addr, nssRcvdURQ); + } + + /* + * If we successfully found the answer in the cache, + * or this is not a recursive query, or we are purposely + * never recursing, or recursion is prohibited by ACL, then + * add the nameserver references("authority section") here + * and we're done. + */ + if (founddata || !hp->rd || NS_OPTION_P(OPTION_NORECURSE) + || recursion_blocked_by_acl) { + /* + * If the qtype was NS, and the np of the authority is + * the same as the np of the data, we don't need to add + * another copy of the answer here in the authority + * section. + */ + if (!founddata || type != T_NS || anp != np) { + n = add_data(np, nsp, *cpp, *buflenp, &count); + if (n < 0) { + hp->tc = 1; + n = (-n); + } + *cpp += n; + *buflenp -= n; + hp->nscount = htons(ntohs(hp->nscount) + + (u_int16_t)count); + } + free_nsp(nsp); + + /* Our caller will handle the Additional section. */ + return (Finish); + } + + /* + * 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. + */ + if (cname) { + omsg = (u_char *)memget((unsigned) *msglenp); + if (omsg == NULL) { + ns_info(ns_log_default, "ns_req: Out Of Memory"); + hp->rcode = ns_r_servfail; + free_nsp(nsp); + return (Finish); + } + id = hp->id; + omsglen = *msglenp; + memcpy(omsg, msg, omsglen); + n = res_nmkquery(&res, QUERY, dname, class, type, + NULL, 0, NULL, msg, + *msglenp + *buflenp); + if (n < 0) { + ns_info(ns_log_default, "res_mkquery(%s) failed", + dname); + memcpy(msg, omsg, omsglen); + memput(omsg, omsglen); + hp->rcode = ns_r_servfail; + free_nsp(nsp); + return (Finish); + } + *msglenp = n; + } + n = ns_forw(nsp, msg, *msglenp, from, qsp, dfd, &qp, + dname, class, type, np, 0, in_tsig); + if (n != FW_OK && cname) { + memcpy(msg, omsg, omsglen); + memput(omsg, omsglen); + *msglenp = omsglen; + omsg = NULL; + } + switch (n) { + case FW_OK: + if (cname) { + qp->q_cname = cname; + qp->q_cmsg = omsg; + qp->q_cmsglen = omsglen; + qp->q_cmsgsize = omsglen; + qp->q_id = id; + } + if (udpsize != 0) { + qp->q_flags |= Q_EDNS; + qp->q_udpsize = udpsize; + } else + qp->q_udpsize = PACKETSZ; + break; + case FW_DUP: + break; /* Duplicate request dropped */ + case FW_NOSERVER: + /* + * Don't go into an infinite loop if + * the admin gave root NS records in the cache + * file without giving address records + * for the root servers. + */ + if (np) { + if (NAME(*np)[0] == '\0') { + ns_notice(ns_log_default, + "ns_req: no address for root server"); + hp->rcode = ns_r_servfail; + free_nsp(nsp); + return (Finish); + } + for (dp = np->n_data; dp ; dp = dp->d_next) + if (dp->d_zone && match(dp, class, T_NS)) + break; + if (dp) { + /* + * we know the child zone exists but are + * missing glue. + * + * nslookup has called sysquery() to get the + * missing glue. + * + * for UDP, drop the response and let the + * client retry. for TCP, we should probably + * (XXX) hold open the TCP connection for a + * while in case the sysquery() comes back + * soon. meanwhile we SERVFAIL. + */ + if (qsp) + goto do_servfail; + break; + } + np = np_parent(np); + } + goto fetchns; /* Try again. */ + case FW_SERVFAIL: + do_servfail: + hp->rcode = ns_r_servfail; + free_nsp(nsp); + return (Finish); + } + free_nsp(nsp); + return (Return); +} + +static enum req_action +req_iquery(HEADER *hp, u_char **cpp, u_char *eom, int *buflenp, + struct sockaddr_in from) +{ + u_int rdata_offset; + size_t alen; + int dlen, n; + ns_type type; + ns_class class; + u_char anbuf[PACKETSZ], *anptr; + char dnbuf[MAXDNAME]; + + nameserIncr(from.sin_addr, nssRcvdIQ); + + if (ntohs(hp->ancount) != 1 || + ntohs(hp->qdcount) != 0 || + ntohs(hp->nscount) != 0 || + ntohs(hp->arcount) != 0) { + ns_debug(ns_log_default, 1, + "FORMERR IQuery header counts wrong"); + hp->rcode = ns_r_formerr; + return (Finish); + } + + /* + * Skip domain name, get class, and type. + */ + anptr = *cpp; + n = dn_skipname(*cpp, eom); + if (n < 0) { + ns_debug(ns_log_default, 1, + "FORMERR IQuery packet name problem"); + hp->rcode = ns_r_formerr; + return (Finish); + } + *cpp += n; + if (*cpp + 3 * INT16SZ + INT32SZ > eom) { + ns_debug(ns_log_default, 1, + "FORMERR IQuery message too short"); + hp->rcode = ns_r_formerr; + return (Finish); + } + GETSHORT(type, *cpp); + GETSHORT(class, *cpp); + *cpp += INT32SZ; /* ttl */ + GETSHORT(dlen, *cpp); + if (*cpp + dlen != eom) { + ns_debug(ns_log_default, 1, + "FORMERR IQuery message length off"); + hp->rcode = ns_r_formerr; + return (Finish); + } + rdata_offset = *cpp - anptr; + *cpp += dlen; + INSIST(*cpp == eom); + + /* + * Not all inverse queries are handled. + */ + if (type != ns_t_a) { + ns_warning(ns_log_security, + "unsupported iquery type from %s", + inet_ntoa(from.sin_addr)); + return (Refuse); + } + if (dlen != INT32SZ) { + ns_warning(ns_log_security, + "bad iquery from %s", + inet_ntoa(from.sin_addr)); + return (Refuse); + } + if (!NS_OPTION_P(OPTION_FAKE_IQUERY)) + return (Refuse); + + ns_debug(ns_log_default, 1, + "req: IQuery class %d type %d", class, type); + + alen = eom - anptr; + if (alen > sizeof anbuf) { + ns_warning(ns_log_security, + "bad iquery from %s", + inet_ntoa(from.sin_addr)); + return (Refuse); + } + memcpy(anbuf, anptr, alen); + *cpp = anptr; + *buflenp -= HFIXEDSZ; + +#ifdef QRYLOG + if (qrylog) { + char tmp[sizeof "255.255.255.255"]; + + strcpy(tmp, inet_ntoa(from.sin_addr)); + ns_info(ns_log_queries, "XX /%s/%s/-%s", + tmp, inet_ntoa(ina_get(&anbuf[rdata_offset])), + p_type(type)); + } +#endif /*QRYLOG*/ + + /* + * We can only get here if the option "fake-iquery" is on in the boot + * file. + * + * What we do here is send back a bogus response of "[dottedquad]". + * A better strategy would be to turn this into a PTR query, but that + * would legitimize inverse queries in a way they do not deserve. + */ + sprintf(dnbuf, "[%s]", inet_ntoa(ina_get(&anbuf[rdata_offset]))); + *buflenp -= QFIXEDSZ; + n = dn_comp(dnbuf, *cpp, *buflenp, NULL, NULL); + if (n < 0) { + hp->tc = 1; + return (Finish); + } + *cpp += n; + *buflenp -= n; + PUTSHORT((u_int16_t)type, *cpp); + *buflenp -= INT16SZ; + PUTSHORT((u_int16_t)class, *cpp); + *buflenp -= INT16SZ; + + hp->qdcount = htons(1); + if ((int)alen > *buflenp) { + hp->tc = 1; + return (Finish); + } + memcpy(*cpp, anbuf, alen); + *cpp += alen; + *buflenp -= alen; + return (Finish); +} + +/* + * Test a datum for validity and return non-zero if it is out of date. + */ +int +stale(struct databuf *dp) { + struct zoneinfo *zp = &zones[dp->d_zone]; + +#ifdef CHECK_MAGIC + INSIST(dp->d_magic == DATABUF_MAGIC); +#endif + + switch (zp->z_type) { + + case z_master: + return (0); + +#ifdef STUBS + case z_stub: + /* root stub zones have DB_F_HINT set */ + if (dp->d_flags & DB_F_HINT) + return (0); + /* FALLTROUGH */ +#endif + case z_slave: + /* + * Check to see whether a slave zone has expired or + * time warped; if so clear authority flag for zone, + * schedule the zone for immediate maintenance, and + * return true. + */ + if ((int32_t)(tt.tv_sec - zp->z_lastupdate) + > (int32_t)zp->z_expire) { + ns_debug(ns_log_default, 1, + "stale: slave zone %s expired", + zp->z_origin); + if (!haveComplained((u_long)zp, (u_long)stale)) { + ns_notice(ns_log_default, + "slave zone \"%s\" expired", + zp->z_origin); + } + zp->z_flags &= ~Z_AUTH; + if ((zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING)) == 0) { + zp->z_time = tt.tv_sec; + sched_zone_maint(zp); + } + return (1); + } + if (zp->z_lastupdate > tt.tv_sec) { + if (!haveComplained((u_long)zp, (u_long)stale)) { + ns_notice(ns_log_default, + "slave zone \"%s\" time warp", + zp->z_origin); + } + zp->z_flags &= ~Z_AUTH; + if ((zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING)) == 0) { + zp->z_time = tt.tv_sec; + sched_zone_maint(zp); + } + return (1); + } + return (0); + + case z_hint: + case z_cache: + if (dp->d_flags & DB_F_HINT || + dp->d_ttl >= (u_int32_t)tt.tv_sec) + return (0); + ns_debug(ns_log_default, 3, "stale: ttl %d %ld (x%lx)", + dp->d_ttl, (long)(dp->d_ttl - tt.tv_sec), + (u_long)dp->d_flags); + return (1); + + default: + /* FALLTHROUGH */ ; + } + panic("stale: impossible condition", NULL); + /* NOTREACHED */ + return (0); /* Make gcc happy. */ +} + +/* + * Copy databuf into a resource record for replies. + * Return size of RR if OK, -1 if buffer is full. + */ +int +make_rr(const char *name, struct databuf *dp, u_char *buf, + int buflen, int doadd, u_char **comp_ptrs, u_char **edp, + int use_minimum) +{ + u_char *cp; + u_char *cp1, *sp; + struct zoneinfo *zp; + int32_t n; + int16_t type = dp->d_type; + u_int32_t ttl; + u_char naptr_flag; + + ns_debug(ns_log_default, 5, + "make_rr(%s, %lx, %lx, %d, %d) %d zone %d ttl %lu", + name, (u_long)dp, (u_long)buf, + buflen, doadd, dp->d_size, dp->d_zone, (u_long)dp->d_ttl); + + if (dp->d_rcode && dp->d_size == 0) + panic("make_rr: impossible d_rcode value", NULL); + + zp = &zones[dp->d_zone]; + /* check for outdated RR before updating comp_ptrs[] by dn_comp() */ + if (zp->z_type == Z_CACHE) { + if ((dp->d_flags & DB_F_HINT) != 0 + || dp->d_ttl < (u_int32_t)tt.tv_sec) { + ttl = 0; + } else + ttl = dp->d_ttl - (u_int32_t) tt.tv_sec; + } else { + if (dp->d_ttl != USE_MINIMUM && !use_minimum) + ttl = dp->d_ttl; + else + ttl = zp->z_minimum; /* really default */ + } + + buflen -= RRFIXEDSZ; + if (buflen < 0) + return (-1); +#ifdef RETURNSOA + if (dp->d_rcode) { + name = (char *)dp->d_data; + name += strlen(name) +1; + name += strlen(name) +1; + name += 5 * INT32SZ; + type = T_SOA; + } +#endif + if ((n = dn_comp(name, buf, buflen, comp_ptrs, edp)) < 0) + goto cleanup; + cp = buf + n; + buflen -= n; + if (buflen < 0) + goto cleanup; + PUTSHORT((u_int16_t)type, cp); + PUTSHORT((u_int16_t)dp->d_class, cp); + PUTLONG(ttl, cp); + sp = cp; + cp += INT16SZ; + switch (type) { + case T_CNAME: + case T_MG: + case T_MR: + case T_PTR: + n = dn_comp((char *)dp->d_data, cp, buflen, comp_ptrs, edp); + if (n < 0) + goto cleanup; + PUTSHORT((u_int16_t)n, sp); + cp += n; + break; + + case T_MB: + case T_NS: + /* Store domain name in answer */ + n = dn_comp((char *)dp->d_data, cp, buflen, comp_ptrs, edp); + if (n < 0) + goto cleanup; + PUTSHORT((u_int16_t)n, sp); + cp += n; + if (doadd) { + addname((char*)dp->d_data, name, + type, T_A, dp->d_class); + addname(name, name, type, T_KEY, dp->d_class); + } + break; + + case T_SOA: + case T_MINFO: + case T_RP: + cp1 = dp->d_data; + n = dn_comp((char *)cp1, cp, buflen, comp_ptrs, edp); + if (n < 0) + goto cleanup; + cp += n; + buflen -= type == T_SOA ? n + 5 * INT32SZ : n; + if (buflen < 0) + goto cleanup; + cp1 += strlen((char *)cp1) + 1; + n = dn_comp((char *)cp1, cp, buflen, comp_ptrs, edp); + if (n < 0) + goto cleanup; + cp += n; + if (type == T_SOA) { + cp1 += strlen((char *)cp1) + 1; +#ifdef BIND_UPDATE + if (zp->z_flags & Z_NEED_SOAUPDATE) + if (incr_serial(zp) < 0) + ns_error(ns_log_default, + "error updating serial number for %s from %d", + zp->z_origin, zp->z_serial); +#endif + n = 5 * INT32SZ; + memcpy(cp, cp1, n); + cp += n; + if (doadd) + addname(name, name, type, T_KEY, dp->d_class); + } + n = (u_int16_t)((cp - sp) - INT16SZ); + PUTSHORT((u_int16_t)n, sp); + break; + + case T_NAPTR: + /* cp1 == our data/ cp == data of RR */ + cp1 = dp->d_data; + + /* copy order */ + buflen -= INT16SZ; + if (buflen < 0) + goto cleanup; + memcpy(cp, cp1, INT16SZ); + cp += INT16SZ; + cp1 += INT16SZ; + n = (u_int16_t)((cp - sp) - INT16SZ); + ns_debug(ns_log_default, 1, "current size n = %u", n); + + /* copy preference */ + buflen -= INT16SZ; + if (buflen < 0) + goto cleanup; + memcpy(cp, cp1, INT16SZ); + cp += INT16SZ; + cp1 += INT16SZ; + n = (u_int16_t)((cp - sp) - INT16SZ); + ns_debug(ns_log_default, 1, "current size n = %u", n); + + /* Flags */ + n = *cp1++; + ns_debug(ns_log_default, 1, "size of n at flags = %d", n); + buflen -= n + 1; + if (buflen < 0) + goto cleanup; + naptr_flag = (n == 1) ? *cp1 : 0; + *cp++ = n; + memcpy(cp, cp1, n); + cp += n; + cp1 += n; + n = (u_int16_t)((cp - sp) - INT16SZ); + ns_debug(ns_log_default, 1, "current size n = %u", n); + + /* Service */ + n = *cp1++; + buflen -= n + 1; + if (buflen < 0) + goto cleanup; + *cp++ = n; + memcpy(cp, cp1, n); + cp += n; + cp1 += n; + n = (u_int16_t)((cp - sp) - INT16SZ); + ns_debug(ns_log_default, 1, "current size n = %u", n); + + /* Regexp */ + n = *cp1++; + buflen -= n + 1; + if (buflen < 0) + goto cleanup; + *cp++ = n; + memcpy(cp, cp1, n); + cp += n; + cp1 += n; + n = (u_int16_t)((cp - sp) - INT16SZ); + ns_debug(ns_log_default, 1, "current size n = %u", n); + + /* Replacement */ + ns_debug(ns_log_default, 1, "Replacement = %s", cp1); + n = dn_comp((char *)cp1, cp, buflen, NULL, NULL); + ns_debug(ns_log_default, 1, "dn_comp's n = %u", n); + if (n < 0) + goto cleanup; + cp += n; + if (doadd && *cp1 != 0) { + if (naptr_flag == 's' || naptr_flag == 'S') + addname((char*)cp1, name, type, T_SRV, + dp->d_class); + if (naptr_flag == 'a' || naptr_flag == 'A') + addname((char*)cp1, name, type, T_A, + dp->d_class); + } + + /* save data length */ + n = (u_int16_t)((cp - sp) - INT16SZ); + ns_debug(ns_log_default, 1, "saved size n = %u", n); + PUTSHORT((u_int16_t)n, sp); + + break; + + case T_MX: + case T_AFSDB: + case T_RT: + case T_SRV: + /* cp1 == our data/ cp == data of RR */ + cp1 = dp->d_data; + + if ((buflen -= INT16SZ) < 0) + goto cleanup; + + /* copy preference */ + memcpy(cp, cp1, INT16SZ); + cp += INT16SZ; + cp1 += INT16SZ; + + if (type == T_SRV) { + buflen -= INT16SZ*2; + if (buflen < 0) + goto cleanup; + memcpy(cp, cp1, INT16SZ*2); + cp += INT16SZ*2; + cp1 += INT16SZ*2; + } + + n = dn_comp((char *)cp1, cp, buflen, + (type == ns_t_mx) ? comp_ptrs : NULL, + (type == ns_t_mx) ? edp : NULL); + if (n < 0) + goto cleanup; + cp += n; + + /* save data length */ + n = (u_int16_t)((cp - sp) - INT16SZ); + PUTSHORT((u_int16_t)n, sp); + if (doadd) + addname((char*)cp1, name, type, T_A, dp->d_class); + break; + + case T_PX: + cp1 = dp->d_data; + + if ((buflen -= INT16SZ) < 0) + goto cleanup; + + /* copy preference */ + memcpy(cp, cp1, INT16SZ); + cp += INT16SZ; + cp1 += INT16SZ; + + n = dn_comp((char *)cp1, cp, buflen, comp_ptrs, edp); + if (n < 0) + goto cleanup; + cp += n; + buflen -= n; + cp1 += strlen((char *)cp1) + 1; + n = dn_comp((char *)cp1, cp, buflen, comp_ptrs, edp); + if (n < 0) + goto cleanup; + cp += n; + + /* save data length */ + n = (u_int16_t)((cp - sp) - INT16SZ); + PUTSHORT((u_int16_t)n, sp); + break; + + case T_SIG: + /* cp1 == our data; cp == data of target RR */ + cp1 = dp->d_data; + + /* first just copy over the type_covered, algorithm, */ + /* labels, orig ttl, two timestamps, and the footprint */ + if (buflen < 18) + goto cleanup; /* out of room! */ + memcpy(cp, cp1, 18); + cp += 18; + cp1 += 18; + buflen -= 18; + + /* then the signer's name */ + n = dn_comp((char *)cp1, cp, buflen, NULL, NULL); + if (n < 0) + goto cleanup; + cp += n; + buflen -= n; + cp1 += strlen((char*)cp1)+1; + + /* finally, we copy over the variable-length signature */ + n = dp->d_size - (u_int16_t)((cp1 - dp->d_data)); + if (n > buflen) + goto cleanup; /* out of room! */ + memcpy(cp, cp1, n); + cp += n; + + /* save data length & return */ + n = (u_int16_t)((cp - sp) - INT16SZ); + PUTSHORT((u_int16_t)n, sp); + break; + + case T_NXT: + cp1 = dp->d_data; + n = dn_comp((char *)cp1, cp, buflen, NULL, NULL); + if (n < 0) + goto cleanup; + + cp += n; + buflen -=n; + cp1 += strlen((char *)cp1) + 1; + + /* copy nxt bit map */ + n = dp->d_size - (u_int16_t)((cp1 - dp->d_data)); + if (n > buflen) + goto cleanup; /* out of room! */ + memcpy(cp, cp1, n); + cp += n; + buflen -= n; + + n = (u_int16_t)((cp - sp) - INT16SZ); + PUTSHORT((u_int16_t)n, sp); + + break; + + default: + if ((type == T_A || type == T_AAAA) && doadd) + addname(name, name, type, T_KEY, dp->d_class); + if (dp->d_size > buflen) + goto cleanup; + memcpy(cp, dp->d_data, dp->d_size); + PUTSHORT((u_int16_t)dp->d_size, sp); + cp += dp->d_size; + } + return (cp - buf); + + cleanup: + /* Rollback RR. */ + ns_name_rollback(buf, (const u_char **)comp_ptrs, + (const u_char **)edp); + return (-1); +} + +static void +addname(const char *dname, const char *rname, + u_int16_t rtype, u_int16_t type, u_int16_t class) +{ + struct addinfo *ap; + int n; + + for (ap = addinfo, n = addcount; --n >= 0; ap++) + if (ns_samename(ap->a_dname, dname) == 1 && ap->a_type == type) + return; + + /* add domain name to additional section */ + if (addcount < NADDRECS) { + addcount++; + ap->a_dname = savestr(dname, 1); + ap->a_rname = savestr(rname, 1); + ap->a_rtype = rtype; + ap->a_type = type; + ap->a_class = class; + } +} + +/* + * Lookup addresses/keys for names in addinfo and put into the message's + * additional section. + */ +int +doaddinfo(HEADER *hp, u_char *msg, int msglen) { + register struct namebuf *np; + register struct databuf *dp; + register struct addinfo *ap; + register u_char *cp; + struct hashbuf *htp; + const char *fname; + register int n, count; + register int ns_logging; + int pass = 0; + int i, doadd; + + + if (!addcount) + return (0); + + ns_logging = ns_wouldlog(ns_log_default, 3); + + if (ns_logging) + ns_debug(ns_log_default, 3, + "doaddinfo() addcount = %d", addcount); + + if (hp->tc) { + ns_debug(ns_log_default, 4, + "doaddinfo(): tc already set, bailing"); + return (0); + } + + count = 0; + cp = msg; +loop: + for (ap = addinfo, i = 0; i < addcount; ap++, i++) { + int auth = 0, + founda = 0, + foundaaaa = 0, + founda6 = 0, + foundcname = 0, + save_count = count, + save_msglen = msglen; + u_char *save_cp = cp; + + if ((pass != 0 && + (pass != 1 || server_options->preferred_glue == 0) && + ap->a_type == T_A) || + (pass != 0 && ap->a_type == T_SRV) || + (pass != 2 && ap->a_type == T_KEY)) + continue; + if (ns_logging) + ns_debug(ns_log_default, 3, + "do additional \"%s\" (from \"%s\")", + ap->a_dname, ap->a_rname); + htp = hashtab; /* because "nlookup" stomps on arg. */ + np = nlookup(ap->a_dname, &htp, &fname, 0); + if (np == NULL || fname != ap->a_dname) + goto next_rr; + if (ns_logging) + ns_debug(ns_log_default, 3, "found it"); + /* look for the data */ + (void)delete_stale(np); + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (dp->d_class != ap->a_class) + continue; + if (dp->d_rcode == NXDOMAIN) { + founda = founda6 = foundaaaa = 1; + continue; + } + switch (dp->d_type) { + case ns_t_a: founda = 1; break; + case ns_t_a6: founda6 = 1; break; + case ns_t_aaaa: foundaaaa = 1; break; + } + if (!dp->d_rcode && dp->d_type == T_CNAME) { + foundcname++; + break; + } + if (auth == 0 && ap->a_type == T_A && + (dp->d_type == ns_t_a || dp->d_type == ns_t_a6 || + dp->d_type == ns_t_aaaa) && + (zones[dp->d_zone].z_type == z_master || + zones[dp->d_zone].z_type == z_slave)) + auth = 1; + if (pass == 0 && ap->a_type == T_A && + server_options->preferred_glue != 0 && + !match(dp, (int)ap->a_class, + server_options->preferred_glue)) { + continue; + } + if (pass != 0 && ap->a_type == T_A && + server_options->preferred_glue != 0 && + match(dp, (int)ap->a_class, + server_options->preferred_glue)) { + continue; + } + if (ap->a_type == T_A && + !match(dp, (int)ap->a_class, T_A) && + !match(dp, (int)ap->a_class, T_AAAA) && + !match(dp, (int)ap->a_class, ns_t_a6)) { + continue; + } + if (ap->a_type == T_KEY && + !match(dp, (int)ap->a_class, T_KEY)) + continue; + if (ap->a_type == T_SRV && + !match(dp, (int)ap->a_class, T_SRV)) + continue; + if (dp->d_rcode) + continue; + /* + * Should be smart and eliminate duplicate + * data here. XXX + */ + doadd = 0; + if (ap->a_type == T_SRV) + doadd = 1; + if ((n = make_rr(ap->a_dname, dp, cp, msglen, doadd, + dnptrs, dnptrs_end, 0)) < 0) { + /* truncation in the additional-data section + * is not all that serious. we do not set TC, + * since the answer and authority sections are + * OK; however, since we're not setting TC we + * have to make sure that none of the RR's for + * this name go out (!TC implies that all + * {name,type} appearances are complete -- and + * since we only do A RR's here, the name is + * the key). vixie, 23apr93 + */ + ns_debug(ns_log_default, 5, + "addinfo: not enough room, remaining msglen = %d", + save_msglen); + /* Rollback RRset. */ + ns_name_rollback(save_cp, + (const u_char **)dnptrs, + (const u_char **)dnptrs_end); + cp = save_cp; + msglen = save_msglen; + count = save_count; + break; + } + ns_debug(ns_log_default, 5, + "addinfo: adding address data n = %d", n); + cp += n; + msglen -= n; + count++; + } + next_rr: + if (!NS_OPTION_P(OPTION_NOFETCHGLUE) && + !foundcname && ap->a_type == T_A) { + /* ask a real server for this info */ + if (!founda && !auth) + (void) sysquery(ap->a_dname, (int)ap->a_class, + ns_t_a, NULL, NULL, 0, ns_port, + QUERY, 0); + if (!foundaaaa && !auth) + (void) sysquery(ap->a_dname, (int)ap->a_class, + ns_t_aaaa, NULL, NULL, 0, + ns_port, QUERY, 0); + if (!founda6 && !auth) + (void) sysquery(ap->a_dname, (int)ap->a_class, + ns_t_a6, NULL, NULL, 0, ns_port, + QUERY, 0); + } + if (foundcname) { + if (!haveComplained(nhash(ap->a_dname), + nhash(ap->a_rname))) { + ns_info(ns_log_cname, + "\"%s %s %s\" points to a CNAME (%s)", + ap->a_rname, p_class(ap->a_class), + p_type(ap->a_rtype), ap->a_dname); + } + } + } + if (pass++ < 2) + goto loop; /* now do the KEYs... */ + hp->arcount = htons((u_int16_t)count); + for (ap = addinfo, i = 0; i < addcount; ap++, i++) { + ap->a_dname = freestr(ap->a_dname); + ap->a_rname = freestr(ap->a_rname); + } + addcount = 0; + return (cp - msg); +} + +int +doaddauth(HEADER *hp, u_char *cp, int buflen, + struct namebuf *np, struct databuf *dp) +{ + char dnbuf[MAXDNAME]; + int n; + + getname(np, dnbuf, sizeof dnbuf); + if (stale(dp)) { + ns_debug(ns_log_default, 1, + "doaddauth: can't add stale '%s' (%d)", + dnbuf, buflen); + return (0); + } + n = make_rr(dnbuf, dp, cp, buflen, 1, dnptrs, dnptrs_end, 1); + if (n <= 0) { + ns_debug(ns_log_default, 1, + "doaddauth: can't add oversize '%s' (%d) (n=%d)", + dnbuf, buflen, n); + if (n < 0) { + hp->tc = 1; + } + return (0); + } + if (dp->d_secure != DB_S_SECURE) + hp->ad = 0; + hp->nscount = htons(ntohs(hp->nscount) + 1); + return (n); +} + +void +free_addinfo() { + struct addinfo *ap; + + for (ap = addinfo; --addcount >= 0; ap++) { + ap->a_dname = freestr(ap->a_dname); + ap->a_rname = freestr(ap->a_rname); + } + addcount = 0; +} + +void +free_nsp(struct databuf **nsp) { + while (*nsp) + db_detach(nsp++); +} + +static void +copyCharString(u_char **dst, const char *src) { + size_t len = strlen(src) & 0xff; + *(*dst)++ = (u_char) len; + memcpy(*dst, src, len); + *dst += len; +} + +/* + * Questionable source ports for queries / responses. + */ +int +drop_port(u_int16_t port) { + switch (port) { + case 7: /* echo */ + case 13: /* daytime */ + case 19: /* chargen */ + case 37: /* time */ + return (1); + case 464: /* kpasswd */ + return (2); + } + return (0); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_req.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_resp.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_resp.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_resp.c (revision 109985) @@ -0,0 +1,4136 @@ +#if !defined(lint) && !defined(SABER) +static const char sccsid[] = "@(#)ns_resp.c 4.65 (Berkeley) 3/3/91"; +static const char rcsid[] = "$Id: ns_resp.c,v 8.178.2.2 2002/11/14 13:39:13 marka Exp $"; +#endif /* not lint */ + +/* + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "port_after.h" + +#include "named.h" + +static u_int8_t norootlogged[MAXCLASS]; /* XXX- should be a bitmap */ + +static const char skipnameFailedAnswer[] = "skipname failed in answer", + skipnameFailedAuth[] = "skipname failed in authority", + skipnameFailedQuery[] = "skipname failed in query", + outofDataQuery[] = "ran out of data in query", + outofDataAnswer[] = "ran out of data in answer", + notSingleQuery[] = "not exactly one query", + expandFailedQuery[] = "dn_expand failed in query", + expandFailedAnswer[] = "dn_expand failed in answer", + expandFailedAuth[] = "dn_expand failed in authority", + outofDataAuth[] = "ran out of data in authority", + dlenOverrunAnswer[] = "dlen overrun in answer", + dlenOverrunAuth[] = "dlen overrun in authority", + dlenUnderrunAnswer[] = "dlen underrun in answer", + outofDataFinal[] = "out of data in final pass", + outofDataAFinal[] = "out of data after final pass", + badNameFound[] = "found an invalid domain name", + wrongQuestion[] = "answer to wrong question", + danglingCname[] = "dangling CNAME pointer", + nonRecursiveForwarder[]= "non-recursive forwarder"; + +struct db_list { + struct db_list *db_next; + struct databuf *db_dp; +}; + +struct flush_set { + char * fs_name; + int fs_type; + int fs_class; + u_int fs_cred; + struct db_list *fs_list; + struct db_list *fs_last; +}; + +static void rrsetadd(struct flush_set *, const char *, + struct databuf *), + rrsetupdate(struct flush_set *, int flags, + struct sockaddr_in, int), + flushrrset(struct flush_set *, struct sockaddr_in), + free_flushset(struct flush_set *, int), + check_hints(struct flush_set *); +static int rrsetcmp(char *, struct db_list *, struct hashbuf *), + check_root(void), + check_ns(void), + wanted(const struct databuf *, int, int), + wantedsig(const struct databuf *, int, int), + rrextract(u_char *, int, u_char *, + struct databuf **, char *, int, + struct sockaddr_in, char **); +static void mark_bad(struct qinfo *qp, struct sockaddr_in from); +static void mark_lame(struct qinfo *qp, struct sockaddr_in from); +static int mark_noedns(struct qinfo *qp, struct sockaddr_in from, + int cache); +static void fast_retry(struct qinfo *qp, struct sockaddr_in from, + int samehost); +static void add_related_additional(char *); +static void free_related_additional(void); +static int related_additional(char *); +static void freestr_maybe(char **); +static enum ordering match_order(const struct namebuf *, int, int); +static int match_name(const struct namebuf *, const char *, size_t); + +#define MAX_RELATED 100 + +static int num_related = 0; +static char *related[MAX_RELATED]; + +static char * +learntFrom(struct qinfo *qp, struct sockaddr_in *server) { + static char *buf = NULL; + const char *a, *ns, *na; + struct databuf *db; + int i; + char nsbuf[20]; + char abuf[20]; + static const char fmt[] = " '%s': learnt (A=%s,NS=%s)"; + + a = ns = na = ""; + + for (i = 0; (u_int)i < qp->q_naddr; i++) { + if (ina_equal(qp->q_addr[i].ns_addr.sin_addr, + server->sin_addr)) { + db = qp->q_addr[i].ns; + if (db != NULL) { + if (db->d_addr.s_addr != htonl(0)) { + strcpy(nsbuf, inet_ntoa(db->d_addr)); + ns = nsbuf; + } else { + ns = zones[db->d_zone].z_origin; + } + if (db->d_rcode == 0) + na = (char*)qp->q_addr[i].ns->d_data; + } + db = qp->q_addr[i].nsdata; + if (db != NULL) { + if (db->d_addr.s_addr != htonl(0)) { + strcpy(abuf, inet_ntoa(db->d_addr)); + a = abuf; + } else { + a = zones[db->d_zone].z_origin; + } + } + break; + } + } + + if (a == ns && ns == na) /* all "UNKNOWN" */ + return (NULL); + + if (*a == '\0') + a = "\".\""; + if (*ns == '\0') + ns = "\".\""; + if (*na == '\0') + na = "\".\""; + + + buf = newstr(sizeof fmt + strlen(na) + strlen(a) + strlen(ns), 0); + if (buf == NULL) + return (NULL); + sprintf(buf, fmt, na, a, ns); + return (buf); +} + +void +ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) +{ + struct qinfo *qp; + HEADER *hp; + struct qserv *qs = NULL; + struct databuf *ns, *ns2; + u_char *cp, *answers, *eom = msg + msglen; + struct flush_set *flushset = NULL; + int flushset_size = 0; + struct sockaddr_in *nsa; + struct databuf *nsp[NSMAX]; + int i, c, n, qdcount, ancount, aucount, nscount, arcount, arfirst; + int soacount; + u_int qtype, qclass; + int restart; /* flag for processing cname response */ + int validanswer, dbflags; + int cname, lastwascname, externalcname; + int count, founddata, foundname; + int buflen; + int newmsglen; + char name[MAXDNAME], qname[MAXDNAME], aname[MAXDNAME]; + char msgbuf[MAXDNAME+100]; + char *dname, tmpdomain[MAXDNAME]; + const char *fname; + const char *formerrmsg = "brain damage"; + u_char newmsg[EDNS_MESSAGE_SZ]; + u_char **dpp, *tp; + time_t rtrip; + struct hashbuf *htp; + struct namebuf *np; + struct fwdinfo *fwd; + struct databuf *dp; + char *tname = NULL; + int sendto_errno = 0; + int has_tsig, oldqlen = 0; + u_char *oldqbuf = NULL; + u_char *smsg = NULL; + int smsglen, smsgsize = 0, siglen; + u_char sig[TSIG_SIG_SIZE]; + time_t tsig_time; + DST_KEY *key; + int expect_cname; + + nameserIncr(from.sin_addr, nssRcvdR); + nsp[0] = NULL; + hp = (HEADER *) msg; + if ((qp = qfindid(hp->id)) == NULL ) { + ns_debug(ns_log_default, 1, "DUP? dropped (id %d)", + ntohs(hp->id)); + nameserIncr(from.sin_addr, nssRcvdDupR); + return; + } + + if (ns_wouldlog(ns_log_default, 2)) { + ns_debug(ns_log_default, 2, "Response (%s %s %s) nsid=%d id=%d", + (qp->q_flags & Q_SYSTEM) ?"SYSTEM" :"USER", + (qp->q_flags & Q_PRIMING) ?"PRIMING" :"NORMAL", + (qp->q_flags & Q_ZSERIAL) ?"ZSERIAL" :"-", + ntohs(qp->q_nsid), ntohs(qp->q_id)); + } + + if (qp->q_nstsig == NULL) + has_tsig = 0; + else { + int ret; + + ret = ns_verify(msg, &msglen, qp->q_nstsig->key, + qp->q_nstsig->sig, qp->q_nstsig->siglen, + NULL, NULL, &tsig_time, 0); + if (ret == 0) + has_tsig = 1; + else { + if (hp->rcode == NOERROR) + hp->rcode = NOTAUTH; + ns_debug(ns_log_default, 1, + "resp: error bad tsig, record dropped"); + return; + } + } + + /* + * Here we handle high level formatting problems by parsing the header. + */ + qdcount = ntohs(hp->qdcount); + ancount = ntohs(hp->ancount); + aucount = ntohs(hp->nscount); + arcount = ntohs(hp->arcount); + free_addinfo(); /* sets addcount to zero */ + cp = msg + HFIXEDSZ; + dpp = dnptrs; + *dpp++ = msg; + if ((*cp & INDIR_MASK) == 0) + *dpp++ = cp; + *dpp = NULL; + if (qdcount == 1) { + n = dn_expand(msg, eom, cp, qname, sizeof(qname)); + if (n <= 0) { + formerrmsg = expandFailedQuery; + goto formerr; + } + cp += n; + if (cp + 2 * INT16SZ > eom) { + formerrmsg = outofDataQuery; + goto formerr; + } + GETSHORT(qtype, cp); + GETSHORT(qclass, cp); + if (!ns_nameok(qp, qname, qclass, NULL, response_trans, + ns_ownercontext(qtype, response_trans), + qname, from.sin_addr)) { + formerrmsg = badNameFound; + goto refused; + } + if (cp > eom) { + formerrmsg = outofDataQuery; + goto formerr; + } + if (qp->q_msg && qp->q_msglen && + !res_nameinquery(qname, qtype, qclass, + qp->q_msg, qp->q_msg + qp->q_msglen)) { + sprintf(msgbuf, + "query section mismatch (%s %s %s)", + qname, p_class(qclass), p_type(qtype)); + formerrmsg = msgbuf; + goto formerr; + } + if (ns_samename(qp->q_name, qname) != 1 || + qp->q_class != qclass || + qp->q_type != qtype) { + formerrmsg = wrongQuestion; + goto formerr; + } + } else { + strcpy(qname, qp->q_name); + qclass = qp->q_class; + qtype = qp->q_type; + } + + /* cp now points after the query section. */ + + /* + * Here we handle bad responses from servers. + * Several possibilities come to mind: + * The server is sick and returns SERVFAIL + * The server returns some garbage opcode (it's sick) + * The server can't understand our query and return FORMERR + * In all these cases, we drop the packet, disable retries on + * this server and immediately force a retry. + */ + if ((hp->rcode != NOERROR && hp->rcode != NXDOMAIN) + || (hp->opcode != QUERY +#ifdef BIND_NOTIFY + && hp->opcode != NS_NOTIFY_OP +#endif + )) { + int noedns = 1; + ns_debug(ns_log_default, 2, + "resp: error (ret %d, op %d), dropped", + hp->rcode, hp->opcode); + switch (hp->rcode) { + case SERVFAIL: + nameserIncr(from.sin_addr, nssRcvdFail); + noedns = mark_noedns(qp, from, 0); + break; + case FORMERR: + nameserIncr(from.sin_addr, nssRcvdFErr); + noedns = mark_noedns(qp, from, 1); + break; + case NOTIMP: + nameserIncr(from.sin_addr, nssRcvdErr); + noedns = mark_noedns(qp, from, 1); + break; + default: + nameserIncr(from.sin_addr, nssRcvdErr); + break; + } + if (ns_samename(qp->q_name, qp->q_domain) == 1 && + hp->rcode == SERVFAIL && hp->opcode == QUERY && + noedns) + mark_lame(qp, from); + if (noedns) + mark_bad(qp, from); + fast_retry(qp, from, noedns ? 0 : 1); + return; + } + + if (qdcount != 1) { + /* We don't generate or forward these (yet). */ + formerrmsg = notSingleQuery; + goto formerr; + } + + /* + * Determine if the response came from a forwarder. Packets from + * anyplace not listed as a forwarder or as a server to whom we + * might have forwarded the query will be dropped. + * XXX - should put this in STATS somewhere. + */ + for (fwd = NS_ZFWDTAB(qp->q_fzone); fwd; fwd = fwd->next) + if (ina_equal(fwd->fwddata->fwdaddr.sin_addr, from.sin_addr)) + break; + /* + * find the qinfo pointer and update + * the rtt and fact that we have called on this server before. + */ + { + struct timeval *stp; + + for (n = 0, qs = qp->q_addr; (u_int)n < qp->q_naddr; n++, qs++) + if (ina_equal(qs->ns_addr.sin_addr, from.sin_addr)) + break; + if ((u_int)n >= qp->q_naddr) { + if (!haveComplained(ina_ulong(from.sin_addr), + (u_long)"unexpected source")) { + ns_info(ns_log_default, + "Response from unexpected source (%s) for query \"%s %s %s\"", + sin_ntoa(from), + *(qp->q_name) ? qp->q_name : ".", + p_class(qp->q_class), p_type(qp->q_type)); + } + /* + * We don't know who this response came from so it + * gets dropped on the floor. + */ + return; + } + stp = &qs->stime; + + /* Handle response from different (untried) interface. */ + if (qs->ns != NULL && stp->tv_sec == 0) { + ns = qs->ns; + while (qs > qp->q_addr + && (qs->stime.tv_sec == 0 || qs->ns != ns)) + qs--; + *stp = qs->stime; + /* XXX - sometimes stp still ends up pointing to + * a zero timeval, in spite of the above attempt. + * Why? What should we do about it? + */ + /* XXX - catch aliases here */ + } + + /* compute query round trip time */ + /* XXX - avoid integer overflow, which is quite likely if stp + * points to a zero timeval (see above). + * rtrip is of type time_t, which we assume is at least + * as big as an int. + */ + if ((tt.tv_sec - stp->tv_sec) > (INT_MAX-999)/1000) { + rtrip = INT_MAX; + } else { + rtrip = ((tt.tv_sec - stp->tv_sec) * 1000 + + (tt.tv_usec - stp->tv_usec) / 1000); + } + + if (ns_wouldlog(ns_log_default, 3)) { + ns_debug(ns_log_default, 3, + "stime %lu/%lu now %lu/%lu rtt %ld", + (u_long)stp->tv_sec, (u_long)stp->tv_usec, + (u_long)tt.tv_sec, (u_long)tt.tv_usec, + (long)rtrip); + } + + /* prevent floating point overflow, limit to 1000 sec */ + if (rtrip > 1000000) { + rtrip = 1000000; + } + ns = qs->nsdata; + /* + * Don't update nstime if this doesn't look + * like an address databuf now. XXX + */ + if (ns && + ns->d_type == T_A && + ns->d_class == qs->ns->d_class) { + u_long t; + + if (ns->d_nstime == 0) + t = rtrip; + else + t = ns->d_nstime * ALPHA + + + (1 - ALPHA) * rtrip; + if (t > 65535) + t = 65535; + else if (t == 0) + t = 1; + ns->d_nstime = (u_int16_t)t; + } + + /* + * Record the source so that we do not use this NS again. + */ + if (ns && qs->ns && (qp->q_nusedns < NSMAX)) { + qp->q_usedns[qp->q_nusedns++] = qs->ns; + if (ns_wouldlog(ns_log_default, 2)) { + ns_debug(ns_log_default, 2, + "NS #%d addr %s used, rtt %d", + n, sin_ntoa(qs->ns_addr), + ns->d_nstime); + } + } + + /* + * Penalize those who had earlier chances but failed + * by multiplying round-trip times by BETA (>1). + * Improve nstime for unused addresses by applying GAMMA. + * The GAMMA factor makes unused entries slowly + * improve, so they eventually get tried again. + * GAMMA should be slightly less than 1. + * Watch out for records that may have timed out + * and are no longer the correct type. XXX + */ + + for (n = 0, qs = qp->q_addr; + (u_int)n < qp->q_naddr; + n++, qs++) { + u_long t; + + ns2 = qs->nsdata; + if (!ns2 || ns2 == ns) + continue; + if (ns2->d_type != T_A || + ns2->d_class != qs->ns->d_class) /* XXX */ + continue; + if (qs->stime.tv_sec) { + if (ns2->d_nstime == 0) + t = (rtrip * BETA) + 1; + else + t = ns2->d_nstime * BETA + + + (1 - ALPHA) * rtrip + 1; + } else + t = ns2->d_nstime * GAMMA; + if (t > 65535) + t = 65535; + else if (t == 0) + t = 1; + ns2->d_nstime = (u_int16_t)t; + if (ns_wouldlog(ns_log_default, 2)) { + ns_debug(ns_log_default, 2, + "NS #%d %s rtt now %d", n, + sin_ntoa(qs->ns_addr), + ns2->d_nstime); + } + } + } + +#ifdef BIND_NOTIFY + /* + * For now, NOTIFY isn't defined for ANCOUNT!=0, AUCOUNT!=0, + * or ADCOUNT!=0. Therefore the only real work to be done for + * a NOTIFY-QR is to remove it from the query queue. + */ + if (hp->opcode == NS_NOTIFY_OP) { + ns_info(ns_log_notify, + "Received NOTIFY answer (%sAA) from %s for \"%s %s %s\"", + hp->aa ? "" : "!", + inet_ntoa(from.sin_addr), + *(qp->q_name) ? qp->q_name : ".", + p_class(qp->q_class), p_type(qp->q_type)); + qremove(qp); + return; + } +#endif + + if ((qp->q_flags & Q_ZSERIAL) != 0) { + if (hp->aa && ancount > 0 && hp->rcode == NOERROR && + qtype == T_SOA && (qclass == C_IN || qclass == C_HS)) + { + int n; + u_int type, class, dlen; + u_int32_t serial; + u_char *tp = cp; + u_char *rdatap; + + n = dn_expand(msg, eom, tp, name, sizeof name); + if (n < 0) { + formerrmsg = expandFailedAnswer; + goto formerr; + } + tp += n; /* name */ + if (tp + 3 * INT16SZ + INT32SZ > eom) { + formerrmsg = outofDataAnswer; + goto formerr; + } + GETSHORT(type, tp); /* type */ + GETSHORT(class, tp); /* class */ + tp += INT32SZ; /* ttl */ + GETSHORT(dlen, tp); /* dlen */ + rdatap = tp; /* start of rdata */ + if (!ns_nameok(qp, name, class, NULL, response_trans, + ns_ownercontext(type, response_trans), + name, from.sin_addr)) { + formerrmsg = badNameFound; + goto refused; + } + if (ns_samename(qname, name) != 1 || + qtype != type || qclass != class) { + sprintf(msgbuf, + "qserial answer mismatch (%s %s %s)", + name, p_class(class), p_type(type)); + formerrmsg = msgbuf; + goto formerr; + } + if (0 >= (n = dn_skipname(tp, eom))) { + formerrmsg = skipnameFailedAnswer; + goto formerr; + } + tp += n; /* mname */ + if (0 >= (n = dn_skipname(tp, eom))) { + formerrmsg = skipnameFailedAnswer; + goto formerr; + } + tp += n; /* rname */ + if (tp + 5 * INT32SZ > eom) { + formerrmsg = dlenUnderrunAnswer; + goto formerr; + } + GETLONG(serial, tp); + tp += 4 * INT32SZ; /* Skip rest of SOA. */ + if ((u_int)(tp - rdatap) != dlen) { + formerrmsg = dlenOverrunAnswer; + goto formerr; + } + for (n = 0, qs = qp->q_addr; (u_int)n < qp->q_naddr; + n++, qs++) + if (ina_equal(qs->ns_addr.sin_addr, + from.sin_addr)) + break; + if (n == qp->q_naddr) { + qserial_answer(qp); + qremove(qp); + return; + } + qs->serial = serial; + } + retry(qp, 0); + return; + } + + /* + * Non-authoritative, no answer, no error, with referral. + */ + if (hp->rcode == NOERROR && !hp->tc && !hp->aa && + ancount == 0 && aucount > 0 +#ifdef BIND_NOTIFY + && hp->opcode != NS_NOTIFY_OP +#endif + ) { + u_char *tp; + int type, class = 0, dlen; + int foundns, foundsoa; +#ifdef DEBUG + if (debug > 0) + res_pquery(&res, msg, msglen, + log_get_stream(packet_channel)); +#endif + /* + * Since there is no answer section (ancount == 0), + * we must be pointing at the authority section (aucount > 0). + */ + tp = cp; + foundns = foundsoa = 0; + for (i = 0 ; i < aucount ; i++) { + n = dn_expand(msg, eom, tp, name, sizeof name); + if (n < 0) { + formerrmsg = expandFailedAuth; + goto formerr; + } + tp += n; + if (tp + 3 * INT16SZ + INT32SZ > eom) { + formerrmsg = outofDataAuth; + goto formerr; + } + GETSHORT(type, tp); + GETSHORT(class, tp); + tp += INT32SZ; /* ttl */ + GETSHORT(dlen, tp); + if (!ns_nameok(qp, name, class, NULL, response_trans, + ns_ownercontext(type, response_trans), + name, from.sin_addr)) { + formerrmsg = badNameFound; + goto refused; + } + /* skip rest of record */ + if (tp + dlen > eom) { + formerrmsg = outofDataAuth; + goto formerr; + } + tp += dlen; + if (type == T_NS) { + strcpy(aname, name); + foundns = 1; + } + if (type == T_SOA) + foundsoa = 1; + } + + /* + * If the answer delegates us either to the same level in + * the hierarchy or closer to the root, we consider this + * server lame. Note that for now we only log the message + * if the T_NS was C_IN, which is technically wrong (NS is + * visible in all classes) but necessary anyway (non-IN + * classes tend to not have good strong delegation graphs). + */ + + if (foundns && !foundsoa && + ns_samedomain(qp->q_domain, aname)) { + if (fwd == NULL) { + nameserIncr(from.sin_addr, nssRcvdLDel); + mark_lame(qp, from); + } + mark_bad(qp, from); + if (class == C_IN && fwd == NULL && + !haveComplained(ina_ulong(from.sin_addr), + nhash(qp->q_domain))) { + char *learnt_from = learntFrom(qp, &from); + + ns_info(ns_log_lame_servers, + "Lame server on '%s' (in '%s'?): %s%s", + qname, qp->q_domain, + sin_ntoa(from), + (learnt_from == NULL) ? "" : + learnt_from); + if (learnt_from != NULL) + learnt_from = freestr(learnt_from); + } else if (fwd != NULL) { + if (!haveComplained(ina_ulong(from.sin_addr), + (u_long)nonRecursiveForwarder)) + ns_warning(ns_log_default, "%s: %s", + nonRecursiveForwarder, + sin_ntoa(from)); + } + + fast_retry(qp, from, 0); + return; + } + } + + /* + * Add the info received in the response to the data base. + */ + arfirst = ancount + aucount; + c = arfirst + arcount; + + /* Don't return if it's a TSIG signed truncated message */ + if (has_tsig > 0 && hp->tc) + goto tcp_retry; + + /* -ve $ing non-existence of record, must handle non-authoritative + * NOERRORs with c == 0. + */ + if (!hp->aa && !hp->tc && hp->rcode == NOERROR && c == 0) + goto return_msg; + + if (qp->q_flags & Q_SYSTEM) + dbflags = DB_NOTAUTH | DB_NODATA; + else + dbflags = DB_NOTAUTH | DB_NODATA | DB_NOHINTS; + count = c; + if (qp->q_flags & Q_PRIMING) + dbflags |= DB_PRIMING; + if (hp->tc) { + count -= arcount; /* truncation had to affect this */ + if (!arcount) { + count -= aucount; /* guess it got this too */ + } + if (!(arcount || aucount)) { + count -= ancount; /* things are pretty grim */ + } + +tcp_retry: + /* retry using tcp provided this was not a tcp query */ + if (!(qp->q_flags & Q_USEVC)) { + qp->q_flags |= Q_USEVC; + unsched(qp); + schedretry(qp, 60); + + nsa = Q_NEXTADDR(qp, 0); + + key = qp->q_keys[0]; + if (key != NULL) + key = qp->q_keys[0] = + tsig_key_from_addr(nsa->sin_addr); + if (key != NULL) { + smsgsize = qp->q_msglen + TSIG_BUF_SIZE; + smsg = memget(smsgsize); + smsglen = qp->q_msglen; + siglen = sizeof(sig); + memcpy(smsg, qp->q_msg, qp->q_msglen); + n = ns_sign(smsg, &smsglen, smsgsize, + NOERROR, key, NULL, 0, + sig, &siglen, 0); + if (n == 0) { + oldqbuf = qp->q_msg; + oldqlen = qp->q_msglen; + qp->q_msglen = smsglen; + qp->q_msg = smsg; + has_tsig = 1; + free_tsig(qp->q_nstsig); + qp->q_nstsig = new_tsig(key, sig, + siglen); + } else { + has_tsig = 0; + free_tsig(qp->q_nstsig); + qp->q_nstsig = NULL; + INSIST(0); + } + } else { + has_tsig = 0; + free_tsig(qp->q_nstsig); + qp->q_nstsig = NULL; + } + + if (tcp_send(qp) != NOERROR) + /* + * We're probably in trouble if tcp_send + * failed, but we'll try to press on because + * there isn't anything else to do. + */ + retry(qp, 0); + + if (has_tsig == 1) { + memput(qp->q_msg, smsgsize); + qp->q_msg = oldqbuf; + qp->q_msglen = oldqlen; + } + return; + } else if (!qsp) { + /* outstanding udp response */ + return; + } + + /* XXX truncated tcp response */ + ns_error(ns_log_default, + "ns_resp: TCP truncated: \"%s\" %s %s from %s", + qname, p_class(qclass), p_type(qtype), + sin_ntoa(from)); + /* mark this server as bad */ + mark_bad(qp, from); + /* try another server, it may have a bigger write buffer */ + retry(qp, 0); + return; + } + + tp = cp; + + restart = 0; + validanswer = -1; + nscount = 0; + soacount = 0; + cname = 0; + lastwascname = 0; + externalcname = 0; + strcpy(aname, qname); + + if (count) { + /* allocate 1 extra record for end of set detection */ + flushset_size = (count + 1) * sizeof *flushset; + flushset = memget(flushset_size); + if (flushset == NULL) + panic("flushset: out of memory", NULL); + memset(flushset, 0, flushset_size); + } else + flushset = NULL; + + expect_cname = 1; + for (i = 0; i < count; i++) { + struct databuf *dp; + int type; + + freestr_maybe(&tname); + if (cp >= eom) { + free_related_additional(); + if (flushset != NULL) + free_flushset(flushset, flushset_size); + formerrmsg = outofDataFinal; + goto formerr; + } + n = rrextract(msg, msglen, cp, &dp, name, sizeof name, from, + &tname); + if (n < 0) { + free_related_additional(); + freestr_maybe(&tname); + if (flushset != NULL) + free_flushset(flushset, flushset_size); + formerrmsg = outofDataFinal; + if (hp->rcode == REFUSED) + goto refused; + else + goto formerr; + } + cp += n; + if (!dp) + continue; + type = dp->d_type; + if (i < ancount) { + /* Answer section. */ + /* + * Check for attempts to overflow the buffer in + * getnameanswer. + */ + if (type == ns_t_cname && !expect_cname) { + ns_warning(ns_log_security, + "late CNAME in answer section for %s %s from %s", + *qname ? qname : ".", p_type(qtype), + sin_ntoa(from)); + + } else if (type != ns_t_cname && type != ns_t_dname && + type != ns_t_sig) + expect_cname = 0; + if (externalcname || ns_samename(name, aname) != 1) { + if (!externalcname) + ns_info(ns_log_resp_checks, + "wrong ans. name (%s != %s)", + name[0] ? name : ".", + aname[0] ? aname : "."); + else + ns_debug(ns_log_resp_checks, 3, + "ignoring answer '%s' after external cname", + name); + db_detach(&dp); + validanswer = 0; + continue; + } + if (type == T_CNAME && + qtype != T_CNAME && qtype != T_ANY) { + strcpy(aname, (char *)dp->d_data); + if (!ns_samedomain(aname, qp->q_domain)) + externalcname = 1; + cname++; + lastwascname = 1; + } else { + if (validanswer) + validanswer = 1; + lastwascname = 0; + } + + if (tname != NULL) { + add_related_additional(tname); + tname = NULL; + } + + dp->d_cred = (hp->aa && ns_samename(name, qname) == 1) + ? DB_C_AUTH + : DB_C_ANSWER; + } else { + /* After answer section. */ + if (lastwascname) { + ns_debug(ns_log_resp_checks, 3, + "last was cname, ignoring auth. and add."); + db_detach(&dp); + validanswer = 0; + break; + } + if (i < arfirst) { + /* Authority section. */ + switch (type) { + case T_NS: + case T_SOA: + if (!ns_samedomain(aname, name)) { + ns_info(ns_log_resp_checks, + "bad referral (%s !< %s) from %s", + aname[0] ? aname : ".", + name[0] ? name : ".", + sin_ntoa(from)); + db_detach(&dp); + validanswer = 0; + continue; + } else if (!ns_samedomain(name, + qp->q_domain)) { + if (fwd == NULL && + !externalcname) + ns_info(ns_log_resp_checks, + "bad referral (%s !< %s) from %s", + name[0] ? name : ".", + qp->q_domain[0] ? + qp->q_domain : ".", + sin_ntoa(from)); + db_detach(&dp); + validanswer = 0; + continue; + } + if (type == T_NS) { + nscount++; + add_related_additional(tname); + tname = NULL; + } + if (type == T_SOA) { + soacount++; + } + break; + case T_NXT: + /* XXX check */ + break; + case T_SIG: + /* XXX check that it relates to an + NS or SOA or NXT */ + break; + default: + ns_info(ns_log_resp_checks, + "invalid RR type '%s' in authority section (name = '%s') from %s", + p_type(type), name, + sin_ntoa(from)); + db_detach(&dp); + validanswer = 0; + continue; + } + dp->d_cred = (hp->aa && (cname == 0)) ? + DB_C_AUTH : (qp->q_flags & Q_PRIMING) + ? DB_C_ANSWER + : DB_C_ADDITIONAL; + } else { + /* Additional section. */ + switch (type) { + case T_A: + case ns_t_a6: + case T_AAAA: + case T_SRV: + if (externalcname || + !ns_samedomain(name, qp->q_domain)) { + ns_debug(ns_log_resp_checks, 3, + "ignoring additional info '%s' type %s", + name, p_type(type)); + db_detach(&dp); + validanswer = 0; + continue; + } + if (!related_additional(name)) { + ns_info(ns_log_resp_checks, + "unrelated additional info '%s' type %s from %s", + name, p_type(type), + sin_ntoa(from)); + db_detach(&dp); + validanswer = 0; + continue; + } + if (type == T_SRV && tname != NULL) { + add_related_additional(tname); + tname = NULL; + } + break; + case T_KEY: + /* XXX check? */ + break; + case T_SIG: + /* + * XXX a SIG RR should relate + * to some other RR in this section, + * although if it's the last RR + * it might be a transaction signature. + */ + break; + case ns_t_opt: + /* + * OPT does not get cached. + */ + db_detach(&dp); + validanswer = 0; + continue; + default: + ns_info(ns_log_resp_checks, + "invalid RR type '%s' in additional section (name = '%s') from %s", + p_type(type), name, + sin_ntoa(from)); + db_detach(&dp); + validanswer = 0; + continue; + } + dp->d_cred = (qp->q_flags & Q_PRIMING) + ? DB_C_ANSWER + : DB_C_ADDITIONAL; + } + } +#ifdef HITCOUNTS + ++dp->d_hitcnt; + ++db_total_hits; +#endif /* HITCOUNTS */ + rrsetadd(flushset, name, dp); + db_detach(&dp); + } + free_related_additional(); + freestr_maybe(&tname); + if (flushset != NULL) { + if ((qp->q_flags & Q_SYSTEM) && (qp->q_flags & Q_PRIMING)) { + check_hints(flushset); /* before rrsetupdate */ + rrsetupdate(flushset, dbflags, from, 1); + } else + rrsetupdate(flushset, dbflags, from, 0); + free_flushset(flushset, flushset_size); + } + if (lastwascname && !externalcname) + ns_debug(ns_log_cname, 3, "%s (%s) q(%s %s %s) %s qd(%s)", + danglingCname, aname, + (qname && *qname) ? qname : ".", + p_class(qclass), p_type(qtype), + sin_ntoa(from), qp->q_domain); + + if (cp > eom) { + formerrmsg = outofDataAFinal; + goto formerr; + } + + if ((qp->q_flags & Q_SYSTEM) && ancount) { + if ((qp->q_flags & Q_PRIMING) && !check_root()) { + /* mark server as bad */ + mark_bad(qp, from); + fast_retry(qp, from, 0); + return; + } + ns_debug(ns_log_default, 3, + "resp: leaving, SYSQUERY ancount %d", ancount); +#ifdef BIND_NOTIFY + if (qp->q_notifyzone != DB_Z_CACHE) { + struct zoneinfo *zp = &zones[qp->q_notifyzone]; + + qp->q_notifyzone = DB_Z_CACHE; + ns_notify(zp->z_origin, zp->z_class, ns_t_soa); + } +#endif + qremove(qp); + return; + } + + if (ancount && count && validanswer != 1) { + /* + * Everything passed validation but we didn't get the + * final answer. The response must have contained + * a dangling CNAME. Force a restart of the query. + * + * Don't set restart if count==0, since this means + * the response was truncated in the answer section, + * causing us to set count to 0 which will cause + * validanswer to be 0 as well even though the answer + * section probably contained valid RRs (just not + * a complete set). + * XXX - this works right if we can just forward this + * response to the client, but not if we found a CNAME + * in a prior response and restarted the query. + */ + restart = 1; + } + + if (!restart && !qp->q_cmsglen && ancount > 1 && qtype == T_A) + sort_response(tp, eom, ancount, &qp->q_from); + + /* + * An answer to a T_ANY query or a successful answer to a + * regular query with no indirection, then just return answer. + */ + if (!restart && ancount && (qtype == T_ANY || !qp->q_cmsglen)) { + ns_debug(ns_log_default, 3, + "resp: got as much answer as there is"); + goto return_msg; + } + + /* + * We might want to cache this negative answer. + * + * if ancount != 0 and rcode == NOERROR we cannot determine if the + * CNAME chain has been processed to completion or not, so just + * restart the query. DNS needs a NODATA return code! + * + * As some servers incorrectly return a NODATA indication when + * there is a CNAME chain instead of NXDOMAIN, we requery to get + * a definitive answer. + */ + if ((hp->rcode == NXDOMAIN && cname == ancount) || + (hp->rcode == NOERROR && ancount == 0 && + (nscount == 0 || soacount != 0) + ) + ) + { + cache_n_resp(msg, msglen, from, qp->q_name, + qp->q_class, qp->q_type); + + if (!qp->q_cmsglen && validanswer) { + ns_debug(ns_log_default, 3, + "resp: leaving NO: auth = %d", hp->aa); + goto return_msg; + } + } + + /* + * All messages in here need further processing. i.e. they + * are either CNAMEs or we got referred again. + */ + count = 0; + founddata = 0; + dname = name; + /* + * XXX - the restart stuff doesn't work if any of the answer RRs + * is not cacheable (TTL==0 or unknown RR type), since all of the + * answer must pass through the cache and be re-assembled. + */ + if (qp->q_cmsglen != 0) { + ns_debug(ns_log_default, 1, "Cname second pass"); + newmsglen = MIN(EDNS_MESSAGE_SZ, qp->q_cmsglen); + memcpy(newmsg, qp->q_cmsg, newmsglen); + } else { + newmsglen = MIN(EDNS_MESSAGE_SZ, msglen); + memcpy(newmsg, msg, newmsglen); + } + hp = (HEADER *) newmsg; + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); + hp->rcode = NOERROR; + dnptrs[0] = newmsg; + dnptrs[1] = NULL; + cp = newmsg + HFIXEDSZ; + /* + * Keep in mind that none of this code works when QDCOUNT>1. + * cp ends up pointed just past the query section in both cases. + */ + /* + * Arrange for dname to contain the query name. The query + * name can be either the original query name if restart==0 + * or the target of the last CNAME if we are following a + * CNAME chain and were referred. + */ + n = dn_expand(newmsg, newmsg + newmsglen, cp, dname, sizeof name); + if (n < 0) { + ns_debug(ns_log_default, 1, "dn_expand failed"); + goto servfail; + } + if (!res_dnok(dname)) { + ns_debug(ns_log_default, 1, "bad name (%s)", dname); + goto servfail; + } + cp += n + QFIXEDSZ; + buflen = sizeof(newmsg) - (cp - newmsg); + + cname = 0; + + try_again: + ns_debug(ns_log_default, 1, "resp: nlookup(%s) qtype=%d", dname, + qtype); + foundname = 0; + fname = ""; + htp = hashtab; /* lookup relative to root */ + np = nlookup(dname, &htp, &fname, 0); + ns_debug(ns_log_default, 1, "resp: %s '%s' as '%s' (cname=%d)", + np == NULL ? "missed" : "found", dname, fname, cname); + if (np == NULL || fname != dname) + goto fetch_ns; + + foundname++; + answers = cp; + count = cp - newmsg; + /* + * Look for NXDOMAIN record. + */ + for (dp = np->n_data; dp; dp = dp->d_next) { + if (!stale(dp) && (dp->d_rcode == NXDOMAIN) && + (dp->d_class == (int)qclass)) { +#ifdef RETURNSOA + n = finddata(np, qclass, T_SOA, hp, &dname, + &buflen, &count); + if ( n != 0) { + if (count) { + cp += n; + buflen -= n; + newmsglen += n; + hp->nscount = htons((u_int16_t)count); + } + if (hp->rcode == NOERROR_NODATA) { + hp->rcode = NOERROR; + goto return_newmsg; + } + } +#else + count = 0; +#endif + hp->rcode = NXDOMAIN; + /* + * XXX forcing AA all the time isn't right, but + * we have to work that way by default + * for compatibility with older servers. + */ + if (!NS_OPTION_P(OPTION_NONAUTH_NXDOMAIN)) + hp->aa = 1; + ns_debug(ns_log_default, 3, "resp: NXDOMAIN aa = %d", + hp->aa); + if ((count == 0) || NS_OPTION_P(OPTION_NORFC2308_TYPE1)) + goto return_newmsg; + founddata = 1; + goto fetch_ns; + } + } + n = finddata(np, qclass, qtype, hp, &dname, &buflen, &count); + if (n == 0) + goto fetch_ns; /* NO data available */ + if (hp->rcode) { + if (hp->rcode == NOERROR_NODATA) + hp->rcode = NOERROR; +#ifdef RETURNSOA + if (count) { + cp += n; + buflen -= n; + hp->nscount = htons((u_int16_t)count); + } +#endif + if ((count == 0) || NS_OPTION_P(OPTION_NORFC2308_TYPE1)) + goto return_newmsg; + founddata = 1; + goto fetch_ns; + } + cp += n; + buflen -= n; + hp->ancount = htons(ntohs(hp->ancount) + (u_int16_t)count); + if (fname != dname && qtype != T_CNAME && qtype != T_ANY) { + cname++; + goto try_again; + } + founddata = 1; + + ns_debug(ns_log_default, 3, + "resp: foundname=%d, count=%d, founddata=%d, cname=%d", + foundname, count, founddata, cname); + + if (count > 1 && qtype == T_A) + sort_response(answers, cp, count, &qp->q_from); + + fetch_ns: + if (hp->tc) + goto return_newmsg; + + /* + * Look for name servers to refer to and fill in the authority + * section or record the address for forwarding the query + * (recursion desired). + */ + free_nsp(nsp); + switch (findns(&np, qclass, nsp, &count, 0)) { + case NXDOMAIN: /* shouldn't happen */ + ns_debug(ns_log_default, 3, "req: leaving (%s, rcode %d)", + dname, hp->rcode); + if (!foundname) + hp->rcode = NXDOMAIN; + if (qclass != C_ANY) { + hp->aa = 1; + if (np && (!foundname || !founddata)) { + n = doaddauth(hp, cp, buflen, np, nsp[0]); + cp += n; + buflen -= n; + } + } + goto return_newmsg; + + case SERVFAIL: + goto servfail; + } + + if (founddata) { + hp = (HEADER *)newmsg; + n = add_data(np, nsp, cp, buflen, &count); + if (n < 0) { + hp->tc = 1; + n = (-n); + } + cp += n; + buflen -= n; + hp->nscount = htons((u_int16_t)count + ntohs(hp->nscount)); + goto return_newmsg; + } + + /* + * If we get here, we don't have the answer yet and are about + * to iterate to try and get it. First, infinite loop avoidance. + */ + if (qp->q_nqueries++ > MAXQUERIES) { + ns_debug(ns_log_default, 1, + "resp: MAXQUERIES exceeded (%s %s %s)", + dname, p_class(qclass), p_type(qtype)); + ns_info(ns_log_default, + "MAXQUERIES exceeded, possible data loop in resolving (%s)", + dname); + goto servfail; + } + + /* Reset the query control structure */ + + ns_freeqns(qp); + qp->q_naddr = 0; + qp->q_curaddr = 0; + nsfwdadd(qp, NS_ZFWDTAB(qp->q_fzone)); + + if (qp->q_domain != NULL) + (void)freestr(qp->q_domain); + getname(np, tmpdomain, sizeof tmpdomain); + qp->q_domain = savestr(tmpdomain, 1); + + if (NS_ZOPTION_P(qp->q_fzone, OPTION_FORWARD_ONLY)) + n = 0; + else if ((n = nslookup(nsp, qp, dname, "ns_resp")) <= 0) { + if (n < 0) { + if (n == -1) + ns_debug(ns_log_default, 3, + "resp: nslookup reports danger"); + if (cname) /* a remote CNAME that does not have data */ + goto return_newmsg; + goto servfail; + } else { + ns_debug(ns_log_default, 3, + "resp: no addrs found for NS's"); + /* + * Timeout while sysquery looks up the NS addresses. + * + * Hopefully we'll have them when the client asks + * again. + * + * too bad we can't just wait for the sysquery + * response to restart this query (it's too hard). + * + * We could try to crawl back up the tree looking + * for reachable servers, but we may have just + * gotten delegated down here by a response with + * no A RRs for the servers. If we blindly tried + * this strategy, we bang on the same server forever. + */ + goto timeout; + } + } + for (n = 0; (u_int)n < qp->q_naddr; n++) + qp->q_addr[n].stime.tv_sec = 0; + qp->q_addr[0].stime = tt; + if (cname) { + if (qp->q_cname++ == MAXCNAMES) { + ns_debug(ns_log_default, 3, + "resp: leaving, MAXCNAMES exceeded"); + goto servfail; + } + ns_debug(ns_log_default, 1, "q_cname = %d", qp->q_cname); + ns_debug(ns_log_default, 3, + "resp: building recursive query; nslookup"); + if (qp->q_cmsg == NULL) { + qp->q_cmsg = qp->q_msg; + qp->q_cmsglen = qp->q_msglen; + qp->q_cmsgsize = qp->q_msgsize; + } else if (qp->q_msg != NULL) + memput(qp->q_msg, qp->q_msgsize); + qp->q_msg = (u_char *)memget(PACKETSZ); + if (qp->q_msg == NULL) { + ns_notice(ns_log_default, "resp: memget error"); + goto servfail; + } + qp->q_msgsize = PACKETSZ; + n = res_nmkquery(&res, QUERY, dname, qclass, qtype, + NULL, 0, NULL, qp->q_msg, PACKETSZ); + if (n < 0) { + ns_info(ns_log_default, "resp: res_mkquery(%s) failed", + dname); + goto servfail; + } + if (qp->q_name != NULL) + (void)freestr(qp->q_name); + qp->q_name = savestr(dname, 1); + qp->q_msglen = n; + hp = (HEADER *) qp->q_msg; + hp->rd = 0; + } else + hp = (HEADER *) qp->q_msg; + hp->id = qp->q_nsid = htons(nsid_next()); + hp->rd = (qp->q_addr[0].forwarder ? 1 : 0); + unsched(qp); + schedretry(qp, retrytime(qp)); + nsa = Q_NEXTADDR(qp, 0); + if (ns_wouldlog(ns_log_default, 1)) { + ns_debug(ns_log_default, 1, + "resp: forw -> %s ds=%d nsid=%d id=%d %dms", + sin_ntoa(*nsa), ds, + ntohs(qp->q_nsid), ntohs(qp->q_id), + (qp->q_addr[0].nsdata != NULL) + ? qp->q_addr[0].nsdata->d_nstime + : -1); + } +#ifdef DEBUG + if (debug >= 10) + res_pquery(&res, qp->q_msg, qp->q_msglen, + log_get_stream(packet_channel)); +#endif + key = qp->q_keys[0]; + if (key == NULL) + key = qp->q_keys[0] = tsig_key_from_addr(nsa->sin_addr); + if (key != NULL || !qp->q_addr[0].noedns) { + smsgsize = qp->q_msglen + TSIG_BUF_SIZE + 11; + smsg = memget(smsgsize); + smsglen = qp->q_msglen; + siglen = sizeof(sig); + memcpy(smsg, qp->q_msg, qp->q_msglen); + } + + if (!qp->q_addr[0].noedns) + smsglen += ns_add_opt(smsg, smsg + smsglen, smsgsize, 0, 0, + EDNS_MESSAGE_SZ, 0, NULL, 0); + if (key != NULL) { + n = ns_sign(smsg, &smsglen, smsgsize, NOERROR, key, NULL, 0, + sig, &siglen, 0); + if (n == 0) { + has_tsig = 1; + free_tsig(qp->q_nstsig); + qp->q_nstsig = new_tsig(key, sig, siglen); + } else { + has_tsig = 0; + free_tsig(qp->q_nstsig); + qp->q_nstsig = NULL; + INSIST(0); + } + } else { + has_tsig = 0; + free_tsig(qp->q_nstsig); + qp->q_nstsig = NULL; + } + + if (smsg != NULL) { + oldqbuf = qp->q_msg; + oldqlen = qp->q_msglen; + qp->q_msglen = smsglen; + qp->q_msg = smsg; + } + + if (qp->q_flags & Q_USEVC) { + if (tcp_send(qp) != NOERROR) { + if (!haveComplained(ina_ulong(nsa->sin_addr), + (u_long)tcpsendStr)) + ns_info(ns_log_default, + "ns_resp: tcp_send(%s) failed: %s", + sin_ntoa(*nsa), strerror(errno)); + } + } else if (sendto(ds, (char*)qp->q_msg, qp->q_msglen, 0, + (struct sockaddr *)nsa, + sizeof(struct sockaddr_in)) < 0) + { + sendto_errno = errno; + if (!haveComplained(ina_ulong(nsa->sin_addr), + (u_long)sendtoStr)) + ns_info(ns_log_default, "ns_resp: sendto(%s): %s", + sin_ntoa(*nsa), strerror(errno)); + nameserIncr(nsa->sin_addr, nssSendtoErr); + } + + if (smsgsize != 0) { + memput(smsg, smsgsize); + qp->q_msg = oldqbuf; + qp->q_msglen = oldqlen; + } + hp->rd = 0; /* leave set to 0 for dup detection */ + nameserIncr(nsa->sin_addr, nssSentFwdR); + nameserIncr(qp->q_from.sin_addr, nssRcvdFwdR); + ns_debug(ns_log_default, 3, "resp: Query sent."); + free_nsp(nsp); + switch (sendto_errno) { + case ENETDOWN: + case ENETUNREACH: + case EHOSTDOWN: + case EHOSTUNREACH: + unsched(qp); + schedretry(qp, (time_t) 0); + } + return; + + formerr: + if (!haveComplained(ina_ulong(from.sin_addr), (u_long)formerrmsg)) + ns_info(ns_log_resp_checks, "Malformed response from %s (%s)", + sin_ntoa(from), formerrmsg); + fast_retry(qp, from, 0); + free_nsp(nsp); + return; + + return_msg: + nameserIncr(from.sin_addr, nssRcvdFwdR); + nameserIncr(qp->q_from.sin_addr, nssSentFwdR); + nameserIncr(qp->q_from.sin_addr, nssSentAns); + if (!hp->aa) + nameserIncr(qp->q_from.sin_addr, nssSentNaAns); + if (hp->rcode == NXDOMAIN) + nameserIncr(qp->q_from.sin_addr, nssSentNXD); + /* The "standard" return code */ + hp->qr = 1; + hp->id = qp->q_id; + hp->rd = 1; + hp->ra = (NS_OPTION_P(OPTION_NORECURSE) == 0); + (void) send_msg(msg, msglen, qp); + qremove(qp); + free_nsp(nsp); + return; + + return_newmsg: + nameserIncr(qp->q_from.sin_addr, nssSentAns); + + if (!hp->aa) + nameserIncr(qp->q_from.sin_addr, nssSentNaAns); + if (hp->rcode == NXDOMAIN) + nameserIncr(qp->q_from.sin_addr, nssSentNXD); + n = doaddinfo(hp, cp, buflen); + cp += n; + buflen -= n; + hp->qr = 1; + hp->id = qp->q_id; + hp->rd = 1; + hp->ra = (NS_OPTION_P(OPTION_NORECURSE) == 0); + (void) send_msg(newmsg, cp - newmsg, qp); + qremove(qp); + free_nsp(nsp); + return; + + refused: + hp = (HEADER *)(qp->q_cmsglen ? qp->q_cmsg : qp->q_msg); + hp->rcode = REFUSED; + hp->qr = 1; + hp->id = qp->q_id; + hp->rd = 1; + hp->ra = (NS_OPTION_P(OPTION_NORECURSE) == 0); + (void) send_msg((u_char *)hp, + (qp->q_cmsglen ? qp->q_cmsglen : qp->q_msglen), + qp); + qremove(qp); + free_nsp(nsp); + return; + + servfail: + nameserIncr(qp->q_from.sin_addr, nssSentFail); + hp = (HEADER *)(qp->q_cmsglen ? qp->q_cmsg : qp->q_msg); + hp->rcode = SERVFAIL; + hp->qr = 1; + hp->id = qp->q_id; + hp->rd = 1; + hp->ra = (NS_OPTION_P(OPTION_NORECURSE) == 0); + (void) send_msg((u_char *)hp, + (qp->q_cmsglen ? qp->q_cmsglen : qp->q_msglen), + qp); + qremove(qp); + free_nsp(nsp); + return; + + timeout: + if (qp->q_stream) + sq_remove(qp->q_stream); + qremove(qp); + free_nsp(nsp); + return; +} + +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eom) { \ + hp->rcode = FORMERR; \ + return (-1); \ + } \ + } while (0) + +static int +rrextract(u_char *msg, int msglen, u_char *rrp, struct databuf **dpp, + char *dname, int namelen, struct sockaddr_in from, char **tnamep) +{ + u_char *cp, *eom, *rdatap; + u_int class, type, dlen; + int n, n1, n2; + u_int32_t ttl; + u_char *cp1, data[MAXDATA*2]; + HEADER *hp = (HEADER *)msg; + enum context context; + + if (tnamep != NULL) + *tnamep = NULL; + + *dpp = NULL; + cp = rrp; + eom = msg + msglen; + if ((n = dn_expand(msg, eom, cp, dname, namelen)) < 0) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ); + GETSHORT(type, cp); + GETSHORT(class, cp); + if (type != ns_t_opt && class > CLASS_MAX) { + ns_debug(ns_log_default, 3, "bad class in rrextract"); + hp->rcode = FORMERR; + return (-1); + } + GETLONG(ttl, cp); + if (ttl > MAXIMUM_TTL) { + ns_debug(ns_log_default, 5, "%s: converted TTL > %u to 0", + dname, MAXIMUM_TTL); + ttl = 0; + } + GETSHORT(dlen, cp); + BOUNDS_CHECK(cp, dlen); + rdatap = cp; + if (!ns_nameok(NULL, dname, class, NULL, response_trans, + ns_ownercontext(type, response_trans), + dname, from.sin_addr)) { + hp->rcode = REFUSED; + return (-1); + } + ns_debug(ns_log_default, 3, + "rrextract: dname %s type %d class %d ttl %d", + dname, type, class, ttl); + /* + * Convert the resource record data into the internal + * database format. + * + * On entry to the switch: + * CP points to the RDATA section of the wire-format RR. + * DLEN is its length. + * The memory area at DATA is available for processing. + * + * On exit from the switch: + * CP has been incremented past the RR. + * CP1 points to the RDATA section of the database-format RR. + * N contains the length of the RDATA section of the dbase-format RR. + * + * The new data at CP1 for length N will be copied into the database, + * so it need not be in any particular storage location. + */ + switch (type) { + case T_A: + if (dlen != INT32SZ) { + hp->rcode = FORMERR; + return (-1); + } + /*FALLTHROUGH*/ + case T_WKS: + case T_HINFO: + case T_TXT: + case T_X25: + case T_ISDN: + case T_NSAP: + case T_AAAA: + case T_LOC: + case T_KEY: + case ns_t_cert: + case ns_t_opt: + cp1 = cp; + n = dlen; + cp += n; + break; + + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_NS: + case T_PTR: + n = dn_expand(msg, eom, cp, (char *)data, sizeof data); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + if (!ns_nameok(NULL, (char *)data, class, NULL, response_trans, + type == T_PTR ?ns_ptrcontext(dname) :domain_ctx, + dname, from.sin_addr)) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + cp1 = data; + n = strlen((char *)data) + 1; + if (tnamep != NULL && (type == T_NS || type == T_MB)) + *tnamep = savestr((char *)cp1, 1); + break; + + case T_SOA: + context = hostname_ctx; + goto soa_rp_minfo; + case T_RP: + case T_MINFO: + context = mailname_ctx; + /* FALLTHROUGH */ + soa_rp_minfo: + n = dn_expand(msg, eom, cp, (char *)data, sizeof data); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + if (!ns_nameok(NULL, (char *)data, class, NULL, response_trans, + context, dname, from.sin_addr)) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + /* + * The next use of 'cp' is dn_expand(), so we don't have + * to BOUNDS_CHECK() here. + */ + cp1 = data + (n = strlen((char *)data) + 1); + n1 = sizeof(data) - n; + if (type == T_SOA) + n1 -= 5 * INT32SZ; + n = dn_expand(msg, eom, cp, (char *)cp1, n1); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + if (type == T_RP) + context = domain_ctx; + else + context = mailname_ctx; + if (!ns_nameok(NULL, (char *)cp1, class, NULL, response_trans, + context, dname, from.sin_addr)) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + cp1 += strlen((char *)cp1) + 1; + if (type == T_SOA) { + n = 5 * INT32SZ; + BOUNDS_CHECK(cp, n); + memcpy(cp1, cp, n); + cp += n; + cp1 += n; + } + n = cp1 - data; + cp1 = data; + if (tnamep != NULL && type == T_SOA) + *tnamep = savestr((char *)cp1, 1); + break; + + case T_NAPTR: + /* Grab weight and port. */ + BOUNDS_CHECK(cp, INT16SZ*2); + memcpy(data, cp, INT16SZ*2); + cp1 = data + INT16SZ*2; + cp += INT16SZ*2; + + /* Flags */ + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); + *cp1++ = n; + memcpy(cp1, cp, n); + cp += n; cp1 += n; + + /* Service */ + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); + *cp1++ = n; + memcpy(cp1, cp, n); + cp += n; cp1 += n; + + /* Regexp */ + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); + *cp1++ = n; + memcpy(cp1, cp, n); + cp += n; cp1 += n; + + /* Replacement */ + n = dn_expand(msg, eom, cp, (char *)cp1, + sizeof data - (cp1 - data)); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + if (!ns_nameok(NULL, (char *)cp1, class, NULL, response_trans, + hostname_ctx, dname, from.sin_addr)) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + + if (tnamep != NULL && *cp1 != 0) + *tnamep = savestr((char *)cp1, 1); + + /* compute end of data */ + cp1 += strlen((char *)cp1) + 1; + /* compute size of data */ + n = cp1 - data; + cp1 = data; + break; + + case T_MX: + case T_AFSDB: + case T_RT: + case T_SRV: + /* grab preference */ + BOUNDS_CHECK(cp, INT16SZ); + memcpy(data, cp, INT16SZ); + cp1 = data + INT16SZ; + cp += INT16SZ; + + if (type == T_SRV) { + /* Grab weight and port. */ + BOUNDS_CHECK(cp, INT16SZ*2); + memcpy(cp1, cp, INT16SZ*2); + cp1 += INT16SZ*2; + cp += INT16SZ*2; + } + + /* get name */ + n = dn_expand(msg, eom, cp, (char *)cp1, + sizeof data - (cp1 - data)); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + if (!ns_nameok(NULL, (char *)cp1, class, NULL, response_trans, + hostname_ctx, dname, from.sin_addr)) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + + if (tnamep != NULL) + *tnamep = savestr((char *)cp1, 1); + + /* compute end of data */ + cp1 += strlen((char *)cp1) + 1; + /* compute size of data */ + n = cp1 - data; + cp1 = data; + break; + + case T_PX: + /* grab preference */ + BOUNDS_CHECK(cp, INT16SZ); + memcpy(data, cp, INT16SZ); + cp1 = data + INT16SZ; + cp += INT16SZ; + + /* get MAP822 name */ + n = dn_expand(msg, eom, cp, (char *)cp1, + sizeof data - INT16SZ); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + if (!ns_nameok(NULL, (char *)cp1, class, NULL, response_trans, + domain_ctx, dname, from.sin_addr)) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + /* + * The next use of 'cp' is dn_expand(), so we don't have + * to BOUNDS_CHECK() here. + */ + cp1 += (n = strlen((char *)cp1) + 1); + n1 = sizeof(data) - n - INT16SZ; + n = dn_expand(msg, eom, cp, (char *)cp1, n1); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + if (!ns_nameok(NULL, (char *)cp1, class, NULL, response_trans, + domain_ctx, dname, from.sin_addr)) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + cp1 += strlen((char *)cp1) + 1; + n = cp1 - data; + cp1 = data; + break; + + case T_SIG: { + u_int32_t origTTL, exptime, signtime, timetilexp, now; + u_int8_t alg; + + /* Check signature time, expiration, and adjust TTL. */ + /* This code is similar to that in db_load.c. */ + + /* Skip coveredType, save alg, skip labels */ + BOUNDS_CHECK(cp, INT16SZ + 1 + 1 + 3*INT32SZ); + cp1 = cp + INT16SZ; + alg = *cp1++; + cp1++; + GETLONG(origTTL, cp1); + GETLONG(exptime, cp1); + GETLONG(signtime, cp1); + now = time(NULL); /* Get current time in GMT/UTC */ + + /* Don't let bogus name servers increase the signed TTL */ + if (ttl > origTTL) { + ns_debug(ns_log_default, 3, + "shrinking SIG TTL from %lu to origTTL %lu", + (unsigned long)ttl, (unsigned long)origTTL); + ttl = origTTL; + } + + /* + * Check that expire and signature times are internally + * consistant. + */ + if (!SEQ_GT(exptime, signtime) && exptime != signtime) { + ns_debug(ns_log_default, 3, + "ignoring SIG: signature expires before it was signed"); + return ((cp - rrp) + dlen); + } + + /* Don't let bogus signers "sign" in the future. */ + if (SEQ_GT(signtime, now)) { + ns_debug(ns_log_default, 3, + "ignoring SIG: signature date %s is in the future", + p_secstodate (signtime)); + return ((cp - rrp) + dlen); + } + + /* Ignore received SIG RR's that are already expired. */ + if (SEQ_GT(now, exptime)) { + ns_debug(ns_log_default, 3, + "ignoring SIG: expiration %s is in the past", + p_secstodate (exptime)); + return ((cp - rrp) + dlen); + } + + /* Lop off the TTL at the expiration time. */ + timetilexp = exptime - now; + if (timetilexp < ttl) { + ns_debug(ns_log_default, 3, + "shrinking expiring %s SIG TTL from %d to %d", + p_secstodate (exptime), ttl, timetilexp); + ttl = timetilexp; + } + + /* The following code is copied from named-xfer.c. */ + cp1 = (u_char *)data; + + /* first just copy over the type_covered, algorithm, */ + /* labels, orig ttl, two timestamps, and the footprint */ + BOUNDS_CHECK(cp, 18); + memcpy(cp1, cp, 18); + cp += 18; + cp1 += 18; + + /* then the signer's name */ + n = dn_expand(msg, eom, cp, (char *)cp1, (sizeof data) - 18); + if (n < 0 || n + NS_SIG_SIGNER > (int)dlen) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + cp1 += strlen((char*)cp1)+1; + + /* finally, we copy over the variable-length signature. + Its size is the total data length, minus what we copied. */ + n = dlen - (NS_SIG_SIGNER + n); + + if (n > (int)(sizeof data) - (cp1 - (u_char *)data)) { + hp->rcode = FORMERR; + return (-1); /* out of room! */ + } + + switch (alg) { + case NS_ALG_MD5RSA: + if (n < NS_MD5RSA_MIN_SIZE || n > NS_MD5RSA_MAX_SIZE) + hp->rcode = FORMERR; + break; + + case NS_ALG_DSA: + if (n != NS_DSA_SIG_SIZE) + hp->rcode = FORMERR; + break; + + default: + break; + } + + if (hp->rcode == FORMERR) + return (-1); + + memcpy(cp1, cp, n); + cp += n; + cp1 += n; + + /* compute size of data */ + n = cp1 - (u_char *)data; + cp1 = (u_char *)data; + break; + } + + case T_NXT: + n = dn_expand(msg, eom, cp, (char *)data, sizeof data); + /* + * By testing if n >= dlen, we are requiring that the type + * bitmap be at least one octet. This is reasonable + * because we always have to look at the 0 bit to see if + * this is a "different format" NXT or not. + */ + if (n < 0 || n >= (int)dlen) { + hp->rcode = FORMERR; + return (-1); + } + if (!ns_nameok(NULL, (char *)data, class, NULL, response_trans, + domain_ctx, dname, from.sin_addr)) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + n1 = strlen((char *)data) + 1; + cp1 = data + n1; + /* + * We don't need to BOUNDS_CHECK() cp here because we've + * previously checked that 'dlen' bytes are in bounds, and + * we know that n < dlen. + */ + n2 = dlen - n; + /* + * The first bit of the first octet determines the format + * of the NXT record. A format for types >= 128 has not + * yet been defined, so if bit zero is set, we just copy + * what's there because we don't understand it. + */ + if ((*cp & 0x80) == 0) { + /* + * Bit zero is not set; this is an ordinary NXT + * record. The bitmap must be at least 4 octets + * because the NXT bit should be set. It should be + * less than or equal to 16 octets because this NXT + * format is only defined for types < 128. + */ + if (n2 < 4 || n2 > 16) { + hp->rcode = FORMERR; + return (-1); + } + } + if (n2 > (int)(sizeof data - n1)) { + hp->rcode = FORMERR; + return (-1); + } + memcpy(cp1, cp, n2); + cp += n2; + cp1 += n2; + + /* compute size of data */ + n = cp1 - (u_char *)data; + cp1 = (u_char *)data; + break; + + default: + /* treat as opaque data */ + ns_debug(ns_log_default, 3, "unknown type %d", type); + cp1 = cp; + n = dlen; + cp += n; + } + + if (cp > eom) { + hp->rcode = FORMERR; + return (-1); + } + if ((u_int)(cp - rdatap) != dlen) { + ns_debug(ns_log_default, 3, + "encoded rdata length is %u, but actual length was %u", + dlen, (u_int)(cp - rdatap)); + hp->rcode = FORMERR; + return (-1); + } + if (n > MAXDATA) { + ns_debug(ns_log_default, 1, + "update type %d: %d bytes is too much data", + type, n); + hp->rcode = FORMERR; + return (-1); + } + + ttl += tt.tv_sec; + if (type == ns_t_opt) + class = 0; /* Lie. */ + *dpp = savedata(class, type, ttl, cp1, n); + return (cp - rrp); +} + +int +send_msg(u_char *msg, int msglen, struct qinfo *qp) { + HEADER *hp = (HEADER *) msg; + u_char *oldmsg; + int oldlen = 0; + int msgsize; + int ret; + int trunc; + int adjust = 0; + + if (qp->q_flags & Q_SYSTEM) + return (1); + + trunc = (qp->q_stream != NULL) ? 65535 : qp->q_udpsize; + if (qp->q_tsig != NULL) + adjust += qp->q_tsig->tsig_size; + if ((qp->q_flags & Q_EDNS) != 0) + adjust += 11; + if (msglen > trunc - adjust) + msglen = trunc_adjust(msg, msglen, trunc - adjust); + + if (ns_wouldlog(ns_log_default, 1)) { + ns_debug(ns_log_default, 1, "send_msg -> %s (%s %d) id=%d", + sin_ntoa(qp->q_from), + qp->q_stream == NULL ? "UDP" : "TCP", + qp->q_stream == NULL ? qp->q_dfd : qp->q_stream->s_rfd, + ntohs(qp->q_id)); + } +#ifdef DEBUG + if (ns_wouldlog(ns_log_default, 4)) { + struct qinfo *tqp; + + for (tqp = nsqhead; tqp != NULL; tqp = tqp->q_link) { + ns_debug(ns_log_default, 4, + "qp %#lx q_id: %d q_nsid: %d q_msglen: %d", + (u_long)tqp, tqp->q_id, + tqp->q_nsid, tqp->q_msglen); + ns_debug(ns_log_default, 4, + "\tq_naddr: %d q_curaddr: %d", + tqp->q_naddr, tqp->q_curaddr); + ns_debug(ns_log_default, 4, + "\tq_next: %#lx q_link: %#lx", + (u_long)qp->q_next, (u_long)qp->q_link); + } + } +#endif /* DEBUG */ + + if (adjust != 0) { + oldmsg = msg; + oldlen = msglen; + msgsize = msglen + adjust; + msg = memget(msgsize); + memcpy(msg, oldmsg, oldlen); + } else + msgsize = msglen; /* silence compiler */ + + if ((qp->q_flags & Q_EDNS) != 0) + msglen += ns_add_opt(msg, msg + msglen, msgsize, 0, + hp->rcode, EDNS_MESSAGE_SZ, 0, NULL, 0); + + if (qp->q_tsig != NULL) { + u_char sig[TSIG_SIG_SIZE]; + int siglen = sizeof(sig); + + ret = ns_sign(msg, &msglen, msgsize, NOERROR, qp->q_tsig->key, + qp->q_tsig->sig, qp->q_tsig->siglen, + sig, &siglen, 0); + + if (ret != 0) { + INSIST(0); + } + } + +#ifdef DEBUG + if (debug >= 6) + res_pquery(&res, msg, msglen, log_get_stream(packet_channel)); +#endif /* DEBUG */ + + if (qp->q_stream == NULL) { + /* + * Don't send FORMERR to certian well known ports. + */ + if (hp->rcode == FORMERR && + drop_port(ntohs(qp->q_from.sin_port))) + return (-1); + if (sendto(qp->q_dfd, (char*)msg, msglen, 0, + (struct sockaddr *)&qp->q_from, + sizeof(qp->q_from)) < 0) { + if (!haveComplained(ina_ulong(qp->q_from.sin_addr), + (u_long)sendtoStr)) +#if defined(SPURIOUS_ECONNREFUSED) + if (errno != ECONNREFUSED) +#endif + ns_info(ns_log_default, + "send_msg: sendto(%s): %s", + sin_ntoa(qp->q_from), + strerror(errno)); + nameserIncr(qp->q_from.sin_addr, nssSendtoErr); + return (1); + } + } else + writestream(qp->q_stream, (u_char*)msg, msglen); + + if (adjust != 0) + memput(msg, oldlen + adjust); + + return (0); +} + +static int +root_server_p(ns_class class) { + struct zoneinfo *zp = find_zone("", class); + + return (zp != NULL && + (zp->z_type == z_master || zp->z_type == z_slave)); +} + +void +prime_cache(void) { + int root = root_server_p(ns_c_in); + + ns_debug(ns_log_default, 1, "prime_cache: priming = %d, root = %d", + priming, root); + if (!priming && !root) { + struct qinfo *qp = sysquery("", ns_c_in, ns_t_ns, + NULL, NULL, 0, ns_port, + ns_o_query, 0); + + if (qp != NULL) { + qp->q_flags |= (Q_SYSTEM | Q_PRIMING); + priming++; + } + } + needs_prime_cache = 0; +} + +struct qinfo * +sysquery(const char *dname, int class, int type, + struct in_addr *nss, struct dst_key **keys, int nsc, + u_int16_t port, int opcode, int distance) +{ + struct qinfo *qp, *oqp; + HEADER *hp; + char tmpdomain[MAXDNAME]; + struct namebuf *np = NULL; + struct databuf *nsp[NSMAX]; + struct hashbuf *htp1; + struct hashbuf *htp2; + struct hashbuf *htp3; + struct sockaddr_in *nsa; + const char *fname; + int n, count; + int sendto_errno = 0; + u_char *oldqbuf = NULL; + int oldqlen = 0, has_tsig; + u_char *smsg = NULL; + int smsglen, smsgsize = 0, siglen; + u_char sig[TSIG_SIG_SIZE]; + DST_KEY *key; + + nsp[0] = NULL; + ns_debug(ns_log_default, 3, "sysquery(%s, %d, %d, %p, %p, %d, %d)", + dname, class, type, nss, keys, nsc, ntohs(port)); + qp = qnew(dname, class, type, (nss != NULL && nsc != 0) ? 0 : 1); + + qp->q_distance = distance; + + if (nss != NULL && nsc != 0) + np = NULL; + else if (!NS_ZOPTION_P(qp->q_fzone, OPTION_FORWARD_ONLY)) { + htp1 = hashtab; + htp2 = hashtab; + htp3 = fcachetab; + if (priming && dname[0] == '\0') { + np = NULL; + } else if (((np = nlookup(dname, &htp1, &fname, 0)) == NULL) && + ((np = nlookup("", &htp2, &fname, 0)) == NULL) && + ((np = nlookup("", &htp3, &fname, 0)) == NULL)) { + ns_info(ns_log_default, + "sysquery: nlookup error on %s?", + dname); + err1: + ns_freeqry(qp); + return (NULL); + } + + n = findns(&np, class, nsp, &count, 0); + switch (n) { + case NXDOMAIN: + case SERVFAIL: + ns_info(ns_log_default, + "sysquery: findns error (%s) on %s?", + n == NXDOMAIN ? "NXDOMAIN" : "SERVFAIL", + dname); + err2: + free_nsp(nsp); + goto err1; + } + } + + /* Build new qinfo struct. */ + qp->q_cmsg = qp->q_msg = NULL; + qp->q_dfd = ds; + if (nss == NULL || nsc == 0) + nsfwdadd(qp, NS_ZFWDTAB(qp->q_fzone)); + qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2; + qp->q_flags |= Q_SYSTEM; + + getname(np, tmpdomain, sizeof tmpdomain); + qp->q_domain = savestr(tmpdomain, 1); + + if ((qp->q_msg = (u_char *)memget(PACKETSZ)) == NULL) { + ns_notice(ns_log_default, "sysquery: memget failed"); + goto err2; + } + qp->q_msgsize = PACKETSZ; + n = res_nmkquery(&res, opcode, dname, class, + type, NULL, 0, NULL, + qp->q_msg, PACKETSZ); + if (n < 0) { + ns_info(ns_log_default, + "sysquery: res_mkquery(%s) failed", dname); + goto err2; + } + qp->q_msglen = n; + hp = (HEADER *) qp->q_msg; + hp->id = qp->q_nsid = htons(nsid_next()); + hp->rd = (qp->q_addr[qp->q_curaddr].forwarder ? 1 : 0); + hp->aa = (opcode == NS_NOTIFY_OP); + + /* First check for an already pending query for this data. */ + for (oqp = nsqhead; oqp != NULL; oqp = oqp->q_link) { + if ((oqp != qp) + && (oqp->q_msglen == qp->q_msglen) + && memcmp(oqp->q_msg+2, qp->q_msg + 2, + qp->q_msglen - 2) == 0 + ) { +#ifdef BIND_NOTIFY + /* XXX - need fancier test to suppress duplicate + * NOTIFYs to the same server (compare nss?) + */ + if (opcode != NS_NOTIFY_OP) +#endif /*BIND_NOTIFY*/ + { + ns_debug(ns_log_default, 3, + "sysquery: duplicate"); + goto err2; + } + } + } + + if (nss != NULL && nsc != 0) { + int i; + struct qserv *qs; + + for (i = 0, qs = qp->q_addr; i < nsc; i++, qs++) { + qs->ns_addr.sin_family = AF_INET; + qs->ns_addr.sin_addr = nss[i]; + qs->ns_addr.sin_port = port; + if (keys != NULL) + qp->q_keys[i] = keys[i]; + qs->ns = NULL; + qs->nsdata = NULL; + qs->stime = tt; + qs->forwarder = 0; + qs->noedns = 1; /* XXXMPA */ + qs->nretry = 0; + } + qp->q_naddr = nsc; + } else if (!NS_ZOPTION_P(qp->q_fzone, OPTION_FORWARD_ONLY)) { + fetch_a: + count = nslookup(nsp, qp, dname, "sysquery"); + if (count <= 0) { + if (count < 0) { + if (n == -1) + ns_info(ns_log_default, + "sysquery: nslookup reports danger (%s)", + dname); + goto err2; + } else if (np && NAME(*np)[0] == '\0') { + /* + * It's not too serious if we don't have + * the root server addresses if we have to + * go through a forwarder anyway. Don't + * bother to log it, since prime_cache() + * won't do anything about it as currently + * implemented. + * + * XXX - should we skip setting + * needs_prime_cache as well? + * + * XXX - what happens when we implement + * selective forwarding? + */ + if (!NS_OPTION_P(OPTION_FORWARD_ONLY)) + ns_warning(ns_log_default, + "sysquery: no addrs found for root NS (%s)", + dname); + if (class == C_IN && !priming) + needs_prime_cache = 1; + goto err2; + } + if (np) { + free_nsp(nsp); + nsp[0] = NULL; + np = np_parent(np); + n = findns(&np, class, nsp, &count, 0); + switch (n) { + case NXDOMAIN: /*FALLTHROUGH*/ + case SERVFAIL: + ns_info(ns_log_default, + "sysquery: findns error (%d) on %s?", + n, dname); + goto err2; + } + getname(np, tmpdomain, sizeof tmpdomain); + if (qp->q_domain != NULL) + (void)freestr(qp->q_domain); + qp->q_domain = savestr(tmpdomain, 1); + goto fetch_a; + } + goto err2; + } + } + + schedretry(qp, retrytime(qp)); + qp->q_addr[0].stime = tt; /* XXX - why not every? */ + nsa = Q_NEXTADDR(qp, 0); + + if (ns_wouldlog(ns_log_default, 1)) { + ns_debug(ns_log_default, 1, + "sysquery: send -> %s dfd=%d nsid=%d id=%d retry=%ld", + sin_ntoa(*nsa), qp->q_dfd, + ntohs(qp->q_nsid), ntohs(qp->q_id), + (long)qp->q_time); + } +#ifdef DEBUG + if (debug >= 10) + res_pquery(&res, qp->q_msg, qp->q_msglen, + log_get_stream(packet_channel)); +#endif + + key = qp->q_keys[0]; + if (key == NULL) + key = qp->q_keys[0] = tsig_key_from_addr(nsa->sin_addr); + if (key != NULL || !qp->q_addr[0].noedns) { + smsgsize = qp->q_msglen + TSIG_BUF_SIZE + 11; + smsg = memget(smsgsize); + smsglen = qp->q_msglen; + siglen = sizeof(sig); + memcpy(smsg, qp->q_msg, qp->q_msglen); + } + + if (!qp->q_addr[0].noedns) + smsglen += ns_add_opt(smsg, smsg + smsglen, smsgsize, 0, 0, + EDNS_MESSAGE_SZ, 0, NULL, 0); + + if (key != NULL) { + n = ns_sign(smsg, &smsglen, smsgsize, NOERROR, key, NULL, 0, + sig, &siglen, 0); + if (n == 0) { + has_tsig = 1; + free_tsig(qp->q_nstsig); + qp->q_nstsig = new_tsig(key, sig, siglen); + } else { + INSIST(0); + has_tsig = 0; + free_tsig(qp->q_nstsig); + qp->q_nstsig = NULL; + } + } else { + has_tsig = 0; + free_tsig(qp->q_nstsig); + qp->q_nstsig = NULL; + } + + if (smsgsize != 0) { + oldqbuf = qp->q_msg; + oldqlen = qp->q_msglen; + qp->q_msglen = smsglen; + qp->q_msg = smsg; + } + + if (sendto(qp->q_dfd, (char*)qp->q_msg, qp->q_msglen, 0, + (struct sockaddr *)nsa, + sizeof(struct sockaddr_in)) < 0) { + sendto_errno = errno; + if (!haveComplained(ina_ulong(nsa->sin_addr), + (u_long)sendtoStr)) + ns_info(ns_log_default, "sysquery: sendto(%s): %s", + sin_ntoa(*nsa), strerror(errno)); + nameserIncr(nsa->sin_addr, nssSendtoErr); + } + + if (smsgsize != 0) { + memput(smsg, smsgsize); + qp->q_msg = oldqbuf; + qp->q_msglen = oldqlen; + } + + nameserIncr(nsa->sin_addr, nssSentSysQ); + free_nsp(nsp); + switch (sendto_errno) { + case ENETDOWN: + case ENETUNREACH: + case EHOSTDOWN: + case EHOSTUNREACH: + unsched(qp); + schedretry(qp, (time_t) 0); + } + return (qp); +} + +/* + * Check the list of root servers after receiving a response + * to a query for the root servers. + */ +static int +check_root() { + struct databuf *dp, *pdp; + struct namebuf *np; + int count = 0; + + priming = 0; + for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next) + if (NAME(*np)[0] == '\0') + break; + if (np == NULL) { + ns_notice(ns_log_default, "check_root: Can't find root!"); + return (0); + } + for (dp = np->n_data; dp != NULL; dp = dp->d_next) + if (dp->d_type == T_NS) + count++; + ns_debug(ns_log_default, 1, "%d root servers", count); + if (count < server_options->minroots) { + ns_notice(ns_log_default, + "check_root: %d root servers after query to root server < min", + count); + return (0); + } + pdp = NULL; + dp = np->n_data; + while (dp != NULL) { + if (dp->d_type == T_NS && dp->d_zone == DB_Z_CACHE && + dp->d_ttl < (u_int32_t)tt.tv_sec) { + ns_debug(ns_log_default, 1, + "deleting old root server '%s'", + dp->d_data); + dp = rm_datum(dp, np, pdp, NULL); + /* SHOULD DELETE FROM HINTS ALSO */ + continue; + } + pdp = dp; + dp = dp->d_next; + } + if (check_ns()) + return (1); + else { + priming = 1; + return (0); + } +} + +/* + * Check the root to make sure that for each NS record we have a A RR + */ +static int +check_ns() { + struct databuf *dp, *tdp; + struct namebuf *np, *tnp; + struct hashbuf *htp; + char *dname; + int found_arr; + const char *fname; + time_t curtime; + int servers = 0, rrsets = 0; + + ns_debug(ns_log_default, 2, "check_ns()"); + + curtime = (u_int32_t) tt.tv_sec; + for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next) { + if (NAME(*np)[0] != '\0') + continue; + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + int cnames = 0; + + if (dp->d_rcode) + continue; + + if (dp->d_type != T_NS) + continue; + + servers++; + + /* look for A records */ + dname = (caddr_t) dp->d_data; + htp = hashtab; + tnp = nlookup(dname, &htp, &fname, 0); + if (tnp == NULL || fname != dname) { + ns_debug(ns_log_default, 3, + "check_ns: %s: not found %s %#lx", + dname, fname, (u_long)tnp); + sysquery(dname, dp->d_class, T_A, NULL, NULL, + 0, ns_port, QUERY, 0); + continue; + } + /* look for name server addresses */ + found_arr = 0; + (void)delete_stale(tnp); + for (tdp = tnp->n_data; + tdp != NULL; + tdp = tdp->d_next) { + if (tdp->d_rcode) + continue; + if (tdp->d_type == T_CNAME) + cnames++; + if (tdp->d_type != T_A || + tdp->d_class != dp->d_class) + continue; + if ((tdp->d_zone == DB_Z_CACHE) && + (tdp->d_ttl < (u_int32_t)curtime)) { + ns_debug(ns_log_default, 3, + "check_ns: stale entry '%s'", + NAME(*tnp)); + found_arr = 0; + break; + } + found_arr++; + } + if (found_arr) + rrsets++; + else if (cnames > 0) + ns_info(ns_log_default, + "Root NS %s -> CNAME %s", + NAME(*np), NAME(*tnp)); + else + sysquery(dname, dp->d_class, T_A, NULL, NULL, + 0, ns_port, QUERY, 0); + } + } + + ns_debug(ns_log_default, 2, "check_ns: %d %d", servers, rrsets); + return ((servers <= 2) + ? (rrsets == servers) + : ((rrsets * 2) >= servers) + ); +} + +/* int findns(npp, class, nsp, countp, flag) + * Find NS's or an SOA + * npp, class: + * dname whose most enclosing NS is wanted + * nsp, countp: + * result array and count; array will also be NULL terminated + * flag: + * boolean: we're being called from ADDAUTH, bypass authority checks + * return value: + * NXDOMAIN: we are authoritative for this {dname,class} + * *countp is bogus, but nsp[] has a single SOA returned in it. + * SERVFAIL: we are auth but zone isn't loaded; or, no root servers found + * *countp and nsp[] are bogus. + * OK: we are not authoritative, and here are the NS records we found. + * *countp and nsp[] return NS records of interest. + */ +int +findns(struct namebuf **npp, int class, + struct databuf **nsp, int *countp, int flag) +{ + struct namebuf *np = *npp; + struct databuf *dp; + struct databuf **nspp; + struct hashbuf *htp; + + nsp[0] = NULL; + + if (priming && (np == NULL || NAME(*np)[0] == '\0')) + htp = fcachetab; + else + htp = hashtab; + + try_again: + if (htp == fcachetab && class == C_IN && !priming) + /* + * XXX - do we want to set needs_prime_cache if + * OPTION_FORWARD_ONLY? + */ + needs_prime_cache = 1; + if (np == NULL) { + /* find the root */ + for (np = htp->h_tab[0]; np != NULL; np = np->n_next) + if (NAME(*np)[0] == '\0') + break; + } + while (np != NULL) { + ns_debug(ns_log_default, 5, "findns: np %p '%s'", np, + NAME(*np)); + /* Look first for SOA records. */ +#ifdef ADDAUTH + if (!flag) +#endif + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (dp->d_zone != DB_Z_CACHE && + ((zones[dp->d_zone].z_type == Z_PRIMARY) || + (zones[dp->d_zone].z_type == Z_SECONDARY)) && + match(dp, class, T_SOA) && dp->d_type == T_SOA) { + ns_debug(ns_log_default, 3, + "findns: SOA found"); + if (zones[dp->d_zone].z_flags & Z_AUTH) { + *npp = np; + nsp[0] = dp; + nsp[1] = NULL; + DRCNTINC(dp); + return (NXDOMAIN); + } else { + /* XXX: zone isn't loaded but we're + * primary or slave for it. + * should we fwd this? + */ + return (SERVFAIL); + } + } + } + + /* If no SOA records, look for NS records. */ + nspp = &nsp[0]; + *nspp = NULL; + (void)delete_stale(np); + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (!match(dp, class, T_NS)) + continue; + if (dp->d_rcode) + continue; + /* + * Don't use records that may become invalid to + * reference later when we do the rtt computation. + * Never delete our safety-belt information! + * + * XXX: this is horribly bogus. + */ + if ((dp->d_zone == DB_Z_CACHE) && + (dp->d_ttl < (u_int32_t)tt.tv_sec) && + !(dp->d_flags & DB_F_HINT)) { + ns_debug(ns_log_default, 1, + "findns: stale entry '%s'", + NAME(*np)); + /* + * We may have already added NS databufs + * and are going to throw them away. Fix + * reference counts. We don't need to free + * them here as we just got them from the + * cache. + */ + while (nspp > &nsp[0]) + db_detach(--nspp); + nsp[0] = NULL; + goto try_parent; + } + if (nspp < &nsp[NSMAX-1]) { + *nspp++ = dp; + DRCNTINC(dp); + } + } + + *countp = nspp - nsp; + if (*countp > 0) { + ns_debug(ns_log_default, 3, + "findns: %d NS's added for '%s'", + *countp, NAME(*np)); + *nspp = NULL; + *npp = np; + return (OK); /* Success, got some NS's */ + } + try_parent: + np = np_parent(np); + } + if (htp == hashtab) { + htp = fcachetab; + goto try_again; + } + ns_debug(ns_log_default, 1, + "findns: No root nameservers for class %s?", p_class(class)); + if ((unsigned)class < MAXCLASS && norootlogged[class] == 0) { + norootlogged[class] = 1; + ns_info(ns_log_default, "No root nameservers for class %s", + p_class(class)); + } + return (SERVFAIL); +} + + +/* + * Extract RR's from the given node that match class and type. + * Return number of bytes added to response. + * If no matching data is found, then 0 is returned. + */ +int +finddata(struct namebuf *np, int class, int type, + HEADER *hp, char **dnamep, int *lenp, int *countp) +{ + struct databuf *dp; + char *cp; + int buflen, n, count = 0; + char *new_dnamep = NULL; + int defer = 0, found_count = 0, choice, i; + struct databuf **found = NULL; + struct databuf **tmpfound = NULL; + int foundcname; + int stalecount; + int ret = 0; + + stalecount = delete_stale(np); + + /* We don't want to return cached SIG records when asked for SIGs, + * since we may have an incomplete set. + */ + if (type == T_SIG && findMyZone(np, class) == DB_Z_CACHE) + return(0); + + if (type != T_ANY && type != T_PTR && type != T_NXT) { + found = memget((stalecount + 1) * sizeof *found); + tmpfound = memget((stalecount + 1) * sizeof *tmpfound); + if (found == NULL || tmpfound == NULL) + ns_panic(ns_log_default, 1, "finddata: out of memory"); + defer = 1; + } + + buflen = *lenp; + +#ifdef DEBUG + if (buflen > PACKETSZ) + ns_debug(ns_log_default, 1, "finddata(): buflen=%d", buflen); +#endif + cp = ((char *)hp) + *countp; + foundcname = 0; + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (!wanted(dp, class, type)) { + if (type == T_CNAME && class == dp->d_class) { + /* any data means no CNAME exists */ + if (dp->d_type != T_NXT && + dp->d_type != T_KEY && + dp->d_type != T_SIG) { + ret = 0; + goto done; + } + } + continue; + } + if (dp->d_cred == DB_C_ADDITIONAL) { +#ifdef NOADDITIONAL + continue; +#else + /* we want to expire additional data very + * quickly. current strategy is to cut 5% + * off each time it is accessed. this makes + * stale(dp) true earlier when this datum is + * used often. + */ + dp->d_ttl = tt.tv_sec + + + 0.95 * (int) (dp->d_ttl - tt.tv_sec); +#endif + } + /* -ve $ing stuff, anant@isi.edu + * if we have a -ve $ed record, change the rcode on the + * header to reflect that + */ + if (dp->d_rcode == NOERROR_NODATA) { + if (count != 0) { + /* + * This should not happen, yet it does... + */ + ns_info(ns_log_default, + "NODATA & data for \"%s\" type %d class %d", + *dnamep, type, class); + continue; + } + if (type == T_ANY) + continue; + hp->rcode = NOERROR_NODATA; + if (dp->d_size == 0) { /* !RETURNSOA */ + ret = 1; + goto done; + } + } + if (dp->d_rcode == NXDOMAIN) { + if (count != 0) { + /* + * This should not happen, yet it might... + */ + ns_info(ns_log_default, + "NXDOMAIN & data for \"%s\" type %d class %d", + *dnamep, type, class); + continue; + } + hp->rcode = NXDOMAIN; + if (dp->d_size == 0) { /* !RETURNSOA */ + ret = 1; + goto done; + } + } +#ifdef HITCOUNTS + ++dp->d_hitcnt; + ++db_total_hits; +#endif /* HITCOUNTS */ + + /* Don't put anything but key or sig RR's in response to + requests for key or sig */ + if (((type == T_SIG) || (type == T_KEY)) && + (!((dp->d_type == T_SIG) || (dp->d_type == T_KEY))) ) + continue; + + if (!defer) { + if (foundcname != 0 && dp->d_type == T_CNAME) + continue; + + if ((n = make_rr(*dnamep, dp, (u_char *)cp, buflen, 1, + dnptrs, dnptrs_end, 0)) < 0) { + hp->tc = 1; + ret = *lenp - buflen; + goto done; + } + if (dp->d_secure != DB_S_SECURE) + hp->ad = 0; + cp += n; + buflen -= n; + count++; + + if (dp->d_type == T_CNAME) { + foundcname = 1; +#define FOLLOWCNAME(type) \ + (type != T_KEY) && (type != T_SIG) && (type != T_NXT) && (type != T_ANY) + /* don't alias if querying for key, sig, nxt, or any */ + + if (FOLLOWCNAME(type)) + new_dnamep = (char *)dp->d_data; + } + } else { + if (dp->d_type == T_CNAME) + foundcname = 1; + found[found_count++] = dp; + } + } + + if (found_count == 0 && count == 0) { + ret = 0; + goto done; + } + + /* + * If the query type was SIG or ANY we will have returned the SIG + * records already. + */ + if (type != T_SIG && type != T_ANY) { + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (!wantedsig(dp, class, type)) + continue; + if (dp->d_cred == DB_C_ADDITIONAL) { +#ifdef NOADDITIONAL + continue; +#else + /* we want to expire additional data very + * quickly. current strategy is to cut 5% + * off each time it is accessed. this makes + * stale(dp) true earlier when this datum is + * used often. + */ + dp->d_ttl = tt.tv_sec + + + 0.95 * (int) (dp->d_ttl - tt.tv_sec); +#endif + } + if (!defer) { + if ((n = make_rr(*dnamep, dp, (u_char *)cp, + buflen, 1, dnptrs, dnptrs_end, + 0)) < 0) { + hp->tc = 1; + ret = *lenp - buflen; + goto done; + } + if (dp->d_secure != DB_S_SECURE) + hp->ad = 0; + cp += n; + buflen -= n; + count++; + } else + found[found_count++] = dp; + } + } + + if (defer && found_count > 0) { + int first_sig; + int non_sig_count; + int sig_count; /* number of SIG records in found */ + int idx, jdx; + enum ordering order; + + order = match_order(np, class, foundcname ? T_CNAME : type); + + /* + * shuffle the SIG records down to the bottom of the array + * as we need to make sure they get packed last, no matter + * what the ordering is. We're sure to maintain the + * original ordering within the two sets of records (so + * that fixed_order can work). + * First we pack the non-SIG records into the temp array. + */ + for (idx = jdx = 0 ; idx < found_count ; idx++) { + if (found[idx]->d_type != T_SIG) { + tmpfound[jdx++] = found[idx]; + } + } + non_sig_count = jdx; + sig_count = found_count - jdx; + first_sig = jdx ; + + /* + * now shift the SIG records down to the end of the array + * and copy in the non-SIG records + */ + for (i = idx = found_count - 1 ; i >= 0 ; idx--) { + if (i < non_sig_count) { + found[i] = tmpfound[i]; + i--; + } else if (found[idx]->d_type == T_SIG) { + found[i--] = found[idx] ; + } + } + + foundcname = 0; + switch (order) { + case fixed_order: + for (i = 0; i < found_count; i++) { + dp = found[i]; + if (foundcname != 0 && dp->d_type == T_CNAME) + continue; + if (dp->d_type == T_CNAME) { + foundcname = 1; + if (FOLLOWCNAME(type)) { + new_dnamep = (char *)dp->d_data; + } + } + if ((n = make_rr(*dnamep, dp, (u_char *)cp, + buflen, 1, + dnptrs, dnptrs_end, 0)) < 0) { + hp->tc = 1; + ret = *lenp - buflen; + goto done; + } + if (dp->d_secure != DB_S_SECURE) + hp->ad = 0; + cp += n; + buflen -= n; + count++; + } + break; + + case random_order: { + /* first we shuffle the non-SIG records */ + int iters = non_sig_count; + for (i = 0; i < iters; i++) { + choice = ((u_int)rand()>>3) % non_sig_count; + non_sig_count--; + dp = found[choice]; + found[choice] = found[non_sig_count]; + if (foundcname != 0 && dp->d_type == T_CNAME) + continue; + if (dp->d_type == T_CNAME) { + foundcname = 1; + if (FOLLOWCNAME(type)) { + new_dnamep = (char *)dp->d_data; + } + } + if ((n = make_rr(*dnamep, dp, (u_char *)cp, + buflen, 1, + dnptrs, dnptrs_end, 0)) < 0) { + hp->tc = 1; + ret = *lenp - buflen; + goto done; + } + if (dp->d_secure != DB_S_SECURE) + hp->ad = 0; + cp += n; + buflen -= n; + count++; + } + + /* now shuffle the SIG records */ + iters = sig_count; + for (i = 0; i < iters; i++) { + choice = ((u_int)rand()>>3) % sig_count; + choice += first_sig; + sig_count--; + dp = found[choice]; + found[choice] = found[sig_count + first_sig]; + if ((n = make_rr(*dnamep, dp, (u_char *)cp, + buflen, 1, + dnptrs, dnptrs_end, 0)) < 0) { + hp->tc = 1; + ret = *lenp - buflen; + goto done; + } + if (dp->d_secure != DB_S_SECURE) + hp->ad = 0; + cp += n; + buflen -= n; + count++; + } + break; + } + + case cyclic_order: + /* first we do the non-SIG records */ + if (non_sig_count > 0) + choice = ((u_int)rand()>>3) % non_sig_count; + else + choice = 0; + for (i = 0; i < non_sig_count ; i++) { + dp = found[(i + choice) % non_sig_count]; + if (foundcname != 0 && dp->d_type == T_CNAME) + continue; + if (dp->d_type == T_CNAME) { + foundcname = 1; + if (FOLLOWCNAME(type)) { + new_dnamep = (char *)dp->d_data; + } + } + if ((n = make_rr(*dnamep, dp, (u_char *)cp, + buflen, 1, + dnptrs, dnptrs_end, 0)) < 0) { + hp->tc = 1; + ret = *lenp - buflen; + goto done; + } + if (dp->d_secure != DB_S_SECURE) + hp->ad = 0; + cp += n; + buflen -= n; + count++; + } + + /* now do the SIG record rotation. */ + if (sig_count > 0) { + choice = ((u_int)rand()>>3) % sig_count; + choice += first_sig; + i = choice; + do { + dp = found[i]; + if ((n = make_rr(*dnamep, dp, + (u_char *)cp, + buflen, 1, + dnptrs, + dnptrs_end, 0)) < 0) { + hp->tc = 1; + ret = *lenp - buflen; + goto done; + } + if (dp->d_secure != DB_S_SECURE) + hp->ad = 0; + cp += n; + buflen -= n; + count++; + i++; + if (i >= found_count) + i = first_sig; + } while (i != choice); + } + + break; + + default: + ns_warning(ns_log_default, "finddata: unknown ordering: %d", + order); + break; + } + } + + if (new_dnamep != NULL) + *dnamep = new_dnamep; + + ns_debug(ns_log_default, 3, "finddata: added %d class %d type %d RRs", + count, class, type); + ret = *lenp - buflen; + done: + if (found != NULL) + memput(found, (stalecount + 1) * sizeof *found); + if (tmpfound != NULL) + memput(tmpfound, (stalecount + 1) * sizeof *tmpfound); + *countp = count; + return (ret); +} + +/* + * Do we want this data record based on the class and type? + */ +static int +wanted(const struct databuf *dp, int class, int type) { + const u_char *cp; + int coveredType; + time_t expiration; +#ifdef DEBUG + char pclass[15], ptype[15]; +#endif + +#ifdef DEBUG + strcpy(pclass, p_class(class)); + strcpy(ptype, p_type(type)); + ns_debug(ns_log_default, 3, "wanted(%p, %s %s) [%s %s]", + dp, pclass, ptype, + p_class(dp->d_class), p_type(dp->d_type)); +#endif + + if (dp->d_class != class && class != C_ANY) + return (0); + /* + * Must check SIG for expiration below, other matches + * return OK here. + */ + if (type == dp->d_type && (type != T_SIG)) + return (1); + /* For a T_ANY query, we do not want to return -ve $ed RRs. */ + if (type == T_ANY && dp->d_rcode == NOERROR_NODATA) + return (0); + + /* First, look at the type of RR. */ + switch (dp->d_type) { + + /* Cases to deal with: + T_ANY search, return all unexpired SIGs. + T_SIG search, return all unexpired SIGs. + T_ search, return all unexp SIG s. + */ + case T_SIG: + cp = dp->d_data; + GETSHORT(coveredType, cp); + cp += INT16SZ + INT32SZ; /* skip alg, labels, & orig TTL */ + GETLONG(expiration,cp); + + if (type == T_ANY || type == T_SIG) { + if (expiration > time(0)) + return (1); /* Unexpired matching SIG */ + } + return (0); /* We don't return this SIG. */ + + case T_ANY: + return (1); + case T_CNAME: + if (dp->d_rcode != NOERROR_NODATA) + return (1); + else + break; + } + /* OK, now look at the type of query. */ + if (type == ns_t_any) + return (1); + else if (type == ns_t_mailb) + switch (dp->d_type) { + case T_MR: + case T_MB: + case T_MG: + case T_MINFO: + return (1); + } + else if (ns_t_xfr_p(type)) { + /* + * This is used to validate transfer requests, not + * generate transfer responses. Is there an SOA? + */ + if (dp->d_type == ns_t_soa && dp->d_zone != DB_Z_CACHE + && (zones[dp->d_zone].z_flags & Z_AUTH)) + return (1); + } + return (0); +} + +static int +wantedsig(const struct databuf *dp, int class, int type) { + const u_char *cp; + int coveredType; + time_t expiration; +#ifdef DEBUG + char pclass[15], ptype[15]; +#endif + +#ifdef DEBUG + strcpy(pclass, p_class(class)); + strcpy(ptype, p_type(type)); + ns_debug(ns_log_default, 3, "wantedtsig(%p, %s %s) [%s %s]", + dp, pclass, ptype, + p_class(dp->d_class), p_type(dp->d_type)); +#endif + + if (dp->d_class != class && class != C_ANY) + return (0); + if (dp->d_type != T_SIG || dp->d_rcode != 0) + return (0); + + cp = dp->d_data; + GETSHORT(coveredType, cp); + cp += INT16SZ + INT32SZ; /* skip alg, labels, & orig TTL */ + GETLONG(expiration,cp); + if (expiration < time(0)) + return (0); + + if (type == T_ANY || type == T_SIG || type == coveredType) + return (1); + if (type == ns_t_mailb) { + switch (coveredType) { + case T_MR: + case T_MB: + case T_MG: + case T_MINFO: + return (1); + } + } + return (0); +} + +/* + * Add RR entries from dpp array to a query/response. + * Return the number of bytes added or negative the amount + * added if truncation occured. Typically you are + * adding NS records to a response. + */ +int +add_data(struct namebuf *np, struct databuf **dpp, + u_char *cp, int buflen, int *countp) +{ + struct databuf *dp; + char dname[MAXDNAME]; + int n, bytes; + + bytes = *countp = 0; + getname(np, dname, sizeof(dname)); + for (dp = *dpp++; dp != NULL; dp = *dpp++) { + if (stale(dp)) + continue; /* ignore old cache entry */ + if (dp->d_rcode) + continue; + if ((n = make_rr(dname, dp, cp, buflen, 1, + dnptrs, dnptrs_end, 0)) < 0) + return (-bytes); /* Truncation */ + cp += n; + buflen -= n; + bytes += n; + (*countp)++; + } + return (bytes); +} + +static void +rrsetadd(struct flush_set *flushset, const char *name, struct databuf *dp) { + struct flush_set *fs = flushset; + struct db_list *dbl; + + while (fs->fs_name && ( + ns_samename(fs->fs_name,name) != 1 || + (fs->fs_class != dp->d_class) || + (fs->fs_type != dp->d_type) || + (fs->fs_cred != dp->d_cred))) { + fs++; + } + if (!fs->fs_name) { + fs->fs_name = savestr(name, 1); + fs->fs_class = dp->d_class; + fs->fs_type = dp->d_type; + fs->fs_cred = dp->d_cred; + fs->fs_list = NULL; + fs->fs_last = NULL; + } + dbl = (struct db_list *)memget(sizeof(struct db_list)); + if (!dbl) + panic("rrsetadd: out of memory", NULL); + dbl->db_next = NULL; + dbl->db_dp = dp; + DRCNTINC(dbl->db_dp); + if (fs->fs_last == NULL) + fs->fs_list = dbl; + else + fs->fs_last->db_next = dbl; + fs->fs_last = dbl; +} + +static int +ttlcheck(const char *name, struct db_list *dbl, int update) { + int type = dbl->db_dp->d_type; + int class = dbl->db_dp->d_class; + struct hashbuf *htp = hashtab; + const char *fname; + struct namebuf *np; + struct db_list *dbp = dbl; + struct databuf *dp; + u_int32_t ttl = 0; /* Make gcc happy. */ + int first; + + + np = nlookup(name, &htp, &fname, 0); + if (np == NULL || fname != name || ns_wildcard(NAME(*np))) + return (1); + + /* check that all the ttl's we have are the same, if not return 1 */ + first = 1; + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (!match(dp, class, type)) + continue; + if (first) { + /* we can't update zone data so return early */ + if (dp->d_zone != DB_Z_CACHE) + return (0); + ttl = dp->d_ttl; + first = 0; + } else if (ttl != dp->d_ttl) + return (1); + } + + /* there are no records of this type in the cache */ + if (first) + return(1); + + /* + * the ttls of all records we have in the cache are the same + * if the ttls differ in the new set we don't want it. + */ + + /* check that all the ttl's we have are the same, if not return 0 */ + first = 1; + while (dbp) { + if (first) { + ttl = dbp->db_dp->d_ttl; + first = 0; + } else if (ttl != dbp->db_dp->d_ttl) { + return(0); + } + dbp = dbp->db_next; + } + + /* update ttl if required */ + if (update) { + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (!match(dp, class, type)) + continue; + if (dp->d_ttl > ttl) + break; + dp->d_ttl = ttl; + fixttl(dp); + } + } + + return(1); +} + +/* + * lookup rrset in table and compare to dbl + * tri state result + * -1: lookup failed + * 0: rrsets same + * 1: rrsets differ + */ + +static int +rrsetcmp(char * name, struct db_list * dbl, struct hashbuf * table) { + int type = dbl->db_dp->d_type; + int class = dbl->db_dp->d_class; + struct hashbuf *htp = table; + const char *fname; + struct namebuf *np; + struct db_list *dbp = dbl; + struct databuf *dp; + int exists = 0; + + + np = nlookup(name, &htp, &fname, 0); + if (np == NULL || fname != name || ns_wildcard(NAME(*np))) { + ns_debug(ns_log_default, 3, "rrsetcmp: name not in database"); + return (-1); + } + + /* check that all entries in dbl are in the cache */ + while (dbp) { + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (!match(dp, class, type)) + continue; + exists = 1; + if (!db_cmp(dp, dbp->db_dp) +#ifdef NOADDITIONAL + && ((dp->d_cred == dbp->db_dp->d_cred) || + (dp->d_cred != DB_C_ADDITIONAL)) +#endif + ) + break; + } + if (!dp) { + ns_debug(ns_log_default, 3, + "rrsetcmp: %srecord%s in database", + exists ? "" : "no ", exists ? " not" : "s"); + return (exists ? 1 : -1); + } + dbp = dbp->db_next; + } + + /* Check that all cache entries are in the list. */ + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (!match(dp, class, type)) + continue; +#ifdef NCACHE + if (dp->d_rcode) + return (1); +#endif + dbp = dbl; + while (dbp) { + if (!db_cmp(dp, dbp->db_dp)) + break; + dbp = dbp->db_next; + } + if (!dbp) { + ns_debug(ns_log_default, 3, + "rrsetcmp: record not in rrset"); + return (1); + } + } + ns_debug(ns_log_default, 3, "rrsetcmp: rrsets matched"); + return (0); +} + +/* + * verify incoming answer against what we already have in the hints + * issue warnings / errors if differences detected. + */ + +static void +check_hints(struct flush_set * flushset) { + struct zoneinfo *zp; + struct flush_set *fs; + struct db_list *dbp; + + /* We don't use hints when in forward only mode */ + if (NS_OPTION_P(OPTION_FORWARD_ONLY)) + return; + + /* find "." NS rrset and hence class */ + for (fs = flushset; fs->fs_name != NULL; fs++) { + if ((fs->fs_name[0] != '\0') || (fs->fs_type != ns_t_ns)) + continue; + + /* see if we are a root server */ + zp = find_zone(fs->fs_name, fs->fs_class); + if (zp != NULL && + (zp->z_type == z_master || zp->z_type == z_slave)) + return; + switch (rrsetcmp(fs->fs_name, fs->fs_list, fcachetab)) { + case -1: + ns_error(ns_log_default, + "check_hints: no NS records for class %d in hints", + fs->fs_class); + break; + case 1: + ns_warning(ns_log_default, + "check_hints: root NS list in hints for class %d does not match root NS list", + fs->fs_class); + break; + case 0: + break; + default: + ns_error(ns_log_default, + "check_hints: unexpected response from rrsetcmp"); + break; + } + break; + } + + if (fs->fs_name == NULL) /* no root NS records */ + return; + + dbp = fs->fs_list; + while (dbp) { + /* for each NS find A rrset in answer and check */ + for (fs = flushset; fs->fs_name != NULL; fs++) { + if (ns_samename(fs->fs_name, (char *)dbp->db_dp->d_data) != 1 + || fs->fs_type != ns_t_a) + continue; + switch (rrsetcmp(fs->fs_name, fs->fs_list, fcachetab)) { + case -1: + ns_error(ns_log_default, + "check_hints: no A records for %s class %d in hints", + fs->fs_name[0] ? fs->fs_name : ".", + fs->fs_class); + break; + case 1: + ns_warning(ns_log_default, + "check_hints: A records for %s class %d do not match hint records", + fs->fs_name[0] ? fs->fs_name : ".", + fs->fs_class); + break; + case 0: + break; + default: + ns_error(ns_log_default, + "check_hints: unexpected response from rrsetcmp"); + break; + } + break; + } + + if (fs->fs_name == NULL) + ns_debug(ns_log_default, 2, + "check_hints: no A records for %s", + dbp->db_dp->d_data); + + dbp = dbp->db_next; + } +} + +static void +rrsetupdate(struct flush_set * flushset, int flags, struct sockaddr_in from, + int updatettl) { + struct flush_set *fs = flushset; + struct db_list *dbp, *odbp; + int n; + void *state = NULL; + + while (fs->fs_name) { + ns_debug(ns_log_default, 2, "rrsetupdate: %s", + fs->fs_name[0] ? fs->fs_name : "."); + if ((n = rrsetcmp(fs->fs_name, fs->fs_list, hashtab)) && + ttlcheck(fs->fs_name, fs->fs_list, 0)) { + if (n > 0) + flushrrset(fs, from); + + dbp = fs->fs_list; + while (dbp) { + n = db_set_update(fs->fs_name, dbp->db_dp, + &state, flags, + &hashtab, from, NULL, + 0, NULL); + ns_debug(ns_log_default, 3, + "rrsetupdate: %s %d", + fs->fs_name[0] ? fs->fs_name : ".", + n); + odbp = dbp; + dbp = dbp->db_next; + db_detach(&odbp->db_dp); + memput(odbp, sizeof *odbp); + } + ns_debug(ns_log_default, 3, + "rrsetupdate: %s %d", + fs->fs_name[0] ? fs->fs_name : ".", n); + } else { + if ((n == 0) && updatettl) + (void)ttlcheck(fs->fs_name,fs->fs_list, 1); + dbp = fs->fs_list; + while (dbp) { + db_detach(&dbp->db_dp); + odbp = dbp; + dbp = dbp->db_next; + memput(odbp, sizeof *odbp); + } + } + fs->fs_list = NULL; + fs++; + } + n = db_set_update(NULL, NULL, &state, flags, &hashtab, from, + NULL, 0, NULL); +} + +static void +flushrrset(struct flush_set * fs, struct sockaddr_in from) { + struct databuf *dp; + int n; + + ns_debug(ns_log_default, 2, "flushrrset(%s, %s, %s, %d)", + fs->fs_name[0]?fs->fs_name:".", p_type(fs->fs_type), + p_class(fs->fs_class), fs->fs_cred); + dp = savedata(fs->fs_class, fs->fs_type, 0, NULL, 0); + dp->d_zone = DB_Z_CACHE; + dp->d_cred = fs->fs_cred; + dp->d_clev = 0; + do { + n = db_update(fs->fs_name, dp, NULL, NULL, DB_DELETE, hashtab, + from); + ns_debug(ns_log_default, 3, "flushrrset: %d", n); + } while (n == OK); + db_detach(&dp); +} + +static void +free_flushset(struct flush_set *flushset, int flushset_size) { + struct flush_set *fs; + struct db_list *dbl; + + for (fs = flushset; fs->fs_name != NULL; fs++) { + fs->fs_name = freestr(fs->fs_name); + while ((dbl = fs->fs_list) != NULL) { + fs->fs_list = dbl->db_next; + dbl->db_next = NULL; + db_detach(&dbl->db_dp); + memput(dbl, sizeof(*dbl)); + } + } + memput(flushset, flushset_size); +} + +/* + * This is best thought of as a "cache invalidate" function. + * It is called whenever a piece of data is determined to have + * become invalid either through a timeout or a validation + * failure. It is better to have no information, than to + * have partial information you pass off as complete. + */ +void +delete_all(struct namebuf *np, int class, int type) { + struct databuf *dp, *pdp; + + ns_debug(ns_log_default, 3, "delete_all(%p:\"%s\" %s %s)", + np, NAME(*np), p_class(class), p_type(type)); + pdp = NULL; + dp = np->n_data; + while (dp != NULL) { + if (dp->d_zone == DB_Z_CACHE && (dp->d_flags & DB_F_HINT) == 0 + && match(dp, class, type)) { + dp = rm_datum(dp, np, pdp, NULL); + continue; + } + pdp = dp; + dp = dp->d_next; + } +} + +/* delete_stale(np) + * for all RRs associated with this name, check for staleness (& delete) + * arguments: + * np = pointer to namebuf to be cleaned. + * returns: + * number of RRs associated with this name. + * side effects: + * delete_all() can be called, freeing memory and relinking chains. + */ +int +delete_stale(np) + struct namebuf *np; +{ + struct databuf *dp; + int count; + again: + count = 0; + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (dp->d_zone == DB_Z_CACHE && stale(dp)) { + delete_all(np, dp->d_class, dp->d_type); + goto again; + } + count++; + } + return (count); +} + + +/* + * Adjust answer message so that it fits in outlen. Set tc if required. + * + * If outlen = msglen, can be used to verify qdcount, ancount, nscount + * and arcount. + * + * return new length + */ + +int +trunc_adjust(u_char *msg, int msglen, int outlen) { + register HEADER *hp; + u_int qdcount, ancount, nscount, arcount, dlen; + u_char *cp = msg, *cp1, *eom_in, *eom_out; + int n; + + eom_in = msg + msglen; + eom_out = msg + outlen; + + hp = (HEADER *)msg; + qdcount = ntohs(hp->qdcount); + ancount = ntohs(hp->ancount); + nscount = ntohs(hp->nscount); + arcount = ntohs(hp->arcount); + cp += HFIXEDSZ; + + while ((qdcount || ancount || nscount || arcount) && + cp < eom_in && cp < eom_out) { + + cp1 = cp; /* use temporary in case we break */ + + n = dn_skipname(cp1, eom_in); + if (n < 0) + break; + cp1 += n + 2 * INT16SZ; /* type, class */ + + if (!qdcount) { + cp1 += INT32SZ; /* ttl */ + if (cp1 + INT16SZ > eom_in) + break; + GETSHORT(dlen, cp1); + cp1 += dlen; + } + + if (cp1 > eom_in || cp1 > eom_out) + break; + + cp = cp1; + + if (qdcount) + qdcount--; + else if (ancount) + ancount--; + else if (nscount) + nscount--; + else + arcount--; + } + + if (qdcount || ancount || nscount || arcount) { + ns_debug(ns_log_default, 1, + "trunc_adjust:%s %d %d %d %d %d, %d %d %d %d %d", + hp->tc?" tc":"", msglen, + ntohs(hp->qdcount), ntohs(hp->ancount), + ntohs(hp->nscount), ntohs(hp->arcount), + cp-msg, qdcount, ancount, nscount, arcount); + hp->tc = 1; + hp->qdcount = htons(ntohs(hp->qdcount) - qdcount); + hp->ancount = htons(ntohs(hp->ancount) - ancount); + hp->nscount = htons(ntohs(hp->nscount) - nscount); + hp->arcount = htons(ntohs(hp->arcount) - arcount); + } + ENSURE(cp <= eom_out); + return (cp - msg); +} + +/* + * mark the server "from" bad in the qp structure so it won't be retried. + */ +static int +mark_noedns(struct qinfo *qp, struct sockaddr_in from, int cache) { + int i; + + for (i = 0; i < (int)qp->q_naddr; i++) + if (ina_equal(qp->q_addr[i].ns_addr.sin_addr, from.sin_addr)) { + if (qp->q_addr[i].noedns) + return (1); + if (qp->q_addr[i].nsdata && cache) + qp->q_addr[i].nsdata->d_noedns = 1; + qp->q_addr[i].noedns = 1; + break; + } + return (0); +} + +static void +mark_bad(struct qinfo *qp, struct sockaddr_in from) { + int i; + + for (i = 0; i < (int)qp->q_naddr; i++) + if (ina_equal(qp->q_addr[i].ns_addr.sin_addr, from.sin_addr)) + qp->q_addr[i].nretry = MAXRETRY; +} + +static void +mark_lame(struct qinfo *qp, struct sockaddr_in from) { + int i; + + for (i = 0; i < (int)qp->q_naddr; i++) + if (ina_equal(qp->q_addr[i].ns_addr.sin_addr, from.sin_addr) && + qp->q_addr[i].ns != NULL) { + qp->q_addr[i].ns->d_flags |= DB_F_LAME; + db_lame_add(qp->q_domain, + (char*)qp->q_addr[i].ns->d_data, + tt.tv_sec + server_options->lame_ttl); + } +} + +/* + * Retry the message if and only if from matches where the query was + * last sent to. The code does not handle responses sent from the + * wrong interface an a multihomed server. + */ +static void +fast_retry(struct qinfo *qp, struct sockaddr_in from, int samehost) { + if (ina_equal(qp->q_addr[qp->q_curaddr].ns_addr.sin_addr, + from.sin_addr)) + retry(qp, samehost); +} + +static void +add_related_additional(char *name) { + int i; + + if (num_related >= MAX_RELATED - 1) + return; + for (i = 0; i < num_related; i++) + if (ns_samename(name, related[i]) == 1) { + (void)freestr(name); + return; + } + related[num_related++] = name; +} + +static void +free_related_additional() { + int i; + + for (i = 0; i < num_related; i++) + related[i] = freestr(related[i]); + num_related = 0; +} + +static int +related_additional(char *name) { + int i; + + for (i = 0; i < num_related; i++) + if (ns_samename(name, related[i]) == 1) + return (1); + return (0); +} + +static void +freestr_maybe(char **tname) { + if (tname == NULL || *tname == NULL) + return; + *tname = freestr(*tname); +} + +/* + * Match a request namebuf against the configured rrset-order info. First + * match wins. There is an implicit '*.' at the front to the ordering names. + */ +static enum ordering +match_order(const struct namebuf *np, int class, int type) { + rrset_order_list orders = server_options->ordering; + rrset_order_element roe; + + if (orders == NULL) + return (DEFAULT_ORDERING); + + for (roe = orders->first ; roe != NULL ; roe = roe->next) { + if (roe->class != C_ANY && roe->class != class) + continue; + if (roe->type != T_ANY && roe->type != type) + continue; + + if (match_name(np, roe->name, strlen(roe->name)) == 0) { + return (roe->order); + } + } + + /* none matched so use default */ + return (DEFAULT_ORDERING); +} + +/* Do a simple compare of the NP data against the given NAME, recursively + * looking at the NP parent if necessary. NAMELEN is the length of the NAME + * that needs to be matched. Matching happen from right to left. Returns -1 + * on failure, on success the index of the first character of the matched + * portion of the string is returned. In the first level call a return + * value of 0 is of interest. + */ +static int +match_name(const struct namebuf *np, const char *name, size_t namelen) +{ + int matched ; + + if (name[0] == '*' && name[1] == '\0') + return 0; + + if (np->n_parent != NULL) { /* recurse to end of np list */ + matched = match_name(np->n_parent,name,namelen); + } else { + matched = namelen; + } + + if (matched > 0) { + int labellen = NAMELEN(*np); + char pch; + const char *start; + + if (labellen > matched) { + return -1; + } else if (labellen < matched) { + /* string is longer than this namebuf's data, so + make sure there's a period before the end of the + match so we don't just match a suffix. */ + start = name + (matched - labellen); + pch = start[-1]; + if (pch != '.') { + return -1; + } + } else { + start = name ; + } + + if (strncasecmp(start, NAME(*np), labellen) == 0) { + /* looking good. tell our caller what portion of + the tail of string has been matched */ + if (start == name) + return (0) ; + else + return (start - name - 1); /* matched '.' too */ + } else { + return (-1); + } + } + + return (matched); +} + Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_resp.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/db_glue.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/db_glue.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/db_glue.c (revision 109985) @@ -0,0 +1,642 @@ +#if !defined(lint) && !defined(SABER) +static const char sccsid[] = "@(#)db_glue.c 4.4 (Berkeley) 6/1/90"; +static const char rcsid[] = "$Id: db_glue.c,v 8.47 2002/05/18 01:02:54 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986, 1988 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "port_after.h" + +#include "named.h" + +struct valuelist { + struct valuelist * next; + struct valuelist * prev; + char * name; + char * proto; + int port; +}; +static struct valuelist *servicelist, *protolist; + +void +buildservicelist() { + struct servent *sp; + struct valuelist *slp; + +#ifdef MAYBE_HESIOD + setservent(0); +#else + setservent(1); +#endif + while ((sp = getservent()) != NULL) { + slp = (struct valuelist *)memget(sizeof(struct valuelist)); + if (!slp) + panic("memget(servent)", NULL); + slp->name = savestr(sp->s_name, 1); + slp->proto = savestr(sp->s_proto, 1); + slp->port = ntohs((u_int16_t)sp->s_port); /* host byt order */ + slp->next = servicelist; + slp->prev = NULL; + if (servicelist) + servicelist->prev = slp; + servicelist = slp; + } + endservent(); +} + +void +destroyservicelist() { + struct valuelist *slp, *slp_next; + + for (slp = servicelist; slp != NULL; slp = slp_next) { + slp_next = slp->next; + slp->name = freestr(slp->name); + slp->proto = freestr(slp->proto); + memput(slp, sizeof *slp); + } + servicelist = NULL; +} + +void +buildprotolist() { + struct protoent *pp; + struct valuelist *slp; + +#ifdef MAYBE_HESIOD + setprotoent(0); +#else + setprotoent(1); +#endif + while ((pp = getprotoent()) != NULL) { + slp = (struct valuelist *)memget(sizeof(struct valuelist)); + if (!slp) + panic("memget(protoent)", NULL); + slp->name = savestr(pp->p_name, 1); + slp->port = pp->p_proto; /* host byte order */ + slp->next = protolist; + slp->prev = NULL; + if (protolist) + protolist->prev = slp; + protolist = slp; + } + endprotoent(); +} + +void +destroyprotolist() { + struct valuelist *plp, *plp_next; + + for (plp = protolist; plp != NULL; plp = plp_next) { + plp_next = plp->next; + plp->name = freestr(plp->name); + memput(plp, sizeof *plp); + } + protolist = NULL; +} + +static int +findservice(const char *s, struct valuelist **list) { + struct valuelist *lp = *list; + int n; + + for (; lp != NULL; lp = lp->next) + if (strcasecmp(lp->name, s) == 0) { + if (lp != *list) { + lp->prev->next = lp->next; + if (lp->next) + lp->next->prev = lp->prev; + (*list)->prev = lp; + lp->next = *list; + *list = lp; + } + return (lp->port); /* host byte order */ + } + if (sscanf(s, "%d", &n) != 1 || n <= 0) + n = -1; + return (n); +} + +/* + * Convert service name or (ascii) number to int. + */ +int +servicenumber(const char *p) { + return (findservice(p, &servicelist)); +} + +/* + * Convert protocol name or (ascii) number to int. + */ +int +protocolnumber(const char *p) { + return (findservice(p, &protolist)); +} + +static struct servent * +cgetservbyport(u_int16_t port, const char *proto) { /* Host byte order. */ + struct valuelist **list = &servicelist; + struct valuelist *lp = *list; + static struct servent serv; + + port = ntohs(port); + for (; lp != NULL; lp = lp->next) { + if (port != (u_int16_t)lp->port) /* Host byte order. */ + continue; + if (strcasecmp(lp->proto, proto) == 0) { + if (lp != *list) { + lp->prev->next = lp->next; + if (lp->next) + lp->next->prev = lp->prev; + (*list)->prev = lp; + lp->next = *list; + *list = lp; + } + serv.s_name = lp->name; + serv.s_port = htons((u_int16_t)lp->port); + serv.s_proto = lp->proto; + return (&serv); + } + } + return (0); +} + +static struct protoent * +cgetprotobynumber(int proto) { /* Host byte order. */ + struct valuelist **list = &protolist; + struct valuelist *lp = *list; + static struct protoent prot; + + for (; lp != NULL; lp = lp->next) + if (lp->port == proto) { /* Host byte order. */ + if (lp != *list) { + lp->prev->next = lp->next; + if (lp->next) + lp->next->prev = lp->prev; + (*list)->prev = lp; + lp->next = *list; + *list = lp; + } + prot.p_name = lp->name; + prot.p_proto = lp->port; /* Host byte order. */ + return (&prot); + } + return (0); +} + +const char * +protocolname(int num) { + static char number[8]; + struct protoent *pp; + + pp = cgetprotobynumber(num); + if (pp == 0) { + (void) sprintf(number, "%d", num); + return (number); + } + return (pp->p_name); +} + +const char * +servicename(u_int16_t port, const char *proto) { /* Host byte order. */ + static char number[8]; + struct servent *ss; + + ss = cgetservbyport(htons(port), proto); + if (ss == 0) { + (void) sprintf(number, "%d", port); + return (number); + } + return (ss->s_name); +} + +static struct map map_class[] = { + { "in", C_IN }, + { "chaos", C_CHAOS }, + { "hs", C_HS }, + { NULL, 0 } +}; + +int +get_class(const char *class) { + const struct map *mp; + + if (isdigit(*class)) + return (atoi(class)); + for (mp = map_class; mp->token != NULL; mp++) + if (strcasecmp(class, mp->token) == 0) + return (mp->val); + return (C_IN); +} + +/* rm_datum(dp, np, pdp, savedpp) + * remove datum 'dp' from name 'np'. pdp is previous data pointer. + * if savedpp is not NULL, and compiled with BIND_UPDATE, save + * datum dp there rather than freeing the memory (caller will take + * care of freeing it) + * return value: + * "next" field from removed datum, suitable for relinking + */ +struct databuf * +rm_datum(struct databuf *dp, struct namebuf *np, struct databuf *pdp, + struct databuf **savedpp) { + struct databuf *ndp = dp->d_next; + + ns_debug(ns_log_db, 3, "rm_datum(%lx, %lx, %lx, %lx) -> %lx", + (u_long)dp, (u_long)np->n_data, (u_long)pdp, + (u_long)savedpp, (u_long)ndp); + if ((dp->d_flags & DB_F_ACTIVE) == 0) + panic("rm_datum: DB_F_ACTIVE not set", NULL); + if (pdp == NULL) + np->n_data = ndp; + else + pdp->d_next = ndp; + if (savedpp != NULL) { + /* mark deleted or pending deletion */ + dp->d_mark |= D_MARK_DELETED; + dp->d_next = *savedpp; + DRCNTINC(dp); + *savedpp = dp; + } else + dp->d_next = NULL; + dp->d_flags &= ~DB_F_ACTIVE; + db_detach(&dp); + return (ndp); +} + +/* rm_name(np, he, pnp) + * remove name 'np' from parent 'pp'. pnp is previous name pointer. + * return value: + * "next" field from removed name, suitable for relinking. + */ +struct namebuf * +rm_name(struct namebuf *np, struct namebuf **pp, struct namebuf *pnp) { + struct namebuf *nnp = np->n_next; + const char *msg; + + /* verify */ + if ( (np->n_data != NULL && (msg = "data") != NULL) + || (np->n_hash != NULL && (msg = "hash") != NULL) + ) { + ns_panic(ns_log_db, 1, "rm_name(%p(%s)): non-nil %s pointer", + np, NAME(*np), msg); + } + + /* unlink */ + if (pnp) + pnp->n_next = nnp; + else + *pp = nnp; + + /* deallocate */ + memput(np, NAMESIZE(NAMELEN(*np))); + + /* done */ + return (nnp); +} + +void +rm_hash(struct hashbuf *htp) { + REQUIRE(htp != NULL); + REQUIRE(htp->h_cnt == 0); + + memput(htp, HASHSIZE(htp->h_size)); +} + +/* + * Get the domain name of 'np' and put in 'buf'. Bounds checking is done. + */ +void +getname(struct namebuf *np, char *buf, int buflen) { + char *cp; + int i; + + cp = buf; + while (np != NULL) { + i = (int) NAMELEN(*np); + if (i + 1 >= buflen) { + strcpy(buf, "Name_Too_Long"); + return; + } + if (cp != buf) + *cp++ = '.'; + memcpy(cp, NAME(*np), i); + cp += i; + buflen -= i + 1; + np = np->n_parent; + } + *cp = '\0'; +} + +/* u_int + * nhash(name) + * compute hash for this name and return it; ignore case differences + * note: + * this logic is intended to produce the same result as nlookup()'s. + */ +u_int +nhash(const char *name) { + u_char ch; + u_int hval; + + hval = 0; + while ((ch = (u_char)*name++) != (u_char)'\0') + HASHIMILATE(hval, ch); + return (hval); +} + +static void +db_freedata(struct databuf *dp) { + int bytes = BIND_DATASIZE(dp->d_size); + + if (dp->d_rcnt != 0) + panic("db_freedata: d_rcnt != 0", NULL); + if ((dp->d_flags & (DB_F_ACTIVE|DB_F_FREE)) != 0) + panic("db_freedata: %s set", + (dp->d_flags & DB_F_FREE) != 0 ? "DB_F_FREE" : + "DB_F_ACTIVE"); + if (dp->d_next != NULL) + panic("db_free: d_next != NULL", NULL); + dp->d_flags |= DB_F_FREE; +#ifdef CHECK_MAGIC + dp->d_magic = 0; +#endif + memput(dp, bytes); +} + +void +db_detach(struct databuf **dpp) { + struct databuf *dp; + + INSIST(dpp != NULL && *dpp != NULL); + dp = *dpp; +#ifdef CHECK_MAGIC + INSIST(dp->d_magic == DATABUF_MAGIC); +#endif + + DRCNTDEC(dp); + if (dp->d_rcnt == 0) + db_freedata(dp); + *dpp = NULL; +} + +struct lame_hash { + struct lame_hash *next; + char *zone; + char *server; + time_t when; + unsigned int hval; +} **lame_hash = NULL; + +static int lame_hash_size = 0; +static int lame_hash_cnt = 0; + +void +db_lame_add(char *zone, char *server, time_t when) { + unsigned int hval = nhash(zone); + struct lame_hash *last, *this; + struct lame_hash **new; + int n; + int newsize; + + db_lame_clean(); + + /* grow / initalise hash table */ + if (lame_hash_cnt >= lame_hash_size) { + if (lame_hash_size == 0) + newsize = hashsizes[0]; + else { + for (n = 0; (newsize = hashsizes[n++]) != 0; (void)NULL) + if (lame_hash_size == newsize) { + newsize = hashsizes[n]; + break; + } + if (newsize == 0) + newsize = lame_hash_size * 2 + 1; + } + new = memget(newsize * sizeof this); + if (new == NULL) + return; + memset(new, 0, newsize * sizeof this); + for (n = 0 ; n < lame_hash_size; n++) { + this = lame_hash[n]; + while (this) { + last = this; + this = this->next; + last->next = new[hval%newsize]; + new[hval%newsize] = last; + } + } + if (lame_hash != NULL) + memput(lame_hash, lame_hash_size * sizeof this); + lame_hash = new; + lame_hash_size = newsize; + } + + last = NULL; + this = lame_hash[hval%lame_hash_size]; + while (this) { + if ((ns_samename(this->server, server) == 1) && + (ns_samename(this->zone, zone) == 1)) { + this->when = when; + return; + } + last = this; + this = this->next; + } + this = memget(sizeof *this); + if (this == NULL) + return; + this->server = savestr(server, 0); + this->zone = savestr(zone, 0); + if (this->server == NULL || this->zone == NULL) { + if (this->server != NULL) + this->server = freestr(this->server); + if (this->zone != NULL) + this->zone = freestr(this->zone); + memput(this, sizeof *this); + return; + } + this->when = when; + this->hval = hval; + this->next = NULL; + if (last != NULL) + last->next = this; + else + lame_hash[hval%lame_hash_size] = this; + lame_hash_cnt++; +} + +time_t +db_lame_find(char *zone, struct databuf *dp) { + unsigned int hval = nhash(zone); + struct lame_hash *this; + + if (lame_hash_size == 0) { + /* db_lame_destroy() must have been called. */ + dp->d_flags &= ~DB_F_LAME; + return (0); + } + + db_lame_clean(); /* Remove expired record so that we can + * clear DB_F_LAME when there are no + * additions. */ + + this = lame_hash[hval % lame_hash_size]; + while (this) { + if ((ns_samename(this->server, (char*)dp->d_data) == 1) && + (ns_samename(this->zone, zone) == 1)) + return (this->when); + this = this->next; + } + dp->d_flags &= ~DB_F_LAME; + return (0); +} + +void +db_lame_clean(void) { + int i; + struct lame_hash *last, *this; + + for (i = 0 ; i < lame_hash_size; i++) { + last = NULL; + this = lame_hash[i]; + while (this != NULL) { + if (this->when < tt.tv_sec) { + this->zone = freestr(this->zone); + this->server = freestr(this->server); + if (last != NULL) { + last->next = this->next; + memput(this, sizeof *this); + this = last->next; + } else { + lame_hash[i] = this->next; + memput(this, sizeof *this); + this = lame_hash[i]; + } + lame_hash_cnt--; + } else { + last = this; + this = this->next; + } + } + } +} + +void +db_lame_destroy(void) { + int i; + struct lame_hash *last, *this; + + if (lame_hash_size == 0) + return; + + for (i = 0 ; i < lame_hash_size; i++) { + this = lame_hash[i]; + while (this != NULL) { + last = this; + this = this->next; + last->zone = freestr(last->zone); + last->server = freestr(last->server); + memput(last, sizeof *this); + } + } + memput(lame_hash, lame_hash_size * sizeof this); + lame_hash_cnt = 0; + lame_hash_size = 0; + lame_hash = NULL; +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/db_glue.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/db_save.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/db_save.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/db_save.c (revision 109985) @@ -0,0 +1,215 @@ +#if !defined(lint) && !defined(SABER) +static const char sccsid[] = "@(#)db_save.c 4.16 (Berkeley) 3/21/91"; +static const char rcsid[] = "$Id: db_save.c,v 8.30 2002/05/18 01:02:56 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * Buffer allocation and deallocation routines. + */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "port_after.h" + +#include "named.h" + +/* + * Allocate a name buffer & save name. + */ +struct namebuf * +savename(const char *name, int len) { + struct namebuf *np; + + /* + * Note that MAXLABEL * 4 < 256, so a single length byte is enough. + * Also, we use MAXLABEL * 4 because each label character can + * expand into up to four characters when rendered in canonical + * form. + */ + INSIST(len >= 0 && len <= (MAXLABEL * 4)); + np = (struct namebuf *) memget(NAMESIZE(len)); + if (np == NULL) + panic("savename: memget", NULL); + memset(np, 0, NAMESIZE(len)); + NAMELEN(*np) = (unsigned)len; + memcpy(NAME(*np), name, len); + NAME(*np)[len] = '\0'; + return (np); +} + +/* + * Allocate a data buffer & save data. + */ +struct databuf * +savedata(class, type, ttl, data, size) + int class, type; + u_int32_t ttl; + u_char *data; + int size; +{ + struct databuf *dp; + int bytes = BIND_DATASIZE(size); + + dp = (struct databuf *)memget(bytes); + if (dp == NULL) + panic("savedata: memget", NULL); + if (class > CLASS_MAX) + panic("savedata: bad class", NULL); + memset(dp, 0, bytes); + dp->d_next = NULL; + dp->d_type = type; + dp->d_class = class; + dp->d_ttl = ttl; + dp->d_size = size; + dp->d_mark = 0; + dp->d_flags = 0; + dp->d_cred = 0; + dp->d_clev = 0; + dp->d_secure = DB_S_INSECURE; + dp->d_rcode = NOERROR; + dp->d_addr.s_addr = htonl(0); + dp->d_nstime = 0; + dp->d_rcnt = 1; +#ifdef CHECK_MAGIC + dp->d_magic = DATABUF_MAGIC; +#endif + memcpy(dp->d_data, data, dp->d_size); + return (dp); +} + +/* + * Allocate a data buffer & save data. + */ +struct hashbuf * +savehash(oldhtp) + struct hashbuf *oldhtp; +{ + struct hashbuf *htp; + struct namebuf *np, *nnp, **hp; + int n, newsize; + + if (oldhtp == NULL) + newsize = hashsizes[0]; + else { + for (n = 0; (newsize = hashsizes[n++]) != 0; (void)NULL) + if (oldhtp->h_size == newsize) { + newsize = hashsizes[n]; + break; + } + if (newsize == 0) + newsize = oldhtp->h_size * 2 + 1; + } + ns_debug(ns_log_db, 4, "savehash GROWING to %d", newsize); + htp = (struct hashbuf *) memget(HASHSIZE(newsize)); + if (htp == NULL) + ns_panic(ns_log_db, 0, "savehash: %s", strerror(errno)); + htp->h_size = newsize; + memset(htp->h_tab, 0, newsize * sizeof(struct namebuf *)); + if (oldhtp == NULL) { + htp->h_cnt = 0; + return (htp); + } + ns_debug(ns_log_db, 4, "savehash(%#lx) cnt=%d, sz=%d, newsz=%d", + (u_long)oldhtp, oldhtp->h_cnt, oldhtp->h_size, newsize); + htp->h_cnt = oldhtp->h_cnt; + for (n = 0; n < oldhtp->h_size; n++) { + for (np = oldhtp->h_tab[n]; np != NULL; np = nnp) { + nnp = np->n_next; + hp = &htp->h_tab[np->n_hashval % htp->h_size]; + np->n_next = *hp; + *hp = np; + } + } + oldhtp->h_cnt = 0; /* Keep rm_hash() happy. */ + rm_hash(oldhtp); + return (htp); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/db_save.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/db_tsig.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/db_tsig.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/db_tsig.c (revision 109985) @@ -0,0 +1,158 @@ + +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: db_tsig.c,v 8.8 2002/05/21 02:34:32 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986, 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "port_after.h" + +#include "named.h" + +typedef struct { + DST_KEY *key; + void *ctx; +} tsig_axfr_state; + +#define TSIG_ALG_MD5 "HMAC-MD5.SIG-ALG.REG.INT" +#define TSIG_ALG_MD5_SHORT "hmac-md5" + +const char * +tsig_alg_name(int value) { + if (value == KEY_HMAC_MD5) + return(TSIG_ALG_MD5); + else + return(NULL); +} + +int +tsig_alg_value(char *name) { + if (ns_samename(name, TSIG_ALG_MD5) == 1 || + strcasecmp(name, TSIG_ALG_MD5_SHORT) == 0) + return (KEY_HMAC_MD5); + else + return (-1); +} + +DST_KEY * +tsig_key_from_addr(struct in_addr addr) { + server_info si = find_server(addr); + if (si == NULL || si->key_list == NULL || si->key_list->first == NULL) + return(NULL); + return(si->key_list->first->key); +} + +struct tsig_record * +new_tsig(DST_KEY *key, u_char *sig, int siglen) { + struct tsig_record *tsig; + + if (siglen > TSIG_SIG_SIZE) + return(NULL); + tsig = memget(sizeof(struct tsig_record)); + if (tsig == NULL) + return(NULL); + tsig->key = key; + tsig->siglen = siglen; + memcpy(tsig->sig, sig, siglen); + return(tsig); +} + +void +free_tsig(struct tsig_record *tsig) { + if (tsig == NULL) + return; + memput(tsig, sizeof(struct tsig_record)); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/db_tsig.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/named.conf =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/named.conf (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/named.conf (revision 109985) @@ -0,0 +1,462 @@ +/* + * This is a worthless, nonrunnable example of a named.conf file that has + * every conceivable syntax element in use. We use it to test the parser. + * It could also be used as a conceptual template for users of new features. + */ + +/* + * C-style comments are OK + */ + +// So are C++-style comments + +# So are shell-style comments + +// watch out for ";" -- it's important! + +key sample_key { // for TSIG + algorithm hmac-md5; // hmac-md5 is the supported algorithm + secret "abcdefgh"; // base 64 encoded secret +}; + +key key2 { + algorithm hmac-md5; + secret "87654321"; +}; + +options { + directory "."; // use current directory + named-xfer "/usr/libexec/named-xfer"; // _PATH_XFER + dump-file "named_dump.db"; // _PATH_DUMPFILE + pid-file "/var/run/named.pid"; // _PATH_PIDFILE + statistics-file "named.stats"; // _PATH_STATS + memstatistics-file "named.memstats"; // _PATH_MEMSTATS + check-names master fail; + check-names slave warn; + check-names response ignore; + host-statistics no; + deallocate-on-exit no; // Painstakingly deallocate all + // objects when exiting instead of + // letting the OS clean up for us. + // Useful a memory leak is suspected. + // Final statistics are written to the + // memstatistics-file. + datasize default; + stacksize default; + coresize default; + files unlimited; + recursion yes; + fetch-glue yes; + fake-iquery no; + notify yes; // send NOTIFY messages. You can set + // notify on a zone-by-zone + // basis in the "zone" statement + // see (below) + // notify explicit; // only sent the notifies to the + // also-notify list + serial-queries 4; // number of parallel SOA queries + // we can have outstanding for master + // zone change testing purposes + auth-nxdomain yes; // always set AA on NXDOMAIN. + // don't set this to 'no' unless + // you know what you're doing -- older + // servers won't like it. + multiple-cnames no; // if yes, then a name my have more + // than one CNAME RR. This use + // is non-standard and is not + // recommended, but it is available + // because previous releases supported + // it and it was used by large sites + // for load balancing. + allow-query { any; }; + allow-transfer { any; }; + transfers-in 10; // DEFAULT_XFERS_RUNNING, cannot be + // set > than MAX_XFERS_RUNNING (20) + transfers-per-ns 2; // DEFAULT_XFERS_PER_NS + transfers-out 0; // not implemented + max-transfer-time-in 120; // MAX_XFER_TIME; the default number + // of minutes an inbound zone transfer + // may run. May be set on a per-zone + // basis. + /* + * The "transfer-format" option specifies the way outbound zone + * transfers (i.e. from us to them) are formatted. Two values are + * allowed: + * + * one-answer Each RR gets its own DNS message. + * This format is not very efficient, + * but is widely understood. All + * versions of BIND prior to 8.1 generate + * this format for outbound zone + * and require it on inbound transfers. + * + * many-answers As many RRs as will fit are put into + * each DNS message. This format is + * the most efficient, but is only known + * to work with BIND 8. Patches to + * BIND 4.9.5 named-xfer that enable it + * to understand 'many-answers' will be + * available. + * + * If you are going to be doing zone transfers to older servers, you + * shouldn't use 'many-answers'. 'transfer-format' may also be set + * on a host-by-host basis using the 'server' statement (see below). + */ + transfer-format one-answer; + query-source address * port *; + /* + * The "forward" option is only meaningful if you've defined + * forwarders. "first" gives the normal BIND + * forwarding behavior, i.e. ask the forwarders first, and if that + * doesn't work then do the full lookup. You can also say + * "forward only;" which is what used to be specified with + * "slave" or "options forward-only". "only" will never attempt + * a full lookup; only the forwarders will be used. + */ + forward first; + forwarders { }; // default is no forwarders + /* + * Here's a forwarders example that isn't trivial + */ + /* + forwarders { + 1.2.3.4; + 5.6.7.8; + }; + */ + topology { localhost; localnets; }; // prefer local nameservers + /* + * Here's a more complicated topology example; it's commented out + * because only one topology block is allowed. + * + topology { + 10/8; // prefer network 10.0.0.0 + // netmask 255.0.0.0 most + !1.2.3/24; // don't like 1.2.3.0 netmask + // 255.255.255.0 at all + { 1.2/16; 3/8; }; // like 1.2.0.0 netmask 255.255.0.0 + // and 3.0.0.0 netmask 255.0.0.0 + // equally well, but less than 10/8 + }; + */ + + listen-on port 53 { any; }; // listen for queries on port 53 on + // any interface on the system + // (i.e. all interfaces). The + // "port 53" is optional; if you + // don't specify a port, port 53 + // is assumed. + /* + * Multiple listen-on statements are allowed. Here's a more + * complicated example: + */ + /* + listen-on { 5.6.7.8; }; // listen on port 53 on interface + // 5.6.7.8 + listen-on port 1234 { // listen on port 1234 on any + !1.2.3.4; // interface on network 1.2.3 + 1.2.3/24; // netmask 255.255.255.0, except for + }; // interface 1.2.3.4. + */ + + /* + * Interval Timers + */ + cleaning-interval 60; // clean the cache of expired RRs + // every 'cleaning-interval' minutes + interface-interval 60; // scan for new or deleted interfaces + // every 'interface-interval' minutes + statistics-interval 60; // log statistics every + // 'statistics-interval' minutes + /* + * IXFR options + */ + maintain-ixfr-base no; // If yes, keep transaction log file for IXFR + max-ixfr-log-size 20; // Not implemented, maximum size the + // IXFR transaction log file to grow +}; + +/* + * Control listeners, for "ndc". Every nameserver needs at least one. + */ +controls { + inet * port 52 allow { any; }; // a bad idea + unix "/var/run/ndc" perm 0600 owner 0 group 0; // the default +}; + +zone "master.demo.zone" { + type master; // what used to be called "primary" + file "master.demo.zone"; + check-names fail; + allow-update { none; }; + allow-transfer { any; }; + allow-query { any; }; + // notify yes; // send NOTIFY messages for this + // zone? The global option is used + // if "notify" is not specified + // here. + // notify explicit; // only sent the notifies to the + // also-notify list + also-notify { }; // don't notify any nameservers other + // than those on the NS list for this + // zone +}; + +zone "slave.demo.zone" { + type slave; // what used to be called "secondary" + file "slave.demo.zone"; + ixfr-base "slave.demo.zone.ixfr"; // File name for IXFR transaction log file + masters { + 1.2.3.4; // where to zone transfer from + 5.6.7.8 key key2; + }; + transfer-source 10.0.0.53; // fixes multihoming problems + check-names warn; + allow-update { none; }; + allow-transfer { any; }; + allow-query { any; }; + max-transfer-time-in 120; // if not set, global option is used. + also-notify { }; // don't notify any nameservers other + // than those on the NS list for this + // zone +}; + +zone "stub.demo.zone" { + type stub; // stub zones are like slave zones, + // except that only the NS records + // are transferred. + file "stub.demo.zone"; + masters { + 1.2.3.4; // where to zone transfer from + 5.6.7.8; + }; + check-names warn; + allow-update { none; }; + allow-transfer { any; }; + allow-query { any; }; + max-transfer-time-in 120; // if not set, global option is used. +}; + +zone "." { + type hint; // used to be specified w/ "cache" + file "cache.db"; + pubkey 257 255 1 "AQP2fHpZ4VMpKo/jc9Fod821uyfY5p8j5h/Am0V/KpBTMZjdXmp9QJe6yFRoIIzkaNCgTIftASdpXGgCwFB2j2KXP/rick6gvEer5VcDEkLR5Q=="; +}; + +trusted-keys { + . 257 255 1 "AQP2fHpZ4VMpKo/jc9Fod821uyfY5p8j5h/Am0V/KpBTMZjdXmp9QJe6yFRoIIzkaNCgTIftASdpXGgCwFB2j2KXP/rick6gvEer5VcDEkLR5Q=="; +}; + + +acl can_query { !1.2.3/24; any; }; // network 1.2.3.0 mask 255.255.255.0 + // is disallowed; rest are OK +acl can_axfr { 1.2.3.4; can_query; }; // host 1.2.3.4 and any host allowed + // by can_query are OK + +zone "non-default-acl.demo.zone" { + type master; + file "foo"; + allow-query { can_query; }; + allow-transfer { can_axfr; }; + allow-update { + 1.2.3.4; + 5.6.7.8; + }; +}; + +acl key_acl { key sample_key; }; // a request signed with sample_key + +server 1.2.3.4 { + edns no; // if no, we won't send ends queries + // to this server + bogus no; // if yes, we won't query or listen + // to this server + transfer-format one-answer; // set transfer format for this + // server (see the description of + // 'transfer-format' above) + // if not specified, the global option + // will be used + transfers 0; // not implemented + keys { sample_key; key2; }; // for TSIG; sign requests to this + // server with this key + support-ixfr yes; // for IXFR supported by server + // if yes, the listed server talks IXFR +}; + +logging { + /* + * All log output goes to one or more "channels"; you can make as + * many of them as you want. + */ + + channel syslog_errors { // this channel will send errors or + syslog user; // or worse to syslog (user facility) + severity error; + }; + + /* + * Channels have a severity level. Messages at severity levels + * greater than or equal to the channel's level will be logged on + * the channel. In order of decreasing severity, the levels are: + * + * critical a fatal error + * error + * warning + * notice a normal, but significant event + * info an informational message + * debug 1 the least detailed debugging info + * ... + * debug 99 the most detailed debugging info + */ + + /* + * Here are the built-in channels: + * + * channel default_syslog { + * syslog daemon; + * severity info; + * }; + * + * channel default_debug { + * file "named.run"; // note: stderr is used instead + * // of "named.run" if the server + * // is started with the "-f" + * // option. + * severity dynamic; // this means log debugging + * // at whatever debugging level + * // the server is at, and don't + * // log anything if not + * // debugging. + * }; + * + * channel null { // this is the bit bucket; + * file "/dev/null"; // any logging to this channel + * // is discarded. + * }; + * + * channel default_stderr { // writes to stderr + * file ""; // this is illustrative only; + * // there's currently no way + * // of saying "stderr" in the + * // configuration language. + * // i.e. don't try this at home. + * severity info; + * }; + * + * default_stderr only works before the server daemonizes (i.e. + * during initial startup) or when it is running in foreground + * mode (-f command line option). + */ + + /* + * There are many categories, so you can send the logs + * you want to see wherever you want, without seeing logs you + * don't want. Right now the categories are + * + * default the catch-all. many things still + * aren't classified into categories, and + * they all end up here. also, if you + * don't specify any channels for a + * category, the default category is used + * instead. + * config high-level configuration file + * processing + * parser low-level configuration file processing + * queries what used to be called "query logging" + * lame-servers messages like "Lame server on ..." + * statistics + * panic if the server has to shut itself + * down due to an internal problem, it + * logs the problem here (as well as + * in the problem's native category) + * update dynamic update + * ncache negative caching + * xfer-in zone transfers we're receiving + * xfer-out zone transfers we're sending + * db all database operations + * eventlib debugging info from the event system + * (see below) + * packet dumps of packets received and sent + * (see below) + * notify the NOTIFY protocol + * cname messages like "XX points to a CNAME" + * security approved/unapproved requests + * os operating system problems + * insist consistency check failures + * maintenance periodic maintenance + * load zone loading + * response-checks messages like + * "Malformed response ..." + * "wrong ans. name ..." + * "unrelated additional info ..." + * "invalid RR type ..." + * "bad referral ..." + */ + + category parser { + syslog_errors; // you can log to as many channels + default_syslog; // as you want + }; + + category lame-servers { null; }; // don't log these at all + + channel moderate_debug { + severity debug 3; // level 3 debugging to file + file "foo"; // foo + print-time yes; // timestamp log entries + print-category yes; // print category name + print-severity yes; // print severity level + /* + * Note that debugging must have been turned on either + * on the command line or with a signal to get debugging + * output (non-debugging output will still be written to + * this channel). + */ + }; + + /* + * If you don't want to see "zone XXXX loaded" messages but do + * want to see any problems, you could do the following. + */ + channel no_info_messages { + syslog; + severity notice; + }; + + category load { no_info_messages; }; + + /* + * You can also define category "default"; it gets used when no + * "category" statement has been given for a category. + */ + category default { + default_syslog; + moderate_debug; + }; + + /* + * If you don't define category default yourself, the default + * default category will be used. It is + * + * category default { default_syslog; default_debug; }; + */ + + /* + * If you don't define category panic yourself, the default + * panic category will be used. It is + * + * category panic { default_syslog; default_stderr; }; + */ + + /* + * Two categories, 'packet' and 'eventlib', are special. Only one + * channel may be assigned to each of them, and it must be a + * file channel. If you don't define them yourself, they default to + * + * category eventlib { default_debug; }; + * + * category packet { default_debug; }; + */ +}; + +include "filename"; // can't do within a statement Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/named.conf ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_config.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_config.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_config.c (revision 109985) @@ -0,0 +1,3194 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_config.c,v 8.135 2002/05/24 03:04:59 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1999 by Check Point Software Technologies, Inc. + * + * 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 Check Point Software Technologies Incorporated 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 CHECK POINT SOFTWARE TECHNOLOGIES + * INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL CHECK POINT SOFTWARE TECHNOLOGIES INCORPRATED + * 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 SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "port_after.h" + +#ifdef HAVE_GETRUSAGE /* XXX */ +#include +#endif + +#include "named.h" +#include "ns_parseutil.h" + +/* Private. */ + +static int tmpnum = 0; +static int config_initialized = 0; + +static int need_logging_free = 0; +static int default_logging_installed; + +static int options_installed = 0; +static int logging_installed = 0; +static int default_options_installed; + +static char **logging_categories; +static char *current_pid_filename = NULL; + +#define ZONE_SYM_TABLE_SIZE 4973 +static symbol_table zone_symbol_table; + +/* Zones */ + +void +free_zone_timerinfo(struct zoneinfo *zp) { + if (zp->z_timerinfo != NULL) { + zp->z_timerinfo->name = freestr(zp->z_timerinfo->name); + memput(zp->z_timerinfo, sizeof *zp->z_timerinfo); + zp->z_timerinfo = NULL; + } else + ns_error(ns_log_config, "timer for zone '%s' had no timerinfo", + zp->z_origin); +} + +void +free_zone_contents(struct zoneinfo *zp, int undefine_sym) { + INSIST(zp != NULL); + + if (undefine_sym) + undefine_symbol(zone_symbol_table, zp->z_origin, zp->z_class); + if (zp->z_flags & Z_TIMER_SET) { + free_zone_timerinfo(zp); + if (evClearTimer(ev, zp->z_timer) < 0) + ns_error(ns_log_config, + "evClearTimer for zone '%s' failed in ns_init: %s", + zp->z_origin, + strerror(errno)); + } + if (zp->z_origin != NULL) + zp->z_origin = freestr(zp->z_origin); + if (zp->z_source != NULL) + zp->z_source = freestr(zp->z_source); + if (zp->z_ixfr_base != NULL) + zp->z_ixfr_base = freestr(zp->z_ixfr_base); + if (zp->z_ixfr_tmp != NULL) + zp->z_ixfr_tmp = freestr(zp->z_ixfr_tmp); + if (zp->z_update_acl != NULL) + free_ip_match_list(zp->z_update_acl); + zp->z_update_acl = NULL; + if (zp->z_query_acl != NULL) + free_ip_match_list(zp->z_query_acl); + zp->z_query_acl = NULL; + if (zp->z_transfer_acl != NULL) + free_ip_match_list(zp->z_transfer_acl); + zp->z_transfer_acl = NULL; +#ifdef BIND_UPDATE + if (zp->z_updatelog != NULL) + zp->z_updatelog = freestr(zp->z_updatelog); +#endif /* BIND_UPDATE */ +#ifdef BIND_NOTIFY + if (zp->z_also_notify != NULL) + memput(zp->z_also_notify, + zp->z_notify_count * sizeof *zp->z_also_notify); + zp->z_also_notify = NULL; +#endif + if (zp->z_fwdtab != NULL) + free_forwarders(zp->z_fwdtab); + zp->z_fwdtab = NULL; + block_signals(); + if (LINKED(zp, z_reloadlink)) + UNLINK(reloadingzones, zp, z_reloadlink); + unblock_signals(); +} + +static void +release_zone(struct zoneinfo *zp) { + INSIST(zp != NULL); + + free_zone_contents(zp, 0); + memput(zp, sizeof *zp); +} + +struct zoneinfo * +find_zone(const char *name, int class) { + struct zoneinfo *zp; + symbol_value value; + + ns_debug(ns_log_config, 3, "find_zone(%s, %d)", + *name ? name : ".", class); + if (lookup_symbol(zone_symbol_table, name, class, &value)) { + INSIST(value.integer >= 0 && value.integer < nzones); + ns_debug(ns_log_config, 3, "find_zone: existing zone %d", + value.integer); + zp = &zones[value.integer]; + return (zp); + } + ns_debug(ns_log_config, 3, "find_zone: unknown zone"); + return (NULL); +} + +static struct zoneinfo * +new_zone(void) { + struct zoneinfo *zp; + + if (EMPTY(freezones)) + make_new_zones(); + + zp = HEAD(freezones); + UNLINK(freezones, zp, z_freelink); + return (zp); +} + +/* + * Check out a zoneinfo structure and return non-zero if it's OK. + */ +static int +validate_zone(struct zoneinfo *zp) { + char filename[MAXPATHLEN+1]; + + /* Check name */ + if (!res_dnok(zp->z_origin)) { + ns_error(ns_log_config, "invalid zone name '%s'", + zp->z_origin); + return (0); + } + + /* Check class */ + if (zp->z_class == C_ANY || zp->z_class == C_NONE) { + ns_error(ns_log_config, "invalid class %d for zone '%s'", + zp->z_class, zp->z_origin); + return (0); + } + + /* Check type. */ + if (zp->z_type == 0) { + ns_error(ns_log_config, "no type specified for zone '%s'", + zp->z_origin); + return (0); + } + if (zp->z_type == z_cache && ns_samename(zp->z_origin, "") != 1) { + ns_error(ns_log_config, + "only the root zone may be a cache zone (zone '%s')", + zp->z_origin); + return (0); + } + if (zp->z_type == z_hint && ns_samename(zp->z_origin, "") != 1) { + ns_error(ns_log_config, + "only the root zone may be a hint zone (zone '%s')", + zp->z_origin); + return (0); + } + + /* Check filename. */ + if (zp->z_type == z_master && zp->z_source == NULL) { + ns_error(ns_log_config, + "'file' statement missing for master zone %s", + zp->z_origin); + return (0); + } + /* + * XXX We should run filename through an OS-specific + * validator here. + */ + if (zp->z_source != NULL && + strlen(zp->z_source) > MAXPATHLEN) { + ns_error(ns_log_config, "filename too long for zone '%s'", + zp->z_origin); + return (0); + } + + if (zp->z_ixfr_base != NULL && strlen(zp->z_ixfr_base) > MAXPATHLEN) { + ns_error(ns_log_config, "ixfr filename too long for zone '%s'", + zp->z_origin); + return (0); + } + if (zp->z_ixfr_tmp != NULL && strlen(zp->z_ixfr_tmp) > MAXPATHLEN) { + ns_error(ns_log_config, "tmp ixfr filename too long for zone '%s'", + zp->z_origin); + return (0); + } + + /* Check masters */ + if (zp->z_addrcnt != 0) { + if (zp->z_type == z_master || zp->z_type == z_hint || + zp->z_type == z_cache) { + ns_error(ns_log_config, + "'masters' statement present for %s zone '%s'", + (zp->z_type == z_master) ? "master" : + (zp->z_type == z_hint) ? "hint" : "cache", + zp->z_origin); + return (0); + } + } else { + if (zp->z_type == z_slave || zp->z_type == z_stub) { + ns_error(ns_log_config, + "no 'masters' statement for non-master zone '%s'", + zp->z_origin); + return (0); + } + } + + /* Check allow-update and allow-transfer. */ + if (zp->z_update_acl || zp->z_transfer_acl) { + if (zp->z_type != z_master && zp->z_type != z_slave) { + ns_error(ns_log_config, + "'allow-{update,transfer}' option for non-{master,slave} zone '%s'", + zp->z_origin); + return (0); + } + } + + /* Check allow-query. */ + if (zp->z_query_acl) { + if (zp->z_type != z_master && + zp->z_type != z_slave && +#ifdef FORWARD_ALLOWS + zp->z_type != z_forward && +#endif + zp->z_type != z_stub) { + ns_error(ns_log_config, +#ifdef FORWARD_ALLOWS + "'allow-query' option for hint zone '%s'", +#else + "'allow-query' option for non-{master,slave,stub} zone '%s'", +#endif + zp->z_origin); + return (0); + } + } + +#ifdef BIND_NOTIFY + /* Check notify */ + if (zp->z_notify != notify_use_default) { + if (zp->z_type != z_master && zp->z_type != z_slave) { + ns_error(ns_log_config, + "'notify' given for non-master, non-slave zone '%s'", + zp->z_origin); + return (0); + } + } + + /* Check also-notify */ + if (zp->z_notify_count != 0) { + if (zp->z_type != z_master && zp->z_type != z_slave) { + ns_error(ns_log_config, + "'also-notify' given for non-master, non-slave zone '%s'", + zp->z_origin); + return (0); + } + } +#endif + +#ifdef BIND_UPDATE + /* XXX need more checking here */ + if (!zp->z_updatelog && zp->z_source) { + /* XXX OS-specific filename validation here */ + if ((strlen(zp->z_source) + (sizeof ".log" - 1)) > + MAXPATHLEN) { + ns_error(ns_log_config, + "filename too long for dynamic zone '%s'", + zp->z_origin); + return (0); + } + /* this sprintf() is now safe */ + sprintf(filename, "%s.log", zp->z_source); + zp->z_updatelog = savestr(filename, 1); + } + + /* Check forward */ + if (zp->z_optset & OPTION_FORWARD_ONLY) { + if (zp->z_type == z_hint) { + ns_error(ns_log_config, + "'forward' given for hint zone '%s'", + zp->z_origin); + return (0); + } + } + /* Check forwarders */ + if (zp->z_fwdtab) { + if (zp->z_type == z_hint) { + ns_error(ns_log_config, + "'forwarders' given for hint zone '%s'", + zp->z_origin); + return (0); + } + } + + if (zp->z_type == z_master) { + if (!zp->z_soaincrintvl) + zp->z_soaincrintvl = SOAINCRINTVL; + if (!zp->z_dumpintvl) + zp->z_dumpintvl = DUMPINTVL; + if (!zp->z_deferupdcnt) + zp->z_deferupdcnt = DEFERUPDCNT; + } +#endif /* BIND_UPDATE */ + + if (!zp->z_ixfr_base && zp->z_source) { + /* XXX OS-specific filename validation here */ + if ((strlen(zp->z_source) + (sizeof ".ixfr" - 1)) > + MAXPATHLEN) { + ns_error(ns_log_config, + "filename too long for dynamic zone '%s'", + zp->z_origin); + return (0); + } + /* this sprintf() is now safe */ + sprintf(filename, "%s.ixfr", zp->z_source); + zp->z_ixfr_base = savestr(filename, 1); + } + if (!zp->z_ixfr_tmp && zp->z_source) { + /* XXX OS-specific filename validation here */ + if ((strlen(zp->z_source) + (sizeof ".ixfr.tmp" - 1)) > + MAXPATHLEN) { + ns_error(ns_log_config, + "filename too long for dynamic zone '%s'", + zp->z_origin); + return (0); + } + /* this sprintf() is now safe */ + sprintf(filename, "%s.ixfr.tmp", zp->z_source); + zp->z_ixfr_tmp = savestr(filename, 1); + } + + return (1); +} + +/* + * Start building a new zoneinfo structure. Returns an opaque + * zone_config suitable for use by the parser. + */ +zone_config +begin_zone(char *name, int class) { + zone_config zh; + struct zoneinfo *zp; + + /* + * require: name is canonical, class is a valid class + */ + + ns_debug(ns_log_config, 3, "begin_zone('%s', %d)", + (*name == '\0') ? "." : name, class); + + zp = (struct zoneinfo *)memget(sizeof (struct zoneinfo)); + if (zp == NULL) + panic("memget failed in begin_zone", NULL); + memset(zp, 0, sizeof (struct zoneinfo)); + zp->z_origin = name; + zp->z_class = class; + zp->z_checknames = not_set; + if (server_options->flags & OPTION_MAINTAIN_IXFR_BASE) + zp->z_maintain_ixfr_base = 1; + else + zp->z_maintain_ixfr_base = 0; + zp->z_max_log_size_ixfr = server_options->max_log_size_ixfr; + zh.opaque = zp; + return (zh); +} + +/* + * Merge new configuration information into an existing zone. The + * new zoneinfo must be valid. + */ +static void +update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) { + char buf[MAXPATHLEN+1]; + int i; + + INSIST(zp != NULL); + INSIST(new_zp != NULL); + + ns_debug(ns_log_config, 1, "update_zone_info('%s', %d)", + (*new_zp->z_origin == '\0') ? "." : new_zp->z_origin, + new_zp->z_type); + +#ifdef BIND_UPDATE + /* + * A dynamic master zone that's becoming non-dynamic may need to be + * dumped before we start the update. + */ + if ((zp->z_flags & Z_DYNAMIC) && !(new_zp->z_flags & Z_DYNAMIC) && + ((zp->z_flags & Z_NEED_SOAUPDATE) || + (zp->z_flags & Z_NEED_DUMP))) + (void) zonedump(zp, ISNOTIXFR); +#endif + + /* + * First do the simple stuff, making sure to free + * any data that was dynamically allocated. + */ + if (zp->z_origin != NULL) + (void)freestr(zp->z_origin); + zp->z_origin = new_zp->z_origin; + new_zp->z_origin = NULL; + zp->z_maintain_ixfr_base = new_zp->z_maintain_ixfr_base; + zp->z_max_log_size_ixfr = new_zp->z_max_log_size_ixfr; + zp->z_class = new_zp->z_class; + zp->z_type = new_zp->z_type; + zp->z_checknames = new_zp->z_checknames; + for (i = 0; i < new_zp->z_addrcnt; i++) { + zp->z_addr[i] = new_zp->z_addr[i]; + zp->z_keys[i] = new_zp->z_keys[i]; + } + zp->z_addrcnt = new_zp->z_addrcnt; + if (zp->z_update_acl) + free_ip_match_list(zp->z_update_acl); + zp->z_update_acl = new_zp->z_update_acl; + new_zp->z_update_acl = NULL; + if (zp->z_query_acl) + free_ip_match_list(zp->z_query_acl); + zp->z_query_acl = new_zp->z_query_acl; + new_zp->z_query_acl = NULL; + zp->z_axfr_src = new_zp->z_axfr_src; + if (zp->z_transfer_acl) + free_ip_match_list(zp->z_transfer_acl); + zp->z_transfer_acl = new_zp->z_transfer_acl; + new_zp->z_transfer_acl = NULL; + zp->z_max_transfer_time_in = new_zp->z_max_transfer_time_in; +#ifdef BIND_NOTIFY + zp->z_notify = new_zp->z_notify; + if (zp->z_also_notify) + memput(zp->z_also_notify, + zp->z_notify_count * sizeof *zp->z_also_notify); + zp->z_also_notify = new_zp->z_also_notify; + zp->z_notify_count = new_zp->z_notify_count; + new_zp->z_also_notify = NULL; + new_zp->z_notify_count = 0; +#endif + if ((new_zp->z_flags & Z_FORWARD_SET) != 0) + zp->z_flags |= Z_FORWARD_SET; + else + zp->z_flags &= ~Z_FORWARD_SET; + if (zp->z_fwdtab != NULL) + free_forwarders(zp->z_fwdtab); + zp->z_fwdtab = new_zp->z_fwdtab; + new_zp->z_fwdtab = NULL; + + zp->z_dialup = new_zp->z_dialup; + zp->z_options = new_zp->z_options; + zp->z_optset = new_zp->z_optset; + +#ifdef BIND_UPDATE + if (new_zp->z_flags & Z_DYNAMIC) + zp->z_flags |= Z_DYNAMIC; + else + zp->z_flags &= ~Z_DYNAMIC; + zp->z_soaincrintvl = new_zp->z_soaincrintvl; + zp->z_dumpintvl = new_zp->z_dumpintvl; + zp->z_deferupdcnt = new_zp->z_deferupdcnt; + if (zp->z_updatelog) + (void)freestr(zp->z_updatelog); + zp->z_updatelog = new_zp->z_updatelog; + new_zp->z_updatelog = NULL; +#endif /* BIND_UPDATE */ + zp->z_port = new_zp->z_port; + + /* + * Now deal with files. + */ + switch (zp->z_type) { + case z_cache: + ns_panic(ns_log_config, 1, "impossible condition"); + break; + case z_hint: + ns_debug(ns_log_config, 1, "source = %s", new_zp->z_source); + zp->z_refresh = 0; /* No dumping. */ + if (zp->z_source != NULL && + strcmp(new_zp->z_source, zp->z_source) == 0 && + (reconfiging || !zonefile_changed_p(zp))) { + ns_debug(ns_log_config, 1, "cache is up to date"); + break; + } + + /* File has changed, or hasn't been loaded yet. */ + if (zp->z_source) { + zp->z_source = freestr(zp->z_source); + ns_stopxfrs(zp); + purge_zone(zp->z_origin, fcachetab, zp->z_class); + } + zp->z_source = new_zp->z_source; + new_zp->z_source = NULL; + + if (zp->z_ixfr_base) + (void)freestr(zp->z_ixfr_base); + zp->z_ixfr_base = new_zp->z_ixfr_base; + new_zp->z_ixfr_base = NULL; + + if (zp->z_ixfr_tmp) + (void)freestr(zp->z_ixfr_tmp); + zp->z_ixfr_tmp = new_zp->z_ixfr_tmp; + new_zp->z_ixfr_tmp = NULL; + + ns_debug(ns_log_config, 1, "reloading hint zone"); + (void) db_load(zp->z_source, zp->z_origin, zp, NULL, + ISNOTIXFR); + break; + + case z_master: + ns_debug(ns_log_config, 1, "source = %s", new_zp->z_source); + /* + * If we've loaded this file, and the file hasn't changed + * then there's no need to reload. + */ + if (zp->z_source != NULL && + strcmp(new_zp->z_source, zp->z_source) == 0 && + (reconfiging || !zonefile_changed_p(zp))) { + ns_debug(ns_log_config, 1, "zone is up to date"); + break; + } +#ifdef BIND_UPDATE + if (zp->z_source && (zp->z_flags & Z_DYNAMIC)) + ns_warning(ns_log_config, + "source file of dynamic zone '%s' has changed", + zp->z_origin); + + primary_reload: +#endif /* BIND_UPDATE */ + if (zp->z_source != NULL) + (void)freestr(zp->z_source); + zp->z_source = new_zp->z_source; + new_zp->z_source = NULL; + + if (zp->z_ixfr_base != NULL) + (void)freestr(zp->z_ixfr_base); + zp->z_ixfr_base = new_zp->z_ixfr_base; + new_zp->z_ixfr_base = NULL; + + if (zp->z_ixfr_tmp != NULL) + (void)freestr(zp->z_ixfr_tmp); + zp->z_ixfr_tmp = new_zp->z_ixfr_tmp; + new_zp->z_ixfr_tmp = NULL; + + if (reload_master(zp) == 1) { + /* + * Note that going to primary_reload + * unconditionally reloads the zone. + */ + new_zp->z_source = savestr(zp->z_source, 1); + new_zp->z_ixfr_base = savestr(zp->z_ixfr_base, 1); + new_zp->z_ixfr_tmp = savestr(zp->z_ixfr_tmp, 1); + goto primary_reload; + } + break; + + case z_slave: +#ifdef STUBS + case z_stub: +#endif + ns_debug(ns_log_config, 1, "addrcnt = %d", zp->z_addrcnt); + if (!new_zp->z_source) { + /* + * We will always transfer this zone again + * after a reload. + */ + sprintf(buf, "NsTmp%ld.%d", (long)getpid(), tmpnum++); + new_zp->z_source = savestr(buf, 1); + zp->z_flags |= Z_TMP_FILE; + } else + zp->z_flags &= ~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 != NULL && + (strcmp(new_zp->z_source, zp->z_source) != 0 || + ((!reconfiging) && zonefile_changed_p(zp)))) { + ns_debug(ns_log_config, 1, + "backup file changed or missing"); + zp->z_source = freestr(zp->z_source); + zp->z_serial = 0; /* force xfer */ + ns_stopxfrs(zp); + /* + * We only need to reload if we have ever + * successfully transferred the zone. + */ + if ((zp->z_flags & Z_AUTH) != 0) { + zp->z_flags &= ~Z_AUTH; + /* + * Purge old data and mark the parent for + * reloading so that NS records are present + * during the zone transfer. + */ + do_reload(zp->z_origin, zp->z_type, + zp->z_class, 1); + } + } + if (zp->z_source == NULL) { + zp->z_source = new_zp->z_source; + new_zp->z_source = NULL; + } + + if (zp->z_ixfr_base != NULL) + (void)freestr(zp->z_ixfr_base); + zp->z_ixfr_base = new_zp->z_ixfr_base; + new_zp->z_ixfr_base = NULL; + + if (zp->z_ixfr_tmp != NULL) + freestr(zp->z_ixfr_tmp); + zp->z_ixfr_tmp = new_zp->z_ixfr_tmp; + new_zp->z_ixfr_tmp = NULL; + + if ((!noexpired || ((zp->z_flags & Z_EXPIRED) == 0)) && + ((zp->z_flags & Z_AUTH) == 0)) + zoneinit(zp); + else { + /* + ** Force slave to try transfer soon after SIGHUP. + */ + if ((zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING)) == 0 && + reloading && !reconfiging) { + qserial_retrytime(zp, tt.tv_sec); + sched_zone_maint(zp); + } + } + break; + case z_forward: + /* + * We don't know if the forwarder's list has changed + * so just purge the cache. In the future we may want + * see if the forwarders list has changed and only + * do this then. + */ + clean_cache_from(zp->z_origin, hashtab); + break; + } + if ((zp->z_flags & Z_FOUND) != 0 && /* already found? */ + (zp - zones) != DB_Z_CACHE) /* cache never sets Z_FOUND */ + ns_error(ns_log_config, "Zone \"%s\" declared more than once", + zp->z_origin); + zp->z_flags |= Z_FOUND; + ns_debug(ns_log_config, 1, + "zone[%d] type %d: '%s' z_time %lu, z_refresh %u", + zp-zones, zp->z_type, + *(zp->z_origin) == '\0' ? "." : zp->z_origin, + (u_long)zp->z_time, zp->z_refresh); +} + +/* + * Finish constructing a new zone. If valid, the constructed zone is + * merged into the zone database. The zone_config used is invalid after + * end_zone() completes. + */ +void +end_zone(zone_config zh, int should_install) { + struct zoneinfo *zp, *new_zp; + const char *zname; + symbol_value value; + + new_zp = zh.opaque; + INSIST(new_zp != NULL); + + zname = (new_zp->z_origin[0] == '\0') ? "." : new_zp->z_origin; + ns_debug(ns_log_config, 3, "end_zone('%s', %d)", zname, + should_install); + + if (!should_install) { + release_zone(new_zp); + return; + } + if (!validate_zone(new_zp)) { + ns_error(ns_log_config, + "zone '%s' did not validate, skipping", zname); + release_zone(new_zp); + return; + } + zp = find_zone(new_zp->z_origin, new_zp->z_class); + if (zp != NULL && zp->z_type != new_zp->z_type) { + remove_zone(zp, "redefined"); + zp = NULL; + } + if (zp == NULL) { + zp = new_zone(); + INSIST(zp != NULL); + value.integer = (zp - zones); + define_symbol(zone_symbol_table, new_zp->z_origin, + new_zp->z_class, value, 0); + } + ns_debug(ns_log_config, 5, "zone '%s', type = %d, class = %d", zname, + new_zp->z_type, new_zp->z_class); + if (new_zp->z_source != NULL) + ns_debug(ns_log_config, 5, " file = %s", new_zp->z_source); + ns_debug(ns_log_config, 5, " checknames = %d", new_zp->z_checknames); + if (new_zp->z_addrcnt != 0) { + int i; + + ns_debug(ns_log_config, 5, " masters:"); + for (i = 0; i < new_zp->z_addrcnt; i++) + ns_debug(ns_log_config, 5, " %s", + inet_ntoa(new_zp->z_addr[i])); + } + + update_zone_info(zp, new_zp); + release_zone(new_zp); + zh.opaque = NULL; +} + +int +set_zone_type(zone_config zh, int type) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + /* Fail if type already set for this zone */ + if (zp->z_type != 0) + return (0); + zp->z_type = type; + return (1); +} + +int +set_zone_filename(zone_config zh, char *filename) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + /* Fail if filename already set for this zone */ + if (zp->z_source != NULL) + return (0); + zp->z_source = filename; + return (1); +} + +int +set_zone_checknames(zone_config zh, enum severity s) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + /* Fail if checknames already set for this zone */ + if (zp->z_checknames != not_set) + return (0); + zp->z_checknames = s; + return (1); +} + +int +set_zone_ixfr_file(zone_config zh, char *filename) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + /* Fail if filename already set for this zone */ + if (zp->z_ixfr_base != NULL) + return (0); + zp->z_ixfr_base = filename; + if (zp->z_ixfr_tmp == NULL) { + int len = strlen(zp->z_ixfr_base) + (sizeof ".tmp"); + char *str = (char *) memget(len); + + sprintf(str, "%s.tmp", zp->z_ixfr_base); + zp->z_ixfr_tmp = savestr(str, 1); + memput(str, len); + } + + return (1); +} + +int +set_zone_ixfr_tmp(zone_config zh, char *filename) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + /* Fail if filename already set for this zone */ + if (zp->z_ixfr_tmp != NULL) + return (0); + zp->z_ixfr_tmp = filename; + return (1); +} + +int +set_zone_dialup(zone_config zh, int value) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + if (value) { + zp->z_dialup = zdialup_yes; +#ifdef BIND_NOTIFY + zp->z_notify = notify_yes; +#endif + } else + zp->z_dialup = zdialup_no; + + return (1); +} + +int +set_zone_notify(zone_config zh, enum notify value) { +#ifdef BIND_NOTIFY + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + zp->z_notify = value; +#endif + return (1); +} + +int +set_zone_maintain_ixfr_base(zone_config zh, int value) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + zp->z_maintain_ixfr_base = value; + + return (1); +} + +int +set_zone_update_acl(zone_config zh, ip_match_list iml) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + /* Fail if update_acl already set for this zone */ + if (zp->z_update_acl != NULL) + return (0); + zp->z_update_acl = iml; +#ifdef BIND_UPDATE + if (!ip_match_is_none(iml)) + zp->z_flags |= Z_DYNAMIC; + else + ns_debug(ns_log_config, 3, "update acl is none for '%s'", + zp->z_origin); +#endif + return (1); +} + +int +set_zone_query_acl(zone_config zh, ip_match_list iml) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + /* Fail if allow-query acl already set for this zone */ + if (zp->z_query_acl != NULL) + return (0); + zp->z_query_acl = iml; + return (1); +} + +int +set_zone_master_port(zone_config zh, u_short port) { + struct zoneinfo *zp = zh.opaque; + + zp->z_port = port; + return (1); +} + +int +set_zone_transfer_source(zone_config zh, struct in_addr ina) { + struct zoneinfo *zp = zh.opaque; + + zp->z_axfr_src = ina; + return (1); +} + +int +set_zone_transfer_acl(zone_config zh, ip_match_list iml) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + /* Fail if allow-transfer acl already set for this zone */ + if (zp->z_transfer_acl != NULL) + return (0); + zp->z_transfer_acl = iml; + return (1); +} + +int +set_zone_transfer_time_in(zone_config zh, long max_time) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + /* Fail if max-transfer-time-in already set for this zone */ + if (zp->z_max_transfer_time_in) + return (0); + zp->z_max_transfer_time_in = max_time; + return (1); +} + +int +set_zone_max_log_size_ixfr(zone_config zh, int size) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + zp->z_max_log_size_ixfr = size; + return (0); +} + +int +set_zone_pubkey(zone_config zh, const int flags, const int proto, + const int alg, const char *str) +{ + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + INSIST(zp != NULL && zp->z_origin != NULL); + return (add_trusted_key(zp->z_origin, flags, proto, alg, str)); +} + +int +set_trusted_key(const char *name, const int flags, const int proto, + const int alg, const char *str) { + INSIST(name != NULL); + return (add_trusted_key(name, flags, proto, alg, str)); +} + +int +add_zone_master(zone_config zh, struct in_addr address, struct dst_key * key) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + zp->z_addr[zp->z_addrcnt] = address; + zp->z_keys[zp->z_addrcnt] = key; + zp->z_addrcnt++; + if (zp->z_addrcnt >= NSMAX) { + ns_warning(ns_log_config, "NSMAX reached for zone '%s'", + zp->z_origin); + zp->z_addrcnt = NSMAX - 1; + } + return (1); +} + +int +add_zone_notify(zone_config zh, struct in_addr address) { +#ifdef BIND_NOTIFY + struct zoneinfo *zp; + int i; + + zp = zh.opaque; + INSIST(zp != NULL); + + /* Check for duplicates. */ + + for (i = 0; i < zp->z_notify_count; i++) { + if (memcmp(zp->z_also_notify + i, + &address, sizeof address) == 0) { + ns_warning(ns_log_config, + "duplicate also-notify address ignored [%s] for zone '%s'", + inet_ntoa(address), zp->z_origin); + return (1); + } + } + i = 0; + + if (zp->z_also_notify == NULL) { + zp->z_also_notify = memget(sizeof *zp->z_also_notify); + if (zp->z_also_notify == NULL) + i = 1; + } else { + register size_t size; + register struct in_addr *an_tmp; + size = zp->z_notify_count * sizeof *zp->z_also_notify; + an_tmp = memget(size + sizeof *zp->z_also_notify); + if (an_tmp == NULL) { + i = 1; + } else { + memcpy(an_tmp, zp->z_also_notify, size); + memput(zp->z_also_notify, size); + zp->z_also_notify = an_tmp; + } + } + if (i == 0) { + zp->z_also_notify[zp->z_notify_count] = address; + zp->z_notify_count++; + } else { + ns_warning(ns_log_config, "also-notify add failed (memget) [%s] for zone '%s'", + inet_ntoa(address), zp->z_origin); + } +#endif + return (1); +} + +/* Options */ + +options +new_options() { + options op; + char hostname[256]; + + op = (options)memget(sizeof (struct options)); + if (op == NULL) + panic("memget failed in new_options()", NULL); + + op->version = savestr(ShortVersion, 1); + if (gethostname(hostname, sizeof(hostname)) == 0) + op->hostname = savestr(hostname, 1); + else + op->hostname = NULL; + op->directory = savestr(".", 1); + op->pid_filename = savestr(_PATH_PIDFILE, 1); + op->named_xfer = savestr(_PATH_XFER, 1); + op->dump_filename = savestr(_PATH_DUMPFILE, 1); + op->stats_filename = savestr(_PATH_STATS, 1); + op->memstats_filename = savestr(_PATH_MEMSTATS, 1); + op->flags = DEFAULT_OPTION_FLAGS; + op->transfers_in = DEFAULT_XFERS_RUNNING; + op->transfers_per_ns = DEFAULT_XFERS_PER_NS; + op->transfers_out = 0; + op->serial_queries = MAXQSERIAL; + op->transfer_format = axfr_one_answer; + op->max_transfer_time_in = MAX_XFER_TIME; + memset(&op->query_source, 0, sizeof op->query_source); + op->query_source.sin_family = AF_INET; + op->query_source.sin_addr.s_addr = htonl(INADDR_ANY); + op->query_source.sin_port = htons(0); /* INPORT_ANY */ + op->axfr_src.s_addr = 0; +#ifdef BIND_NOTIFY + op->notify_count = 0; + op->also_notify = NULL; +#endif + op->blackhole_acl = NULL; + op->query_acl = NULL; + op->transfer_acl = NULL; + op->recursion_acl = NULL; + op->sortlist = NULL; + op->topology = NULL; + op->data_size = 0UL; /* use system default */ + op->stack_size = 0UL; /* use system default */ + op->core_size = 0UL; /* use system default */ + op->files = ULONG_MAX; /* unlimited */ + op->check_names[primary_trans] = fail; + op->check_names[secondary_trans] = warn; + op->check_names[response_trans] = ignore; + op->listen_list = NULL; + op->fwdtab = NULL; + /* XXX init forwarding */ + op->clean_interval = 3600; + op->interface_interval = 3600; + op->stats_interval = 3600; + op->ordering = NULL; + op->max_ncache_ttl = DEFAULT_MAX_NCACHE_TTL; + op->max_host_stats = 0; + op->lame_ttl = NTTL; + op->heartbeat_interval = 3600; + op->max_log_size_ixfr = 0; + op->minroots = MINROOTS; + op->preferred_glue = 0; +#ifdef BIND_NOTIFY + op->notify = notify_yes; +#endif + return (op); +} + +void +free_options(options op) { + INSIST(op != NULL); + + if (op->hostname) + op->hostname = freestr(op->hostname); + if (op->version) + op->version = freestr(op->version); + if (op->directory) + op->directory = freestr(op->directory); + if (op->pid_filename) + op->pid_filename = freestr(op->pid_filename); + if (op->named_xfer) + op->named_xfer = freestr(op->named_xfer); + if (op->dump_filename) + op->dump_filename = freestr(op->dump_filename); + if (op->stats_filename) + op->stats_filename = freestr(op->stats_filename); + if (op->memstats_filename) + op->memstats_filename = freestr(op->memstats_filename); +#ifdef BIND_NOTIFY + if (op->also_notify) + free_also_notify(op); +#endif + if (op->blackhole_acl) + free_ip_match_list(op->blackhole_acl); + if (op->query_acl) + free_ip_match_list(op->query_acl); + if (op->recursion_acl) + free_ip_match_list(op->recursion_acl); + if (op->transfer_acl) + free_ip_match_list(op->transfer_acl); + if (op->sortlist) + free_ip_match_list(op->sortlist); + if (op->ordering) + free_rrset_order_list(op->ordering); + if (op->topology) + free_ip_match_list(op->topology); + if (op->listen_list) + free_listen_info_list(op->listen_list); + if (op->fwdtab) + free_forwarders(op->fwdtab); + memput(op, sizeof *op); +} + +static void +set_boolean_option(u_int *op_flags, int bool_opt, int value) { + INSIST(op_flags != NULL); + + switch (bool_opt) { +#ifdef HITCOUNTS + case OPTION_HITCOUNT: +#endif /* HITCOUNTS */ + case OPTION_NORECURSE: + case OPTION_NOFETCHGLUE: + case OPTION_FORWARD_ONLY: + case OPTION_FAKE_IQUERY: + case OPTION_SUPNOTIFY_INITIAL: + case OPTION_NONAUTH_NXDOMAIN: + case OPTION_MULTIPLE_CNAMES: + case OPTION_USE_IXFR: + case OPTION_MAINTAIN_IXFR_BASE: + case OPTION_HOSTSTATS: + case OPTION_DEALLOC_ON_EXIT: + case OPTION_USE_ID_POOL: + case OPTION_NORFC2308_TYPE1: + case OPTION_NODIALUP: + case OPTION_TREAT_CR_AS_SPACE: + if (value) + *op_flags |= bool_opt; + else + *op_flags &= ~bool_opt; + break; + default: + panic("unexpected option in set_boolean_option", NULL); + } +} + +void +set_global_boolean_option(options op, int bool_opt, int value) { + + INSIST(op != NULL); + + set_boolean_option(&op->flags, bool_opt, value); +} + +void +set_zone_boolean_option(zone_config zh, int bool_opt, int value) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + set_boolean_option(&zp->z_options, bool_opt, value); + + /* Flag that zone option overrides corresponding global option */ + zp->z_optset |= bool_opt; +} + +#ifdef HAVE_GETRUSAGE +enum limit { Datasize, Stacksize, Coresize, Files }; + +static struct rlimit initial_data_size; +static struct rlimit initial_stack_size; +static struct rlimit initial_core_size; +static struct rlimit initial_num_files; + +static void +get_initial_limits() { + int fdlimit = evHighestFD(ev) + 1; + +# ifdef RLIMIT_DATA + if (getrlimit(RLIMIT_DATA, &initial_data_size) < 0) + ns_warning(ns_log_config, "getrlimit(DATA): %s", + strerror(errno)); +# endif +# ifdef RLIMIT_STACK + if (getrlimit(RLIMIT_STACK, &initial_stack_size) < 0) + ns_warning(ns_log_config, "getrlimit(STACK): %s", + strerror(errno)); +# endif +# ifdef RLIMIT_CORE + if (getrlimit(RLIMIT_CORE, &initial_core_size) < 0) + ns_warning(ns_log_config, "getrlimit(CORE): %s", + strerror(errno)); +# endif +# ifdef RLIMIT_NOFILE + if (getrlimit(RLIMIT_NOFILE, &initial_num_files) < 0) + ns_warning(ns_log_config, "getrlimit(NOFILE): %s", + strerror(errno)); + else if (initial_num_files.rlim_cur > fdlimit) { + initial_num_files.rlim_cur = fdlimit; + if (initial_num_files.rlim_cur > initial_num_files.rlim_max) + initial_num_files.rlim_max = fdlimit; + if (setrlimit(RLIMIT_NOFILE, &initial_num_files) < 0) { + ns_warning(ns_log_config, "setrlimit(files): %s", + strerror(errno)); + } else { + ns_warning(ns_log_config, + "limit files set to fdlimit (%d)", + fdlimit); + } + } +# endif +} + +static void +ns_rlimit(enum limit limit, u_long limit_value) { + struct rlimit limits, old_limits; + int rlimit = -1; + int fdlimit = evHighestFD(ev) + 1; + const char *name; + rlimit_type value; + + if (limit_value == ULONG_MAX) { +#ifndef RLIMIT_FILE_INFINITY + if (limit == Files) + value = MIN((rlimit_type)evHighestFD(ev) + 1, + initial_num_files.rlim_max); + else +#endif + value = (rlimit_type)RLIM_INFINITY; + } else + value = (rlimit_type)limit_value; + + limits.rlim_cur = limits.rlim_max = value; + switch (limit) { + case Datasize: +#ifdef RLIMIT_DATA + rlimit = RLIMIT_DATA; +#endif + name = "max data size"; + if (value == 0) + limits = initial_data_size; + break; + case Stacksize: +#ifdef RLIMIT_STACK + rlimit = RLIMIT_STACK; +#endif + name = "max stack size"; + if (value == 0) + limits = initial_stack_size; + break; + case Coresize: +#ifdef RLIMIT_CORE + rlimit = RLIMIT_CORE; +#endif + name = "max core size"; + if (value == 0) + limits = initial_core_size; + break; + case Files: +#ifdef RLIMIT_NOFILE + rlimit = RLIMIT_NOFILE; +#endif + name = "max number of open files"; + if (value == 0) + limits = initial_num_files; + if ((int)value > fdlimit) + limits.rlim_cur = limits.rlim_max = value = fdlimit; + break; + default: + name = NULL; /* Make gcc happy. */ + panic("impossible condition in ns_rlimit()", NULL); + } + if (rlimit == -1) { + ns_warning(ns_log_config, + "limit \"%s\" not supported on this system - ignored", + name); + return; + } + if (getrlimit(rlimit, &old_limits) < 0) { + ns_warning(ns_log_config, "getrlimit(%s): %s", name, + strerror(errno)); + } + if (user_id != 0 && limits.rlim_max == RLIM_INFINITY) + limits.rlim_cur = limits.rlim_max = old_limits.rlim_max; + if (setrlimit(rlimit, &limits) < 0) { + ns_warning(ns_log_config, "setrlimit(%s): %s", name, + strerror(errno)); + return; + } else { + if (value == 0) + ns_debug(ns_log_config, 3, "%s is default", name); + else if (value == RLIM_INFINITY) + ns_debug(ns_log_config, 3, "%s is unlimited", name); + else +#ifdef RLIMIT_LONGLONG + ns_debug(ns_log_config, 3, "%s is %llu", name, + (unsigned long long)value); +#else + ns_debug(ns_log_config, 3, "%s is %lu", name, value); +#endif + } +} +#endif /* HAVE_GETRUSAGE */ + +listen_info_list +new_listen_info_list() { + listen_info_list ll; + + ll = (listen_info_list)memget(sizeof (struct listen_info_list)); + if (ll == NULL) + panic("memget failed in new_listen_info_list()", NULL); + ll->first = NULL; + ll->last = NULL; + return (ll); +} + +void +free_listen_info_list(listen_info_list ll) { + listen_info li, next_li; + + INSIST(ll != NULL); + for (li = ll->first; li != NULL; li = next_li) { + next_li = li->next; + free_ip_match_list(li->list); + memput(li, sizeof *li); + } + memput(ll, sizeof *ll); +} + +void +add_listen_on(options op, u_short port, ip_match_list iml) { + listen_info_list ll; + listen_info ni; + + INSIST(op != NULL); + + if (op->listen_list == NULL) + op->listen_list = new_listen_info_list(); + ll = op->listen_list; + ni = (listen_info)memget(sizeof (struct listen_info)); + if (ni == NULL) + panic("memget failed in add_listen_on", NULL); + ni->port = port; + ni->list = iml; + ni->next = NULL; + if (ll->last != NULL) + ll->last->next = ni; + ll->last = ni; + if (ll->first == NULL) + ll->first = ni; +} + +FILE * +write_open(char *filename) { + FILE *stream; + int fd; + struct stat sb; + int regular; + + if (stat(filename, &sb) < 0) { + if (errno != ENOENT) { + ns_error(ns_log_os, + "write_open: stat of %s failed: %s", + filename, strerror(errno)); + return (NULL); + } + regular = 1; + } else + regular = (sb.st_mode & S_IFREG); + + if (!regular) { + ns_error(ns_log_os, "write_open: %s isn't a regular file", + filename); + return (NULL); + } + + (void)unlink(filename); + fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, + S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); + if (fd < 0) + return (NULL); + (void) fchown(fd, user_id, group_id); + stream = fdopen(fd, "w"); + if (stream == NULL) { + (void)unlink(filename); + (void)close(fd); + } + return (stream); +} + +void +update_pid_file() { + FILE *fp; + + REQUIRE(server_options != NULL); + REQUIRE(server_options->pid_filename != NULL); + + /* XXX */ ns_debug(ns_log_default, 1, "update_pid_file()"); + if (current_pid_filename != NULL) { + (void)unlink(current_pid_filename); + current_pid_filename = freestr(current_pid_filename); + } + current_pid_filename = savestr(server_options->pid_filename, 0); + if (current_pid_filename == NULL) { + ns_error(ns_log_config, + "savestr() failed in update_pid_file()"); + return; + } + fp = write_open(current_pid_filename); + if (fp != NULL) { + (void) fprintf(fp, "%ld\n", (long)getpid()); + (void) fclose(fp); + } else + ns_error(ns_log_config, "couldn't create pid file '%s'", + server_options->pid_filename); +} + +/* + * XXX This function will eventually be public and will be relocated to + * the UNIX OS support library. + */ + +static int +os_change_directory(const char *name) { + struct stat sb; + + if (name == NULL || + *name == '\0') { + errno = EINVAL; + return (0); + } + + if (chdir(name) < 0) + return (0); + + if (stat(name, &sb) < 0) { + ns_error(ns_log_os, "stat(%s) failed: %s", name, + strerror(errno)); + return (1); + } + if (sb.st_mode & S_IWOTH) + ns_warning(ns_log_os, "directory %s is world-writable", name); + + return (1); +} + +static void +periodic_getnetconf(evContext ctx, void *uap, struct timespec due, + struct timespec inter) +{ + UNUSED(ctx); + UNUSED(uap); + UNUSED(due); + UNUSED(inter); + + getnetconf(1); +} + +static int clean_interval = 0; +static int interface_interval = 0; +static int stats_interval = 0; +static int heartbeat_interval = 0; + +static void +set_interval_timer(int which_timer, int interval) { + evTimerID *tid = NULL; + evTimerFunc func = NULL; + int changed = 0; + + switch (which_timer) { + case CLEAN_TIMER: + if (clean_interval != interval) + changed = 1; + clean_interval = interval; + tid = &clean_timer; + func = ns_cleancache; + break; + case INTERFACE_TIMER: + if (interface_interval != interval) + changed = 1; + interface_interval = interval; + tid = &interface_timer; + func = periodic_getnetconf; + break; + case STATS_TIMER: + if (stats_interval != interval) + changed = 1; + stats_interval = interval; + tid = &stats_timer; + func = ns_logstats; + break; + case HEARTBEAT_TIMER: + if (heartbeat_interval != interval) + changed = 1; + heartbeat_interval = interval; + tid = &heartbeat_timer; + func = ns_heartbeat; + break; + default: + ns_panic(ns_log_config, 1, + "set_interval_timer: unknown timer %d", which_timer); + } + if ((active_timers & which_timer) != 0) { + if (interval > 0) { + if (changed && + evResetTimer(ev, *tid, func, NULL, + evAddTime(evNowTime(), + evConsTime(interval, 0)), + evConsTime(interval, 0)) < 0) + ns_error(ns_log_config, + "evResetTimer %d interval %d failed: %s", + which_timer, interval, + strerror(errno)); + } else { + if (evClearTimer(ev, *tid) < 0) + ns_error(ns_log_config, + "evClearTimer %d failed: %s", + which_timer, strerror(errno)); + else + active_timers &= ~which_timer; + } + } else if (interval > 0) { + if (evSetTimer(ev, func, NULL, + evAddTime(evNowTime(), + evConsTime(interval, 0)), + evConsTime(interval, 0), tid) < 0) + ns_error(ns_log_config, + "evSetTimer %d interval %d failed: %s", + which_timer, interval, strerror(errno)); + else + active_timers |= which_timer; + } +} + +/* + * Set all named global options based on the global options structure + * generated by the parser. + */ +void +set_options(options op, int is_default) { + INSIST(op != NULL); + + if (op->listen_list == NULL) { + ip_match_list iml; + ip_match_element ime; + struct in_addr address; + + op->listen_list = new_listen_info_list(); + + address.s_addr = htonl(INADDR_ANY); + iml = new_ip_match_list(); + ime = new_ip_match_pattern(address, 0); + add_to_ip_match_list(iml, ime); + add_listen_on(op, htons(NS_DEFAULTPORT), iml); + } + if (op->topology == NULL) { + ip_match_list iml; + ip_match_element ime; + + /* default topology is { localhost; localnets; } */ + iml = new_ip_match_list(); + ime = new_ip_match_localhost(); + add_to_ip_match_list(iml, ime); + ime = new_ip_match_localnets(); + add_to_ip_match_list(iml, ime); + op->topology = iml; + } + if (server_options != NULL) + free_options(server_options); + server_options = op; + + /* XXX should validate pid filename */ + INSIST(op->pid_filename != NULL); + + if (op->directory && !os_change_directory(op->directory)) + ns_panic(ns_log_config, 0, "can't change directory to %s: %s", + op->directory, strerror(errno)); + + /* XXX currently a value of 0 means "use default"; it would be + better if the options block had a "attributes updated" vector + (like the way X deals with GC updates) */ + + if (!op->transfers_in) + op->transfers_in = DEFAULT_XFERS_RUNNING; + else if (op->transfers_in > MAX_XFERS_RUNNING) { + ns_warning(ns_log_config, + "the maximum number of concurrent inbound transfers is %d", + MAX_XFERS_RUNNING); + op->transfers_in = MAX_XFERS_RUNNING; + } + + if (!op->transfers_per_ns) + op->transfers_per_ns = DEFAULT_XFERS_PER_NS; + + if (!op->max_transfer_time_in) + op->max_transfer_time_in = MAX_XFER_TIME; + + /* XXX currently transfers_out is not used */ + + if (!op->max_ncache_ttl) + op->max_ncache_ttl = DEFAULT_MAX_NCACHE_TTL; + else if (op->max_ncache_ttl > max_cache_ttl) + op->max_ncache_ttl = max_cache_ttl; + + if (op->lame_ttl > (3 * NTTL)) + op->lame_ttl = 3 * NTTL; + + /* + * Limits + */ + +#ifdef HAVE_GETRUSAGE + ns_rlimit(Datasize, op->data_size); + ns_rlimit(Stacksize, op->stack_size); + ns_rlimit(Coresize, op->core_size); + ns_rlimit(Files, op->files); +#else + ns_info(ns_log_config, "cannot set resource limits on this system"); +#endif + + /* + * Timers + */ + set_interval_timer(CLEAN_TIMER, server_options->clean_interval); + set_interval_timer(INTERFACE_TIMER, + server_options->interface_interval); + set_interval_timer(STATS_TIMER, server_options->stats_interval); + set_interval_timer(HEARTBEAT_TIMER, + server_options->heartbeat_interval); + + options_installed = 1; + default_options_installed = is_default; +} + +void +use_default_options() { + set_options(new_options(), 1); +} + +/* + * rrset order types + */ +static struct res_sym order_table [] = { + { unknown_order, " unknown ", NULL }, /* can't match */ + { fixed_order, "fixed", NULL }, + { cyclic_order, "cyclic", NULL }, + { random_order, "random", NULL }, + { unknown_order, NULL, NULL } +}; + +/* + * Return the print name of the ordering value. + */ +const char * +p_order(int order) { + return (__sym_ntos(order_table, order, (int *)0)); +} + +/* + * Lookup the ordering by name and return the matching enum value. + */ +enum ordering +lookup_ordering(const char *name) { + int i; + + for (i = 0; order_table[i].name != NULL; i++) + if (strcasecmp(name,order_table[i].name) == 0) + return ((enum ordering)order_table[i].number); + return (unknown_order); +} + +/* + * rrset-order Lists + */ +rrset_order_list +new_rrset_order_list() { + rrset_order_list rol ; + + rol = (rrset_order_list)memget(sizeof (struct rrset_order_list)); + if (rol == NULL) + panic("memget failed in new_rrset_order_list", NULL); + rol->first = NULL; + rol->last = NULL; + + return (rol); +} + +void +free_rrset_order_list(rrset_order_list rol) { + rrset_order_element roe, next_element; + + for (roe = rol->first; roe != NULL; roe = next_element) { + next_element = roe->next; + roe->name = freestr(roe->name); + memput(roe, sizeof (*roe)); + } + memput(rol, sizeof (*rol)); +} + +void +add_to_rrset_order_list(rrset_order_list rol, rrset_order_element roe) { + INSIST(rol != NULL); + INSIST(roe != NULL); + + if (rol->last != NULL) + rol->last->next = roe; + roe->next = NULL; + rol->last = roe; + if (rol->first == NULL) + rol->first = roe; +} + +#ifdef notyet +/* XXX this isn't being used yet, but it probably should be. Where? */ +void +dprint_rrset_order_list(int category, rrset_order_list rol, int indent, + char *allow, char *deny) { + rrset_order_element roe ; + char spaces[40+1]; + + INSIST(rol != NULL); + + if (indent > 40) + indent = 40; + if (indent) + memset(spaces, ' ', indent); + spaces[indent] = '\0'; + + for (roe = rol->first; roe != NULL; roe = roe->next) { + ns_debug(category, 7, "%sclass %s type %s name %s order %s", + spaces, p_class(roe->class), p_type(roe->type), + roe->name, p_order(roe->order)); + } +} +#endif + +rrset_order_element +new_rrset_order_element(int class, int type, char *name, enum ordering order) +{ + rrset_order_element roe; + int i ; + + roe = (rrset_order_element)memget(sizeof (struct rrset_order_element)); + if (roe == NULL) + panic("memget failed in new_rrset_order_element", NULL); + roe->class = class ; + roe->type = type ; + roe->name = name; + roe->order = order; + + i = strlen(roe->name) - 1; + INSIST (i >= 0); + if (roe->name[i - 1] == '.') { + /* We compare from right to left so we don't need a dot on + the end. */ + roe->name[i - 1] = '\0' ; + } + + return roe ; +} + + +/* + * IP Matching Lists + */ + +ip_match_list +new_ip_match_list() { + ip_match_list iml; + + iml = (ip_match_list)memget(sizeof (struct ip_match_list)); + if (iml == NULL) + panic("memget failed in new_ip_match_list", NULL); + iml->first = NULL; + iml->last = NULL; + return (iml); +} + +void +free_ip_match_list(ip_match_list iml) { + ip_match_element ime, next_element; + + for (ime = iml->first; ime != NULL; ime = next_element) { + next_element = ime->next; + memput(ime, sizeof *ime); + } + memput(iml, sizeof *iml); +} + +ip_match_element +new_ip_match_pattern(struct in_addr address, u_int mask_bits) { + ip_match_element ime; + u_int32_t mask; + + ime = (ip_match_element)memget(sizeof (struct ip_match_element)); + if (ime == NULL) + panic("memget failed in new_ip_match_pattern", NULL); + ime->type = ip_match_pattern; + ime->flags = 0; + ime->u.direct.address = address; + if (mask_bits == 0) + /* can't shift >= the size of a type in bits, so + we deal with an empty mask here */ + mask = 0; + else { + /* set the 'mask_bits' most significant bits */ + mask = 0xffffffffU; + mask >>= (32 - mask_bits); + mask <<= (32 - mask_bits); + } + mask = ntohl(mask); + ime->u.direct.mask.s_addr = mask; + ime->next = NULL; + if (!ina_onnet(ime->u.direct.address, ime->u.direct.address, + ime->u.direct.mask)) { + memput(ime, sizeof *ime); + ime = NULL; + } + return (ime); +} + +ip_match_element +new_ip_match_mask(struct in_addr address, struct in_addr mask) { + ip_match_element ime; + + ime = (ip_match_element)memget(sizeof (struct ip_match_element)); + if (ime == NULL) + panic("memget failed in new_ip_match_pattern", NULL); + ime->type = ip_match_pattern; + ime->flags = 0; + ime->u.direct.address = address; + ime->u.direct.mask = mask; + ime->next = NULL; + if (!ina_onnet(ime->u.direct.address, ime->u.direct.address, + ime->u.direct.mask)) { + memput(ime, sizeof *ime); + ime = NULL; + } + return (ime); +} + +ip_match_element +new_ip_match_indirect(ip_match_list iml) { + ip_match_element ime; + + INSIST(iml != NULL); + + ime = (ip_match_element)memget(sizeof (struct ip_match_element)); + if (ime == NULL) + panic("memget failed in new_ip_match_indirect", NULL); + ime->type = ip_match_indirect; + ime->flags = 0; + ime->u.indirect.list = iml; + ime->next = NULL; + return (ime); +} + +ip_match_element +new_ip_match_key(DST_KEY *dst_key) { + ip_match_element ime; + + ime = (ip_match_element)memget(sizeof (struct ip_match_element)); + if (ime == NULL) + panic("memget failed in new_ip_match_key", NULL); + ime->type = ip_match_key; + ime->flags = 0; + ime->u.key.key = dst_key; + return (ime); +} + +ip_match_element +new_ip_match_localhost() { + ip_match_element ime; + + ime = (ip_match_element)memget(sizeof (struct ip_match_element)); + if (ime == NULL) + panic("memget failed in new_ip_match_localhost", NULL); + ime->type = ip_match_localhost; + ime->flags = 0; + ime->u.indirect.list = NULL; + ime->next = NULL; + return (ime); +} + +ip_match_element +new_ip_match_localnets() { + ip_match_element ime; + + ime = (ip_match_element)memget(sizeof (struct ip_match_element)); + if (ime == NULL) + panic("memget failed in new_ip_match_localnets", NULL); + ime->type = ip_match_localnets; + ime->flags = 0; + ime->u.indirect.list = NULL; + ime->next = NULL; + return (ime); +} + +void +ip_match_negate(ip_match_element ime) { + if (ime->flags & IP_MATCH_NEGATE) + ime->flags &= ~IP_MATCH_NEGATE; + else + ime->flags |= IP_MATCH_NEGATE; +} + +void +add_to_ip_match_list(ip_match_list iml, ip_match_element ime) { + INSIST(iml != NULL); + INSIST(ime != NULL); + + if (iml->last != NULL) + iml->last->next = ime; + ime->next = NULL; + iml->last = ime; + if (iml->first == NULL) + iml->first = ime; +} + +void +dprint_ip_match_list(int category, ip_match_list iml, int indent, + const char *allow, const char *deny) { + ip_match_element ime; + char spaces[40+1]; + char addr_text[sizeof "255.255.255.255"]; + char mask_text[sizeof "255.255.255.255"]; + + INSIST(iml != NULL); + + if (indent > 40) + indent = 40; + if (indent) + memset(spaces, ' ', indent); + spaces[indent] = '\0'; + + for (ime = iml->first; ime != NULL; ime = ime->next) { + switch (ime->type) { + case ip_match_pattern: + memset(addr_text, 0, sizeof addr_text); + strncpy(addr_text, inet_ntoa(ime->u.direct.address), + ((sizeof addr_text) - 1)); + memset(mask_text, 0, sizeof mask_text); + strncpy(mask_text, inet_ntoa(ime->u.direct.mask), + ((sizeof mask_text) - 1)); + ns_debug(category, 7, "%s%saddr: %s, mask: %s", + spaces, + (ime->flags & IP_MATCH_NEGATE) ? deny : allow, + addr_text, mask_text); + break; + case ip_match_localhost: + ns_debug(category, 7, "%s%slocalhost", spaces, + (ime->flags & IP_MATCH_NEGATE) ? + deny : allow); + break; + case ip_match_localnets: + ns_debug(category, 7, "%s%slocalnets", spaces, + (ime->flags & IP_MATCH_NEGATE) ? + deny : allow); + break; + case ip_match_indirect: + ns_debug(category, 7, "%s%sindirect list %p", spaces, + (ime->flags & IP_MATCH_NEGATE) ? deny : allow, + ime->u.indirect.list); + if (ime->u.indirect.list != NULL) + dprint_ip_match_list(category, + ime->u.indirect.list, + indent+2, allow, deny); + break; + case ip_match_key: + ns_debug(category, 7, "%s%skey %s", spaces, + (ime->flags & IP_MATCH_NEGATE) ? deny : allow, + ime->u.key.key->dk_key_name); + break; + default: + panic("unexpected ime type in dprint_ip_match_list()", + NULL); + } + } +} + +int +ip_match_addr_or_key(ip_match_list iml, struct in_addr address, + DST_KEY *key) +{ + ip_match_element ime; + int ret; + int indirect; + + INSIST(iml != NULL); + for (ime = iml->first; ime != NULL; ime = ime->next) { + switch (ime->type) { + case ip_match_pattern: + indirect = 0; + break; + case ip_match_indirect: + indirect = 1; + break; + case ip_match_localhost: + ime->u.indirect.list = local_addresses; + indirect = 1; + break; + case ip_match_localnets: + ime->u.indirect.list = local_networks; + indirect = 1; + break; + case ip_match_key: + if (key == NULL) { + indirect = 0; + break; + } + else { + if (ns_samename(ime->u.key.key->dk_key_name, + key->dk_key_name) == 1) + return (1); + else + continue; + } + default: + indirect = 0; + panic("unexpected ime type in ip_match_addr_or_key()", + NULL); + } + if (indirect) { + ret = ip_match_addr_or_key(ime->u.indirect.list, + address, key); + if (ret > 0) { + if (ime->flags & IP_MATCH_NEGATE) + ret = (ret) ? 0 : 1; + return (ret); + } + } else { + if (ina_onnet(address, ime->u.direct.address, + ime->u.direct.mask)) { + if (ime->flags & IP_MATCH_NEGATE) + return (0); + else + return (1); + } + } + } + return (-1); +} + +int +ip_match_address(ip_match_list iml, struct in_addr address) { + return ip_match_addr_or_key(iml, address, NULL); +} + +int +ip_addr_or_key_allowed(ip_match_list iml, struct in_addr address, + DST_KEY *key) +{ + int ret; + + if (iml == NULL) + return (0); + ret = ip_match_addr_or_key(iml, address, key); + if (ret < 0) + ret = 0; + return (ret); +} + +int +ip_address_allowed(ip_match_list iml, struct in_addr address) { + return(ip_addr_or_key_allowed(iml, address, NULL)); +} + +int +ip_match_network(ip_match_list iml, struct in_addr address, + struct in_addr mask) { + ip_match_element ime; + int ret; + int indirect; + + INSIST(iml != NULL); + for (ime = iml->first; ime != NULL; ime = ime->next) { + switch (ime->type) { + case ip_match_pattern: + indirect = 0; + break; + case ip_match_indirect: + indirect = 1; + break; + case ip_match_localhost: + ime->u.indirect.list = local_addresses; + indirect = 1; + break; + case ip_match_localnets: + ime->u.indirect.list = local_networks; + indirect = 1; + break; + case ip_match_key: + indirect = 0; + break; + default: + indirect = 0; /* Make gcc happy. */ + panic("unexpected ime type in ip_match_network()", + NULL); + } + if (indirect) { + ret = ip_match_network(ime->u.indirect.list, + address, mask); + if (ret >= 0) { + if (ime->flags & IP_MATCH_NEGATE) + ret = (ret) ? 0 : 1; + return (ret); + } + } else { + if (address.s_addr == ime->u.direct.address.s_addr && + mask.s_addr == ime->u.direct.mask.s_addr) { + if (ime->flags & IP_MATCH_NEGATE) + return (0); + else + return (1); + } + } + } + return (-1); +} + +int +distance_of_address(ip_match_list iml, struct in_addr address) { + ip_match_element ime; + int ret; + int indirect; + int distance; + + INSIST(iml != NULL); + for (distance = 1, ime = iml->first; + ime != NULL; ime = ime->next, distance++) { + switch (ime->type) { + case ip_match_pattern: + indirect = 0; + break; + case ip_match_indirect: + indirect = 1; + break; + case ip_match_localhost: + ime->u.indirect.list = local_addresses; + indirect = 1; + break; + case ip_match_localnets: + ime->u.indirect.list = local_networks; + indirect = 1; + break; + case ip_match_key: + indirect = 0; + return (-1); + default: + indirect = 0; /* Make gcc happy. */ + panic("unexpected ime type in distance_of_address()", + NULL); + } + if (indirect) { + ret = ip_match_address(ime->u.indirect.list, address); + if (ret >= 0) { + if (ime->flags & IP_MATCH_NEGATE) + ret = (ret) ? 0 : 1; + if (distance > MAX_TOPOLOGY_DISTANCE) + distance = MAX_TOPOLOGY_DISTANCE; + if (ret) + return (distance); + else + return (MAX_TOPOLOGY_DISTANCE); + } + } else { + if (ina_onnet(address, ime->u.direct.address, + ime->u.direct.mask)) { + if (distance > MAX_TOPOLOGY_DISTANCE) + distance = MAX_TOPOLOGY_DISTANCE; + if (ime->flags & IP_MATCH_NEGATE) + return (MAX_TOPOLOGY_DISTANCE); + else + return (distance); + } + } + } + return (UNKNOWN_TOPOLOGY_DISTANCE); +} + +int +ip_match_is_none(ip_match_list iml) { + ip_match_element ime; + + if ((iml == NULL) || (iml->first == NULL)) + return (1); + ime = iml->first; + if (ime->type == ip_match_indirect) { + if (ime->flags & IP_MATCH_NEGATE) + return (0); + iml = ime->u.indirect.list; + if ((iml == NULL) || (iml->first == NULL)) + return (0); + ime = iml->first; + } + if (ime->type == ip_match_pattern) { + if ((ime->flags & IP_MATCH_NEGATE) && + ime->u.direct.address.s_addr == 0 && + ime->u.direct.mask.s_addr == 0) + return (1); + } + return (0); +} + +/* + * find_forwarder finds the fwddata structure for an address, + * allocating one if we can't find one already existing. + */ + +static struct fwddata * +find_forwarder(struct in_addr address) +{ + struct fwddata *fdp; + struct fwddata **fdpp = NULL; + register int i; + + for (i = 0; i < fwddata_count; i++) { + fdp = fwddata[i]; + if (fdp == NULL) { + if (fdpp == NULL) + fdpp = &fwddata[i]; + continue; + } + if (memcmp(&fdp->fwdaddr.sin_addr, &address, + sizeof(address)) == 0) { + fdp->ref_count++; + return (fdp); + } + } + + fdp = (struct fwddata *)memget(sizeof(struct fwddata)); + if (!fdp) + panic("memget failed in find_forwarder", NULL); + + memset(&fdp->fwdaddr, 0, sizeof(fdp->fwdaddr)); + fdp->fwdaddr.sin_family = AF_INET; + fdp->fwdaddr.sin_addr = address; + fdp->fwdaddr.sin_port = ns_port; + + fdp->ns = savedata(C_IN, T_NS, 0, NULL, 0); + if (!fdp->ns) + panic("memget failed in find_forwarder", NULL); + + fdp->nsdata = savedata(C_IN, T_A, 0, NULL, 0); + if (!fdp->nsdata) + panic("memget failed in find_forwarder", NULL); + fdp->nsdata->d_nstime = 1 + (int)(25.0*rand()/(RAND_MAX + 1.0)); + + fdp->ref_count = 1; + + if (fdpp != NULL) { + *fdpp = fdp; + return (fdp); + } + + i = 0; + if (fwddata == NULL) { + fwddata = memget(sizeof *fwddata); + if (fwddata == NULL) + i = 1; + } else { + register size_t size; + register struct fwddata **an_tmp; + + size = fwddata_count * sizeof *fwddata; + an_tmp = memget(size + sizeof *fwddata); + if (an_tmp == NULL) { + i = 1; + } else { + memcpy(an_tmp, fwddata, size); + memput(fwddata, size); + fwddata = an_tmp; + } + } + + if (i == 0) { + fwddata[fwddata_count] = fdp; + fwddata_count++; + } else { + ns_warning(ns_log_config, "forwarder add failed (memget) [%s]", + inet_ntoa(address)); + } + + return (fdp); +} + +/* + * Forwarder glue + * + * XXX This will go away when the rest of bind understands + * forward zones. + */ + +static void +add_forwarder(struct fwdinfo **fipp, struct in_addr address) { + struct fwdinfo *fip = *fipp, *ftp = NULL; + struct fwddata *fdp; + +#ifdef FWD_LOOP + if (aIsUs(address)) { + ns_error(ns_log_config, "forwarder '%s' ignored, my address", + inet_ntoa(address)); + return; + } +#endif /* FWD_LOOP */ + + /* On multiple forwarder lines, move to end of the list. */ + while (fip != NULL && fip->next != NULL) + fip = fip->next; + + fdp = find_forwarder(address); + ftp = (struct fwdinfo *)memget(sizeof(struct fwdinfo)); + if (!ftp) + panic("memget failed in add_forwarder", NULL); + ftp->fwddata = fdp; + ftp->next = NULL; + if (fip == NULL) + *fipp = ftp; /* First time only */ + else + fip->next = ftp; +} + +void +free_also_notify(options op) { +#ifdef BIND_NOTIFY + memput(op->also_notify, op->notify_count * sizeof *op->also_notify); + op->also_notify = NULL; + op->notify_count = 0; +#endif +} + +int +add_global_also_notify(options op, struct in_addr address) { +#ifdef BIND_NOTIFY + int i; + + INSIST(op != NULL); + + ns_debug(ns_log_config, 2, "adding global notify %s", + inet_ntoa(address)); + + /* Check for duplicates. */ + + for (i = 0; i < op->notify_count; i++) { + if (memcmp(op->also_notify + i, + &address, sizeof address) == 0) { + ns_warning(ns_log_config, + "duplicate global also-notify address ignored [%s]", + inet_ntoa(address)); + return (1); + } + } + i = 0; + + if (op->also_notify == NULL) { + op->also_notify = memget(sizeof *op->also_notify); + if (op->also_notify == NULL) + i = 1; + } else { + register size_t size; + register struct in_addr *an_tmp; + size = op->notify_count * sizeof *op->also_notify; + an_tmp = memget(size + sizeof *op->also_notify); + if (an_tmp == NULL) { + i = 1; + } else { + memcpy(an_tmp, op->also_notify, size); + memput(op->also_notify, size); + op->also_notify = an_tmp; + } + } + if (i == 0) { + op->also_notify[op->notify_count] = address; + op->notify_count++; + } else { + ns_warning(ns_log_config, + "global also-notify add failed (memget) [%s]", + inet_ntoa(address)); + } +#endif + return (1); +} + +void +add_global_forwarder(options op, struct in_addr address) { + + INSIST(op != NULL); + + ns_debug(ns_log_config, 2, "adding default forwarder %s", + inet_ntoa(address)); + + add_forwarder(&op->fwdtab, address); +} + +void +set_zone_forward(zone_config zh) { + struct zoneinfo *zp; + zp = zh.opaque; + + zp->z_flags |= Z_FORWARD_SET; + set_zone_boolean_option(zh, OPTION_FORWARD_ONLY, 0); +} + +void +add_zone_forwarder(zone_config zh, struct in_addr address) { + struct zoneinfo *zp; + const char *zname; + + zp = zh.opaque; + INSIST(zp != NULL); + + zname = (zp->z_origin[0] == '\0') ? "." : zp->z_origin; + ns_debug(ns_log_config, 2, "adding forwarder %s for zone zone '%s'", + inet_ntoa(address), zname); + + zp->z_flags |= Z_FORWARD_SET; + + add_forwarder(&zp->z_fwdtab, address); +} + +void +free_forwarders(struct fwdinfo *fwdtab) { + struct fwdinfo *ftp, *fnext; + int i; + + for (ftp = fwdtab; ftp != NULL; ftp = fnext) { + fnext = ftp->next; + if (--ftp->fwddata->ref_count == 0) { + for (i = 0 ; i < fwddata_count; i++) + if (fwddata[i] == ftp->fwddata) { + fwddata[i] = NULL; + break; + } + db_detach(&ftp->fwddata->ns); + db_detach(&ftp->fwddata->nsdata); + memput(ftp->fwddata, sizeof *ftp->fwddata); + } + memput(ftp, sizeof *ftp); + } + fwdtab = NULL; +} + +/* + * Servers + */ + +static server_info +new_server(struct in_addr address) { + server_info si; + + si = (server_info)memget(sizeof (struct server_info)); + if (si == NULL) + panic("memget failed in new_server()", NULL); + si->address = address; + si->flags = 0U; + si->transfers = 0; + si->transfer_format = axfr_use_default; + si->key_list = NULL; + si->next = NULL; + if (server_options->flags & OPTION_MAINTAIN_IXFR_BASE) + si->flags |= SERVER_INFO_SUPPORT_IXFR; + else + si->flags &= ~SERVER_INFO_SUPPORT_IXFR; + si->flags |= SERVER_INFO_EDNS; + return (si); +} + +static void +free_server(server_info si) { + if (si->key_list) + free_key_info_list(si->key_list); + memput(si, sizeof *si); +} + +server_info +find_server(struct in_addr address) { + server_info si; + + for (si = nameserver_info; si != NULL; si = si->next) + if (si->address.s_addr == address.s_addr) + break; + return (si); +} + +static void +add_server(server_info si) { + ip_match_element ime; + + si->next = nameserver_info; + nameserver_info = si; + + /* + * To ease transition, we'll add bogus nameservers to an + * ip matching list. This will probably be redone when the + * merging of nameserver data structures occurs. + */ + if (si->flags & SERVER_INFO_BOGUS) { + ime = new_ip_match_pattern(si->address, 32); + INSIST(ime != NULL); + add_to_ip_match_list(bogus_nameservers, ime); + } + ns_debug(ns_log_config, 3, "server %s: flags %08x transfers %d", + inet_ntoa(si->address), si->flags, si->transfers); + if (si->key_list != NULL) + dprint_key_info_list(si->key_list); +} + +static void +free_nameserver_info() { + server_info si_next, si; + + for (si = nameserver_info; si != NULL; si = si_next) { + si_next = si->next; + free_server(si); + } + nameserver_info = NULL; + if (bogus_nameservers != NULL) { + free_ip_match_list(bogus_nameservers); + bogus_nameservers = NULL; + } +} + +static void +free_secretkey_info() { + if (secretkey_info != NULL) { + free_key_info_list(secretkey_info); + secretkey_info = NULL; + } +} + +server_config +begin_server(struct in_addr address) { + server_config sc; + + sc.opaque = new_server(address); + return (sc); +} + +void +end_server(server_config sc, int should_install) { + server_info si; + + si = sc.opaque; + + INSIST(si != NULL); + + if (should_install) + add_server(si); + else + free_server(si); + sc.opaque = NULL; +} + +void +set_server_option(server_config sc, int bool_opt, int value) { + server_info si; + + si = sc.opaque; + + INSIST(si != NULL); + + switch (bool_opt) { + case SERVER_INFO_BOGUS: + case SERVER_INFO_SUPPORT_IXFR: + case SERVER_INFO_EDNS: + if (value) + si->flags |= bool_opt; + else + si->flags &= ~bool_opt; + break; + default: + panic("unexpected option in set_server_option", NULL); + } +} + +void +set_server_transfers(server_config sc, int transfers) { + server_info si; + + si = sc.opaque; + + INSIST(si != NULL); + + if (transfers < 0) + transfers = 0; + si->transfers = transfers; +} + +void +set_server_transfer_format(server_config sc, + enum axfr_format transfer_format) { + server_info si; + + si = sc.opaque; + + INSIST(si != NULL); + + si->transfer_format = transfer_format; +} + +void +add_server_key_info(server_config sc, DST_KEY *dst_key) { + server_info si; + + si = sc.opaque; + + INSIST(si != NULL); + + if (si->key_list == NULL) + si->key_list = new_key_info_list(); + add_to_key_info_list(si->key_list, dst_key); +} + +/* + * Keys + */ + +DST_KEY * +new_key_info(char *name, char *algorithm, char *secret) { + DST_KEY *dst_key; + int alg, blen; + u_char buffer[1024]; + + INSIST(name != NULL); + INSIST(algorithm != NULL); + INSIST(secret != NULL); + alg = tsig_alg_value(algorithm); + if (alg == -1) { + ns_warning(ns_log_config, "Unsupported TSIG algorithm %s", + algorithm); + return (NULL); + } + + blen = b64_pton(secret, buffer, sizeof(buffer)); + if (blen < 0) { + ns_warning(ns_log_config, "Invalid TSIG secret \"%s\"", secret); + return (NULL); + } + dst_key = dst_buffer_to_key(name, alg, + NS_KEY_TYPE_AUTH_ONLY|NS_KEY_NAME_ENTITY, + NS_KEY_PROT_ANY, buffer, blen); + if (dst_key == NULL) + ns_warning(ns_log_config, + "dst_buffer_to_key failed in new_key_info"); + return (dst_key); +} + +void +free_key_info(DST_KEY *dst_key) { + INSIST(dst_key != NULL); + dst_free_key(dst_key); +} + +DST_KEY * +find_key(char *name, char *algorithm) { + key_list_element ke; + + if (secretkey_info == NULL) + return (NULL); + + for (ke = secretkey_info->first; ke != NULL; ke = ke->next) { + DST_KEY *dst_key = ke->key; + + if (ns_samename(name, dst_key->dk_key_name) != 1) + continue; + if (algorithm == NULL || + dst_key->dk_alg == tsig_alg_value(algorithm)) + break; + } + if (ke == NULL) + return (NULL); + return (ke->key); +} + +void +dprint_key_info(DST_KEY *dst_key) { + INSIST(dst_key != NULL); + ns_debug(ns_log_config, 7, "key %s", dst_key->dk_key_name); + ns_debug(ns_log_config, 7, " algorithm %d", dst_key->dk_alg); +} + +key_info_list +new_key_info_list() { + key_info_list kil; + + kil = (key_info_list)memget(sizeof (struct key_info_list)); + if (kil == NULL) + panic("memget failed in new_key_info_list()", NULL); + kil->first = NULL; + kil->last = NULL; + return (kil); +} + +void +free_key_info_list(key_info_list kil) { + key_list_element kle, kle_next; + + INSIST(kil != NULL); + for (kle = kil->first; kle != NULL; kle = kle_next) { + kle_next = kle->next; + /* note we do NOT free kle->info */ + memput(kle, sizeof *kle); + } + memput(kil, sizeof *kil); +} + +void +add_to_key_info_list(key_info_list kil, DST_KEY *dst_key) { + key_list_element kle; + + INSIST(kil != NULL); + INSIST(dst_key != NULL); + + kle = (key_list_element)memget(sizeof (struct key_list_element)); + if (kle == NULL) + panic("memget failed in add_to_key_info_list()", NULL); + kle->key = dst_key; + if (kil->last != NULL) + kil->last->next = kle; + kle->next = NULL; + kil->last = kle; + if (kil->first == NULL) + kil->first = kle; +} + +void +dprint_key_info_list(key_info_list kil) { + key_list_element kle; + + INSIST(kil != NULL); + + for (kle = kil->first; kle != NULL; kle = kle->next) + dprint_key_info(kle->key); +} + +/* + * Logging. + */ + +log_config +begin_logging() { + log_config log_cfg; + log_context lc; + + log_cfg = (log_config)memget(sizeof (struct log_config)); + if (log_cfg == NULL) + ns_panic(ns_log_config, 0, + "memget failed creating log_config"); + if (log_new_context(ns_log_max_category, logging_categories, &lc) < 0) + ns_panic(ns_log_config, 0, + "log_new_context() failed: %s", strerror(errno)); + log_cfg->log_ctx = lc; + log_cfg->eventlib_channel = NULL; + log_cfg->packet_channel = NULL; + log_cfg->default_debug_active = 0; + return (log_cfg); +} + +void +add_log_channel(log_config log_cfg, int category, log_channel chan) { + log_channel_type type; + + INSIST(log_cfg != NULL); + + type = log_get_channel_type(chan); + if (category == ns_log_eventlib) { + if (type != log_file && type != log_null) { + ns_error(ns_log_config, + "must specify a file or null channel for the eventlib category"); + return; + } + if (log_cfg->eventlib_channel != NULL) { + ns_error(ns_log_config, + "only one channel allowed for the eventlib category"); + return; + } + log_cfg->eventlib_channel = chan; + } + if (category == ns_log_packet) { + if (type != log_file && type != log_null) { + ns_error(ns_log_config, + "must specify a file or null channel for the packet category"); + return; + } + if (log_cfg->packet_channel != NULL) { + ns_error(ns_log_config, + "only one channel allowed for the packet category"); + return; + } + log_cfg->packet_channel = chan; + } + + if (log_add_channel(log_cfg->log_ctx, category, chan) < 0) { + ns_error(ns_log_config, "log_add_channel() failed"); + return; + } + + if (chan == debug_channel) + log_cfg->default_debug_active = 1; +} + +void +open_special_channels() { + int using_null = 0; + + if (log_open_stream(eventlib_channel) == NULL) { + eventlib_channel = null_channel; + using_null = 1; + } + if (log_open_stream(packet_channel) == NULL) { + packet_channel = null_channel; + using_null = 1; + } + + if (using_null && + log_open_stream(null_channel) == NULL) + ns_panic(ns_log_config, 1, "couldn't open null channel"); +} + +void +set_logging(log_config log_cfg, int is_default) { + log_context lc; + + INSIST(log_cfg != NULL); + lc = log_cfg->log_ctx; + + /* + * Add the default category if it's not in the context already. + */ + if (!log_category_is_active(lc, ns_log_default)) { + add_log_channel(log_cfg, ns_log_default, debug_channel); + add_log_channel(log_cfg, ns_log_default, syslog_channel); + } + + /* + * Add the panic category if it's not in the context already. + */ + if (!log_category_is_active(lc, ns_log_panic)) { + add_log_channel(log_cfg, ns_log_panic, stderr_channel); + add_log_channel(log_cfg, ns_log_panic, syslog_channel); + } + + /* + * Add the eventlib category if it's not in the context already. + */ + if (!log_category_is_active(lc, ns_log_eventlib)) + add_log_channel(log_cfg, ns_log_eventlib, debug_channel); + + /* + * Add the packet category if it's not in the context already. + */ + if (!log_category_is_active(lc, ns_log_packet)) + add_log_channel(log_cfg, ns_log_packet, debug_channel); + +#ifdef DEBUG + /* + * Preserve debugging state. + */ + log_option(lc, LOG_OPTION_DEBUG, debug); + log_option(lc, LOG_OPTION_LEVEL, debug); +#endif + + /* + * Special case for query-log, so we can co-exist with the command + * line option and SIGWINCH. + */ + if (log_category_is_active(lc, ns_log_queries)) + qrylog = 1; + + /* + * Cleanup the old context. + */ + if (need_logging_free) + log_free_context(log_ctx); + + /* + * The default file channels will never have their reference counts + * drop to zero, and so they will not be closed by the logging system + * when log_free_context() is called. We don't want to keep files + * open unnecessarily, and we want them to behave like user-created + * channels, so we close them here. + */ + if (log_get_stream(debug_channel) != stderr) + (void)log_close_stream(debug_channel); + (void)log_close_stream(null_channel); + + /* + * Install the new context. + */ + log_ctx = lc; + eventlib_channel = log_cfg->eventlib_channel; + packet_channel = log_cfg->packet_channel; + +#ifdef DEBUG + if (debug) { + open_special_channels(); + evSetDebug(ev, debug, log_get_stream(eventlib_channel)); + } +#endif + + log_ctx_valid = 1; + need_logging_free = 1; + logging_installed = 1; + default_logging_installed = is_default; +} + +void +end_logging(log_config log_cfg, int should_install) { + if (should_install) + set_logging(log_cfg, 0); + else + log_free_context(log_cfg->log_ctx); + memput(log_cfg, sizeof (struct log_config)); +} + +void +use_default_logging() { + log_config log_cfg; + + log_cfg = begin_logging(); + set_logging(log_cfg, 1); + memput(log_cfg, sizeof (struct log_config)); +} + +static void +init_default_log_channels() { + u_int flags; + const char *name; + FILE *stream; + + syslog_channel = log_new_syslog_channel(0, log_info, ISC_FACILITY); + if (syslog_channel == NULL || log_inc_references(syslog_channel) < 0) + ns_panic(ns_log_config, 0, "couldn't create syslog_channel"); + + flags = LOG_USE_CONTEXT_LEVEL|LOG_REQUIRE_DEBUG; + if (foreground) { + name = NULL; + stream = stderr; + } else { + name = _PATH_DEBUG; + stream = NULL; + } + debug_channel = log_new_file_channel(flags, log_info, name, stream, + 0, ULONG_MAX); + if (debug_channel == NULL || log_inc_references(debug_channel) < 0) + ns_panic(ns_log_config, 0, "couldn't create debug_channel"); + log_set_file_owner(debug_channel, user_id, group_id); + + stderr_channel = log_new_file_channel(0, log_info, NULL, stderr, + 0, ULONG_MAX); + if (stderr_channel == NULL || log_inc_references(stderr_channel) < 0) + ns_panic(ns_log_config, 0, "couldn't create stderr_channel"); + log_set_file_owner(stderr_channel, user_id, group_id); + + null_channel = log_new_file_channel(LOG_CHANNEL_OFF, log_info, + _PATH_DEVNULL, NULL, 0, ULONG_MAX); + if (null_channel == NULL || log_inc_references(null_channel) < 0) + ns_panic(ns_log_config, 0, "couldn't create null_channel"); + log_set_file_owner(null_channel, user_id, group_id); +} + +static void +shutdown_default_log_channels() { + log_free_channel(syslog_channel); + log_free_channel(debug_channel); + log_free_channel(stderr_channel); + log_free_channel(null_channel); +} + +void +init_logging() { + int size; + const struct ns_sym *s; + char category_name[256]; + + size = ns_log_max_category * (sizeof (char *)); + + logging_categories = (char **)memget(size); + if (logging_categories == NULL) + ns_panic(ns_log_config, 0, "memget failed in init_logging"); + memset(logging_categories, 0, size); + for (s = category_constants; s != NULL && s->name != NULL; s++) { + sprintf(category_name, "%s: ", s->name); + logging_categories[s->number] = savestr(category_name, 1); + } + + init_default_log_channels(); + use_default_logging(); +} + +void +shutdown_logging() { + int size; + const struct ns_sym *s; + + evSetDebug(ev, 0, NULL); + shutdown_default_log_channels(); + log_free_context(log_ctx); + + for (s = category_constants; s != NULL && s->name != NULL; s++) + logging_categories[s->number] = + freestr(logging_categories[s->number]); + size = ns_log_max_category * (sizeof (char *)); + memput(logging_categories, size); + logging_categories = NULL; +} + +/* + * Main Loader + */ + +void +init_configuration() { + /* + * Remember initial limits for use if "default" is specified in + * a config file. + */ +#ifdef HAVE_GETRUSAGE + get_initial_limits(); +#endif + zone_symbol_table = new_symbol_table(ZONE_SYM_TABLE_SIZE, NULL); + use_default_options(); + parser_initialize(); + ns_ctl_initialize(); + config_initialized = 1; +} + +void +shutdown_configuration() { + REQUIRE(config_initialized); + + ns_ctl_shutdown(); + if (server_options != NULL) { + free_options(server_options); + server_options = NULL; + } + if (current_pid_filename != NULL) + current_pid_filename = freestr(current_pid_filename); + free_nameserver_info(); + free_secretkey_info(); + free_symbol_table(zone_symbol_table); + parser_shutdown(); + if (fwddata != NULL) + memput(fwddata, fwddata_count * sizeof *fwddata); + fwddata = NULL; + fwddata_count = 0; + config_initialized = 0; +} + +time_t +load_configuration(const char *filename) { + time_t mtime; + + REQUIRE(config_initialized); + + ns_debug(ns_log_config, 3, "load configuration %s", filename); + + loading = 1; + + /* + * Clean up any previous configuration and initialize + * global data structures we'll be updating. + */ + free_nameserver_info(); + free_secretkey_info(); + bogus_nameservers = new_ip_match_list(); + + options_installed = 0; + logging_installed = 0; + + mtime = parse_configuration(filename); + + /* + * If the user didn't specify logging or options, but they previously + * had specified one or both of them, then we need to + * re-establish the default environment. We have to be careful + * about when we install default options because the parser + * must respect limits (e.g. data-size, number of open files) + * specified in the options file. In the ordinary case where the + * options section isn't changing on a zone reload, it would be bad + * to lower these limits temporarily, because we might not survive + * to the point where they get raised back again. The logging case + * has similar motivation -- we don't want to override the existing + * logging scheme (perhaps causing log messages to go somewhere + * unexpected) when the user hasn't expressed a desire for a new + * scheme. + */ + if (!logging_installed) + use_default_logging(); + if (!options_installed && !default_options_installed) { + use_default_options(); + ns_warning(ns_log_config, "re-establishing default options"); + } + + update_pid_file(); + + /* Init or reinit the interface/port list and associated sockets. */ + getnetconf(0); + opensocket_f(); + + initial_configuration = 0; + loading = 0; + /* release queued notifies */ + notify_afterload(); + return (mtime); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_config.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_ctl.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_ctl.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_ctl.c (revision 109985) @@ -0,0 +1,1147 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_ctl.c,v 8.47 2002/06/24 07:11:07 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1997-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* Extern. */ + +#include "port_before.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "port_after.h" + +#include "named.h" + +/* Defs. */ + +#define CONTROL_FOUND 0x0001 /* for mark and sweep. */ +#define MAX_STR_LEN 500 + +struct control { + LINK(struct control) link; + enum { t_dead, t_inet, t_unix } type; + struct ctl_sctx *sctx; + u_int flags; + union { + struct { + struct sockaddr_in in; + ip_match_list allow; + } v_inet; +#ifndef NO_SOCKADDR_UN + struct { + struct sockaddr_un un; + mode_t mode; + uid_t owner; + gid_t group; + } v_unix; +#endif + } var; +}; + +/* Forward. */ + +static struct ctl_sctx *mksrvr(control, const struct sockaddr *, size_t); +static control new_control(void); +static void free_control(controls *, control); +static void free_controls(controls *); +static int match_control(control, control); +static control find_control(controls, control); +static void propagate_changes(const control, control); +static void install(control); +static void install_inet(control); +static void install_unix(control); +static void logger(enum ctl_severity, const char *fmt, ...) + ISC_FORMAT_PRINTF(2,3); +static void verb_connect(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, const void *, void *); +static void verb_getpid(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, const void *, void *); +static void getpid_closure(struct ctl_sctx *, struct ctl_sess *, + void *); +static void verb_status(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, const void *, void *); +static void status_closure(struct ctl_sctx *, struct ctl_sess *, + void *); +static void verb_stop(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, const void *, void *); +static void verb_exec(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, const void *, void *); +static void exec_closure(struct ctl_sctx *, struct ctl_sess *, + void *); +static void verb_reload(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, const void *, void *); +static void verb_reconfig(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, const void *, void *); +static void verb_dumpdb(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, const void *, void *); +static void verb_stats(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, const void *, void *); +static void verb_trace(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, const void *, void *); +static void trace_closure(struct ctl_sctx *, struct ctl_sess *, + void *); +static void verb_notrace(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, const void *, void *); +static void verb_querylog(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, const void *, void *); +static void verb_help(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, const void *, void *); +static void verb_quit(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, const void *, void *); +static void verb_args(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, const void *, void *); + +/* Private data. */ + +static controls server_controls; + +static struct ctl_verb verbs[] = { + { "", verb_connect, ""}, + { "getpid", verb_getpid, "getpid"}, + { "status", verb_status, "status"}, + { "stop", verb_stop, "stop"}, + { "exec", verb_exec, "exec"}, + { "reload", verb_reload, "reload [zone] ..."}, + { "reconfig", verb_reconfig, "reconfig [-noexpired] (just sees new/gone zones)"}, + { "dumpdb", verb_dumpdb, "dumpdb"}, + { "stats", verb_stats, "stats [clear]"}, + { "trace", verb_trace, "trace [level]"}, + { "notrace", verb_notrace, "notrace"}, + { "querylog", verb_querylog, "querylog"}, + { "qrylog", verb_querylog, "qrylog"}, + { "help", verb_help, "help"}, + { "quit", verb_quit, "quit"}, + { "args", verb_args, "args"}, + { NULL, NULL, NULL} +}; + +/* Public functions. */ + +void +ns_ctl_initialize(void) { + INIT_LIST(server_controls); +} + +void +ns_ctl_shutdown(void) { + if (!EMPTY(server_controls)) + free_controls(&server_controls); +} + +void +ns_ctl_defaults(controls *list) { +#ifdef NO_SOCKADDR_UN + struct in_addr saddr; + ip_match_list iml; + ip_match_element ime; + + /* + * If the operating system does not support local domain sockets, + * connect with ndc on 127.0.0.1, port 101, and only allow + * connections from 127.0.0.1. + */ + saddr.s_addr = htonl (INADDR_LOOPBACK); + iml = new_ip_match_list(); + ime = new_ip_match_pattern(saddr, 32); + add_to_ip_match_list(iml, ime); + + ns_ctl_add(list, ns_ctl_new_inet(saddr, htons (101), iml)); +#else +#ifdef NEED_SECURE_DIRECTORY + ns_ctl_add(list, ns_ctl_new_unix(_PATH_NDCSOCK, 0700, 0, 0)); +#else + ns_ctl_add(list, ns_ctl_new_unix(_PATH_NDCSOCK, 0600, 0, 0)); +#endif +#endif /*NO_SOCKADDR_UN*/ +} + +void +ns_ctl_add(controls *list, control new) { + if (!find_control(*list, new)) + APPEND(*list, new, link); +} + +control +ns_ctl_new_inet(struct in_addr saddr, u_int sport, ip_match_list allow) { + control new = new_control(); + + INIT_LINK(new, link); + new->type = t_inet; + memset(&new->var.v_inet.in, 0, sizeof new->var.v_inet.in); + new->var.v_inet.in.sin_family = AF_INET; + new->var.v_inet.in.sin_addr = saddr; + new->var.v_inet.in.sin_port = sport; + new->var.v_inet.allow = allow; + return (new); +} + +#ifndef NO_SOCKADDR_UN +control +ns_ctl_new_unix(const char *path, mode_t mode, uid_t owner, gid_t group) { + control new = new_control(); + + INIT_LINK(new, link); + new->type = t_unix; + memset(&new->var.v_unix.un, 0, sizeof new->var.v_unix.un); + new->var.v_unix.un.sun_family = AF_UNIX; + strncpy(new->var.v_unix.un.sun_path, path, + sizeof new->var.v_unix.un.sun_path - 1); + new->var.v_unix.mode = mode; + new->var.v_unix.owner = owner; + new->var.v_unix.group = group; + return (new); +} +#endif + +void +ns_ctl_install(controls *new) { + control ctl, old, next; + + /* Find all the controls which aren't new or deleted. */ + for (ctl = HEAD(server_controls); ctl != NULL; ctl = NEXT(ctl, link)) + ctl->flags &= ~CONTROL_FOUND; + for (ctl = HEAD(*new); ctl != NULL; ctl = next) { + next = NEXT(ctl, link); + old = find_control(server_controls, ctl); + if (old != NULL) { + old->flags |= CONTROL_FOUND; + propagate_changes(ctl, old); + if (old->sctx == NULL) + free_control(&server_controls, old); + free_control(new, ctl); + } + } + + /* Destroy any old controls which weren't found. */ + for (ctl = HEAD(server_controls); ctl != NULL; ctl = next) { + next = NEXT(ctl, link); + if ((ctl->flags & CONTROL_FOUND) == 0) + free_control(&server_controls, ctl); + } + + /* Add any new controls which were found. */ + for (ctl = HEAD(*new); ctl != NULL; ctl = next) { + next = NEXT(ctl, link); + UNLINK(*new, ctl, link); + APPEND(server_controls, ctl, link); + install(ctl); + if (ctl->sctx == NULL) + free_control(&server_controls, ctl); + } +} + +/* Private functions. */ + +static struct ctl_sctx * +mksrvr(control ctl, const struct sockaddr *sa, size_t salen) { + return (ctl_server(ev, sa, salen, verbs, 500, 222, + 600, 5, 10, logger, ctl)); +} + +static control +new_control(void) { + control new = memget(sizeof *new); + + if (new == NULL) + panic("memget failed in new_control()", NULL); + new->type = t_dead; + new->sctx = NULL; + return (new); +} + +static void +free_control(controls *list, control this) { + int was_live = 0; + struct stat sb; + + if (this->sctx != NULL) { + ctl_endserver(this->sctx); + this->sctx = NULL; + was_live = 1; + } + switch (this->type) { + case t_inet: + if (this->var.v_inet.allow != NULL) { + free_ip_match_list(this->var.v_inet.allow); + this->var.v_inet.allow = NULL; + } + break; +#ifndef NO_SOCKADDR_UN + case t_unix: + /* XXX Race condition. */ + if (was_live && + stat(this->var.v_unix.un.sun_path, &sb) == 0 && + (S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode))) { + /* XXX Race condition. */ + unlink(this->var.v_unix.un.sun_path); + } + break; +#endif + default: + panic("impossible type in free_control", NULL); + /* NOTREACHED */ + } + UNLINK(*list, this, link); + memput(this, sizeof *this); +} + +static void +free_controls(controls *list) { + control ctl, next; + + for (ctl = HEAD(*list); ctl != NULL; ctl = next) { + next = NEXT(ctl, link); + free_control(list, ctl); + } + INIT_LIST(*list); +} + +static int +match_control(control l, control r) { + int match = 1; + + if (l->type != r->type) + match = 0; + else + switch (l->type) { + case t_inet: + if (l->var.v_inet.in.sin_family != + r->var.v_inet.in.sin_family || + l->var.v_inet.in.sin_port != + r->var.v_inet.in.sin_port || + l->var.v_inet.in.sin_addr.s_addr != + r->var.v_inet.in.sin_addr.s_addr) + match = 0; + break; +#ifndef NO_SOCKADDR_UN + case t_unix: + if (l->var.v_unix.un.sun_family != + r->var.v_unix.un.sun_family || + strcmp(l->var.v_unix.un.sun_path, + r->var.v_unix.un.sun_path) != 0) + match = 0; + break; +#endif + default: + panic("impossible type in match_control", NULL); + /* NOTREACHED */ + } + ns_debug(ns_log_config, 20, "match_control(): %d", match); + return (match); +} + +static control +find_control(controls list, control new) { + control ctl; + + for (ctl = HEAD(list); ctl != NULL; ctl = NEXT(ctl, link)) + if (match_control(ctl, new)) + return (ctl); + return (NULL); +} + +static void +propagate_changes(const control diff, control base) { + int need_install = 0; + + switch (base->type) { + case t_inet: + if (base->var.v_inet.allow != NULL) + free_ip_match_list(base->var.v_inet.allow); + base->var.v_inet.allow = diff->var.v_inet.allow; + diff->var.v_inet.allow = NULL; + need_install++; + break; +#ifndef NO_SOCKADDR_UN + case t_unix: + if (base->var.v_unix.mode != diff->var.v_unix.mode) { + base->var.v_unix.mode = diff->var.v_unix.mode; + need_install++; + } + if (base->var.v_unix.owner != diff->var.v_unix.owner) { + base->var.v_unix.owner = diff->var.v_unix.owner; + need_install++; + } + if (base->var.v_unix.group != diff->var.v_unix.group) { + base->var.v_unix.group = diff->var.v_unix.group; + need_install++; + } + break; +#endif + default: + panic("impossible type in ns_ctl::propagate_changes", NULL); + /* NOTREACHED */ + } + if (need_install) + install(base); +} + +static void +install(control ctl) { + switch (ctl->type) { + case t_inet: + install_inet(ctl); + break; +#ifndef NO_SOCKADDR_UN + case t_unix: + install_unix(ctl); + break; +#endif + default: + panic("impossible type in ns_ctl::install", NULL); + /* NOTREACHED */ + } +} + +static void +install_inet(control ctl) { + if (ctl->sctx == NULL) { + ctl->sctx = mksrvr(ctl, + (struct sockaddr *)&ctl->var.v_inet.in, + sizeof ctl->var.v_inet.in); + } +} + +#ifndef NO_SOCKADDR_UN +/* + * Unattach an old unix domain socket if it exists. + */ +static void +unattach(control ctl) { + int s; + struct stat sb; + + s = socket(AF_UNIX, SOCK_STREAM, 0); + if (s < 0) { + ns_warning(ns_log_config, + "unix control \"%s\" socket failed: %s", + ctl->var.v_unix.un.sun_path, + strerror(errno)); + return; + } + + if (stat(ctl->var.v_unix.un.sun_path, &sb) < 0) { + switch (errno) { + case ENOENT: /* We exited cleanly last time */ + break; + default: + ns_warning(ns_log_config, + "unix control \"%s\" stat failed: %s", + ctl->var.v_unix.un.sun_path, + strerror(errno)); + break; + } + goto cleanup; + } + + if (!(S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode))) { + ns_warning(ns_log_config, "unix control \"%s\" not socket", + ctl->var.v_unix.un.sun_path); + goto cleanup; + } + + if (connect(s, (struct sockaddr *)&ctl->var.v_unix.un, + sizeof ctl->var.v_unix.un) < 0) { + switch (errno) { + case ECONNREFUSED: + case ECONNRESET: + if (unlink(ctl->var.v_unix.un.sun_path) < 0) + ns_warning(ns_log_config, + "unix control \"%s\" unlink failed: %s", + ctl->var.v_unix.un.sun_path, + strerror(errno)); + break; + default: + ns_warning(ns_log_config, + "unix control \"%s\" connect failed: %s", + ctl->var.v_unix.un.sun_path, + strerror(errno)); + break; + } + } + cleanup: + close(s); +} + +static void +install_unix(control ctl) { + char *path; +#ifdef NEED_SECURE_DIRECTORY + char *slash; + + path = savestr(ctl->var.v_unix.un.sun_path, 1); + + slash = strrchr(path, '/'); + if (slash != NULL) { + if (slash != path) + *slash = '\0'; + else { + (void)freestr(path); + path = savestr("/", 1); + } + } else { + (void)freestr(path); + path = savestr(".", 1); + } + if (mkdir(path, ctl->var.v_unix.mode) < 0) { + if (errno != EEXIST) { + ns_warning(ns_log_config, + "unix control \"%s\" mkdir failed: %s", + path, strerror(errno)); + } + } +#else + path = ctl->var.v_unix.un.sun_path; +#endif + + if (ctl->sctx == NULL) { + unattach(ctl); + ctl->sctx = mksrvr(ctl, + (struct sockaddr *)&ctl->var.v_unix.un, + sizeof ctl->var.v_unix.un); + } + if (ctl->sctx != NULL) { + /* XXX Race condition. */ + if (chmod(path, ctl->var.v_unix.mode) < 0) { + ns_warning(ns_log_config, "chmod(\"%s\", 0%03o): %s", + ctl->var.v_unix.un.sun_path, + ctl->var.v_unix.mode, + strerror(errno)); + } + if (chown(path, ctl->var.v_unix.owner, + ctl->var.v_unix.group) < 0) { + ns_warning(ns_log_config, "chown(\"%s\", %d, %d): %s", + ctl->var.v_unix.un.sun_path, + ctl->var.v_unix.owner, + ctl->var.v_unix.group, + strerror(errno)); + } + } +#ifdef NEED_SECURE_DIRECTORY + (void)freestr(path); +#endif +} +#endif + +static void +logger(enum ctl_severity ctlsev, const char *format, ...) { + va_list args; + int logsev; + + switch (ctlsev) { + case ctl_debug: logsev = log_debug(5); break; + case ctl_warning: logsev = log_warning; break; + case ctl_error: logsev = log_error; break; + default: logsev = 0; + panic("invalid ctlsev in logger", NULL); + } + if (!log_ctx_valid) + return; + va_start(args, format); + log_vwrite(log_ctx, ns_log_control, logsev, format, args); + va_end(args); +} + +static void +verb_connect(struct ctl_sctx *ctl, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + const struct sockaddr *sa = (const struct sockaddr *)respctx; + control nsctl = (control)uctx; + + UNUSED(ctl); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + + if (sa->sa_family == AF_INET) { + const struct sockaddr_in *in = (const struct sockaddr_in *)sa; + const ip_match_list acl = nsctl->var.v_inet.allow; + + if (!ip_address_allowed(acl, in->sin_addr)) { + ctl_response(sess, 502, "Permission denied.", + CTL_EXIT, NULL, NULL, NULL, NULL, 0); + return; + } + } + ctl_response(sess, 220, server_options->version, 0, NULL, NULL, NULL, + NULL, 0); +} + +static void +verb_getpid(struct ctl_sctx *ctl, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + char *msg = memget(MAX_STR_LEN); + + UNUSED(ctl); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + if (msg == NULL) { + ctl_response(sess, 503, "(out of memory)", 0, + NULL, NULL, NULL, NULL, 0); + return; + } + sprintf(msg, "my pid is <%ld>", (long)getpid()); + ctl_response(sess, 250, msg, 0, NULL, getpid_closure, msg, NULL, 0); +} + +static void +getpid_closure(struct ctl_sctx *sctx, struct ctl_sess *sess, void *uap) { + char *msg = uap; + + UNUSED(sctx); + UNUSED(sess); + + memput(msg, MAX_STR_LEN); +} + +enum state { + e_version = 0, + e_config, + e_nzones, + e_debug, + e_xfersrun, + e_xfersdfr, + e_qserials, + e_qrylog, + e_priming, + e_finito +}; + +struct pvt_status { + enum state state; + char text[MAX_STR_LEN]; +}; + +static void +verb_status(struct ctl_sctx *ctl, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct pvt_status *pvt = ctl_getcsctx(sess); + + UNUSED(ctl); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + if (pvt == NULL) { + pvt = memget(sizeof *pvt); + if (pvt == NULL) { + ctl_response(sess, 505, "(out of memory)", + 0, NULL, NULL, NULL, NULL, 0); + return; + } + pvt->state = (enum state)0; + (void)ctl_setcsctx(sess, pvt); + } + switch (pvt->state++) { + case e_version: + strncpy(pvt->text, Version, sizeof pvt->text); + pvt->text[sizeof pvt->text - 1] = '\0'; + break; + case e_config: + sprintf(pvt->text, "config (%s) last loaded at age: %24s", + conffile, ctime(&confmtime)); + break; + case e_nzones: + sprintf(pvt->text, "number of zones allocated: %d", nzones); + break; + case e_debug: + sprintf(pvt->text, "debug level: %d", debug); + break; + case e_xfersrun: + sprintf(pvt->text, "xfers running: %d", xfers_running); + break; + case e_xfersdfr: + sprintf(pvt->text, "xfers deferred: %d", xfers_deferred); + break; + case e_qserials: + sprintf(pvt->text, "soa queries in progress: %d", + qserials_running); + break; + case e_qrylog: + sprintf(pvt->text, "query logging is %s", + qrylog ? "ON" : "OFF"); + break; + case e_priming: + if (priming) + sprintf(pvt->text, "server is initialising itself"); + else + sprintf(pvt->text, "server is up and running"); + break; + case e_finito: + return; + } + ctl_response(sess, 250, pvt->text, + (pvt->state == e_finito) ? 0 : CTL_MORE, + NULL, status_closure, NULL, NULL, 0); +} + +static void +status_closure(struct ctl_sctx *sctx, struct ctl_sess *sess, void *uap) { + struct pvt_status *pvt = ctl_getcsctx(sess); + + UNUSED(sctx); + UNUSED(uap); + + memput(pvt, sizeof *pvt); + ctl_setcsctx(sess, NULL); +} + +static void +verb_stop(struct ctl_sctx *ctl, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + UNUSED(ctl); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + ns_need(main_need_exit); + ctl_response(sess, 250, "Shutdown initiated.", 0, NULL, NULL, NULL, + NULL, 0); +} + +static void +verb_exec(struct ctl_sctx *ctl, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct stat sb; + + UNUSED(ctl); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + if (rest != NULL && *rest != '\0') { + if (stat(rest, &sb) < 0) { + ctl_response(sess, 503, strerror(errno), + 0, NULL, NULL, NULL, NULL, 0); + return; + } + saved_argv[0] = savestr(rest, 1); /* Never strfreed. */ + } + + if (stat(saved_argv[0], &sb) < 0) { + const char *save = strerror(errno); + + ns_warning(ns_log_default, "can't exec, %s: %s", + saved_argv[0], save); + ctl_response(sess, 502, save, 0, NULL, NULL, NULL, + NULL, 0); + } else if (user_name != NULL || group_name != NULL) { + ctl_response(sess, 502, + "can't exec as user or group was specified", + 0, NULL, NULL, NULL, NULL, 0); + } else { + ctl_response(sess, 250, "Restart initiated.", 0, NULL, + exec_closure, NULL, NULL, 0); + } +} + +static void +exec_closure(struct ctl_sctx *sctx, struct ctl_sess *sess, void *uap) { + + UNUSED(sctx); + UNUSED(sess); + UNUSED(uap); + ns_need(main_need_restart); +} + +static void +verb_reload(struct ctl_sctx *ctl, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + static const char spaces[] = " \t"; + struct zoneinfo *zp; + char *tmp = NULL, *x; + const char *cl; + const char *msg; + int class, code, success; + + UNUSED(ctl); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + /* If there are no args, this is a classic reload of the config. */ + if (rest == NULL || *rest == '\0') { + ns_need(main_need_reload); + code = 250; + msg = "Reload initiated."; + goto respond; + } + + /* Look for optional zclass argument. Default is "in". */ + tmp = savestr(rest, 1); + x = tmp + strcspn(tmp, spaces); + if (*x != '\0') { + *x++ = '\0'; + x += strspn(x, spaces); + } + cl = (x == NULL || *x == '\0') ? "in" : x; + class = res_nametoclass(cl, &success); + if (!success) { + code = 507; + msg = "unrecognized class"; + goto respond; + } + + /* Look for the zone, and do the right thing to it. */ + zp = find_zone(tmp, class); + if (zp == NULL) { + code = 506; + msg = "Zone not found."; + goto respond; + } + switch (zp->z_type) { + case z_master: + ns_stopxfrs(zp); + /*FALLTHROUGH*/ + case z_hint: + block_signals(); + code = 251; + msg = deferred_reload_unsafe(zp); + unblock_signals(); + break; + case z_slave: + case z_stub: + ns_stopxfrs(zp); + if (zonefile_changed_p(zp)) + zp->z_serial = 0; /* force xfer */ + addxfer(zp); + code = 251; + msg = "Slave transfer queued."; + goto respond; + case z_forward: + case z_cache: + default: + msg = "Non reloadable zone."; + code = 507; + break; + } + + respond: + ctl_response(sess, code, msg, 0, NULL, NULL, NULL, NULL, 0); + if (tmp != NULL) + (void)freestr(tmp); +} + +static void +verb_reconfig(struct ctl_sctx *ctl, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + UNUSED(ctl); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + if (strcmp(rest, "-noexpired") != 0) + ns_need(main_need_reconfig); + else + ns_need(main_need_noexpired); + ctl_response(sess, 250, "Reconfig initiated.", + 0, NULL, NULL, NULL, NULL, 0); +} + +static void +verb_dumpdb(struct ctl_sctx *ctl, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + UNUSED(ctl); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + ns_need(main_need_dump); + ctl_response(sess, 250, "Database dump initiated.", 0, NULL, + NULL, NULL, NULL, 0); +} + +static void +verb_stats(struct ctl_sctx *ctl, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + UNUSED(ctl); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + if (rest != NULL && strcmp(rest, "clear") == 0) { + ns_need(main_need_statsdumpandclear); + ctl_response(sess, 250, "Statistics dump and clear initiated.", + 0, NULL, NULL, NULL, NULL, 0); + } else { + ns_need(main_need_statsdump); + ctl_response(sess, 250, "Statistics dump initiated.", + 0, NULL, NULL, NULL, NULL, 0); + } +} + +static void +verb_trace(struct ctl_sctx *ctl, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + int i = atoi(rest); + char *msg = memget(MAX_STR_LEN); + + UNUSED(ctl); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + if (msg == NULL) { + ctl_response(sess, 503, "(out of memory)", 0, + NULL, NULL, NULL, NULL, 0); + return; + } + if (isdigit(*(const unsigned char *)rest) && i >= 0) + desired_debug = i; + else + desired_debug++; + ns_need(main_need_debug); + if (desired_debug == 0) + sprintf(msg, "Debugging turned off."); + else + sprintf(msg, "Debug level: %d", desired_debug); + ctl_response(sess, 250, msg, 0, NULL, trace_closure, msg, NULL, 0); +} + +static void +trace_closure(struct ctl_sctx *sctx, struct ctl_sess *sess, void *uap) { + char *msg = uap; + + UNUSED(sctx); + UNUSED(sess); + + memput(msg, MAX_STR_LEN); +} + +static void +verb_notrace(struct ctl_sctx *ctl, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + UNUSED(ctl); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + desired_debug = 0; + ns_need(main_need_debug); + ctl_response(sess, 250, "Debugging turned off.", + 0, NULL, NULL, NULL, NULL, 0); +} + +static void +verb_querylog(struct ctl_sctx *ctl, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + static const char on[] = "Query logging is now on.", + off[] = "Query logging is now off."; + + UNUSED(ctl); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + toggle_qrylog(); + ctl_response(sess, 250, qrylog ? on : off, + 0, NULL, NULL, NULL, NULL, 0); +} + +static void +verb_help(struct ctl_sctx *ctl, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + UNUSED(ctl); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + ctl_sendhelp(sess, 214); +} + +static void +verb_quit(struct ctl_sctx *ctl, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + UNUSED(ctl); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + ctl_response(sess, 221, "End of control session.", CTL_EXIT, NULL, + NULL, NULL, NULL, 0); +} + +static char hex[] = "0123456789abcdef"; + +struct pvt_args { + int argc; + char text[MAX_STR_LEN]; +}; + +static void +args_closure(struct ctl_sctx *sctx, struct ctl_sess *sess, void *uap) { + struct pvt_args *pvt = ctl_getcsctx(sess); + + UNUSED(sctx); + UNUSED(uap); + + memput(pvt, sizeof *pvt); + ctl_setcsctx(sess, NULL); +} + +static void +verb_args(struct ctl_sctx *ctl, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct pvt_args *pvt = ctl_getcsctx(sess); + char *cp, *tp; + + UNUSED(ctl); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + if (pvt == NULL) { + unsigned int i = 0; + pvt = memget(sizeof *pvt); + if (pvt == NULL) { + ctl_response(sess, 505, "(out of memory)", + 0, NULL, NULL, NULL, NULL, 0); + return; + } + pvt->argc = 0; + ctl_setcsctx(sess, pvt); + + /* Send the arguement count. */ + while (saved_argv[i] != NULL) + i++; + sprintf(pvt->text, "%u", i); + ctl_response(sess, 250, pvt->text, CTL_MORE, + NULL, args_closure, NULL, NULL, 0); + return; + } + + /* + * Percent escape arguement. + */ + cp = saved_argv[pvt->argc++]; + tp = pvt->text; + while (cp && *cp != NULL) + if (*cp == '%' || *cp == ' ' || + !isprint((unsigned char)*cp)) { + if (tp >= pvt->text + sizeof(pvt->text) - 4) + break; + *tp++ = '%'; + *tp++ = hex[(*cp>>4)&0xf]; + *tp++ = hex[(*cp++)&0xf]; + } else { + if (tp >= pvt->text + sizeof(pvt->text) - 2) + break; + *tp++ = *cp++; + } + *tp = '\0'; + + ctl_response(sess, 250, pvt->text, + saved_argv[pvt->argc] == NULL ? 0 : CTL_MORE, + NULL, args_closure, NULL, NULL, 0); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_ctl.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_forw.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_forw.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_forw.c (revision 109985) @@ -0,0 +1,1314 @@ +#if !defined(lint) && !defined(SABER) +static const char sccsid[] = "@(#)ns_forw.c 4.32 (Berkeley) 3/3/91"; +static const char rcsid[] = "$Id: ns_forw.c,v 8.91 2002/05/24 03:04:57 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "port_after.h" + +#include "named.h" + +struct complaint { + u_long tag1, tag2; + time_t expire; + struct complaint *next; +}; + +static struct complaint *complaints = NULL; +static int retry_timer_set = 0; + +/* + * Forward the query to get the answer since its not in the database. + * Returns FW_OK if a request struct is allocated and the query sent. + * Returns FW_DUP if this is a duplicate of a pending request. + * Returns FW_NOSERVER if there were no addresses for the nameservers. + * Returns FW_SERVFAIL on memory allocation error or if asked to do something + * dangerous, such as fwd to ourselves or fwd to the host that asked us. + * + * (no action is taken on errors and qpp is not filled in.) + */ +int +ns_forw(struct databuf *nsp[], u_char *msg, int msglen, + struct sockaddr_in from, struct qstream *qsp, int dfd, + struct qinfo **qpp, const char *dname, int class, int type, + struct namebuf *np, int use_tcp, struct tsig_record *in_tsig) +{ + struct qinfo *qp; + char tmpdomain[MAXDNAME]; + struct sockaddr_in *nsa; + HEADER *hp; + u_int16_t id; + int sendto_errno = 0; + int n, has_tsig, oldqlen = 0; + u_char *oldqbuf = NULL; + u_char *smsg = NULL; + int smsglen, smsgsize = 0, siglen; + u_char sig[TSIG_SIG_SIZE]; + DST_KEY *key; + + ns_debug(ns_log_default, 3, "ns_forw()"); + + hp = (HEADER *) msg; + id = hp->id; + /* Look at them all */ + for (qp = nsqhead; qp != NULL; qp = qp->q_link) { + if (qp->q_id == id && + memcmp(&qp->q_from, &from, sizeof qp->q_from) == 0 && + ((qp->q_cmsglen == 0 && qp->q_msglen == msglen && + memcmp(qp->q_msg + 2, msg + 2, msglen - 2) == 0) || + (qp->q_cmsglen == msglen && + memcmp(qp->q_cmsg + 2, msg + 2, msglen - 2) == 0) + )) { + ns_debug(ns_log_default, 3, "forw: dropped DUP id=%d", + ntohs(id)); + nameserIncr(from.sin_addr, nssRcvdDupQ); + return (FW_DUP); + } + } + + qp = qnew(dname, class, type, 1); + getname(np, tmpdomain, sizeof tmpdomain); + qp->q_domain = savestr(tmpdomain, 1); + qp->q_from = from; /* nslookup wants to know this */ + if (NS_ZFWDTAB(qp->q_fzone)) + nsfwdadd(qp, NS_ZFWDTAB(qp->q_fzone)); + if (NS_ZOPTION_P(qp->q_fzone, OPTION_FORWARD_ONLY)) + n = 0; + else + n = nslookup(nsp, qp, dname, "ns_forw"); + if (n < 0) { + if (n == -1) + ns_debug(ns_log_default, 2, + "forw: nslookup reports danger"); + ns_freeqry(qp); + return (FW_SERVFAIL); + } + if (n == 0 && !NS_ZFWDTAB(qp->q_fzone)) { + ns_debug(ns_log_default, 2, "forw: no nameservers found"); + ns_freeqry(qp); + return (FW_NOSERVER); + } + qp->q_stream = qsp; + qp->q_curaddr = 0; + qp->q_dfd = dfd; + qp->q_id = id; + qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2; + if (in_tsig != NULL) + qp->q_tsig = new_tsig(in_tsig->key, in_tsig->sig, + in_tsig->siglen); + if (use_tcp) + qp->q_flags |= Q_USEVC; + hp->id = qp->q_nsid = htons(nsid_next()); + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); + if ((qp->q_msg = (u_char *)memget((unsigned)msglen)) == NULL) { + ns_notice(ns_log_default, "forw: memget: %s", + strerror(errno)); + ns_freeqry(qp); + return (FW_SERVFAIL); + } + qp->q_msgsize = msglen; + memcpy(qp->q_msg, msg, qp->q_msglen = msglen); + hp = (HEADER *) qp->q_msg; + hp->rd = (qp->q_addr[0].forwarder ? 1 : 0); + qp->q_addr[0].stime = tt; + + schedretry(qp, retrytime(qp)); + + nsa = Q_NEXTADDR(qp, 0); + ns_debug(ns_log_default, 1, + "forw: forw -> [%s].%d ds=%d nsid=%d id=%d %dms retry %dsec", + inet_ntoa(nsa->sin_addr), + ntohs(nsa->sin_port), ds, + ntohs(qp->q_nsid), ntohs(qp->q_id), + (qp->q_addr[0].nsdata != NULL) + ? qp->q_addr[0].nsdata->d_nstime + : -1, + (int)(qp->q_time - tt.tv_sec)); + +#ifdef DEBUG + if (debug >= 10) + res_pquery(&res, msg, msglen, log_get_stream(packet_channel)); +#endif + key = qp->q_keys[0]; + if (key == NULL) + key = qp->q_keys[0] = tsig_key_from_addr(nsa->sin_addr); + if (key != NULL || !qp->q_addr[0].noedns) { + smsgsize = qp->q_msglen + TSIG_BUF_SIZE + 11; + smsg = memget(smsgsize); + if (smsg == NULL) + ns_panic(ns_log_default, 1, "ns_forw: memget failed"); + smsglen = qp->q_msglen; + siglen = sizeof(sig); + memcpy(smsg, qp->q_msg, qp->q_msglen); + } + + if (!qp->q_addr[0].noedns) + smsglen += ns_add_opt(smsg, smsg + smsglen, smsgsize, 0, 0, + EDNS_MESSAGE_SZ, 0, NULL, 0); + + if (key != NULL) { + n = ns_sign(smsg, &smsglen, smsgsize, NOERROR, key, NULL, 0, + sig, &siglen, 0); + if (n == 0) { + has_tsig = 1; + free_tsig(qp->q_nstsig); + qp->q_nstsig = new_tsig(key, sig, siglen); + } else { + has_tsig = 0; + free_tsig(qp->q_nstsig); + qp->q_nstsig = NULL; + INSIST(0); + } + } else { + has_tsig = 0; + free_tsig(qp->q_nstsig); + qp->q_nstsig = NULL; + } + + if (smsg != NULL) { + oldqbuf = qp->q_msg; + oldqlen = qp->q_msglen; + qp->q_msglen = smsglen; + qp->q_msg = smsg; + hp = (HEADER *) qp->q_msg; + } + + if (qp->q_flags & Q_USEVC) { + if (tcp_send(qp) != NOERROR) { + if (!haveComplained(ina_ulong(nsa->sin_addr), + (u_long)tcpsendStr)) + ns_info(ns_log_default, + "ns_forw: tcp_send(%s) failed: %s", + sin_ntoa(*nsa), strerror(errno)); + } + } else if (sendto(ds, (char *)qp->q_msg, qp->q_msglen, 0, + (struct sockaddr *)nsa, + sizeof(struct sockaddr_in)) < 0) { + sendto_errno = errno; + if (!haveComplained(ina_ulong(nsa->sin_addr), + (u_long)sendtoStr)) + ns_info(ns_log_default, "ns_forw: sendto(%s): %s", + sin_ntoa(*nsa), strerror(errno)); + nameserIncr(nsa->sin_addr, nssSendtoErr); + } + + if (smsgsize != 0) { + memput(smsg, smsgsize); + qp->q_msg = oldqbuf; + qp->q_msglen = oldqlen; + hp = (HEADER *) qp->q_msg; + } + + nameserIncr(from.sin_addr, nssRcvdFwdQ); + nameserIncr(nsa->sin_addr, nssSentFwdQ); + if (qpp) + *qpp = qp; + hp->rd = 1; + switch (sendto_errno) { + case ENETDOWN: + case ENETUNREACH: + case EHOSTDOWN: + case EHOSTUNREACH: + unsched(qp); + schedretry(qp, (time_t) 0); + } + return (0); +} + +/* haveComplained(tag1, tag2) + * check to see if we have complained about (tag1,tag2) recently + * returns: + * boolean: have we complained recently? + * side-effects: + * outdated complaint records removed from our static list + * author: + * Paul Vixie (DECWRL) April 1991 + */ +int +haveComplained(u_long tag1, u_long tag2) { + struct complaint *cur, *next, *prev; + int r = 0; + + for (cur = complaints, prev = NULL; + cur != NULL; + prev = cur, cur = next) { + next = cur->next; + if (tt.tv_sec > cur->expire) { + if (prev) + prev->next = next; + else + complaints = next; + memput(cur, sizeof *cur); + cur = prev; + } else if (tag1 == cur->tag1 && tag2 == cur->tag2) + r++; + } + if (!r) { + cur = (struct complaint *)memget(sizeof(struct complaint)); + if (cur) { + cur->tag1 = tag1; + cur->tag2 = tag2; + cur->expire = tt.tv_sec + INIT_REFRESH; /* "10:00" */ + cur->next = NULL; + if (prev) + prev->next = cur; + else + complaints = cur; + } + } + return (r); +} + +void +freeComplaints(void) { + struct complaint *cur, *next; + + for (cur = complaints; cur != NULL; cur = next) { + next = cur->next; + memput(cur, sizeof *cur); + } + complaints = NULL; +} + +/* void + * nslookupComplain(sysloginfo, queryname, complaint, dname, a_rr) + * Issue a complaint about a dangerous situation found by nslookup(). + * params: + * sysloginfo is a string identifying the complainant. + * queryname is the domain name associated with the problem. + * complaint is a string describing what is wrong. + * dname and a_rr are the problematic other name server. + */ +static void +nslookupComplain(const char *sysloginfo, const char *queryname, + const char *complaint, const char *dname, + const struct databuf *a_rr, const struct databuf *nsdp) +{ + char *a, *ns; + const char *a_type; + int print_a; + + ns_debug(ns_log_default, 2, "NS '%s' %s", dname, complaint); + if (sysloginfo && queryname && !haveComplained((u_long)queryname, + (u_long)complaint)) { + char nsbuf[20], abuf[20]; + + a = ns = (char *)NULL; + print_a = (a_rr->d_type == T_A); + a_type = p_type(a_rr->d_type); + if (a_rr->d_rcode) { + print_a = 0; + switch(a_rr->d_rcode) { + case NXDOMAIN: + a_type = "NXDOMAIN"; + break; + case NOERROR_NODATA: + a_type = "NODATA"; + break; + } + } + if (nsdp != NULL) { + if (nsdp->d_addr.s_addr != htonl(0)) { + strcpy(nsbuf, + inet_ntoa(nsdp->d_addr)); + ns = nsbuf; + } else { + ns = zones[nsdp->d_zone].z_origin; + } + } + if (a_rr->d_addr.s_addr != htonl(0)) { + strcpy(abuf, inet_ntoa(a_rr->d_addr)); + a = abuf; + } else { + a = zones[a_rr->d_zone].z_origin; + } + if (a != NULL || ns != NULL) + ns_info(ns_log_default, + "%s: query(%s) %s (%s:%s) learnt (%s=%s:NS=%s)", + sysloginfo, queryname, + complaint, dname, + print_a ? + inet_ntoa(ina_get(a_rr->d_data)) : "", + a_type, + a ? a : "", + ns ? ns : "" ); + else + ns_info(ns_log_default, "%s: query(%s) %s (%s:%s)", + sysloginfo, queryname, + complaint, dname, + print_a ? + inet_ntoa(ina_get(a_rr->d_data)) : ""); + } +} + +/* + * nslookup(nsp, qp, syslogdname, sysloginfo) + * Lookup the address for each nameserver in `nsp' and add it to + * the list saved in the qinfo structure pointed to by `qp'. + * Omits information about nameservers that we shouldn't ask. + * Detects the following dangerous operations: + * One of the A records for one of the nameservers in nsp + * refers to the address of one of our own interfaces; + * One of the A records refers to the nameserver port on + * the host that asked us this question. + * returns: the number of addresses added, or -1 if a dangerous operation + * is detected. + * side effects: + * logs if a dangerous situation is detected and + * (syslogdname && sysloginfo) + */ +int +nslookup(struct databuf *nsp[], struct qinfo *qp, + const char *syslogdname, const char *sysloginfo) +{ + struct namebuf *np; + struct databuf *dp, *nsdp; + struct qserv *qs; + int n; + u_int i; + struct hashbuf *tmphtp; + char *dname; + const char *fname; + int oldn, naddr, class, found_arr, potential_ns, lame_ns; + time_t curtime; + int found_auth6; + + ns_debug(ns_log_default, 3, "nslookup(nsp=%p, qp=%p, \"%s\", d=%d)", + nsp, qp, syslogdname, qp->q_distance); + + lame_ns = potential_ns = 0; + naddr = n = qp->q_naddr; + curtime = (u_long) tt.tv_sec; + while ((nsdp = *nsp++) != NULL && n < NSMAX) { + class = nsdp->d_class; + dname = (char *)nsdp->d_data; + ns_debug(ns_log_default, 3, + "nslookup: NS \"%s\" c=%d t=%d (flags 0x%lu)", + dname, class, nsdp->d_type, (u_long)nsdp->d_flags); + + /* don't put in servers we have tried */ + for (i = 0; i < qp->q_nusedns; i++) { + if (qp->q_usedns[i] == nsdp) { + ns_debug(ns_log_default, 2, + "skipping used NS w/name %s", + nsdp->d_data); + goto skipserver; + } + } + + /* skip lame servers */ + if ((nsdp->d_flags & DB_F_LAME) != 0) { + time_t when; + when = db_lame_find(qp->q_domain, nsdp); + if (when != 0 && when > tt.tv_sec) { + ns_debug(ns_log_default, 3, + "skipping lame NS"); + lame_ns++; + goto skipserver; + } + } + + found_arr = 0; + found_auth6 = 0; + tmphtp = ((nsdp->d_flags & DB_F_HINT) ?fcachetab :hashtab); + np = nlookup(dname, &tmphtp, &fname, 0); + if (np == NULL) { + ns_debug(ns_log_default, 3, "%s: not found %s %p", + dname, fname, np); + goto need_sysquery; + } + if (fname != dname) + goto need_sysquery; + oldn = n; + + /* look for name server addresses */ + (void)delete_stale(np); + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + struct in_addr nsa; + + if (dp->d_type == T_CNAME && dp->d_class == class) { + static const char *complaint = + "NS points to CNAME"; + if (dp->d_rcode) + continue; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); + goto skipserver; + } + if (dp->d_rcode == NXDOMAIN && dp->d_class == class) + goto skipserver; + if (dp->d_class == class && + (dp->d_type == T_AAAA || dp->d_type == ns_t_a6) && + (zones[dp->d_zone].z_type == z_master || + zones[dp->d_zone].z_type == z_slave)) { + found_auth6++; + continue; + } + if (dp->d_type != T_A || dp->d_class != class) + continue; + if (dp->d_rcode) { + /* Negative caching element. */ + goto skipserver; + } + if (ina_hlong(ina_get(dp->d_data)) == INADDR_ANY) { + static const char *complaint = + "Bogus (0.0.0.0) A RR"; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); + continue; + } +#ifdef INADDR_LOOPBACK + if (ina_hlong(ina_get(dp->d_data))==INADDR_LOOPBACK) { + static const char *complaint = + "Bogus LOOPBACK A RR"; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); + continue; + } +#endif +#ifdef INADDR_BROADCAST + if (ina_hlong(ina_get(dp->d_data))==INADDR_BROADCAST){ + static const char *complaint = + "Bogus BROADCAST A RR"; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); + continue; + } +#endif +#ifdef IN_MULTICAST + if (IN_MULTICAST(ina_hlong(ina_get(dp->d_data)))) { + static const char *complaint = + "Bogus MULTICAST A RR"; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); + continue; + } +#endif + /* + * Don't use records that may become invalid to + * reference later when we do the rtt computation. + * Never delete our safety-belt information! + */ + if ((dp->d_zone == DB_Z_CACHE) && + (dp->d_ttl < (u_int32_t)curtime) && + !(dp->d_flags & DB_F_HINT) ) + { + ns_debug(ns_log_default, 1, + "nslookup: stale '%s'", + NAME(*np)); + n = oldn; + found_arr = 0; + goto need_sysquery; + } + + found_arr++; + nsa = ina_get(dp->d_data); + /* don't put in duplicates */ + qs = qp->q_addr; + for (i = 0; i < (u_int)n; i++, qs++) + if (ina_equal(qs->ns_addr.sin_addr, nsa)) + goto skipaddr; + qs->ns_addr.sin_family = AF_INET; + qs->ns_addr.sin_port = ns_port; + qs->ns_addr.sin_addr = nsa; + qp->q_keys[n] = NULL; + qs->ns = nsdp; + qs->nsdata = dp; + qs->forwarder = 0; + qs->noedns = dp->d_noedns; + if (!qs->noedns) { + server_info si = find_server(nsa); + if (si && (si->flags & SERVER_INFO_EDNS) == 0) + qs->noedns = 1; + } + qs->nretry = 0; + /* + * If this A RR has no RTT, initialize its RTT to a + * small random value. + */ + if (dp->d_nstime == 0) + dp->d_nstime = 1 + + (int)(25.0*rand()/(RAND_MAX + 1.0)); + /* + * if we are being asked to fwd a query whose + * nameserver list includes our own name/address(es), + * then we have detected a lame delegation and rather + * than melt down the network and hose down the other + * servers (who will hose us in return), we'll return + * -1 here which will cause SERVFAIL to be sent to + * the client's resolver which will hopefully then + * shut up. + * + * (originally done in nsContainsUs by vix@dec mar92; + * moved into nslookup by apb@und jan1993) + * + * try to limp along instead of denying service + * gdonl mar96 + */ + if (aIsUs(nsa)) { + static const char *complaint = + "contains our address"; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); + continue; + } + /* + * If we want to forward to a host that asked us + * this question then either we or they are sick + * (unless they asked from some port other than + * their nameserver port). (apb@und jan1993) + * + * try to limp along instead of denying service + * gdonl mar96 + */ + if (memcmp(&qp->q_from, &qs->ns_addr, + sizeof(qp->q_from)) == 0) + { + static const char *complaint = "forwarding loop"; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); + continue; + } +#ifdef BOGUSNS + /* + * Don't forward queries to bogus servers. Note + * that this is unlike the previous tests, which + * are fatal to the query. Here we just skip the + * server, which is only fatal if it's the last + * server. Note also that we antialias here -- all + * A RR's of a server are considered the same server, + * and if any of them is bogus we skip the whole + * server. Those of you using multiple A RR's to + * load-balance your servers will (rightfully) lose + * here. But (unfortunately) only if they are bogus. + */ + if (ip_match_address(bogus_nameservers, nsa) > 0) + goto skipserver; +#endif + if (server_options->blackhole_acl != NULL && + ip_match_address(server_options->blackhole_acl, + nsa) == 1) + continue; + + n++; + if (n >= NSMAX) + break; + skipaddr: + (void)NULL; + } + ns_debug(ns_log_default, 8, "nslookup: %d ns addrs", n); + need_sysquery: + if (found_arr == 0 && found_auth6 == 0) { + potential_ns++; + if (qp->q_distance < NS_MAX_DISTANCE) + (void) sysquery(dname, class, T_A, NULL, NULL, + 0, ns_port, QUERY, + qp->q_distance + 1); + } + skipserver: + (void)NULL; + } + ns_debug(ns_log_default, 3, "nslookup: %d ns addrs total", n); + qp->q_naddr = n; + if (n == 0 && potential_ns == 0 && !NS_ZFWDTAB(qp->q_fzone)) { + static const char *complaint = "No possible A RRs"; + if (lame_ns != 0) + complaint = "All possible A RR's lame"; + if (sysloginfo && syslogdname && + !haveComplained((u_long)syslogdname, (u_long)complaint)) + { + ns_info(ns_log_default, "%s: query(%s) %s", + sysloginfo, syslogdname, complaint); + } + return ((lame_ns == 0) ? -1 : -2); + } + /* Update the refcounts before the sort. */ + for (i = naddr; i < (u_int)n; i++) { + DRCNTINC(qp->q_addr[i].nsdata); + DRCNTINC(qp->q_addr[i].ns); + } + /* Just sort the NS RR's we added, since the forwarders may + * be ahead of us (naddr > 0) + */ + if (n > naddr) { + qsort((char *)(qp->q_addr+naddr), n-naddr, sizeof(struct qserv), + (int (*)(const void *, const void *))qcomp); + } + return (n - naddr); +} + +/* + * qcomp - compare two NS addresses, and return a negative, zero, or + * positive value depending on whether the first NS address is + * "better than", "equally good as", or "inferior to" the second + * NS address. + * + * How "goodness" is defined (for the purposes of this routine): + * - If the estimated round trip times differ by an amount deemed significant + * then the one with the smaller estimate is preferred; else + * - If we can determine which one is topologically closer then the + * closer one is preferred; else + * - The one with the smaller estimated round trip time is preferred + * (zero is returned if the two estimates are identical). + * + * How "topological closeness" is defined (for the purposes of this routine): + * Ideally, named could consult some magic map of the Internet and + * determine the length of the path to an arbitrary destination. Sadly, + * no such magic map exists. However, named does have a little bit of + * topological information in the form of the sortlist (which includes + * the directly connected subnet(s), the directly connected net(s), and + * any additional nets that the administrator has added using the "sortlist" + * directive in the bootfile. Thus, if only one of the addresses matches + * something in the sortlist then it is considered to be topologically + * closer. If both match, but match different entries in the sortlist, + * then the one that matches the entry closer to the beginning of the + * sorlist is considered to be topologically closer. In all other cases, + * topological closeness is ignored because it's either indeterminate or + * equal. + * + * How times are compared: + * Both times are rounded to the closest multiple of the NOISE constant + * defined below and then compared. If the rounded values are equal + * then the difference in the times is deemed insignificant. Rounding + * is used instead of merely taking the absolute value of the difference + * because doing the latter would make the ordering defined by this + * routine be incomplete in the mathematical sense (e.g. A > B and + * B > C would not imply A > C). The mathematics are important in + * practice to avoid core dumps in qsort(). + * + * XXX: this doesn't solve the European root nameserver problem very well. + * XXX: we should detect and mark as inferior nameservers that give bogus + * answers + * + * (this was originally vixie's stuff but almquist fixed fatal bugs in it + * and wrote the above documentation) + */ + +/* + * RTT delta deemed to be significant, in milliseconds. With the current + * definition of RTTROUND it must be a power of 2. + */ +#define NOISE 64 + +#define RTTROUND(rtt) (((rtt) + (NOISE >> 1)) & ~(NOISE - 1)) + +int +qcomp(struct qserv *qs1, struct qserv *qs2) { + u_int rtt1, rtt2, rttr1, rttr2; + + if (qs1->nsdata == NULL) { + rtt1 = 0; + rttr1 = 0; + } else { + rtt1 = qs1->nsdata->d_nstime; + rttr1 = RTTROUND(rtt1); + } + if (qs2->nsdata == NULL) { + rtt2 = 0; + rttr2 = 0; + } else { + rtt2 = qs2->nsdata->d_nstime; + rttr2 = RTTROUND(rtt2); + } + +#ifdef DEBUG + if (debug >= 10) { + char t[sizeof "255.255.255.255"]; + + strcpy(t, inet_ntoa(qs1->ns_addr.sin_addr)); + ns_debug(ns_log_default, 10, + "qcomp(%s, %s) %u (%u) - %u (%u) = %u", + t, inet_ntoa(qs2->ns_addr.sin_addr), + rtt1, rttr1, rtt2, rttr2, rtt1 - rtt2); + } +#endif + if (rttr1 == rttr2) { + int pos1, pos2, pdiff; + + pos1 = distance_of_address(server_options->topology, + qs1->ns_addr.sin_addr); + pos2 = distance_of_address(server_options->topology, + qs2->ns_addr.sin_addr); + pdiff = pos1 - pos2; + ns_debug(ns_log_default, 10, "\tpos1=%d, pos2=%d", pos1, pos2); + if (pdiff != 0) + return (pdiff); + } + return (rtt1 - rtt2); +} +#undef RTTROUND + +/* + * Arrange that forwarded query (qp) is retried after t seconds. + * Query list will be sorted after z_time is updated. + */ +void +schedretry(struct qinfo *qp, time_t t) { + struct qinfo *qp1, *qp2; + + ns_debug(ns_log_default, 4, "schedretry(%p, %ld sec)", qp, (long)t); + if (qp->q_time) + ns_debug(ns_log_default, 4, + "WARNING: schedretry(%#lx, %ld) q_time already %ld", + (u_long)qp, (long)t, (long)qp->q_time); + gettime(&tt); + t += (u_long) tt.tv_sec; + qp->q_time = t; + + if ((qp1 = retryqp) == NULL) { + retryqp = qp; + qp->q_next = NULL; + goto done; + } + if (t < qp1->q_time) { + qp->q_next = qp1; + retryqp = qp; + goto done; + } + while ((qp2 = qp1->q_next) != NULL && qp2->q_time < t) + qp1 = qp2; + qp1->q_next = qp; + qp->q_next = qp2; + done: + reset_retrytimer(); +} + +/* + * Unsched is called to remove a forwarded query entry. + */ +void +unsched(struct qinfo *qp) { + struct qinfo *np; + + ns_debug(ns_log_default, 3, "unsched(%#lx, %d)", + (u_long)qp, ntohs(qp->q_id)); + if (retryqp == qp) { + retryqp = qp->q_next; + } else { + for (np = retryqp; np->q_next != NULL; np = np->q_next) { + if (np->q_next != qp) + continue; + np->q_next = qp->q_next; /* dequeue */ + break; + } + } + qp->q_next = NULL; /* sanity check */ + qp->q_time = 0; + reset_retrytimer(); +} + +void +reset_retrytimer() { + static evTimerID id; + + if (retry_timer_set) { + (void) evClearTimer(ev, id); + retry_timer_set = 0; + } + + if (retryqp) { + evSetTimer(ev, retrytimer, NULL, + evConsTime(retryqp->q_time, 0), + evConsTime(0, 0), &id); + retry_timer_set = 1; + } else + memset(&id, 0, sizeof id); +} + +void +retrytimer(evContext ctx, void *uap, struct timespec due, + struct timespec ival) { + + UNUSED(ctx); + UNUSED(uap); + UNUSED(due); + UNUSED(ival); + + retry_timer_set = 0; + retry(retryqp, 0); +} + +/* + * Retry is called to retransmit query 'qp'. + */ +void +retry(struct qinfo *qp, int samehost) { + int n, has_tsig, oldqlen = 0; + HEADER *hp; + struct sockaddr_in *nsa; + int sendto_errno = 0; + u_char *oldqbuf = NULL; + u_char *smsg = NULL; + int smsglen, smsgsize = 0, siglen; + u_char sig[TSIG_SIG_SIZE]; + DST_KEY *key; + + ns_debug(ns_log_default, 3, "retry(%#lx) id=%d", (u_long)qp, + ntohs(qp->q_id)); + + if (qp->q_msg == NULL) { + qremove(qp); + return; + } + + if (qp->q_expire < tt.tv_sec) { + ns_debug(ns_log_default, 1, + "retry(%#lx): expired @ %lu (%d secs before now (%lu))", + (u_long)qp, (u_long)qp->q_expire, + (int)(tt.tv_sec - qp->q_expire), + (u_long)tt.tv_sec); + goto fail; + } + + /* Try next address. */ + n = qp->q_curaddr; + if (samehost) { + qp->q_addr[n].nretry++; + if (qp->q_addr[n].nretry < MAXRETRY) + goto found; + qp->q_addr[n].nretry--; + } + + if (qp->q_naddr > 0) { + qp->q_addr[n].noedns = 1; + ++qp->q_addr[n].nretry; + do { + if (++n >= (int)qp->q_naddr) + n = 0; + if ((qp->q_flags & Q_ZSERIAL) != 0 && + qp->q_addr[n].serial != 0) + continue; + if (qp->q_addr[n].nretry < MAXRETRY) + goto found; + } while (n != qp->q_curaddr); + if ((qp->q_flags & Q_ZSERIAL) != 0) { + qremove(qp); + return; + } + } + fail: + /* + * Give up. Can't reach destination. + */ + hp = (HEADER *)(qp->q_cmsg ? qp->q_cmsg : qp->q_msg); + if ((qp->q_flags & Q_PRIMING) != 0) { + /* Can't give up priming */ + if (qp->q_expire < tt.tv_sec) { + /* + * The query has expired. Reset it and retry from + * the beginning. + */ + hp->rcode = NOERROR; + hp->qr = hp->aa = 0; + for (n = 0; n < (int)qp->q_naddr; n++) + qp->q_addr[n].nretry = 0; + n = 0; + qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2; + goto found; + } + /* + * The query hasn't expired yet; it probably ran out + * of servers or forwarders. Wait up to 60 seconds + * past the expire time. + */ + unsched(qp); + schedretry(qp, (time_t)(qp->q_expire - tt.tv_sec + 60)); + return; + } + ns_debug(ns_log_default, 5, "give up"); + if ((qp->q_flags & Q_SYSTEM) == 0) { + n = (qp->q_cmsg ? qp->q_cmsglen : qp->q_msglen); + hp->id = qp->q_id; + hp->qr = 1; + hp->ra = (NS_OPTION_P(OPTION_NORECURSE) == 0); + hp->rd = 1; + hp->rcode = SERVFAIL; +#ifdef DEBUG + if (debug >= 10) + res_pquery(&res, qp->q_msg, n, + log_get_stream(packet_channel)); +#endif + if (send_msg((u_char *)hp, n, qp)) { + ns_debug(ns_log_default, 1, + "gave up retry(%#lx) nsid=%d id=%d", + (u_long)qp, + ntohs(qp->q_nsid), ntohs(qp->q_id)); + } + if (NS_OPTION_P(OPTION_HOSTSTATS)) + nameserIncr(qp->q_from.sin_addr, nssSentFail); + } + qremove(qp); + return; + + found: + if (qp->q_addr[n].nretry == 0) + qp->q_addr[n].stime = tt; + qp->q_curaddr = n; + hp = (HEADER *)qp->q_msg; + hp->rd = (qp->q_addr[n].forwarder ? 1 : 0); + nsa = Q_NEXTADDR(qp, n); + ns_debug(ns_log_default, 1, + "%s(addr=%d n=%d) -> [%s].%d ds=%d nsid=%d id=%d %dms", + (qp->q_addr[n].forwarder ? "reforw" : "resend"), + n, qp->q_addr[n].nretry, + inet_ntoa(nsa->sin_addr), + ntohs(nsa->sin_port), ds, + ntohs(qp->q_nsid), ntohs(qp->q_id), + (qp->q_addr[n].nsdata != 0) + ? qp->q_addr[n].nsdata->d_nstime + : (-1)); +#ifdef DEBUG + if (debug >= 10) + res_pquery(&res, qp->q_msg, qp->q_msglen, + log_get_stream(packet_channel)); +#endif + key = qp->q_keys[n]; + if (key == NULL) + key = qp->q_keys[n] = tsig_key_from_addr(nsa->sin_addr); + if (key != NULL || !qp->q_addr[n].noedns) { + smsgsize = qp->q_msglen + TSIG_BUF_SIZE + 11; + smsg = memget(smsgsize); + smsglen = qp->q_msglen; + siglen = sizeof(sig); + memcpy(smsg, qp->q_msg, qp->q_msglen); + } + + if (!qp->q_addr[n].noedns) + smsglen += ns_add_opt(smsg, smsg + smsglen, smsgsize, 0, 0, + EDNS_MESSAGE_SZ, 0, NULL, 0); + + if (key != NULL) { + n = ns_sign(smsg, &smsglen, smsgsize, NOERROR, key, NULL, 0, + sig, &siglen, 0); + if (n == 0) { + has_tsig = 1; + free_tsig(qp->q_nstsig); + qp->q_nstsig = new_tsig(key, sig, siglen); + } else { + has_tsig = 0; + free_tsig(qp->q_nstsig); + qp->q_nstsig = NULL; + INSIST(0); + } + } else { + has_tsig = 0; + free_tsig(qp->q_nstsig); + qp->q_nstsig = NULL; + } + + if (smsg != NULL) { + oldqbuf = qp->q_msg; + oldqlen = qp->q_msglen; + qp->q_msglen = smsglen; + qp->q_msg = smsg; + } + + if (qp->q_flags & Q_USEVC) { + if (tcp_send(qp) != NOERROR) + ns_debug(ns_log_default, 3, + "error resending tcp msg: %s", + strerror(errno)); + } else if (sendto(ds, (char*)qp->q_msg, qp->q_msglen, 0, + (struct sockaddr *)nsa, + sizeof(struct sockaddr_in)) < 0) + { + sendto_errno = errno; + ns_debug(ns_log_default, 3, "error resending msg: %s", + strerror(errno)); + } + if (smsgsize != 0) { + memput(smsg, smsgsize); + qp->q_msg = oldqbuf; + qp->q_msglen = oldqlen; + } + hp->rd = 1; /* leave set to 1 for dup detection */ + nameserIncr(nsa->sin_addr, nssSentDupQ); + unsched(qp); + switch (sendto_errno) { + case ENETDOWN: + case ENETUNREACH: + case EHOSTDOWN: + case EHOSTUNREACH: + schedretry(qp, (time_t) 0); + return; + } + schedretry(qp, retrytime(qp)); +} + +/* + * Compute retry time for the next server for a query. + * Use a minimum time of RETRYBASE (4 sec.) or twice the estimated + * service time; * back off exponentially on retries, but place a 45-sec. + * ceiling on retry times for now. (This is because we don't hold a reference + * on servers or their addresses, and we have to finish before they time out.) + */ +time_t +retrytime(struct qinfo *qp) { + time_t t, u, v; + struct qserv *ns = &qp->q_addr[qp->q_curaddr]; + + if (ns->nsdata != NULL) + t = (time_t) MAX(RETRYBASE, 2 * ns->nsdata->d_nstime / 1000); + else + t = (time_t) RETRYBASE; + u = t << ns->nretry; + v = MIN(u, RETRY_TIMEOUT); /* max. retry timeout for now */ + ns_debug(ns_log_default, 3, + "retrytime: nstime%ldms t%ld nretry%ld u%ld : v%ld", + ns->nsdata ? (long)(ns->nsdata->d_nstime / 1000) : (long)-1, + (long)t, (long)ns->nretry, (long)u, (long)v); + return (v); +} + +void +qflush() { + while (nsqhead) + qremove(nsqhead); + nsqhead = NULL; + priming = 0; +} + +void +qremove(struct qinfo *qp) { + ns_debug(ns_log_default, 3, "qremove(%#lx)", (u_long)qp); + + if ((qp->q_flags & Q_ZSERIAL) != 0) + qserial_answer(qp); + unsched(qp); + ns_freeqry(qp); +} + +struct qinfo * +qfindid(u_int16_t id) { + struct qinfo *qp; + + for (qp = nsqhead; qp != NULL; qp = qp->q_link) + if (qp->q_nsid == id) + break; + ns_debug(ns_log_default, 3, "qfindid(%d) -> %#lx", ntohs(id), + (u_long)qp); + return (qp); +} + +struct qinfo * +qnew(const char *name, int class, int type, int forward) { + struct qinfo *qp; + const char *s; + int escape = 0; + + qp = (struct qinfo *)memget(sizeof *qp); + if (qp == NULL) + ns_panic(ns_log_default, 1, "qnew: memget failed"); + memset(qp, 0, sizeof *qp); + ns_debug(ns_log_default, 5, "qnew(%#lx)", (u_long)qp); +#ifdef BIND_NOTIFY + qp->q_notifyzone = DB_Z_CACHE; +#endif + qp->q_link = nsqhead; + nsqhead = qp; + qp->q_name = savestr(name, 1); + qp->q_class = (u_int16_t)class; + qp->q_type = (u_int16_t)type; + qp->q_flags = 0; + s = name; + qp->q_fzone = NULL; + for (;forward;) { /* find forwarding zone, if any */ + if ((qp->q_fzone = find_zone(s, class)) != NULL && + (qp->q_fzone->z_flags & Z_FORWARD_SET) != 0) + break; + qp->q_fzone = NULL; + if (*s == '\0') + break; + while (*s != '\0' && (escape || *s != '.')) { + escape = escape ? 0 : (*s == '\\'); + s++; + } + if (*s != '\0') + s++; + } + return (qp); +} + +void +ns_freeqns(struct qinfo *qp) { + unsigned int i; + + for (i = 0 ; i < qp->q_naddr ; i++) { + if (qp->q_addr[i].ns != NULL) + db_detach(&qp->q_addr[i].ns); + if (qp->q_addr[i].nsdata != NULL) + db_detach(&qp->q_addr[i].nsdata); + } +} + +void +ns_freeqry(struct qinfo *qp) { + struct qinfo *np; + + ns_debug(ns_log_default, 3, "ns_freeqry(%#lx)", (u_long)qp); + if (qp->q_next) + ns_debug(ns_log_default, 1, + "WARNING: ns_freeqry of linked ptr %#lx", (u_long)qp); + if (qp->q_msg != NULL) + memput(qp->q_msg, qp->q_msgsize); + if (qp->q_cmsg != NULL) + memput(qp->q_cmsg, qp->q_cmsgsize); + if (qp->q_domain != NULL) + qp->q_domain = freestr(qp->q_domain); + if (qp->q_name != NULL) + qp->q_name = freestr(qp->q_name); + if (qp->q_tsig != NULL) + memput(qp->q_tsig, sizeof(struct tsig_record)); + if (qp->q_nstsig != NULL) + memput(qp->q_nstsig, sizeof(struct tsig_record)); + ns_freeqns(qp); + if (nsqhead == qp) + nsqhead = qp->q_link; + else { + for(np = nsqhead; + np->q_link != NULL; + np = np->q_link) { + if (np->q_link != qp) + continue; + np->q_link = qp->q_link; /* dequeue */ + break; + } + } + memput(qp, sizeof *qp); +} + +void +nsfwdadd(struct qinfo *qp, struct fwdinfo *fwd) { + int i, n; + struct qserv *qs; + + n = qp->q_naddr; + while (fwd != NULL && n < NSMAX) { + qs = qp->q_addr; + for (i = 0; i < n; i++, qs++) + if (ina_equal(qs->ns_addr.sin_addr, + fwd->fwddata->fwdaddr.sin_addr)) + goto nextfwd; + qs->ns_addr = fwd->fwddata->fwdaddr; + qs->ns = fwd->fwddata->ns; + qs->nsdata = fwd->fwddata->nsdata; + qs->forwarder = 1; + qs->noedns = fwd->fwddata->nsdata->d_noedns; + if (!qs->noedns) { + server_info si = find_server(qs->ns_addr.sin_addr); + if (si && (si->flags & SERVER_INFO_EDNS) == 0) + qs->noedns = 1; + } + qs->nretry = 0; + n++; + nextfwd: + fwd = fwd->next; + } + + /* Update the refcounts before the sort. */ + for (i = qp->q_naddr; i < n; i++) { + DRCNTINC(qp->q_addr[i].nsdata); + DRCNTINC(qp->q_addr[i].ns); + } + qp->q_naddr = n; + if (n > 1) { + qsort((char *)qp->q_addr, n, sizeof(struct qserv), + (int (*)(const void *, const void *))qcomp); + } +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_forw.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_glob.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_glob.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_glob.h (revision 109985) @@ -0,0 +1,346 @@ +/* + * from ns.h 4.33 (Berkeley) 8/23/90 + * $Id: ns_glob.h,v 8.58 2002/06/05 04:53:50 marka Exp $ + */ + +/* + * Copyright (c) 1986 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * Global variables for the name server. + */ + + /* original argv[] from main() */ +DECL char **saved_argv; + +#ifdef DEBUG +DECL int debug INIT(0); +DECL int desired_debug INIT(0); +#endif + + /* global event context */ +DECL evContext ev; + + /* global resolver context. */ +DECL struct __res_state res; + + /* list of open streams */ +DECL struct qstream *streamq; + + /* often set to the current time */ +DECL struct timeval tt; + + /* head of allocated queries */ +DECL struct qinfo *nsqhead; + + /* datagram socket for sysquery() and ns_forw(). */ +DECL int ds INIT(-1); + + /* event ID for reads of "ds". */ +DECL evFileID ds_evID; + +#ifdef QRYLOG + /* is query logging turned on? */ +DECL int qrylog; +#endif /*QRYLOG*/ + + /* port to which we send queries */ +DECL u_int16_t ns_port; + + /* Source addr of our internal resolver. */ +DECL struct sockaddr_in source_addr; /* INITs to . */ + + /* Used by ns_stats */ +DECL time_t boottime; + +DECL time_t resettime; + + /* next query to retry */ +DECL struct qinfo *retryqp; + + /* configuration file name */ +DECL char *conffile; + + /* configuration file mtime */ +DECL time_t confmtime; + + /* default debug output file */ +DECL char *debugfile; + + /* zone information */ +DECL struct zoneinfo *zones; + + /* number of zones allocated */ +DECL int nzones; + + /* free list of unused zones[] elements. */ +DECL LIST(struct zoneinfo) freezones; + + /* list of zones that have a reload pending. */ +DECL LIST(struct zoneinfo) reloadingzones; + + /* set if we need a priming */ +DECL int needs_prime_cache; + + /* is cache being primed */ +DECL int priming; + + /* ptrs to dnames in msg for dn_comp */ +DECL u_char *dnptrs[40]; + + /* end pointer for dnptrs */ +DECL u_char **dnptrs_end + INIT(dnptrs + sizeof dnptrs / sizeof(u_char*)); + + /* data about all forwarders */ +DECL struct fwddata **fwddata; + /* how many forwarders are there in fwddata? */ +DECL int fwddata_count; + + /* number of names in addinfo */ +DECL int addcount; + + /* name of cache file */ +DECL const char *cache_file; + +#ifdef BIND_UPDATE +DECL const char * LogSignature INIT(";BIND LOG V8\n"); +DECL const char * DumpSignature INIT(";BIND DUMP V8\n"); +DECL const char * DumpSuffix INIT(".dumptmp"); +#endif + +DECL const char sendtoStr[] INIT("sendto"); +DECL const char tcpsendStr[] INIT("tcp_send"); + + /* defined in version.c, can't use DECL/INIT */ +extern char Version[]; +extern char ShortVersion[]; + + /* If getnum() has an error, here will be the result. */ +DECL int getnum_error INIT(0); + +enum context { domain_ctx, owner_ctx, mailname_ctx, hostname_ctx }; +DECL const char *context_strings[] +#ifdef MAIN_PROGRAM + = { "domain", "owner", "mail", "host", NULL } +#endif +; + +DECL const char *transport_strings[] +#ifdef MAIN_PROGRAM + = { "primary", "secondary", "response", NULL } +#endif +; + +DECL const char *severity_strings[] +#ifdef MAIN_PROGRAM + = { "ignore", "warn", "fail", "not_set", NULL } +#endif +; + +DECL struct in_addr inaddr_any; /* Inits to 0.0.0.0 */ + +DECL options server_options INIT(NULL); + +DECL server_info nameserver_info INIT(NULL); +DECL key_info_list secretkey_info INIT(NULL); + +DECL ip_match_list bogus_nameservers INIT(NULL); + +DECL log_context log_ctx; +DECL int log_ctx_valid INIT(0); + +DECL log_channel syslog_channel INIT(NULL); +DECL log_channel debug_channel INIT(NULL); +DECL log_channel stderr_channel INIT(NULL); +DECL log_channel eventlib_channel INIT(NULL); +DECL log_channel packet_channel INIT(NULL); +DECL log_channel null_channel INIT(NULL); + +DECL ip_match_list local_addresses INIT(NULL); +DECL ip_match_list local_networks INIT(NULL); + + /* are we running in no-fork mode? */ +DECL int foreground INIT(0); + +DECL const struct ns_sym logging_constants[] +#ifdef MAIN_PROGRAM += { + { log_info, "info" }, + { log_notice, "notice" }, + { log_warning, "warning" }, + { log_error, "error" }, + { log_critical, "critical" }, + { 0, NULL } +} +#endif +; + +DECL const struct ns_sym syslog_constants[] +#ifdef MAIN_PROGRAM += { + { LOG_KERN, "kern" }, + { LOG_USER, "user" }, + { LOG_MAIL, "mail" }, + { LOG_DAEMON, "daemon" }, + { LOG_AUTH, "auth" }, + { LOG_SYSLOG, "syslog" }, + { LOG_LPR, "lpr" }, +#ifdef LOG_NEWS + { LOG_NEWS, "news" }, +#endif +#ifdef LOG_UUCP + { LOG_UUCP, "uucp" }, +#endif +#ifdef LOG_CRON + { LOG_CRON, "cron" }, +#endif +#ifdef LOG_AUTHPRIV + { LOG_AUTHPRIV, "authpriv" }, +#endif +#ifdef LOG_FTP + { LOG_FTP, "ftp" }, +#endif + { LOG_LOCAL0, "local0"}, + { LOG_LOCAL1, "local1"}, + { LOG_LOCAL2, "local2"}, + { LOG_LOCAL3, "local3"}, + { LOG_LOCAL4, "local4"}, + { LOG_LOCAL5, "local5"}, + { LOG_LOCAL6, "local6"}, + { LOG_LOCAL7, "local7"}, + { 0, NULL } +} +#endif +; + +DECL const struct ns_sym category_constants[] +#ifdef MAIN_PROGRAM += { + { ns_log_default, "default" }, + { ns_log_config, "config" }, + { ns_log_parser, "parser" }, + { ns_log_queries, "queries" }, + { ns_log_lame_servers, "lame-servers" }, + { ns_log_statistics, "statistics" }, + { ns_log_panic, "panic" }, + { ns_log_update, "update" }, + { ns_log_ncache, "ncache" }, + { ns_log_xfer_in, "xfer-in" }, + { ns_log_xfer_out, "xfer-out" }, + { ns_log_db, "db" }, + { ns_log_eventlib, "eventlib" }, + { ns_log_packet, "packet" }, +#ifdef BIND_NOTIFY + { ns_log_notify, "notify" }, +#endif + { ns_log_cname, "cname" }, + { ns_log_security, "security" }, + { ns_log_os, "os" }, + { ns_log_insist, "insist" }, + { ns_log_maint, "maintenance" }, + { ns_log_load, "load" }, + { ns_log_resp_checks, "response-checks" }, + { ns_log_control, "control" }, + { 0, NULL } +} +#endif +; + +DECL const char panic_msg_no_options[] + INIT("no server_options in NS_OPTION_P"); + +DECL const char panic_msg_insist_failed[] + INIT("%s:%d: insist '%s' failed: %s"); + +DECL const char panic_msg_bad_which[] + INIT("%s:%d: INCRSTATS(%s): bad \"which\""); + +DECL u_long globalStats[nssLast]; + +DECL evTimerID clean_timer; +DECL evTimerID interface_timer; +DECL evTimerID stats_timer; +DECL evTimerID heartbeat_timer; +DECL int active_timers INIT(0); + +DECL uid_t user_id; +DECL char * user_name INIT(NULL); +DECL gid_t group_id; +DECL char * group_name INIT(NULL); +DECL char * chroot_dir INIT(NULL); +DECL char * working_dir INIT(NULL); + +DECL int loading INIT(0); + +DECL int xfers_running INIT(0); +DECL int xfers_deferred INIT(0); +DECL int qserials_running INIT(0); +DECL int initial_configuration INIT(1); Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_glob.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_ixfr.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_ixfr.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_ixfr.c (revision 109985) @@ -0,0 +1,590 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_ixfr.c,v 8.32 2002/05/18 01:02:57 marka Exp $"; +#endif /* not lint */ + +/* + * Portions Copyright (c) 1999 by Check Point Software Technologies, Inc. + * + * 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 Check Point Software Technologies Incorporated 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 CHECK POINT SOFTWARE TECHNOLOGIES + * INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL CHECK POINT SOFTWARE TECHNOLOGIES INCORPRATED + * 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 SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#include "named.h" + +static void sx_new_ixfrmsg(struct qstream * qsp); +void sx_send_ixfr(struct qstream * qsp); + +static int sx_flush(struct qstream * qsp), + sx_addrr(struct qstream * qsp, + const char *dname, + struct databuf * dp); + +/* + * u_char * sx_new_ixfrmsg(msg) init the header of a message, reset the + * compression pointers, and reset the write pointer to the first byte + * following the header. + */ +static void +sx_new_ixfrmsg(struct qstream *qsp) { + HEADER * hp = (HEADER *) qsp->xfr.msg; + + memset(hp, 0, HFIXEDSZ); + hp->id = htons(qsp->xfr.id); + hp->opcode = qsp->xfr.opcode; + hp->qr = 1; + hp->aa = 1; + hp->rcode = NOERROR; + + qsp->xfr.ptrs[0] = qsp->xfr.msg; + qsp->xfr.ptrs[1] = NULL; + + qsp->xfr.cp = qsp->xfr.msg + HFIXEDSZ; + if (qsp->xfr.ixfr_zone == 0) { + int count, n; + int buflen; + struct namebuf *np; + struct hashbuf *htp; + struct zoneinfo *zp; + const char * fname; + + qsp->xfr.ixfr_zone = qsp->xfr.zone; + zp = &zones[qsp->xfr.zone]; + n = dn_comp(zp->z_origin, qsp->xfr.cp, + XFER_BUFSIZE - (qsp->xfr.cp - qsp->xfr.msg), NULL, NULL); + qsp->xfr.cp += n; + PUTSHORT((u_int16_t) T_IXFR, qsp->xfr.cp); + PUTSHORT((u_int16_t) zp->z_class, qsp->xfr.cp); + hp->qdcount = htons(ntohs(hp->qdcount) + 1); + count = qsp->xfr.cp - qsp->xfr.msg; + htp = hashtab; + np = nlookup(zp->z_origin, &htp, &fname, 0); + buflen = XFER_BUFSIZE; + } +} + +/* + * int + * sx_flush(qsp) + * flush the intermediate buffer out to the stream IO system. + * return: + * passed through from sq_write(). + */ +static int +sx_flush(struct qstream *qsp) { + int ret; + +#ifdef DEBUG + if (debug >= 10) + fp_nquery(qsp->xfr.msg, qsp->xfr.cp - qsp->xfr.msg, + log_get_stream(packet_channel)); +#endif + if (qsp->xfr.tsig_state != NULL && qsp->xfr.tsig_skip == 0) { + int msglen = qsp->xfr.cp - qsp->xfr.msg; + + ns_sign_tcp(qsp->xfr.msg, &msglen, qsp->xfr.eom - qsp->xfr.msg, + NOERROR, qsp->xfr.tsig_state, + qsp->xfr.state == s_x_done); + + if (qsp->xfr.state == s_x_done) { + memput(qsp->xfr.tsig_state, sizeof(ns_tcp_tsig_state)); + qsp->xfr.tsig_state = NULL; + } + qsp->xfr.cp = qsp->xfr.msg + msglen; + + } + if (qsp->xfr.cp - qsp->xfr.msg > 0) + ret = sq_write(qsp, qsp->xfr.msg, qsp->xfr.cp - qsp->xfr.msg); + else { + ns_debug(ns_log_default, 3, " Flush negative number *********"); + ret = -1; + } + if (ret >= 0) { + qsp->xfr.cp = NULL; + qsp->xfr.tsig_skip = 0; + } + else + qsp->xfr.tsig_skip = 1; + return (ret); +} +/* + * int sx_addrr(qsp, name, dp) add name/dp's RR to the current assembly + * message. if it won't fit, write current message out, renew the message, + * and then RR should fit. return: -1 = the sq_write() failed so we could not + * queue the full message. 0 = one way or another, everything is fine. side + * effects: on success, the ANCOUNT is incremented and the pointers are + * advanced. + */ +static int +sx_addrr(struct qstream *qsp, const char *dname, struct databuf *dp) { + HEADER *hp = (HEADER *) qsp->xfr.msg; + u_char **edp = qsp->xfr.ptrs + sizeof qsp->xfr.ptrs / sizeof(u_char *); + int n; + + if (qsp->xfr.cp != NULL) { + if (qsp->xfr.transfer_format == axfr_one_answer && + sx_flush(qsp) < 0) + return (-1); + } + if (qsp->xfr.cp == NULL) + sx_new_ixfrmsg(qsp); + n = make_rr(dname, dp, qsp->xfr.cp, qsp->xfr.eom - qsp->xfr.cp, + 0, qsp->xfr.ptrs, edp, 0); + if (n < 0) { + if (sx_flush(qsp) < 0) + return (-1); + if (qsp->xfr.cp == NULL) + sx_new_ixfrmsg(qsp); + n = make_rr(dname, dp, qsp->xfr.cp, qsp->xfr.eom - qsp->xfr.cp, + 0, qsp->xfr.ptrs, edp, 0); + INSIST(n >= 0); + } + hp->ancount = htons(ntohs(hp->ancount) + 1); + qsp->xfr.cp += n; + return (0); +} + +void +sx_send_ixfr(struct qstream *qsp) { + char * cp; + struct zoneinfo *zp = NULL; + struct databuf *soa_dp; + struct databuf *old_soadp; + ns_delta *dp; + ns_updrec *rp; + int foundsoa; + + zp = &zones[qsp->xfr.zone]; + soa_dp = (struct databuf *) findzonesoa(zp); + if (soa_dp == NULL) { + /* XXX should be more graceful */ + ns_panic(ns_log_update, 1, + "sx_send_ixfr: unable to locate soa"); + } + old_soadp = memget(BIND_DATASIZE(soa_dp->d_size)); + if (old_soadp == NULL) + ns_panic(ns_log_update, 1, "sx_send_ixfr: out of memory"); + memcpy(old_soadp, soa_dp, BIND_DATASIZE(soa_dp->d_size)); + + again: + switch (qsp->xfr.state) { + case s_x_firstsoa: + ns_debug(ns_log_default, 3, + "IXFR: s_x_firstsoa (%s)", zp->z_origin); + if (sx_addrr(qsp, zp->z_origin, soa_dp) < 0) + goto cleanup; + qsp->xfr.state = s_x_deletesoa; + /* FALLTHROUGH */ + case s_x_deletesoa: + ns_debug(ns_log_default, 3, + "IXFR: s_x_deletesoa (%s)", zp->z_origin); + dp = NULL; + if (qsp->xfr.top.ixfr != NULL && !EMPTY(*qsp->xfr.top.ixfr)) + dp = HEAD(*qsp->xfr.top.ixfr); + if (dp != NULL) { + foundsoa = 0; + + rp = HEAD(dp->d_changes); + while (rp != NULL) { + if (rp->r_opcode == DELETE && + rp->r_dp != NULL && + rp->r_dp->d_type == T_SOA) { + if (sx_addrr(qsp, rp->r_dname, + rp->r_dp) < 0) + goto cleanup; + db_detach(&rp->r_dp); + foundsoa = 1; + break; + } + rp = NEXT(rp, r_link); + } + + if (!foundsoa) { + cp = (char *)findsoaserial(old_soadp->d_data); + PUTLONG(HEAD(dp->d_changes)->r_zone, cp); + + if (sx_addrr(qsp, zp->z_origin, old_soadp) < 0) + goto cleanup; + } + } + qsp->xfr.state = s_x_deleting; + /* FALLTHROUGH */ + case s_x_deleting: + ns_debug(ns_log_default, 3, + "IXFR: s_x_deleting (%s)", zp->z_origin); + dp = NULL; + if (qsp->xfr.top.ixfr != NULL && !EMPTY(*qsp->xfr.top.ixfr)) + dp = HEAD(*qsp->xfr.top.ixfr); + if (dp != NULL) { + rp = HEAD(dp->d_changes); + while (rp != NULL) { + if (rp->r_opcode == DELETE && + rp->r_dp != NULL) { + /* + * Drop any SOA deletes + */ + if (rp->r_dp->d_type != T_SOA && + sx_addrr(qsp, rp->r_dname, + rp->r_dp) < 0) + goto cleanup; + db_detach(&rp->r_dp); + } + rp = NEXT(rp, r_link); + } + } + qsp->xfr.state = s_x_addsoa; + /* FALLTHROUGH */ + case s_x_addsoa: + ns_debug(ns_log_default, 3, + "IXFR: s_x_addsoa (%s)", zp->z_origin); + dp = NULL; + if (qsp->xfr.top.ixfr != NULL && !EMPTY(*qsp->xfr.top.ixfr)) + dp = HEAD(*qsp->xfr.top.ixfr); + if (dp != NULL) { + foundsoa = 0; + rp = HEAD(dp->d_changes); + while (rp != NULL) { + if (rp->r_opcode == ADD && + rp->r_dp != NULL && + rp->r_dp->d_type == T_SOA) { + if (sx_addrr(qsp, rp->r_dname, + rp->r_dp) < 0) + goto cleanup; + db_detach(&rp->r_dp); + foundsoa = 1; + break; + } + rp = NEXT(rp, r_link); + } + + if (!foundsoa) { + cp = (char *)findsoaserial(old_soadp->d_data); + if (NEXT(dp, d_link) != NULL) { + PUTLONG(HEAD(dp->d_changes)->r_zone, cp); + if (sx_addrr(qsp, zp->z_origin, + old_soadp) < 0) + goto cleanup; + } else { + if (sx_addrr(qsp, zp->z_origin, + soa_dp) < 0) + goto cleanup; + } + } + } + qsp->xfr.state = s_x_adding; + /* FALLTHROUGH */ + case s_x_adding: + ns_debug(ns_log_default, 3, + "IXFR: s_x_adding (%s)", zp->z_origin); + dp = NULL; + if (qsp->xfr.top.ixfr != NULL && !EMPTY(*qsp->xfr.top.ixfr)) { + dp = HEAD(*qsp->xfr.top.ixfr); + if (dp != NULL) { + /* see s_x_deleting */ + rp = HEAD(dp->d_changes); + while (rp != NULL) { + if (rp->r_opcode == ADD && + rp->r_dp != NULL && + rp->r_dp->d_type != T_SOA) { + if (sx_addrr(qsp, rp->r_dname, + rp->r_dp) < 0) + goto cleanup; + db_detach(&rp->r_dp); + } + rp = NEXT(rp, r_link); + } + + /* move to next update */ + UNLINK(*qsp->xfr.top.ixfr, dp, d_link); + + /* clean up old update */ + while ((rp = HEAD(dp->d_changes)) != NULL) { + UNLINK(dp->d_changes, rp, r_link); + if (rp->r_dp != NULL) + db_detach(&rp->r_dp); + res_freeupdrec(rp); + } + memput(dp, sizeof (*dp)); + if (HEAD(*qsp->xfr.top.ixfr) != NULL) { + qsp->xfr.state = s_x_deletesoa; + goto again; + } + } + } + qsp->xfr.state = s_x_lastsoa; + /* FALLTHROUGH */ + case s_x_lastsoa: + ns_debug(ns_log_default, 3, + "IXFR: s_x_lastsoa (%s)", zp->z_origin); + if (qsp->xfr.ixfr_zone != 0) + sx_addrr(qsp, zp->z_origin, soa_dp); + break; + default: + break; + } + ns_debug(ns_log_default, 3, "IXFR: flushing %s", zp->z_origin); + qsp->xfr.state = s_x_done; + sx_flush(qsp); + sq_writeh(qsp, sq_flushw); + if (qsp->xfr.top.ixfr != NULL) { + if(!EMPTY(*qsp->xfr.top.ixfr)) { + while ((dp = HEAD(*qsp->xfr.top.ixfr)) != NULL) { + UNLINK(*qsp->xfr.top.ixfr, dp, d_link); + while ((rp = HEAD(dp->d_changes)) != NULL) { + UNLINK(dp->d_changes, rp, r_link); + if (rp->r_dp != NULL) + db_detach(&rp->r_dp); + res_freeupdrec(rp); + } + memput(dp, sizeof *dp); + } + } + memput(qsp->xfr.top.ixfr, sizeof *qsp->xfr.top.ixfr); + qsp->xfr.top.ixfr = NULL; + } + cleanup: + memput(old_soadp, BIND_DATASIZE(old_soadp->d_size)); +} + + +#ifndef MAXBSIZE +#define MAXBSIZE 8192 +#endif + + +/* + * int ixfr_log_maint(struct zoneinfo *zp, int fast_trim) + * + * zp - pointer to the zone information + */ +int +ixfr_log_maint(struct zoneinfo *zp) { + int fd, rcount, wcount; + int found = 0; + int error = 0; + long seek = 0; + FILE *to_fp, *from_fp, *db_fp; + char *tmpname; + int len; + struct stat db_sb; + struct stat sb; + static char buf[MAXBSIZE]; + + ns_debug(ns_log_default, 3, "ixfr_log_maint(%s)", zp->z_origin); + + /* find out how big the zone db file is */ + if ((db_fp = fopen(zp->z_source, "r")) == NULL) { + ns_warning(ns_log_db, "%s: %s", + zp->z_source, strerror(errno)); + return (-1); + } + if (fstat(fileno(db_fp), &db_sb) < 0) { + ns_warning(ns_log_db, "%s: %s", + zp->z_source, strerror(errno)); + (void) my_fclose(db_fp); + return (-1); + } + (void) my_fclose(db_fp); + ns_debug(ns_log_default, 3, "%s, size %ld", + zp->z_source, (long)db_sb.st_size); + + /* open up the zone ixfr log */ + if ((from_fp = fopen(zp->z_ixfr_base, "r")) == NULL) { + ns_warning(ns_log_db, "%s: %s", + zp->z_ixfr_base, strerror(errno)); + return (-1); + } + + if (fstat(fileno(from_fp), &sb) < 0) { + ns_warning(ns_log_db, "%s: %s", + zp->z_ixfr_base, strerror(errno)); + (void) my_fclose(from_fp); + return (-1); + } + ns_debug(ns_log_default, 3, "%s, size %ld max %ld\n", zp->z_ixfr_base, + (long)sb.st_size, (long)zp->z_max_log_size_ixfr); + if (zp->z_max_log_size_ixfr) { + if (sb.st_size > zp->z_max_log_size_ixfr) + seek = sb.st_size - + (size_t)(zp->z_max_log_size_ixfr + + (zp->z_max_log_size_ixfr * 0.10) ); + else + seek = 0; + } else { + if (sb.st_size > (db_sb.st_size * 0.50)) + seek = sb.st_size - (size_t)((db_sb.st_size * 0.50) + + ((db_sb.st_size * zp->z_max_log_size_ixfr) * 0.10)); + else + seek = 0; + } + ns_debug(ns_log_default, 3, "seek: %ld", (long)seek); + if (seek < 1) { + ns_debug(ns_log_default, 3, "%s does not need to be reduced", + zp->z_ixfr_base); + (void) my_fclose(from_fp); + return (-1); + } + + len = strlen(zp->z_ixfr_base) + sizeof(".XXXXXX") + 1; + tmpname = memget(len); + if (!tmpname) { + ns_warning(ns_log_default, "memget failed"); + return (-1); + } +#ifdef SHORT_FNAMES + filenamecpy(tmpname, zp->z_ixfr_base); +#else + (void) strcpy(tmpname, zp->z_ixfr_base); +#endif /* SHORT_FNAMES */ + + (void) strcat(tmpname, ".XXXXXX"); + if ((fd = mkstemp(tmpname)) == -1) { + ns_warning(ns_log_db, "can't make tmpfile (%s): %s", + tmpname, strerror(errno)); + memput(tmpname, len); + (void) my_fclose(from_fp); + return (-1); + } + if ((to_fp = fdopen(fd, "r+")) == NULL) { + ns_warning(ns_log_db, "%s: %s", + tmpname, strerror(errno)); + (void) unlink(tmpname); + memput(tmpname, len); + (void) my_fclose(from_fp); + (void) close(fd); + return (-1); + } + + if (fgets(buf, sizeof(buf), from_fp) == NULL) { + ns_error(ns_log_update, "fgets() from %s failed: %s", + zp->z_ixfr_base, strerror(errno)); + error++; + goto clean_up; + } + if (strcmp(buf, LogSignature) != 0) { + ns_error(ns_log_update, "invalid log file %s", + zp->z_ixfr_base); + error++; + goto clean_up; + } + + if (fseek( from_fp, seek, 0) < 0) { + error++; + goto clean_up; + } + + found = 0; + for (;;) { + if (getword(buf, sizeof buf, from_fp, 0)) { + if (strcasecmp(buf, "[END_DELTA]") == 0) { + if (!(fgets(buf, 2, from_fp) == NULL)) /* eat */ + found = 1; + break; + } + } + if (feof(from_fp)) + break; + } + if (found) { + ns_debug(ns_log_default, 1, + "ixfr_log_maint(): found [END_DELTA]"); + + fprintf(to_fp, "%s", LogSignature); + + while ((rcount = fread(buf, sizeof(char), MAXBSIZE, from_fp)) > 0) { + wcount = fwrite(buf, sizeof(char), rcount, to_fp); + if (rcount != wcount || wcount == -1) { + ns_warning(ns_log_default, + "ixfr_log_maint: error in writting copy"); + break; + } + } + if (rcount < 0) + ns_warning(ns_log_default, + "ixfr_log_maint: error in reading copy"); + } + clean_up: + (void) my_fclose(to_fp); + (void) my_fclose(from_fp); + if (error == 0) { + if (isc_movefile(tmpname, zp->z_ixfr_base) == -1) { + ns_warning(ns_log_default, + "can not rename %s to %s :%s", + tmpname, zp->z_ixfr_base, strerror(errno)); + } + if ((from_fp = fopen(zp->z_ixfr_base, "r")) == NULL) { + ns_warning(ns_log_db, "%s: %s", + zp->z_ixfr_base, strerror(errno)); + memput(tmpname, len); + return (-1); + } + if (fstat(fileno(from_fp), &sb) < 0) { + ns_warning(ns_log_db, "%s: %s", + zp->z_ixfr_base, strerror(errno)); + memput(tmpname, len); + (void) my_fclose(from_fp); + return (-1); + } + if (sb.st_size <= 0) + (void) unlink(zp->z_ixfr_base); + else if (chmod(zp->z_ixfr_base, 0644) < 0) + ns_error(ns_log_update, + "chmod(%s,%o) failed, pressing on: %s", + zp->z_source, sb.st_mode, strerror(errno)); + (void) my_fclose(from_fp); + } + (void) unlink(tmpname); + memput(tmpname, len); + + /* signal to read for lowest serial number */ + zp->z_serial_ixfr_start = 0; + + ns_debug(ns_log_default, 3, "%s, size %ld max %ld\n", zp->z_ixfr_base, + (long)sb.st_size, (long)zp->z_max_log_size_ixfr); + + if (error) + return(-1); + else + return (0); +} + Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_ixfr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_lexer.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_lexer.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_lexer.c (revision 109985) @@ -0,0 +1,825 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_lexer.c,v 8.31 2002/05/24 03:05:03 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "port_after.h" + +#include "named.h" +#include "ns_parser.h" +#include "ns_parseutil.h" +#include "ns_lexer.h" + +typedef enum lexer_state { + scan, number, identifier, ipv4, quoted_string +} LexerState; + +#define LEX_EOF 0x01 +#define LEXER_MAX_PUSHBACK 2 + +typedef struct lexer_file_context { + char * name; + FILE * stream; + int line_number; + LexerState state; + u_int flags; + int warnings; + int errors; + u_int pushback_count; + char pushback[LEXER_MAX_PUSHBACK]; + struct lexer_file_context * + next; +} *LexerFileContext; + +LexerFileContext current_file = NULL; + +#define LEX_LAST_WAS_DOT 0x01 +#define LEX_CONSECUTIVE_DOTS 0x02 + +typedef struct lexer_identifier { + char buffer[LEX_MAX_IDENT_SIZE+1]; + int index; + int num_dots; + unsigned int flags; +} *LexerIdentifier; + +static LexerIdentifier id; + +static char special_chars[256]; + +#define whitespace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') +#define domain_char(c) (isalnum((c)) || (c) == '.' || (c) == '-') +#define special_char(c) (special_chars[(c)] == 1) +#define identifier_char(c) (!whitespace(c) && !special_char(c)) + +static int last_token; +static YYSTYPE last_yylval; + +static int lexer_initialized = 0; + +/* + * Problem Reporting + */ + +static char * +token_to_text(int token, YYSTYPE lval) { + static char buffer[LEX_MAX_IDENT_SIZE+50]; + + if (token < 128) { + if (token == 0) + strcpy(buffer, ""); + else + sprintf(buffer, "'%c'", token); + } else { + switch (token) { + case L_EOS: + strcpy(buffer, ";"); + break; + case L_STRING: + sprintf(buffer, "'%s'", lval.cp); + break; + case L_QSTRING: + sprintf(buffer, "\"%s\"", lval.cp); + break; + case L_IPADDR: + sprintf(buffer, "%s", inet_ntoa(lval.ip_addr)); + break; + case L_NUMBER: + sprintf(buffer, "%ld", lval.num); + break; + case L_END_INCLUDE: + sprintf(buffer, ""); + break; + default: + sprintf(buffer, "%s", lval.cp); + } + } + + return (buffer); +} + +static char where[MAXPATHLEN + 100]; +static char message[20480]; + +static void +parser_complain(int is_warning, int print_last_token, const char *format, + va_list args) ISC_FORMAT_PRINTF(3, 0); + +static void +parser_complain(int is_warning, int print_last_token, const char *format, + va_list args) +{ + LexerFileContext lf; + int severity; + + if (is_warning) { + severity = log_warning; + } else { + severity = log_error; + } + + INSIST(current_file != NULL); + if (current_file->next != NULL) { + for (lf = current_file; lf != NULL; lf = lf->next) { + log_write(log_ctx, ns_log_parser, severity, + "%s '%s' line %d", + (lf == current_file) ? + "In" : "included from", + lf->name, lf->line_number); + } + } + sprintf(where, "%s:%d: ", current_file->name, + current_file->line_number); + vsprintf(message, format, args); + if (print_last_token) + log_write(log_ctx, ns_log_parser, severity, "%s%s near %s", + where, message, + token_to_text(last_token, last_yylval)); + else + log_write(log_ctx, ns_log_parser, severity, + "%s%s", where, message); +} + +int +parser_warning(int print_last_token, const char *format, ...) { + va_list args; + + va_start(args, format); + parser_complain(1, print_last_token, format, args); + va_end(args); + current_file->warnings++; + return (1); +} + +int +parser_error(int print_last_token, const char *format, ...) { + va_list args; + + va_start(args, format); + parser_complain(0, print_last_token, format, args); + va_end(args); + current_file->errors++; + return (1); +} + +void +yyerror(const char *message) { + parser_error(1, "%s", message); +} + +/* + * Keywords + */ + +struct keyword { + const char *name; + int token; +}; + +/* + * "keywords" is an array of the keywords which are the fixed syntactic + * elements of the configuration file. Each keyword has a string version + * of the keyword and a token id, which should be an identifier which + * matches that in a %token statement inside the parser.y file. + */ +static struct keyword keywords[] = { + {"acl", T_ACL}, + {"address", T_ADDRESS}, + {"algorithm", T_ALGID}, + {"allow", T_ALLOW}, + {"allow-query", T_ALLOW_QUERY}, + {"allow-recursion", T_ALLOW_RECURSION}, + {"allow-transfer", T_ALLOW_TRANSFER}, + {"allow-update", T_ALLOW_UPDATE}, +#ifdef BIND_NOTIFY + {"also-notify", T_ALSO_NOTIFY}, +#endif + {"auth-nxdomain", T_AUTH_NXDOMAIN}, + {"blackhole", T_BLACKHOLE}, + {"bogus", T_BOGUS}, + {"category", T_CATEGORY}, + {"class", T_CLASS}, + {"channel", T_CHANNEL}, + {"check-names", T_CHECK_NAMES}, + {"cleaning-interval", T_CLEAN_INTERVAL}, + {"controls", T_CONTROLS}, + {"coresize", T_CORESIZE}, + {"datasize", T_DATASIZE}, + {"deallocate-on-exit", T_DEALLOC_ON_EXIT}, + {"debug", T_DEBUG}, + {"default", T_DEFAULT}, + {"dialup", T_DIALUP}, + {"directory", T_DIRECTORY}, + {"dump-file", T_DUMP_FILE}, + {"dynamic", T_DYNAMIC}, + {"edns", T_EDNS}, + {"explicit", T_EXPLICIT}, + {"fail", T_FAIL}, + {"fake-iquery", T_FAKE_IQUERY}, + {"false", T_FALSE}, + {"fetch-glue", T_FETCH_GLUE}, + {"file", T_FILE}, + {"files", T_FILES}, + {"first", T_FIRST}, + {"forward", T_FORWARD}, + {"forwarders", T_FORWARDERS}, + {"group", T_GROUP}, + {"has-old-clients", T_HAS_OLD_CLIENTS}, + {"heartbeat-interval", T_HEARTBEAT}, + {"hint", T_HINT}, +#ifdef HITCOUNTS + {"hit-count", T_HITCOUNT}, +#endif /* HITCOUNTS */ + {"host-statistics", T_HOSTSTATS}, + {"host-statistics-max", T_HOSTSTATSMAX}, + {"hostname", T_HOSTNAME}, + {"if-no-answer", T_IF_NO_ANSWER}, + {"if-no-domain", T_IF_NO_DOMAIN}, + {"ignore", T_IGNORE}, + {"include", T_INCLUDE}, + {"inet", T_INET}, + {"interface-interval", T_INTERFACE_INTERVAL}, + {"ixfr-base", T_FILE_IXFR}, + {"ixfr-tmp-file", T_IXFR_TMP}, + {"key", T_SEC_KEY}, + {"keys", T_KEYS}, + {"lame-ttl", T_LAME_TTL}, + {"listen-on", T_LISTEN_ON}, + {"logging", T_LOGGING}, + {"maintain-ixfr-base", T_MAINTAIN_IXFR_BASE}, + {"many-answers", T_MANY_ANSWERS}, + {"master", T_MASTER}, + {"masters", T_MASTERS}, + {"max-ixfr-log-size", T_MAX_LOG_SIZE_IXFR}, + {"max-ncache-ttl", T_MAX_NCACHE_TTL}, + {"max-transfer-time-in", T_MAX_TRANSFER_TIME_IN}, + {"memstatistics-file", T_MEMSTATS_FILE}, + {"min-roots", T_MIN_ROOTS}, + {"multiple-cnames", T_MULTIPLE_CNAMES}, + {"name", T_NAME}, + {"named-xfer", T_NAMED_XFER}, + {"no", T_NO}, +#ifdef BIND_NOTIFY + {"notify", T_NOTIFY}, +#endif + {"null", T_NULL_OUTPUT}, + {"one-answer", T_ONE_ANSWER}, + {"only", T_ONLY}, + {"order", T_ORDER}, + {"options", T_OPTIONS}, + {"owner", T_OWNER}, + {"perm", T_PERM}, + {"pid-file", T_PIDFILE}, + {"port", T_PORT}, + {"preferred-glue", T_PREFERRED_GLUE}, + {"print-category", T_PRINT_CATEGORY}, + {"print-severity", T_PRINT_SEVERITY}, + {"print-time", T_PRINT_TIME}, + {"pubkey", T_PUBKEY}, + {"query-source", T_QUERY_SOURCE}, + {"rfc2308-type1", T_RFC2308_TYPE1}, + {"rrset-order", T_RRSET_ORDER}, + {"recursion", T_RECURSION}, + {"response", T_RESPONSE}, + {"secret", T_SECRET}, + {"serial-queries", T_SERIAL_QUERIES}, + {"server", T_SERVER}, + {"severity", T_SEVERITY}, + {"size", T_SIZE}, + {"slave", T_SLAVE}, + {"sortlist", T_SORTLIST}, + {"stacksize", T_STACKSIZE}, + {"statistics-file", T_STATS_FILE}, + {"statistics-interval", T_STATS_INTERVAL}, + {"stub", T_STUB}, + {"support-ixfr", T_SUPPORT_IXFR}, +#ifdef BIND_NOTIFY + {"suppress-initial-notify", T_NOTIFY_INITIAL}, +#endif + {"syslog", T_SYSLOG}, + {"topology", T_TOPOLOGY}, + {"transfer-format", T_TRANSFER_FORMAT}, + {"transfer-source", T_TRANSFER_SOURCE}, + {"transfers", T_TRANSFERS}, + {"transfers-in", T_TRANSFERS_IN}, + {"transfers-out", T_TRANSFERS_OUT}, + {"transfers-per-ns", T_TRANSFERS_PER_NS}, + {"treat-cr-as-space", T_TREAT_CR_AS_SPACE}, + {"true", T_TRUE}, + {"trusted-keys", T_TRUSTED_KEYS}, + {"type", T_TYPE}, + {"unix", T_UNIX}, + {"unlimited", T_UNLIMITED}, + {"use-id-pool", T_USE_ID_POOL}, + {"use-ixfr", T_USE_IXFR}, + {"version", T_VERSION}, + {"versions", T_VERSIONS}, + {"warn", T_WARN}, + {"yes", T_YES}, + {"zone", T_ZONE}, + {(char *) NULL, 0}, +}; + +/* + * The table size should be a prime chosen to minimize collisions. + */ +#define KEYWORD_TABLE_SIZE 461 + +static symbol_table keyword_table = NULL; + +static void +init_keywords() { + struct keyword *k; + symbol_value value; + + if (keyword_table != NULL) + free_symbol_table(keyword_table); + keyword_table = new_symbol_table(KEYWORD_TABLE_SIZE, NULL); + for (k = keywords; k->name != NULL; k++) { + value.integer = k->token; + define_symbol(keyword_table, k->name, 0, value, 0); + } + dprint_symbol_table(99, keyword_table); +} + +/* + * File Contexts + */ + +void +lexer_begin_file(const char *filename, FILE *stream) { + LexerFileContext lf; + + if (stream == NULL) { + stream = fopen(filename, "r"); + if (stream == NULL) { + parser_error(0, "couldn't open include file '%s'", + filename); + return; + } + } + lf = (LexerFileContext)memget(sizeof (struct lexer_file_context)); + if (lf == NULL) + panic("memget failed in lexer_begin_file", NULL); + INSIST(stream != NULL); + lf->stream = stream; + lf->name = savestr(filename, 1); + lf->line_number = 1; + lf->state = scan; + lf->flags = 0; + lf->warnings = 0; + lf->errors = 0; + lf->pushback_count = 0; + lf->next = current_file; + current_file = lf; +} + +void +lexer_end_file(void) { + LexerFileContext lf; + + INSIST(current_file != NULL); + lf = current_file; + current_file = lf->next; + fclose(lf->stream); + freestr(lf->name); + memput(lf, sizeof *lf); +} + +/* + * Character Input + */ + +#define LEXER_GETC(c, cf) \ + do { \ + if ((cf)->pushback_count > 0) { \ + (cf)->pushback_count--; \ + (c) = (cf)->pushback[(cf)->pushback_count]; \ + } else \ + (c) = getc((cf)->stream); \ + } while (0); + +#define LEXER_UNGETC(c, cf) \ + do { \ + INSIST((cf)->pushback_count < LEXER_MAX_PUSHBACK); \ + (cf)->pushback[(cf)->pushback_count++] = (c); \ + } while (0); + +static void +scan_to_comment_end(int c_plus_plus_style) { + int c; + int done = 0; + int prev_was_star = 0; + + while (!done) { + LEXER_GETC(c, current_file); + switch (c) { + case EOF: + if (!c_plus_plus_style) + parser_error(0, "EOF in comment"); + current_file->flags |= LEX_EOF; + done = 1; + break; + case '*': + prev_was_star = 1; + break; + case '/': + if (prev_was_star && !c_plus_plus_style) + done = 1; + prev_was_star = 0; + break; + case '\n': + if (c_plus_plus_style) { + /* don't consume the newline because + we want it to be a delimiter for + anything before the comment + started */ + LEXER_UNGETC(c, current_file); + done = 1; + } else { + current_file->line_number++; + } + prev_was_star = 0; + break; + default: + prev_was_star = 0; + } + } +} + +static int +get_next_char(int comment_ok) { + int c, nc; + + if (current_file->flags & LEX_EOF) + return (EOF); + + LEXER_GETC(c, current_file); + + if (comment_ok) { + while (c == '/' || c == '#') { + if (c == '#') { + scan_to_comment_end(1); + if (current_file->flags & LEX_EOF) + return (EOF); + LEXER_GETC(c, current_file); + } else { + LEXER_GETC(nc, current_file); + switch (nc) { + case EOF: + current_file->flags |= LEX_EOF; + return ('/'); + case '*': + case '/': + scan_to_comment_end((nc == '/')); + if (current_file->flags & LEX_EOF) + return (EOF); + LEXER_GETC(c, current_file); + break; + default: + LEXER_UNGETC(nc, current_file); + return ('/'); + } + } + } + } + + if (c == EOF) + current_file->flags |= LEX_EOF; + else if (c == '\n') + current_file->line_number++; + return (c); +} + +static void +put_back_char(int c) { + if (c == EOF) + current_file->flags |= LEX_EOF; + else { + LEXER_UNGETC(c, current_file); + if (c == '\n') + current_file->line_number--; + } +} + + +/* + * Identifiers + */ + +static void +clear_identifier(LexerIdentifier id) { + INSIST(id != NULL); + id->index = 0; + id->num_dots = 0; + id->flags = 0; +} + +static char * +dup_identifier(LexerIdentifier id) { + char *duplicate; + + INSIST(id != NULL); + duplicate = savestr(id->buffer, 1); + return (duplicate); +} + +static void +finish_identifier(LexerIdentifier id) { + INSIST(id != NULL && id->index < LEX_MAX_IDENT_SIZE); + id->buffer[id->index] = '\0'; +} + +static void +add_to_identifier(LexerIdentifier id, int c) { + INSIST(id != NULL); + id->buffer[id->index] = c; + id->index++; + if (id->index >= LEX_MAX_IDENT_SIZE) { + parser_error(0, "identifier too long"); + current_file->state = scan; + /* discard chars until we hit a non-identifier char */ + while (c != EOF && identifier_char(c)) { + c = get_next_char(1); + } + put_back_char(c); + clear_identifier(id); + } else { + if (c == '.') { + if (id->flags & LEX_LAST_WAS_DOT) + id->flags |= LEX_CONSECUTIVE_DOTS; + id->flags |= LEX_LAST_WAS_DOT; + id->num_dots++; + } else { + id->flags &= ~LEX_LAST_WAS_DOT; + } + } +} + +/* + * yylex() -- return the next token from the current input stream + */ +int +yylex() { + int c; + int comment_ok = 1; + int token = -1; + symbol_value value; + + while (token < 0) { + c = get_next_char(comment_ok); + switch(current_file->state) { + case scan: + if (c == EOF) { + if (current_file->next == NULL) + /* + * We don't want to call + * lexer_end_file() here because we + * want to keep the toplevel file + * context to log errors against. + */ + token = 0; + else { + lexer_end_file(); + token = L_END_INCLUDE; + } + break; + } + if (whitespace(c)) + break; + if (identifier_char(c)) { + if (isdigit(c)) + current_file->state = number; + else + current_file->state = identifier; + clear_identifier(id); + add_to_identifier(id, c); + } else + if (special_char(c)) { + if (c == ';') { + token = L_EOS; + break; + } + if (c == '"') { + clear_identifier(id); + current_file->state = + quoted_string; + comment_ok = 0; + break; + } + token = c; + } else { + parser_error(0, + "invalid character '%c'", + c); + } + break; + + case number: + if (c != EOF && identifier_char(c)) { + if (!isdigit(c)) + current_file->state = + (c == '.') ? ipv4 : identifier; + add_to_identifier(id, c); + } else { + put_back_char(c); + current_file->state = scan; + finish_identifier(id); + yylval.num = strtol(id->buffer, (char**)0, 0); + token = L_NUMBER; + } + break; + + case identifier: + if (c != EOF && identifier_char(c)) { + add_to_identifier(id, c); + } else { + put_back_char(c); + current_file->state = scan; + finish_identifier(id); + /* is it a keyword? */ + if (lookup_symbol(keyword_table, id->buffer, + 0, &value)) { + yylval.cp = id->buffer; + token = value.integer; + } else { + yylval.cp = dup_identifier(id); + token = L_STRING; + } + } + break; + + case ipv4: + if (c != EOF && identifier_char(c)) { + if (!isdigit(c)) { + if (c != '.' || + (id->flags & LEX_CONSECUTIVE_DOTS)) + current_file->state = + identifier; + } + add_to_identifier(id, c); + } else { + put_back_char(c); + if (id->num_dots > 3 || + (id->flags & LEX_LAST_WAS_DOT)) + current_file->state = identifier; + else { + if (id->num_dots == 1) { + add_to_identifier(id, '.'); + add_to_identifier(id, '0'); + add_to_identifier(id, '.'); + add_to_identifier(id, '0'); + } else if (id->num_dots == 2) { + add_to_identifier(id, '.'); + add_to_identifier(id, '0'); + } + current_file->state = scan; + finish_identifier(id); + token = L_IPADDR; + if (inet_aton(id->buffer, + &(yylval.ip_addr))==0) { + yylval.cp = dup_identifier(id); + token = L_STRING; + } + } + } + break; + + case quoted_string: + if (c == EOF) { + parser_error(0, "EOF in quoted string"); + return 0; + } else { + if (c == '"') { + comment_ok = 1; + current_file->state = scan; + finish_identifier(id); + yylval.cp = dup_identifier(id); + token = L_QSTRING; + } else { + /* XXX add backslash escapes here */ + add_to_identifier(id, c); + } + } + break; + + default: + panic("unhandled state in yylex", NULL); + } + } + + last_token = token; + last_yylval = yylval; + return (token); +} + +/* + * Initialization + */ + +symbol_table constants; + +static void +import_constants(const struct ns_sym *s, int type) { + symbol_value value; + for ((void)NULL; s != NULL && s->name != NULL; s++) { + value.integer = s->number; + define_symbol(constants, s->name, type, value, 0); + } +} + +static void +import_res_constants(const struct res_sym *r, int type) { + symbol_value value; + for ((void)NULL; r != NULL && r->name != NULL; r++) { + value.integer = r->number; + define_symbol(constants, r->name, type, value, 0); + } +} + +#define CONSTANTS_TABLE_SIZE 397 /* should be prime */ + +static void +import_all_constants() { + constants = new_symbol_table(CONSTANTS_TABLE_SIZE, NULL); + import_res_constants(__p_class_syms, SYM_CLASS); + import_constants(category_constants, SYM_CATEGORY); + import_constants(logging_constants, SYM_LOGGING); + import_constants(syslog_constants, SYM_SYSLOG); +} + +void +lexer_initialize() { + memset(special_chars, 0, sizeof special_chars); + special_chars[';'] = 1; + special_chars['{'] = 1; + special_chars['}'] = 1; + special_chars['!'] = 1; + special_chars['/'] = 1; + special_chars['"'] = 1; + special_chars['*'] = 1; + id = (LexerIdentifier)memget(sizeof (struct lexer_identifier)); + if (id == NULL) + panic("memget failed in lexer_initialize", NULL); + init_keywords(); + import_all_constants(); + lexer_initialized = 1; +} + +void +lexer_setup(void) { + REQUIRE(lexer_initialized); + + current_file = NULL; /* XXX should we INSIST(current_file==NULL)? */ + INSIST(id != NULL); +} + +void +lexer_shutdown(void) { + REQUIRE(lexer_initialized); + + free_symbol_table(keyword_table); + free_symbol_table(constants); + memput(id, sizeof (struct lexer_identifier)); + id = NULL; + lexer_initialized = 0; +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_lexer.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_main.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_main.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_main.c (revision 109985) @@ -0,0 +1,3003 @@ +#if !defined(lint) && !defined(SABER) +static const char sccsid[] = "@(#)ns_main.c 4.55 (Berkeley) 7/1/91"; +static const char rcsid[] = "$Id: ns_main.c,v 8.160 2002/06/24 07:06:55 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986, 1989, 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(lint) && !defined(SABER) +char copyright[] = +"@(#) Copyright (c) 1986, 1989, 1990 The Regents of the University of California.\n" +"portions Copyright (c) 1993 Digital Equipment Corporation\n" +"portions Copyright (c) 1995-1999 Internet Software Consortium\n" +"portions Copyright (c) 1999 Check Point Software Technologies\n" +"All rights reserved.\n"; +#endif /* not lint */ + +/* + * Internet Name server (see RCF1035 & others). + */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SVR4 /* XXX */ +# include +#else +#ifndef __hpux +# include +#endif +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef HAVE_GETRUSAGE /* XXX */ +#include +#endif + +#define MAIN_PROGRAM +#include "named.h" +#undef MAIN_PROGRAM + +typedef void (*handler)(void); + +typedef struct _savedg { + struct sockaddr_in from; + int dfd; + interface * ifp; + time_t gen; + u_char * buf; + u_int16_t buflen; +} savedg; + + /* list of interfaces */ +static LIST(struct _interface) iflist; +static int iflist_initialized = 0; +static int iflist_dont_rescan = 0; + +static const int drbufsize = 32 * 1024, /* UDP rcv buf size */ + dsbufsize = 48 * 1024, /* UDP snd buf size */ + sbufsize = 16 * 1024, /* TCP snd buf size */ +#ifdef BROKEN_RECVFROM + nudptrans = 1, +#else + nudptrans = 20, /* #/udps per select */ +#endif + listenmax = 50; + +static u_int16_t nsid_state; +static u_int16_t *nsid_pool; /* optional query id pool */ +static u_int16_t *nsid_vtable; /* optional shuffle table */ +static u_int32_t nsid_hash_state; +static u_int16_t nsid_a1, nsid_a2, nsid_a3; +static u_int16_t nsid_c1, nsid_c2, nsid_c3; +static u_int16_t nsid_state2; +static int nsid_algorithm; + +static int needs = 0, needs_exit = 0, needs_restart = 0; +static handler handlers[main_need_num]; +static void savedg_waitfunc(evContext, void*, const void*); +static void need_waitfunc(evContext, void *, const void *); +static int drain_rcvbuf(evContext, interface *, int, + int *, int *); +static int drain_all_rcvbuf(evContext); + +static struct qstream *sq_add(void); +static int opensocket_d(interface *), + opensocket_s(interface *); +static void sq_query(struct qstream *), + dq_remove(interface *); +static int sq_dowrite(struct qstream *); +static void use_desired_debug(void); +static void stream_write(evContext, void *, int, int); + +static interface * if_find(struct in_addr, u_int16_t port); + +static void deallocate_everything(void), + stream_accept(evContext, void *, int, + const void *, int, + const void *, int), + stream_getlen(evContext, void *, int, int), + stream_getmsg(evContext, void *, int, int), + datagram_read(evContext, void *, int, int), + dispatch_message(u_char *, int, int, + struct qstream *, + struct sockaddr_in, int, + interface *); +static void stream_send(evContext, void *, int, + const void *, int, + const void *, int); +static int only_digits(const char *); + +static void init_needs(void), + handle_needs(void), + exit_handler(void); + +#ifndef HAVE_CUSTOM +static void custom_init(void), + custom_shutdown(void); +#endif + +static void +usage() { + fprintf(stderr, +"Usage: named [-d #] [-q] [-r] [-v] [-f] [-p port] [[-b|-c] configfile]\n"); +#ifdef CAN_CHANGE_ID + fprintf(stderr, +" [-u (username|uid)] [-g (groupname|gid)]\n"); +#endif +#ifdef HAVE_CHROOT + fprintf(stderr, +" [-t directory]\n"); +#endif + exit(1); +} + +static const char bad_p_option[] = +"-p remote/local obsolete; use 'listen-on' in config file to specify local"; + +static const char bad_directory[] = "chdir failed for directory '%s': %s"; + +/*ARGSUSED*/ +int +main(int argc, char *argv[]) { + int n; + char *p; + int ch; + struct passwd *pw; + struct group *gr; + +#ifdef _AUX_SOURCE + set42sig(); +#endif + debugfile = savestr(_PATH_DEBUG, 1); + + user_id = getuid(); + group_id = getgid(); + + ns_port = htons(NAMESERVER_PORT); + desired_debug = debug; + + /* BSD has a better random number generator but it's not clear + * that we need it here. + */ + gettime(&tt); + srand(((unsigned)getpid()) + (unsigned)tt.tv_usec); + + (void) umask(022); + + /* Save argv[] before getopt() destroys it -- needed for execvp(). */ + saved_argv = malloc(sizeof(char *) * (argc + 1)); + INSIST(saved_argv != NULL); + for (n = 0; n < argc; n++) { + saved_argv[n] = strdup(argv[n]); + INSIST(saved_argv[n] != NULL); + } + saved_argv[argc] = NULL; + /* XXX we need to free() this for clean shutdowns. */ + + while ((ch = getopt(argc, argv, "b:c:d:g:p:t:u:vw:qrf")) != -1) { + switch (ch) { + case 'b': + case 'c': + if (conffile != NULL) + (void)freestr(conffile); + conffile = savestr(optarg, 1); + break; + + case 'd': + desired_debug = atoi(optarg); + if (desired_debug <= 0) + desired_debug = 1; + break; + + case 'p': + /* use nonstandard port number. + * usage: -p remote/local + * remote is the port number to which + * we send queries. local is the port + * on which we listen for queries. + * local defaults to same as remote. + */ + ns_port = htons((u_int16_t) atoi(optarg)); + p = strchr(optarg, '/'); + if (p) { + syslog(LOG_WARNING, bad_p_option); + fprintf(stderr, bad_p_option); + fputc('\n', stderr); + } + break; + + case 'w': + working_dir = savestr(optarg, 1); + break; +#ifdef QRYLOG + case 'q': + qrylog = 1; + break; +#endif + + case 'r': + ns_setoption(OPTION_NORECURSE); + break; + + case 'f': + foreground = 1; + break; + + case 't': + chroot_dir = savestr(optarg, 1); + break; + + case 'v': + fprintf(stdout, "%s\n", Version); + exit(0); + +#ifdef CAN_CHANGE_ID + case 'u': + user_name = savestr(optarg, 1); + if (only_digits(user_name)) + user_id = atoi(user_name); + else { + pw = getpwnam(user_name); + if (pw == NULL) { + fprintf(stderr, + "user \"%s\" unknown\n", + user_name); + exit(1); + } + user_id = pw->pw_uid; + if (group_name == NULL) { + char name[256]; + + sprintf(name, "%lu", + (u_long)pw->pw_gid); + group_name = savestr(name, 1); + group_id = pw->pw_gid; + } + } + break; + + case 'g': + if (group_name != NULL) + (void)freestr(group_name); + group_name = savestr(optarg, 1); + if (only_digits(group_name)) + group_id = atoi(group_name); + else { + gr = getgrnam(group_name); + if (gr == NULL) { + fprintf(stderr, + "group \"%s\" unknown\n", + group_name); + exit(1); + } + group_id = gr->gr_gid; + } + break; +#endif /* CAN_CHANGE_ID */ + + case '?': + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (argc) { + if (conffile != NULL) + (void)freestr(conffile); + conffile = savestr(*argv, 1); + argc--, argv++; + } + if (argc) + usage(); + + if (conffile == NULL) + conffile = savestr(_PATH_CONF, 1); + + /* + * Make sure we don't inherit any open descriptors + * other than those that daemon() can deal with. + */ + for (n = sysconf(_SC_OPEN_MAX) - 1; n >= 0; n--) + if (n != STDIN_FILENO && + n != STDOUT_FILENO && + n != STDERR_FILENO) + (void) close(n); + + /* + * Chroot if desired. + */ + if (chroot_dir != NULL) { +#ifdef HAVE_CHROOT + if (chroot(chroot_dir) < 0) { + fprintf(stderr, "chroot %s failed: %s\n", chroot_dir, + strerror(errno)); + exit(1); + } + if (chdir("/") < 0) { + fprintf(stderr, "chdir(\"/\") failed: %s\n", + strerror(errno)); + exit(1); + } +#else + fprintf(stderr, "warning: chroot() not available\n"); + chroot_dir = freestr(chroot_dir); +#endif + } + /* + * Set working directory. + */ + if (working_dir != NULL) { + if (chdir(working_dir) < 0) { + syslog(LOG_CRIT, bad_directory, working_dir, + strerror(errno)); + fprintf(stderr, bad_directory, working_dir, + strerror(errno)); + fputc('\n', stderr); + exit(1); + } + } + + /* Establish global event context. */ + evCreate(&ev); + + /* Establish global resolver context. */ + res_ninit(&res); + res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE); + + /* + * Set up logging. + */ + n = LOG_PID; +#ifdef LOG_NOWAIT + n |= LOG_NOWAIT; +#endif +#ifdef LOG_NDELAY + n |= LOG_NDELAY; +#endif +#if defined(LOG_CONS) && defined(USE_LOG_CONS) + n |= LOG_CONS; +#endif +#ifdef SYSLOG_42BSD + openlog("named", n); +#else + openlog("named", n, ISC_FACILITY); +#endif + + init_logging(); + set_assertion_failure_callback(ns_assertion_failed); + +#ifdef DEBUG + use_desired_debug(); +#endif + + /* Perform system-dependent initialization */ + custom_init(); + + init_needs(); + init_signals(); + + ns_notice(ns_log_default, "starting (%s). %s", conffile, Version); + + /* + * Initialize and load database. + */ + gettime(&tt); + buildservicelist(); + buildprotolist(); + confmtime = ns_init(conffile); + time(&boottime); + resettime = boottime; + + nsid_init(); + + /* + * Fork and go into background now that + * we've done any slow initialization + * and are ready to answer queries. + */ + + if (foreground == 0) { + if (daemon(1, 0)) + ns_panic(ns_log_default, 1, "daemon: %s", + strerror(errno)); + update_pid_file(); + } + + /* Check that udp checksums are on. */ + ns_udp(); + + /* + * We waited until now to log this because we wanted logging to + * be set up the way the user prefers. + */ + if (chroot_dir != NULL) + ns_info(ns_log_security, "chrooted to %s", chroot_dir); + +#ifdef CAN_CHANGE_ID + /* + * Set user and group if desired. + */ + if (group_name != NULL) { + if (setgid(group_id) < 0) + ns_panic(ns_log_security, 1, "setgid(%s): %s", + group_name, strerror(errno)); + ns_info(ns_log_security, "group = %s", group_name); + } + if (user_name != NULL) { + if (getuid() == 0 && initgroups(user_name, group_id) < 0) + ns_panic(ns_log_security, 1, "initgroups(%s, %d): %s", + user_name, (int)group_id, strerror(errno)); + endgrent(); + endpwent(); + if (setuid(user_id) < 0) + ns_panic(ns_log_security, 1, "setuid(%s): %s", + user_name, strerror(errno)); + ns_info(ns_log_security, "user = %s", user_name); + if (user_id != 0) + iflist_dont_rescan++; + } +#endif /* CAN_CHANGE_ID */ + + ns_notice(ns_log_default, "Ready to answer queries."); + gettime(&tt); + prime_cache(); + while (!needs_exit) { + evEvent event; + + ns_debug(ns_log_default, 15, "main loop"); + if (needs != 0) + handle_needs(); + else if (evGetNext(ev, &event, EV_WAIT) != -1) + INSIST_ERR(evDispatch(ev, event) != -1); + else + INSIST_ERR(errno == EINTR); + } + if (needs_restart) + ns_info(ns_log_default, "named restarting"); + else + ns_info(ns_log_default, "named shutting down"); +#ifdef BIND_UPDATE + dynamic_about_to_exit(); +#endif + if (server_options && server_options->pid_filename) + (void)unlink(server_options->pid_filename); + ns_logstats(ev, NULL, evNowTime(), evConsTime(0, 0)); + + if (NS_OPTION_P(OPTION_DEALLOC_ON_EXIT)) + deallocate_everything(); + else + shutdown_configuration(); + + if (needs_restart) + execvp(saved_argv[0], saved_argv); + else + /* Cleanup for system-dependent stuff */ + custom_shutdown(); + + return (0); +} + +static int +sq_closeone(void) { + struct qstream *sp, *nextsp; + struct qstream *candidate = NULL; + time_t lasttime, maxctime = 0; + int result = 0; + + gettime(&tt); + + for (sp = streamq; sp; sp = nextsp) { + nextsp = sp->s_next; + if (sp->s_refcnt) + continue; + lasttime = tt.tv_sec - sp->s_time; + if (lasttime >= VQEXPIRY) { + sq_remove(sp); + result = 1; + } else if (lasttime > maxctime) { + candidate = sp; + maxctime = lasttime; + } + } + if (candidate) { + sq_remove(candidate); + result = 1; + } + return (result); +} + +static int +ns_socket(int domain, int type, int protocol) { + int fd, tmp; + + again: + fd = socket(domain, type, protocol); +#ifdef F_DUPFD /* XXX */ + /* + * Leave a space for stdio to work in. + */ + if (fd >= 0 && fd <= 20) { + int new; + if ((new = fcntl(fd, F_DUPFD, 20)) == -1) + ns_notice(ns_log_default, "fcntl(fd, F_DUPFD, 20): %s", + strerror(errno)); + tmp = errno; + close(fd); + errno = tmp; + fd = new; + } +#endif + tmp = errno; + if (errno == EMFILE) + if (sq_closeone()) + goto again; + errno = tmp; + return (fd); +} + +#ifndef IP_OPT_BUF_SIZE +/* arbitrary size */ +#define IP_OPT_BUF_SIZE 50 +#endif + +static void +stream_accept(evContext lev, void *uap, int rfd, + const void *lav, int lalen, + const void *rav, int ralen) +{ + interface *ifp = uap; + struct qstream *sp; + struct iovec iov; + ISC_SOCKLEN_T len; + int n; + const int on = 1; +#ifdef IP_OPTIONS /* XXX */ + u_char ip_opts[IP_OPT_BUF_SIZE]; +#endif + const struct sockaddr_in *la, *ra; + + UNUSED(lalen); + UNUSED(ralen); + + la = (const struct sockaddr_in *)lav; + ra = (const struct sockaddr_in *)rav; + + INSIST(ifp != NULL); + +#ifdef F_DUPFD + /* + * Leave a space for stdio to work in. + */ + if (rfd >= 0 && rfd <= 20) { + int new, tmp; + new = fcntl(rfd, F_DUPFD, 20); + tmp = errno; + if (new == -1) + ns_notice(ns_log_default, + "fcntl(rfd, F_DUPFD, 20): %s", + strerror(errno)); + close(rfd); + errno = tmp; + rfd = new; + } +#endif + + if (rfd < 0) { + switch (errno) { + case EINTR: + case EAGAIN: +#if (EWOULDBLOCK != EAGAIN) + case EWOULDBLOCK: +#endif + case ECONNABORTED: +#ifdef EPROTO + case EPROTO: +#endif + case EHOSTUNREACH: + case EHOSTDOWN: + case ENETUNREACH: + case ENETDOWN: + case ECONNREFUSED: +#ifdef ENONET + case ENONET: +#endif + /* + * These errors are expected and harmless, so + * we ignore them. + */ + return; + case EBADF: + case ENOTSOCK: + case EFAULT: + /* + * If one these happens, we're broken. + */ + ns_panic(ns_log_default, 1, "accept: %s", + strerror(errno)); + case EMFILE: + /* + * If we're out of file descriptors, find the least + * busy fd and close it. Then we'll return to the + * eventlib which will call us right back. + */ + if (streamq) { + (void)sq_closeone(); + return; + } + /* fall through */ + default: + /* + * Either we got an error we didn't expect, or we + * got EMFILE and didn't have anything left to close. + * Log it and press on. + */ + ns_info(ns_log_default, "accept: %s", strerror(errno)); + return; + } + } + + /* Condition the socket. */ + +#ifndef CANNOT_SET_SNDBUF + if (setsockopt(rfd, SOL_SOCKET, SO_SNDBUF, + (const char*)&sbufsize, sizeof sbufsize) < 0) { + ns_info(ns_log_default, "setsockopt(rfd, SO_SNDBUF, %d): %s", + sbufsize, strerror(errno)); + (void) close(rfd); + return; + } +#endif + if (setsockopt(rfd, SOL_SOCKET, SO_KEEPALIVE, + (const char *)&on, sizeof on) < 0) { + ns_info(ns_log_default, "setsockopt(rfd, KEEPALIVE): %s", + strerror(errno)); + (void) close(rfd); + return; + } + +#ifdef USE_FIONBIO_IOCTL + if (ioctl(ifp->dfd, FIONBIO, (char *) &on) == -1) { + ns_info(ns_log_default, "ioctl(rfd, FIONBIO): %s", + strerror(errno)); + (void) close(rfd); + return; + } +#else + if ((n = fcntl(rfd, F_GETFL, 0)) == -1) { + ns_info(ns_log_default, "fcntl(rfd, F_GETFL): %s", + strerror(errno)); + (void) close(rfd); + return; + } + if (fcntl(rfd, F_SETFL, n|PORT_NONBLOCK) == -1) { + ns_info(ns_log_default, "fcntl(rfd, NONBLOCK): %s", + strerror(errno)); + (void) close(rfd); + return; + } +#endif + + /* + * We don't like IP options. Turn them off if the connection came in + * with any. log this event since it usually indicates a security + * problem. + */ +#if defined(IP_OPTIONS) /* XXX */ + len = sizeof ip_opts; + if (getsockopt(rfd, IPPROTO_IP, IP_OPTIONS, + (char *)ip_opts, &len) < 0) { + ns_info(ns_log_default, "getsockopt(rfd, IP_OPTIONS): %s", + strerror(errno)); + (void) close(rfd); + return; + } + if (len != 0) { + nameserIncr(ra->sin_addr, nssRcvdOpts); + if (!haveComplained(ina_ulong(ra->sin_addr), + (u_long)"rcvd ip options")) { + ns_info(ns_log_default, + "rcvd IP_OPTIONS from %s (ignored)", + sin_ntoa(*ra)); + } + if (setsockopt(rfd, IPPROTO_IP, IP_OPTIONS, NULL, 0) < 0) { + ns_info(ns_log_default, "setsockopt(!IP_OPTIONS): %s", + strerror(errno)); + (void) close(rfd); + } + } +#endif + + /* Create and populate a qsp for this socket. */ + if ((sp = sq_add()) == NULL) { + (void) close(rfd); + return; + } + sp->s_rfd = rfd; /* stream file descriptor */ + gettime(&tt); + sp->s_time = tt.tv_sec; /* last transaction time */ + sp->s_from = *ra; /* address to respond to */ + sp->s_ifp = ifp; + INSIST(sizeof sp->s_temp >= INT16SZ); + iov = evConsIovec(sp->s_temp, INT16SZ); + INSIST_ERR(evRead(lev, rfd, &iov, 1, stream_getlen, sp, &sp->evID_r) + != -1); + sp->flags |= STREAM_READ_EV; + ns_debug(ns_log_default, 1, "IP/TCP connection from %s (fd %d)", + sin_ntoa(sp->s_from), rfd); +} + +int +tcp_send(struct qinfo *qp) { + struct qstream *sp; + struct sockaddr_in src; + int on = 1, n; + int fd; + + ns_debug(ns_log_default, 1, "tcp_send"); + if ((fd = ns_socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) == -1) + return (SERVFAIL); + if (fd > evHighestFD(ev)) { + close(fd); + return (SERVFAIL); + } + if ((sp = sq_add()) == NULL) { + close(fd); + return (SERVFAIL); + } + sp->s_rfd = fd; + if (setsockopt(sp->s_rfd, SOL_SOCKET, SO_REUSEADDR, + (char*)&on, sizeof(on)) < 0) + ns_info(ns_log_default, + "tcp_send: setsockopt(SO_REUSEADDR): %s", + strerror(errno)); +#ifdef SO_REUSEPORT + if (setsockopt(sp->s_rfd, SOL_SOCKET, SO_REUSEPORT, + (char*)&on, sizeof(on)) < 0) + ns_info(ns_log_default, + "tcp_send: setsockopt(SO_REUSEPORT): %s", + strerror(errno)); +#endif + src = server_options->query_source; + src.sin_port = htons(0); + if (bind(sp->s_rfd, (struct sockaddr *)&src, sizeof(src)) < 0) + ns_info(ns_log_default, "tcp_send: bind(query_source): %s", + strerror(errno)); + if (fcntl(sp->s_rfd, F_SETFD, 1) < 0) { + sq_remove(sp); + return (SERVFAIL); + } +#ifdef USE_FIONBIO_IOCTL + if (ioctl(sp->s_rfd, FIONBIO, (char *) &on) == -1) { + sq_remove(sp); + return (SERVFAIL); + } +#else + if ((n = fcntl(sp->s_rfd, F_GETFL, 0)) == -1) { + sq_remove(sp); + return (SERVFAIL); + } + if (fcntl(sp->s_rfd, F_SETFL, n|PORT_NONBLOCK) == -1) { + sq_remove(sp); + return (SERVFAIL); + } +#endif + if (sq_openw(sp, qp->q_msglen + INT16SZ) == -1) { + sq_remove(sp); + return (SERVFAIL); + } + if (sq_write(sp, qp->q_msg, qp->q_msglen) == -1) { + sq_remove(sp); + return (SERVFAIL); + } + + if (setsockopt(sp->s_rfd, SOL_SOCKET, SO_KEEPALIVE, + (char*)&on, sizeof(on)) < 0) + ns_info(ns_log_default, + "tcp_send: setsockopt(SO_KEEPALIVE): %s", + strerror(errno)); + gettime(&tt); + sp->s_size = -1; + sp->s_time = tt.tv_sec; /* last transaction time */ + sp->s_refcnt = 1; + sp->flags |= STREAM_DONE_CLOSE; + sp->s_from = qp->q_addr[qp->q_curaddr].ns_addr; + if (evConnect(ev, sp->s_rfd, &sp->s_from, sizeof(sp->s_from), + stream_send, sp, &sp->evID_c) == -1) { + sq_remove(sp); + return (SERVFAIL); + } + sp->flags |= STREAM_CONNECT_EV; + return (NOERROR); +} + +static void +stream_send(evContext lev, void *uap, int fd, const void *la, int lalen, + const void *ra, int ralen) { + struct qstream *sp = uap; + + UNUSED(lev); + UNUSED(la); + UNUSED(lalen); + UNUSED(ra); + UNUSED(ralen); + + ns_debug(ns_log_default, 1, "stream_send"); + + sp->flags &= ~STREAM_CONNECT_EV; + + if (fd == -1) { + /* connect failed */ + sq_remove(sp); + return; + } + if (evSelectFD(ev, sp->s_rfd, EV_WRITE, + stream_write, sp, &sp->evID_w) < 0) { + sq_remove(sp); + return; + } + sp->flags |= STREAM_WRITE_EV; +} + +static void +stream_write(evContext ctx, void *uap, int fd, int evmask) { + struct qstream *sp = uap; + struct iovec iov; + + ns_debug(ns_log_default, 1, "stream_write"); + INSIST(evmask & EV_WRITE); + INSIST(fd == sp->s_rfd); + if (sq_dowrite(sp) < 0) { + sq_remove(sp); + return; + } + if (sp->s_wbuf_free != sp->s_wbuf_send) + return; + + if (sp->s_wbuf) { + memput(sp->s_wbuf, sp->s_wbuf_end - sp->s_wbuf); + sp->s_wbuf_send = sp->s_wbuf_free = NULL; + sp->s_wbuf_end = sp->s_wbuf = NULL; + } + (void) evDeselectFD(ev, sp->evID_w); + sp->flags &= ~STREAM_WRITE_EV; + sp->s_refcnt = 0; + iov = evConsIovec(sp->s_temp, INT16SZ); + INSIST_ERR(evRead(ctx, fd, &iov, 1, stream_getlen, sp, &sp->evID_r) != + -1); + sp->flags |= STREAM_READ_EV; +} + +static void +stream_getlen(evContext lev, void *uap, int fd, int bytes) { + struct qstream *sp = uap; + struct iovec iov; + + UNUSED(fd); + + sp->flags &= ~STREAM_READ_EV; + if (bytes != INT16SZ) { + /* + * bytes == 0 is normal EOF; see if something unusual + * happened. + */ + if (bytes < 0) { + /* + * ECONNRESET happens frequently and is not worth + * logging. + */ + if (errno != ECONNRESET) + ns_info(ns_log_default, + "stream_getlen(%s): %s", + sin_ntoa(sp->s_from), strerror(errno)); + } else if (bytes != 0) + ns_error(ns_log_default, + "stream_getlen(%s): unexpected byte count %d", + sin_ntoa(sp->s_from), bytes); + sq_remove(sp); + return; + } + + /* + * Unpack the size, allocate memory for the query. This is + * tricky since in a low memory situation with possibly very + * large (64KB) queries, we want to make sure we can read at + * least the header since we need it to send back a SERVFAIL + * (owing to the out-of-memory condition). + */ + sp->s_size = ns_get16(sp->s_temp); + ns_debug(ns_log_default, 5, "stream message: %d bytes", sp->s_size); + if (sp->s_size < HFIXEDSZ) { + ns_error(ns_log_default, + "stream_getlen(%s): request too small", + sin_ntoa(sp->s_from)); + sq_remove(sp); + return; + } + + if (!(sp->flags & STREAM_MALLOC)) { + sp->s_bufsize = 64*1024-1; /* maximum tcp message size */ + sp->s_buf = (u_char *)memget(sp->s_bufsize); + if (sp->s_buf != NULL) + sp->flags |= STREAM_MALLOC; + else { + sp->s_buf = sp->s_temp; + sp->s_bufsize = HFIXEDSZ; + } + } + + iov = evConsIovec(sp->s_buf, (sp->s_size <= sp->s_bufsize) ? + sp->s_size : sp->s_bufsize); + if (evRead(lev, sp->s_rfd, &iov, 1, stream_getmsg, sp, &sp->evID_r) + == -1) + ns_panic(ns_log_default, 1, "evRead(fd %d): %s", + sp->s_rfd, strerror(errno)); + sp->flags |= STREAM_READ_EV; +} + +static void +stream_getmsg(evContext lev, void *uap, int fd, int bytes) { + struct qstream *sp = uap; + + UNUSED(lev); + UNUSED(fd); + + sp->flags &= ~STREAM_READ_EV; + if (bytes == -1) { + ns_info(ns_log_default, "stream_getmsg(%s): %s", + sin_ntoa(sp->s_from), strerror(errno)); + sq_remove(sp); + return; + } + + gettime(&tt); + sp->s_time = tt.tv_sec; + + if (ns_wouldlog(ns_log_default,5)) { + ns_debug(ns_log_default, 5, + "sp %p rfd %d size %d time %ld next %p", + sp, sp->s_rfd, sp->s_size, (long)sp->s_time, + sp->s_next); + ns_debug(ns_log_default, 5, "\tbufsize %d bytes %d", sp->s_bufsize, + bytes); + } + + /* + * Do we have enough memory for the query? If not, and if we have a + * query id, then we will send a SERVFAIL error back to the client. + */ + if (bytes != sp->s_size) { + HEADER *hp = (HEADER *)sp->s_buf; + + hp->qr = 1; + hp->ra = (NS_OPTION_P(OPTION_NORECURSE) == 0); + hp->ancount = htons(0); + hp->qdcount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); + hp->rcode = SERVFAIL; + writestream(sp, sp->s_buf, HFIXEDSZ); + sp->flags |= STREAM_DONE_CLOSE; + return; + } + + nameserIncr(sp->s_from.sin_addr, nssRcvdTCP); + sq_query(sp); + dispatch_message(sp->s_buf, bytes, sp->s_bufsize, sp, sp->s_from, -1, + sp->s_ifp); +} + +static void +datagram_read(evContext lev, void *uap, int fd, int evmask) { + interface *ifp = uap; + struct sockaddr_in from; + ISC_SOCKLEN_T from_len = sizeof from; + int n, nudp; + union { + HEADER h; /* Force alignment of 'buf'. */ + u_char buf[EDNS_MESSAGE_SZ+1]; + } u; + + UNUSED(lev); + UNUSED(evmask); + + tt = evTimeVal(evNowTime()); + nudp = 0; + + more: + n = recvfrom(fd, (char *)u.buf, sizeof u.buf, 0, + (struct sockaddr *)&from, &from_len); + + if (n < 0) { + switch (errno) { + case EINTR: + case EAGAIN: +#if (EWOULDBLOCK != EAGAIN) + case EWOULDBLOCK: +#endif + case EHOSTUNREACH: + case EHOSTDOWN: + case ENETUNREACH: + case ENETDOWN: + case ECONNREFUSED: +#ifdef ENONET + case ENONET: +#endif + /* + * These errors are expected and harmless, so we + * ignore them. + */ + return; + default: + /* + * An error we don't expect. Log it and press + * on. + */ + ns_info(ns_log_default, "recvfrom: %s", + strerror(errno)); + return; + } + } + + /* Handle bogosity on systems that need it. */ + if (n == 0) + return; + + if (ns_wouldlog(ns_log_default, 1)) { + ns_debug(ns_log_default, 1, "datagram from %s, fd %d, len %d", + sin_ntoa(from), fd, n); + } + + if (n > EDNS_MESSAGE_SZ) { + /* + * The message is too big. It's probably a response to + * one of our questions, so we truncate it and press on. + */ + n = trunc_adjust(u.buf, EDNS_MESSAGE_SZ, EDNS_MESSAGE_SZ); + ns_debug(ns_log_default, 1, "truncated oversize UDP packet"); + } + + dispatch_message(u.buf, n, EDNS_MESSAGE_SZ, NULL, from, fd, ifp); + if (++nudp < nudptrans) + goto more; +} + +static void +savedg_waitfunc(evContext ctx, void *uap, const void *tag) { + savedg *dg = (savedg *)uap; + + UNUSED(ctx); + UNUSED(tag); + + if (!EMPTY(iflist) && HEAD(iflist)->gen == dg->gen) { + u_char buf[EDNS_MESSAGE_SZ]; + + memcpy(buf, dg->buf, dg->buflen); + dispatch_message(buf, dg->buflen, sizeof buf, NULL, + dg->from, dg->dfd, dg->ifp); + } + memput(dg->buf, dg->buflen); + memput(dg, sizeof *dg); +} + +static void +dispatch_message(u_char *msg, int msglen, int buflen, struct qstream *qsp, + struct sockaddr_in from, int dfd, interface *ifp) +{ + HEADER *hp = (HEADER *)msg; + + if (msglen < HFIXEDSZ) { + ns_debug(ns_log_default, 1, "dropping undersize message"); + if (qsp) { + qsp->flags |= STREAM_DONE_CLOSE; + sq_done(qsp); + } + return; + } + + if (server_options->blackhole_acl != NULL && + ip_match_address(server_options->blackhole_acl, + from.sin_addr) == 1) { + ns_debug(ns_log_default, 1, + "dropping blackholed %s from %s", + hp->qr ? "response" : "query", + sin_ntoa(from)); + if (qsp) { + qsp->flags |= STREAM_DONE_CLOSE; + sq_done(qsp); + } + return; + } + + /* Drop UDP packets from port zero. They are invariable forged. */ + if (qsp == NULL && ntohs(from.sin_port) == 0) { + ns_notice(ns_log_security, + "dropping source port zero packet from %s", + sin_ntoa(from)); + return; + } + + if (hp->qr) { + ns_resp(msg, msglen, from, qsp); + if (qsp) + sq_done(qsp); + /* Now is a safe time for housekeeping. */ + if (needs_prime_cache) + prime_cache(); + } else if (ifp != NULL) + ns_req(msg, msglen, buflen, qsp, from, dfd); + else { + ns_notice(ns_log_security, + "refused query on non-query socket from %s", + sin_ntoa(from)); + if (qsp) { + qsp->flags |= STREAM_DONE_CLOSE; + sq_done(qsp); + } + /* XXX Send refusal here. */ + } +} + +void +getnetconf(int periodic_scan) { + struct ifconf ifc; + struct ifreq ifreq; + struct in_addr ina; + interface *ifp; + char *buf, *cp, *cplim; + static int bufsiz = 4095; + time_t my_generation = time(NULL); + int s, cpsize, n; + int found; + listen_info li; + ip_match_element ime; + u_char *mask_ptr; + struct in_addr mask; + + if (iflist_initialized) { + if (iflist_dont_rescan) + return; + } else { + INIT_LIST(iflist); + iflist_initialized = 1; + } + + ns_debug(ns_log_default, 1, "getnetconf(generation %lu)", + (u_long)my_generation); + + /* Get interface list from system. */ + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + if (!periodic_scan) + ns_panic(ns_log_default, 1, "socket(SOCK_RAW): %s", + strerror(errno)); + ns_error(ns_log_default, "socket(SOCK_RAW): %s", + strerror(errno)); + return; + } + + if (local_addresses != NULL) + free_ip_match_list(local_addresses); + local_addresses = new_ip_match_list(); + if (local_networks != NULL) + free_ip_match_list(local_networks); + local_networks = new_ip_match_list(); + + for (;;) { + buf = memget(bufsiz); + if (!buf) + ns_panic(ns_log_default, 1, "memget(interface)"); + ifc.ifc_len = bufsiz; + ifc.ifc_buf = buf; +#ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF + /* + * This is a fix for IRIX OS in which the call to ioctl with + * the flag SIOCGIFCONF may not return an entry for all the + * interfaces like most flavors of Unix. + */ + if (emul_ioctl(&ifc) >= 0) + break; +#else + if ((n = ioctl(s, SIOCGIFCONF, (char *)&ifc)) != -1) { + /* + * Some OS's just return what will fit rather + * than set EINVAL if the buffer is too small + * to fit all the interfaces in. If + * ifc.ifc_len is too near to the end of the + * buffer we will grow it just in case and + * retry. + */ + if ((int)(ifc.ifc_len + 2 * sizeof(ifreq)) < bufsiz) + break; + } +#endif + if ((n == -1) && errno != EINVAL) + ns_panic(ns_log_default, 1, + "get interface configuration: %s", + strerror(errno)); + + if (bufsiz > 1000000) + ns_panic(ns_log_default, 1, + "get interface configuration: maximum buffer size exceeded"); + memput(buf, bufsiz); + bufsiz += 4096; + } + + ns_debug(ns_log_default, 2, "getnetconf: SIOCGIFCONF: ifc_len = %d", + ifc.ifc_len); + + /* Parse system's interface list and open some sockets. */ + cplim = buf + ifc.ifc_len; /* skip over if's with big ifr_addr's */ + for (cp = buf; cp < cplim; cp += cpsize) { + memcpy(&ifreq, cp, sizeof ifreq); +#ifdef HAVE_SA_LEN +#ifdef FIX_ZERO_SA_LEN + if (ifreq.ifr_addr.sa_len == 0) + ifreq.ifr_addr.sa_len = 16; +#endif +#ifdef HAVE_MINIMUM_IFREQ + ns_debug(ns_log_default, 2, "%s sa_len = %d", + ifreq.ifr_name, (int)ifreq.ifr_addr.sa_len); + cpsize = sizeof ifreq; + if (ifreq.ifr_addr.sa_len > sizeof (struct sockaddr)) + cpsize += (int)ifreq.ifr_addr.sa_len - + (int)(sizeof (struct sockaddr)); +#else + cpsize = sizeof ifreq.ifr_name + ifreq.ifr_addr.sa_len; +#endif /* HAVE_MINIMUM_IFREQ */ +#elif defined SIOCGIFCONF_ADDR + cpsize = sizeof ifreq; +#else + cpsize = sizeof ifreq.ifr_name; + if (ioctl(s, SIOCGIFADDR, (char *)&ifreq) < 0) { + ns_notice(ns_log_default, + "get interface addr (%s): %s", + ifreq.ifr_name, strerror(errno)); + continue; + } +#endif + if (ifreq.ifr_addr.sa_family != AF_INET) { + ns_debug(ns_log_default, 2, + "getnetconf: %s AF %d != INET", + ifreq.ifr_name, ifreq.ifr_addr.sa_family); + continue; + } + ina = ina_get((u_char *)&((struct sockaddr_in *) + &ifreq.ifr_addr)->sin_addr); + ns_debug(ns_log_default, 1, + "getnetconf: considering %s [%s]", + ifreq.ifr_name, inet_ntoa(ina)); + /* + * Don't test IFF_UP, packets may still be received at this + * address if any other interface is up. + */ + if (ina_hlong(ina) == INADDR_ANY) { + ns_debug(ns_log_default, 2, + "getnetconf: INADDR_ANY, ignoring."); + continue; + } + + INSIST(server_options != NULL); + INSIST(server_options->listen_list != NULL); + + found=0; + for (li = server_options->listen_list->first; + li != NULL; + li = li->next) { + if (ip_match_address(li->list, ina) > 0) { + found++; + /* + * Look for an already existing source + * interface address/port pair. + * This happens mostly when reinitializing. + * Also, if the machine has multiple point to + * point interfaces, then the local address + * may appear more than once. + */ + ifp = if_find(ina, li->port); + if (ifp != NULL) { + ns_debug(ns_log_default, 1, + "dup interface addr [%s].%u (%s)", + inet_ntoa(ina), + ntohs(li->port), + ifreq.ifr_name); + ifp->gen = my_generation; + continue; + } + + ifp = (interface *)memget(sizeof *ifp); + if (!ifp) + ns_panic(ns_log_default, 1, + "memget(interface)"); + memset(ifp, 0, sizeof *ifp); + INIT_LINK(ifp, link); + APPEND(iflist, ifp, link); + ifp->addr = ina; + ifp->port = li->port; + ifp->gen = my_generation; + ifp->flags = 0; + ifp->dfd = -1; + ifp->sfd = -1; + if (opensocket_d(ifp) < 0 || + opensocket_s(ifp) < 0) { + dq_remove(ifp); + found = 0; + break; + } + ns_info(ns_log_default, + "listening on [%s].%u (%s)", + inet_ntoa(ina), ntohs(li->port), + ifreq.ifr_name); + } + } + if (!found) + ns_debug(ns_log_default, 1, + "not listening on addr [%s] (%s)", + inet_ntoa(ina), ifreq.ifr_name); + + /* + * Add this interface's address to the list of local + * addresses if we haven't added it already. + */ + if (ip_match_address(local_addresses, ina) < 0) { + ime = new_ip_match_pattern(ina, 32); + add_to_ip_match_list(local_addresses, ime); + } + + /* + * Get interface flags. + */ + if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { + ns_notice(ns_log_default, "get interface flags: %s", + strerror(errno)); + continue; + } + + if ((ifreq.ifr_flags & IFF_POINTOPOINT)) { + /* + * The local network for a PPP link is just the + * two ends of the link, so for each endpoint we + * add a pattern that will only match the endpoint. + */ + if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { + ns_notice(ns_log_default, "get dst addr: %s", + strerror(errno)); + continue; + } + + mask.s_addr = htonl(INADDR_BROADCAST); + + /* + * Our end. + * + * Only add it if we haven't seen it before. + */ + if (ip_match_network(local_networks, ina, mask) < 0) { + ime = new_ip_match_pattern(ina, 32); + add_to_ip_match_list(local_networks, ime); + } + + /* + * The other end. + */ + ina = ((struct sockaddr_in *) + &ifreq.ifr_addr)->sin_addr; + /* + * Only add it if we haven't seen it before. + */ + if (ip_match_network(local_networks, ina, mask) < 0) { + ime = new_ip_match_pattern(ina, 32); + add_to_ip_match_list(local_networks, ime); + } + } else { + /* + * Add this interface's network and netmask to the + * list of local networks. + */ + +#ifdef SIOCGIFNETMASK /* XXX */ + if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreq) < 0) { + ns_notice(ns_log_default, "get netmask: %s", + strerror(errno)); + continue; + } + /* + * Use ina_get because the ifreq structure might not + * be aligned. + */ + mask_ptr = (u_char *) + &((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr; + mask = ina_get(mask_ptr); +#else + mask = net_mask(ina); +#endif + + ina.s_addr &= mask.s_addr; /* make network address */ + + /* + * Only add it if we haven't seen it before. + */ + if (ip_match_network(local_networks, ina, mask) < 0) { + ime = new_ip_match_mask(ina, mask); + add_to_ip_match_list(local_networks, ime); + } + } + } + close(s); + memput(buf, bufsiz); + + ns_debug(ns_log_default, 7, "local addresses:"); + dprint_ip_match_list(ns_log_default, local_addresses, 2, "", ""); + ns_debug(ns_log_default, 7, "local networks:"); + dprint_ip_match_list(ns_log_default, local_networks, 2, "", ""); + + /* + * now go through the iflist and delete anything that + * does not have the current generation number. this is + * how we catch interfaces that go away or change their + * addresses. note that 0.0.0.0 is the wildcard element + * and should never be deleted by this code. + */ + dq_remove_gen(my_generation); + + if (EMPTY(iflist)) + ns_warning(ns_log_default, "not listening on any interfaces"); +} + +/* opensocket_d(ifp) + * Open datagram socket bound to interface address. + * Returns: + * 0 on success. + * -1 on failure. + */ +static int +opensocket_d(interface *ifp) { + struct sockaddr_in nsa; + const int on = 1; + ISC_SOCKLEN_T m; + int n; + + memset(&nsa, 0, sizeof nsa); + nsa.sin_family = AF_INET; + nsa.sin_addr = ifp->addr; + nsa.sin_port = ifp->port; + + if ((ifp->dfd = ns_socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + ns_error(ns_log_default, "socket(SOCK_DGRAM): %s", + strerror(errno)); + return (-1); + } + if (ifp->dfd > evHighestFD(ev)) { + ns_error(ns_log_default, "socket too high: %d", ifp->dfd); + close(ifp->dfd); + return (-1); + } +#ifdef USE_FIONBIO_IOCTL + if (ioctl(ifp->dfd, FIONBIO, (char *) &on) == -1) { + ns_info(ns_log_default, "ioctl(ifp->dfd, FIONBIO): %s", + strerror(errno)); + (void) close(ifp->dfd); + return (-1); + } +#else + if ((n = fcntl(ifp->dfd, F_GETFL, 0)) == -1) { + ns_info(ns_log_default, "fcntl(ifp->dfd, F_GETFL): %s", + strerror(errno)); + (void) close(ifp->dfd); + return (-1); + } + if (fcntl(ifp->dfd, F_SETFL, n|PORT_NONBLOCK) == -1) { + ns_info(ns_log_default, "fcntl(ifp->dfd, NONBLOCK): %s", + strerror(errno)); + (void) close(ifp->dfd); + return (-1); + } +#endif + if (fcntl(ifp->dfd, F_SETFD, 1) < 0) { + ns_error(ns_log_default, "F_SETFD: %s", strerror(errno)); + close(ifp->dfd); + return (-1); + } + ns_debug(ns_log_default, 1, "ifp->addr %s d_dfd %d", + sin_ntoa(nsa), ifp->dfd); + if (setsockopt(ifp->dfd, SOL_SOCKET, SO_REUSEADDR, + (const char *)&on, sizeof(on)) != 0) { + ns_notice(ns_log_default, "setsockopt(REUSEADDR): %s", + strerror(errno)); + /* XXX press on regardless, this is not too serious. */ + } +#ifdef SO_RCVBUF /* XXX */ + m = sizeof n; + if ((getsockopt(ifp->dfd, SOL_SOCKET, SO_RCVBUF, (char*)&n, &m) >= 0) + && (m == sizeof n) + && (n < drbufsize)) { + (void) setsockopt(ifp->dfd, SOL_SOCKET, SO_RCVBUF, + (const char *)&drbufsize, sizeof drbufsize); + } +#endif /* SO_RCVBUF */ +#ifndef CANNOT_SET_SNDBUF + if (setsockopt(ifp->dfd, SOL_SOCKET, SO_SNDBUF, + (const char*)&dsbufsize, sizeof dsbufsize) < 0) { + ns_info(ns_log_default, + "setsockopt(dfd=%d, SO_SNDBUF, %d): %s", + ifp->dfd, dsbufsize, strerror(errno)); + /* XXX press on regardless, this is not too serious. */ + } +#endif +#ifdef SO_BSDCOMPAT + if (setsockopt(ifp->dfd, SOL_SOCKET, SO_BSDCOMPAT, + (char*)&on, sizeof on) < 0) { + ns_info(ns_log_default, + "setsockopt(dfd=%d, SO_BSDCOMPAT): %s", + ifp->dfd, strerror(errno)); + } +#endif + if (bind(ifp->dfd, (struct sockaddr *)&nsa, sizeof nsa)) { + ns_error(ns_log_default, "bind(dfd=%d, %s): %s", + ifp->dfd, sin_ntoa(nsa), strerror(errno)); + return (-1); + } + if (evSelectFD(ev, ifp->dfd, EV_READ, datagram_read, ifp, + &ifp->evID_d) == -1) { + ns_error(ns_log_default, "evSelectFD(dfd=%d): %s", + ifp->dfd, strerror(errno)); + return (-1); + } + ifp->flags |= INTERFACE_FILE_VALID; + return (0); +} + +static int +drain_rcvbuf(evContext ctx, interface *ifp, int fd, int *mread, int *mstore) { + int drop = 0; + + drop = 0; + for (; *mread > 0; (*mread)--) { + union { + HEADER h; + u_char buf[EDNS_MESSAGE_SZ+1]; + } u; + struct sockaddr_in from; + ISC_SOCKLEN_T from_len = sizeof from; + savedg *dg; + int n; + + n = recvfrom(fd, (char *)u.buf, sizeof u.buf, 0, + (struct sockaddr *)&from, &from_len); + if (n <= 0) + break; /* Socket buffer assumed empty. */ + drop++; /* Pessimistic assumption. */ + if (n > EDNS_MESSAGE_SZ) + continue; /* Oversize message - EDNS0 needed. */ + if (from.sin_family != AF_INET) + continue; /* Not IPv4 - IPv6 needed. */ + if (u.h.opcode == ns_o_query && u.h.qr == 0) + continue; /* Query - what we're here to axe. */ + if (*mstore <= 0) + continue; /* Reached storage quota, ignore. */ + if ((dg = memget(sizeof *dg)) == NULL) + continue; /* No memory - probably fatal. */ + if ((dg->buf = memget(n)) == NULL) { + memput(dg, sizeof *dg); + continue; /* No memory - probably fatal. */ + } + dg->from = from; + dg->dfd = fd; + dg->ifp = ifp; + dg->gen = ifp->gen; + dg->buflen = n; + memcpy(dg->buf, u.buf, n); + if (evWaitFor(ctx, (void *)drain_all_rcvbuf, savedg_waitfunc, + dg, NULL) < 0) + { + memput(dg->buf, dg->buflen); + memput(dg, sizeof *dg); + continue; /* No memory - probably fatal. */ + } + drop--; /* Pessimism was inappropriate. */ + (*mstore)--; + } + return (drop); +} + +static int +drain_all_rcvbuf(evContext ctx) { + interface *ifp; + int mread = MAX_SYNCDRAIN; + int mstore = MAX_SYNCSTORE; + int drop = 0; + + for (ifp = HEAD(iflist); ifp != NULL; ifp = NEXT(ifp, link)) + if (ifp->dfd != -1) + drop += drain_rcvbuf(ctx, ifp, ifp->dfd, + &mread, &mstore); + if (mstore < MAX_SYNCSTORE) + INSIST_ERR(evDo(ctx, (void *)drain_all_rcvbuf) != -1); + return (drop); +} + +/* opensocket_s(ifp) + * Open stream (listener) socket bound to interface address. + * Returns: + * 0 on success. + * -1 on failure. + */ +static int +opensocket_s(interface *ifp) { + struct sockaddr_in nsa; + const int on = 1; + int n; + + memset(&nsa, 0, sizeof nsa); + nsa.sin_family = AF_INET; + nsa.sin_addr = ifp->addr; + nsa.sin_port = ifp->port; + + /* + * Open stream (listener) port. + */ + n = 0; + again: + if ((ifp->sfd = ns_socket(AF_INET, SOCK_STREAM, 0)) < 0) { + ns_error(ns_log_default, "socket(SOCK_STREAM): %s", + strerror(errno)); + return (-1); + } + if (ifp->sfd > evHighestFD(ev)) { + ns_error(ns_log_default, "socket too high: %d", ifp->sfd); + close(ifp->sfd); + return (-1); + } + if (fcntl(ifp->sfd, F_SETFD, 1) < 0) { + ns_error(ns_log_default, "F_SETFD: %s", strerror(errno)); + close(ifp->sfd); + return (-1); + } + if (setsockopt(ifp->sfd, SOL_SOCKET, SO_REUSEADDR, + (const char *)&on, sizeof on) != 0) { + ns_notice(ns_log_default, "setsockopt(REUSEADDR): %s", + strerror(errno)); + /* Consider that your first warning of trouble to come. */ + } + if (bind(ifp->sfd, (struct sockaddr *)&nsa, sizeof nsa) < 0) { + if (errno != EADDRINUSE || ++n > 4) { + if (errno == EADDRINUSE) + ns_error(ns_log_default, + "There may be a name server already running on %s", + sin_ntoa(nsa)); + else + ns_error(ns_log_default, + "bind(sfd=%d, %s): %s", ifp->sfd, + sin_ntoa(nsa), strerror(errno)); + return (-1); + } + + /* Retry opening the socket a few times */ + close(ifp->sfd); + ifp->sfd = -1; + sleep(30); + goto again; + } + if (evListen(ev, ifp->sfd, listenmax, stream_accept, ifp, &ifp->evID_s) + == -1) { + ns_error(ns_log_default, "evListen(sfd=%d): %s", + ifp->sfd, strerror(errno)); + return (-1); + } + ifp->flags |= INTERFACE_CONN_VALID; + return (0); +} + +/* opensocket_f() + * Open datagram socket bound to no particular interface; use for ns_forw + * and sysquery. + */ +void +opensocket_f() { + static struct sockaddr_in prev_qsrc; + static int been_here; + static interface *prev_ifp; + struct sockaddr_in nsa; + const int on = 1; + ISC_SOCKLEN_T n; + int need_close; + interface *ifp; + + need_close = 0; + if (been_here) { + if (prev_ifp != NULL) + prev_ifp->flags &= ~INTERFACE_FORWARDING; + else if (server_options->query_source.sin_port == htons(0) || + prev_qsrc.sin_addr.s_addr != + server_options->query_source.sin_addr.s_addr || + prev_qsrc.sin_port != + server_options->query_source.sin_port) + need_close = 1; + } else + ds = -1; + + been_here = 1; + INSIST(server_options != NULL); + + if (need_close) { + evDeselectFD(ev, ds_evID); + close(ds); + ds = -1; + } + + /* + * If we're already listening on the query_source address and port, + * we don't need to open another socket. We mark the interface, so + * we'll notice we're in trouble if it goes away. + */ + ifp = if_find(server_options->query_source.sin_addr, + server_options->query_source.sin_port); + if (ifp != NULL) { + ifp->flags |= INTERFACE_FORWARDING; + prev_ifp = ifp; + ds = ifp->dfd; + ns_info(ns_log_default, "forwarding source address is %s", + sin_ntoa(server_options->query_source)); + return; + } + + /* + * If we're already using the correct query source, we're done. + */ + if (ds >= 0) + return; + + prev_qsrc = server_options->query_source; + prev_ifp = NULL; + + if ((ds = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + ns_panic(ns_log_default, 1, "socket(SOCK_DGRAM): %s", + strerror(errno)); + if (ds > evHighestFD(ev)) + ns_panic(ns_log_default, 1, "socket too high: %d", ds); + if (fcntl(ds, F_SETFD, 1) < 0) + ns_panic(ns_log_default, 1, "F_SETFD: %s", strerror(errno)); + if (setsockopt(ds, SOL_SOCKET, SO_REUSEADDR, + (const char *)&on, sizeof on) != 0) { + ns_notice(ns_log_default, "setsockopt(REUSEADDR): %s", + strerror(errno)); + /* XXX press on regardless, this is not too serious. */ + } +#ifdef SO_BSDCOMPAT + if (setsockopt(ds, SOL_SOCKET, SO_BSDCOMPAT, + (char *)&on, sizeof on) != 0) { + ns_notice(ns_log_default, "setsockopt(BSDCOMPAT): %s", + strerror(errno)); + /* XXX press on regardless, this is not too serious. */ + } +#endif + if (bind(ds, (struct sockaddr *)&server_options->query_source, + sizeof server_options->query_source) < 0) + ns_panic(ns_log_default, 0, "opensocket_f: bind(%s): %s", + sin_ntoa(server_options->query_source), + strerror(errno)); + + n = sizeof nsa; + if (getsockname(ds, (struct sockaddr *)&nsa, &n) < 0) + ns_panic(ns_log_default, 1, "opensocket_f: getsockaddr: %s", + strerror(errno)); + + ns_debug(ns_log_default, 1, "fwd ds %d addr %s", ds, sin_ntoa(nsa)); + ns_info(ns_log_default, "Forwarding source address is %s", + sin_ntoa(nsa)); + + if (evSelectFD(ev, ds, EV_READ, datagram_read, NULL, &ds_evID) == -1) + ns_panic(ns_log_default, 1, "evSelectFD(fd %d): %s", + ds, strerror(errno)); + /* XXX: should probably use a different FileFunc that only accepts + * responses, since requests on this socket make no sense. + */ +} + +static void +setdebug(int new_debug) { +#ifdef DEBUG + int old_debug; + + if (!new_debug) + ns_debug(ns_log_default, 1, "Debug off"); + old_debug = debug; + debug = new_debug; + log_option(log_ctx, LOG_OPTION_DEBUG, debug); + log_option(log_ctx, LOG_OPTION_LEVEL, debug); + if (old_debug && !debug) + log_close_debug_channels(log_ctx); + evSetDebug(ev, debug, log_get_stream(eventlib_channel)); + if (debug) { + if (!old_debug) + open_special_channels(); + ns_debug(ns_log_default, 1, "Debug level %d", debug); + if (!old_debug) { + ns_debug(ns_log_default, 1, "Version = %s", Version); + ns_debug(ns_log_default, 1, "conffile = %s", conffile); + } + } +#endif +} + +/* +** Routines for managing stream queue +*/ + +static struct qstream * +sq_add() { + struct qstream *sqp; + + if (!(sqp = (struct qstream *)memget(sizeof *sqp))) { + ns_error(ns_log_default, "sq_add: memget: %s", + strerror(errno)); + return (NULL); + } + memset(sqp, 0, sizeof *sqp); + ns_debug(ns_log_default, 3, "sq_add(%#lx)", (u_long)sqp); + + sqp->flags = 0; + /* XXX should init other fields too? */ + sqp->s_next = streamq; + streamq = sqp; + return (sqp); +} + +/* sq_remove(qp) + * remove stream queue structure `qp'. + * no current queries may refer to this stream when it is removed. + * side effects: + * memory is deallocated. sockets are closed. lists are relinked. + */ +void +sq_remove(struct qstream *qp) { + struct qstream *qsp; + + ns_debug(ns_log_default, 2, "sq_remove(%#lx, %d) rfcnt=%d", + (u_long)qp, qp->s_rfd, qp->s_refcnt); + + if (qp->s_wbuf != NULL) { + memput(qp->s_wbuf, qp->s_wbuf_end - qp->s_wbuf); + qp->s_wbuf_send = qp->s_wbuf_free = NULL; + qp->s_wbuf_end = qp->s_wbuf = NULL; + } + if (qp->flags & STREAM_MALLOC) + memput(qp->s_buf, qp->s_bufsize); + if (qp->flags & STREAM_READ_EV) + INSIST_ERR(evCancelRW(ev, qp->evID_r) != -1); + if (qp->flags & STREAM_WRITE_EV) + INSIST_ERR(evDeselectFD(ev, qp->evID_w) != -1); + if (qp->flags & STREAM_CONNECT_EV) + INSIST_ERR(evCancelConn(ev, qp->evID_c) != -1); + if (qp->flags & STREAM_AXFR || qp->flags & STREAM_AXFRIXFR) + ns_freexfr(qp); + (void) close(qp->s_rfd); + if (qp == streamq) + streamq = qp->s_next; + else { + for (qsp = streamq; + qsp && (qsp->s_next != qp); + qsp = qsp->s_next) + (void)NULL; + if (qsp) + qsp->s_next = qp->s_next; + } + memput(qp, sizeof *qp); +} + +/* void + * sq_flush(allbut) + * call sq_remove() on all open streams except `allbut' + * side effects: + * global list `streamq' modified + * idiocy: + * is N^2 due to the scan inside of sq_remove() + */ +void +sq_flush(struct qstream *allbut) { + struct qstream *sp, *spnext; + + for (sp = streamq; sp != NULL; sp = spnext) { + spnext = sp->s_next; + if (sp != allbut) + sq_remove(sp); + } +} + +/* int + * sq_openw(qs, buflen) + * add a write buffer to a stream + * return: + * 0 = success + * -1 = failure (check errno) + */ +int +sq_openw(struct qstream *qs, int buflen) { +#ifdef DO_SO_LINGER /* XXX */ + static const struct linger ll = { 1, 120 }; +#endif + + INSIST(qs->s_wbuf == NULL); + qs->s_wbuf = (u_char *)memget(buflen); + if (qs->s_wbuf == NULL) + return (-1); + qs->s_wbuf_send = qs->s_wbuf; + qs->s_wbuf_free = qs->s_wbuf; + qs->s_wbuf_end = qs->s_wbuf + buflen; +#ifdef DO_SO_LINGER /* XXX */ + /* kernels that map pages for IO end up failing if the pipe is full + * at exit and we take away the final buffer. this is really a kernel + * bug but it's harmless on systems that are not broken, so... + */ + setsockopt(qs->s_rfd, SOL_SOCKET, SO_LINGER, (char *)&ll, sizeof ll); +#endif + return (0); +} + +/* static void + * sq_dowrite(qs) + * try to submit data to the system, remove it from our queue. + */ +static int +sq_dowrite(struct qstream *qs) { + if (qs->s_wbuf_free > qs->s_wbuf_send) { + int n = write(qs->s_rfd, qs->s_wbuf_send, + qs->s_wbuf_free - qs->s_wbuf_send); + INSIST(qs->s_wbuf != NULL); + if (n < 0) { + if (errno != EINTR && errno != EAGAIN +#if (EWOULDBLOCK != EAGAIN) + && errno != EWOULDBLOCK +#endif + ) + return (-1); + return (0); + } + qs->s_wbuf_send += n; + if (qs->s_wbuf_free > qs->s_wbuf_send) { + /* XXX: need some kind of delay here during which the + * socket will be deselected so we don't spin. + */ + n = qs->s_wbuf_free - qs->s_wbuf_send; + memmove(qs->s_wbuf, qs->s_wbuf_send, n); + qs->s_wbuf_send = qs->s_wbuf; + qs->s_wbuf_free = qs->s_wbuf + n; + } + } + if (qs->s_wbuf_free == qs->s_wbuf_send) + qs->s_wbuf_free = qs->s_wbuf_send = qs->s_wbuf; + return (0); +} + +/* void + * sq_flushw(qs) + * called when the socket becomes writable and we want to flush our + * buffers and the system's socket buffers. use as a closure with + * sq_writeh(). + */ +void +sq_flushw(struct qstream *qs) { + if (qs->s_wbuf_free == qs->s_wbuf_send) { + sq_writeh(qs, NULL); + sq_done(qs); + } +} + +/* static void + * sq_writable(ctx, uap, fd, evmask) + * glue between eventlib closures and qstream closures + */ +static void +sq_writable(evContext ctx, void *uap, int fd, int evmask) { + struct qstream *qs = uap; + + UNUSED(ctx); + + INSIST(evmask & EV_WRITE); + INSIST(fd == qs->s_rfd); + if (sq_dowrite(qs) < 0) { + sq_remove(qs); + return; + } + if (qs->s_wbuf_closure + && qs->s_wbuf_end - qs->s_wbuf_free >= HFIXEDSZ+2) /* XXX guess */ + (*qs->s_wbuf_closure)(qs); + if (sq_dowrite(qs) < 0) { + sq_remove(qs); + return; + } +} + +/* int + * sq_writeh(qs, closure) + * register a closure to be called when a stream becomes writable + * return: + * 0 = success + * -1 = failure (check errno) + */ +int +sq_writeh(struct qstream *qs, sq_closure c) { + if (c) { + if (!qs->s_wbuf_closure) { + if (evSelectFD(ev, qs->s_rfd, EV_WRITE, + sq_writable, qs, &qs->evID_w) < 0) { + return (-1); + } + qs->flags |= STREAM_WRITE_EV; + } + } else { + (void) evDeselectFD(ev, qs->evID_w); + qs->flags &= ~STREAM_WRITE_EV; + } + qs->s_wbuf_closure = c; + return (0); +} + +/* int + * sq_write(qs, buf, len) + * queue a message onto the stream, prepended by a two byte length field + * return: + * 0 = success + * -1 = failure (check errno; E2BIG means we can't handle this right now) + */ +int +sq_write(struct qstream *qs, const u_char *buf, int len) { + INSIST(qs->s_wbuf != NULL); + if (NS_INT16SZ + len > qs->s_wbuf_end - qs->s_wbuf_free) { + if (sq_dowrite(qs) < 0) + return (-1); + if (NS_INT16SZ + len > qs->s_wbuf_end - qs->s_wbuf_free) { + errno = E2BIG; + return (-1); + } + } + __putshort(len, qs->s_wbuf_free); + qs->s_wbuf_free += NS_INT16SZ; + memcpy(qs->s_wbuf_free, buf, len); + qs->s_wbuf_free += len; + return (0); +} + +/* + * Initiate query on stream; + * mark as referenced and stop selecting for input. + */ +static void +sq_query(struct qstream *sp) { + sp->s_refcnt++; +} + +/* + * Note that the current request on a stream has completed, + * and that we should continue looking for requests on the stream. + */ +void +sq_done(struct qstream *sp) { + struct iovec iov; + + if (sp->s_wbuf != NULL) { + INSIST(sp->s_wbuf_send == sp->s_wbuf_free); + memput(sp->s_wbuf, sp->s_wbuf_end - sp->s_wbuf); + sp->s_wbuf_send = sp->s_wbuf_free = NULL; + sp->s_wbuf_end = sp->s_wbuf = NULL; + } + if (sp->flags & STREAM_AXFR || sp->flags & STREAM_AXFRIXFR) + ns_freexfr(sp); + sp->s_refcnt = 0; + sp->s_time = tt.tv_sec; + if (sp->flags & STREAM_DONE_CLOSE) { + /* XXX */ + sq_remove(sp); + return; + } + iov = evConsIovec(sp->s_temp, INT16SZ); + if (evRead(ev, sp->s_rfd, &iov, 1, stream_getlen, sp, &sp->evID_r) == + -1) + ns_panic(ns_log_default, 1, "evRead(fd %d): %s", + sp->s_rfd, strerror(errno)); + sp->flags |= STREAM_READ_EV; +} + +/* void + * dq_remove_gen(gen) + * close/deallocate all the udp sockets (except 0.0.0.0) which are + * not from the current generation. + * side effects: + * global list `iflist' is modified. + */ +void +dq_remove_gen(time_t gen) { + interface *this, *next; + + for (this = HEAD(iflist); this != NULL; this = next) { + next = NEXT(this, link); + if (this->gen != gen && ina_hlong(this->addr) != INADDR_ANY) + dq_remove(this); + } +} + +/* void + * dq_remove_all() + * close/deallocate all interfaces. + * side effects: + * global list `iflist' is modified. + */ +void +dq_remove_all() { + interface *this, *next; + + for (this = HEAD(iflist); this != NULL; this = next) { + next = NEXT(this, link); + /* + * Clear the forwarding flag so we don't panic the server. + */ + this->flags &= ~INTERFACE_FORWARDING; + dq_remove(this); + } +} + +/* void + * dq_remove(interface *this) + * close/deallocate an interface's sockets. called on errors + * or if the interface disappears. + * side effects: + * global list `iflist' is modified. + */ +static void +dq_remove(interface *this) { + ns_notice(ns_log_default, "deleting interface [%s].%u", + inet_ntoa(this->addr), ntohs(this->port)); + + if ((this->flags & INTERFACE_FORWARDING) != 0) + ns_panic(ns_log_default, 0, + "forwarding interface [%s].%u gone", + inet_ntoa(this->addr), + ntohs(this->port)); + + /* Deallocate fields. */ + if ((this->flags & INTERFACE_FILE_VALID) != 0) + (void) evDeselectFD(ev, this->evID_d); + if (this->dfd >= 0) + (void) close(this->dfd); + if ((this->flags & INTERFACE_CONN_VALID) != 0) + (void) evCancelConn(ev, this->evID_s); + if (this->sfd >= 0) + (void) close(this->sfd); + + UNLINK(iflist, this, link); + memput(this, sizeof *this); +} + +/* struct in_addr + * net_mask(ina) + * makes a classful assumption in a classless world, and returns it. + */ +struct in_addr +net_mask(struct in_addr ina) { + u_long hl = ina_hlong(ina); + struct in_addr ret; + + if (IN_CLASSA(hl)) + hl = IN_CLASSA_NET; + else if (IN_CLASSB(hl)) + hl = IN_CLASSB_NET; + else if (IN_CLASSC(hl)) + hl = IN_CLASSC_NET; + else + hl = INADDR_BROADCAST; + ina_ulong(ret) = htonl(hl); + return (ret); +} + +/* aIsUs(addr) + * scan our list of interface addresses for "addr". + * returns: + * 0: address isn't one of our interfaces + * >0: address is one of our interfaces, or INADDR_ANY + */ +int +aIsUs(struct in_addr addr) { + + if (ina_hlong(addr) == INADDR_ANY || if_find(addr, 0) != NULL) + return (1); + return (0); +} + +/* interface * + * if_find(addr, port) + * scan our list of interface addresses for "addr" and port. + * port == 0 means match any port + * returns: + * pointer to interface with this address/port, or NULL if there isn't + * one. + */ +static interface * +if_find(struct in_addr addr, u_int16_t port) { + interface *ifp; + + for (ifp = HEAD(iflist); ifp != NULL; ifp = NEXT(ifp, link)) + if (ina_equal(addr, ifp->addr)) + if (port == 0 || ifp->port == port) + break; + return (ifp); +} + +/* + * These are here in case we ever want to get more clever, like perhaps + * using a bitmap to keep track of outstanding queries and a random + * allocation scheme to make it a little harder to predict them. Note + * that the resolver will need the same protection so the cleverness + * should be put there rather than here; this is just an interface layer. + * + * This is true but ... most clients only send out a few queries, they + * use varying port numbers, and the queries aren't sent to the outside + * world which we know is full of spoofers. Doing a good job of randomizing + * ids may also be to expensive for each client. Queries forwarded by the + * server always come from the same port (unless you let 8.x pick a port + * and restart it periodically - maybe it should open several and use + * them randomly). The server sends out lots more queries, and if it's + * cache is corrupted, it has the potential to affect more clients. + * NOTE: - randomizing the ID or source port doesn't help a bit if the + * queries can be sniffed. + * -- DL + */ + +/* + * Allow the user to pick one of two ID randomization algorithms. + * + * The first algorithm is an adaptation of the sequence shuffling + * algorithm discovered by Carter Bays and S. D. Durham [ACM Trans. Math. + * Software 2 (1976), 59-64], as documented as Algorithm B in Chapter + * 3.2.2 in Volume 2 of Knuth's "The Art of Computer Programming". We use + * a randomly selected linear congruential random number generator with a + * modulus of 2^16, whose increment is a randomly picked odd number, and + * whose multiplier is picked from a set which meets the following + * criteria: + * Is of the form 8*n+5, which ensures "high potency" according to + * principle iii in the summary chapter 3.6. This form also has a + * gcd(a-1,m) of 4 which is good according to principle iv. + * + * Is between 0.01 and 0.99 times the modulus as specified by + * principle iv. + * + * Passes the spectral test "with flying colors" (ut >= 1) in + * dimensions 2 through 6 as calculated by Algorithm S in Chapter + * 3.3.4 and the ratings calculated by formula 35 in section E. + * + * Of the multipliers that pass this test, pick the set that is + * best according to the theoretical bounds of the serial + * correlation test. This was calculated using a simplified + * version of Knuth's Theorem K in Chapter 3.3.3. + * + * These criteria may not be important for this use, but we might as well + * pick from the best generators since there are so many possible ones and + * we don't have that many random bits to do the picking. + * + * We use a modulus of 2^16 instead of something bigger so that we will + * tend to cycle through all the possible IDs before repeating any, + * however the shuffling will perturb this somewhat. Theoretically there + * is no minimimum interval between two uses of the same ID, but in + * practice it seems to be >64000. + * + * Our adaptatation of Algorithm B mixes the hash state which has + * captured various random events into the shuffler to perturb the + * sequence. + * + * One disadvantage of this algorithm is that if the generator parameters + * were to be guessed, it would be possible to mount a limited brute force + * attack on the ID space since the IDs are only shuffled within a limited + * range. + * + * The second algorithm uses the same random number generator to populate + * a pool of 65536 IDs. The hash state is used to pick an ID from a window + * of 4096 IDs in this pool, then the chosen ID is swapped with the ID + * at the beginning of the window and the window position is advanced. + * This means that the interval between uses of the ID will be no less + * than 65536-4096. The ID sequence in the pool will become more random + * over time. + * + * For both algorithms, two more linear congruential random number generators + * are selected. The ID from the first part of algorithm is used to seed + * the first of these generators, and its output is used to seed the second. + * The strategy is use these generators as 1 to 1 hashes to obfuscate the + * properties of the generator used in the first part of either algorithm. + * + * The first algorithm may be suitable for use in a client resolver since + * its memory requirements are fairly low and it's pretty random out of + * the box. It is somewhat succeptible to a limited brute force attack, + * so the second algorithm is probably preferable for a longer running + * program that issues a large number of queries and has time to randomize + * the pool. + */ + +#define NSID_SHUFFLE_TABLE_SIZE 100 /* Suggested by Knuth */ +/* + * Pick one of the next 4096 IDs in the pool. + * There is a tradeoff here between randomness and how often and ID is reused. + */ +#define NSID_LOOKAHEAD 4096 /* Must be a power of 2 */ +#define NSID_SHUFFLE_ONLY 1 /* algorithm 1 */ +#define NSID_USE_POOL 2 /* algorithm 2 */ + +/* + * Keep a running hash of various bits of data that we'll use to + * stir the ID pool or perturb the ID generator + */ +void +nsid_hash(u_char *data, size_t len) { + /* + * Hash function similar to the one we use for hashing names. + * We don't fold case or toss the upper bit here, though. + * This hash doesn't do much interesting when fed binary zeros, + * so there may be a better hash function. + * This function doesn't need to be very strong since we're + * only using it to stir the pool, but it should be reasonably + * fast. + */ + while (len-- > 0) { + nsid_hash_state = HASHROTATE(nsid_hash_state); + nsid_hash_state += *data++; + } +} + +/* + * Table of good linear congruential multipliers for modulus 2^16 + * in order of increasing serial correlation bounds (so trim from + * the end). + */ +static const u_int16_t nsid_multiplier_table[] = { + 17565, 25013, 11733, 19877, 23989, 23997, 24997, 25421, + 26781, 27413, 35901, 35917, 35973, 36229, 38317, 38437, + 39941, 40493, 41853, 46317, 50581, 51429, 53453, 53805, + 11317, 11789, 12045, 12413, 14277, 14821, 14917, 18989, + 19821, 23005, 23533, 23573, 23693, 27549, 27709, 28461, + 29365, 35605, 37693, 37757, 38309, 41285, 45261, 47061, + 47269, 48133, 48597, 50277, 50717, 50757, 50805, 51341, + 51413, 51581, 51597, 53445, 11493, 14229, 20365, 20653, + 23485, 25541, 27429, 29421, 30173, 35445, 35653, 36789, + 36797, 37109, 37157, 37669, 38661, 39773, 40397, 41837, + 41877, 45293, 47277, 47845, 49853, 51085, 51349, 54085, + 56933, 8877, 8973, 9885, 11365, 11813, 13581, 13589, + 13613, 14109, 14317, 15765, 15789, 16925, 17069, 17205, + 17621, 17941, 19077, 19381, 20245, 22845, 23733, 24869, + 25453, 27213, 28381, 28965, 29245, 29997, 30733, 30901, + 34877, 35485, 35613, 36133, 36661, 36917, 38597, 40285, + 40693, 41413, 41541, 41637, 42053, 42349, 45245, 45469, + 46493, 48205, 48613, 50861, 51861, 52877, 53933, 54397, + 55669, 56453, 56965, 58021, 7757, 7781, 8333, 9661, + 12229, 14373, 14453, 17549, 18141, 19085, 20773, 23701, + 24205, 24333, 25261, 25317, 27181, 30117, 30477, 34757, + 34885, 35565, 35885, 36541, 37957, 39733, 39813, 41157, + 41893, 42317, 46621, 48117, 48181, 49525, 55261, 55389, + 56845, 7045, 7749, 7965, 8469, 9133, 9549, 9789, + 10173, 11181, 11285, 12253, 13453, 13533, 13757, 14477, + 15053, 16901, 17213, 17269, 17525, 17629, 18605, 19013, + 19829, 19933, 20069, 20093, 23261, 23333, 24949, 25309, + 27613, 28453, 28709, 29301, 29541, 34165, 34413, 37301, + 37773, 38045, 38405, 41077, 41781, 41925, 42717, 44437, + 44525, 44613, 45933, 45941, 47077, 50077, 50893, 52117, + 5293, 55069, 55989, 58125, 59205, 6869, 14685, 15453, + 16821, 17045, 17613, 18437, 21029, 22773, 22909, 25445, + 25757, 26541, 30709, 30909, 31093, 31149, 37069, 37725, + 37925, 38949, 39637, 39701, 40765, 40861, 42965, 44813, + 45077, 45733, 47045, 50093, 52861, 52957, 54181, 56325, + 56365, 56381, 56877, 57013, 5741, 58101, 58669, 8613, + 10045, 10261, 10653, 10733, 11461, 12261, 14069, 15877, + 17757, 21165, 23885, 24701, 26429, 26645, 27925, 28765, + 29197, 30189, 31293, 39781, 39909, 40365, 41229, 41453, + 41653, 42165, 42365, 47421, 48029, 48085, 52773, 5573, + 57037, 57637, 58341, 58357, 58901, 6357, 7789, 9093, + 10125, 10709, 10765, 11957, 12469, 13437, 13509, 14773, + 15437, 15773, 17813, 18829, 19565, 20237, 23461, 23685, + 23725, 23941, 24877, 25461, 26405, 29509, 30285, 35181, + 37229, 37893, 38565, 40293, 44189, 44581, 45701, 47381, + 47589, 48557, 4941, 51069, 5165, 52797, 53149, 5341, + 56301, 56765, 58581, 59493, 59677, 6085, 6349, 8293, + 8501, 8517, 11597, 11709, 12589, 12693, 13517, 14909, + 17397, 18085, 21101, 21269, 22717, 25237, 25661, 29189, + 30101, 31397, 33933, 34213, 34661, 35533, 36493, 37309, + 40037, 4189, 42909, 44309, 44357, 44389, 4541, 45461, + 46445, 48237, 54149, 55301, 55853, 56621, 56717, 56901, + 5813, 58437, 12493, 15365, 15989, 17829, 18229, 19341, + 21013, 21357, 22925, 24885, 26053, 27581, 28221, 28485, + 30605, 30613, 30789, 35437, 36285, 37189, 3941, 41797, + 4269, 42901, 43293, 44645, 45221, 46893, 4893, 50301, + 50325, 5189, 52109, 53517, 54053, 54485, 5525, 55949, + 56973, 59069, 59421, 60733, 61253, 6421, 6701, 6709, + 7101, 8669, 15797, 19221, 19837, 20133, 20957, 21293, + 21461, 22461, 29085, 29861, 30869, 34973, 36469, 37565, + 38125, 38829, 39469, 40061, 40117, 44093, 47429, 48341, + 50597, 51757, 5541, 57629, 58405, 59621, 59693, 59701, + 61837, 7061, 10421, 11949, 15405, 20861, 25397, 25509, + 25893, 26037, 28629, 28869, 29605, 30213, 34205, 35637, + 36365, 37285, 3773, 39117, 4021, 41061, 42653, 44509, + 4461, 44829, 4725, 5125, 52269, 56469, 59085, 5917, + 60973, 8349, 17725, 18637, 19773, 20293, 21453, 22533, + 24285, 26333, 26997, 31501, 34541, 34805, 37509, 38477, + 41333, 44125, 46285, 46997, 47637, 48173, 4925, 50253, + 50381, 50917, 51205, 51325, 52165, 52229, 5253, 5269, + 53509, 56253, 56341, 5821, 58373, 60301, 61653, 61973, + 62373, 8397, 11981, 14341, 14509, 15077, 22261, 22429, + 24261, 28165, 28685, 30661, 34021, 34445, 39149, 3917, + 43013, 43317, 44053, 44101, 4533, 49541, 49981, 5277, + 54477, 56357, 57261, 57765, 58573, 59061, 60197, 61197, + 62189, 7725, 8477, 9565, 10229, 11437, 14613, 14709, + 16813, 20029, 20677, 31445, 3165, 31957, 3229, 33541, + 36645, 3805, 38973, 3965, 4029, 44293, 44557, 46245, + 48917, 4909, 51749, 53709, 55733, 56445, 5925, 6093, + 61053, 62637, 8661, 9109, 10821, 11389, 13813, 14325, + 15501, 16149, 18845, 22669, 26437, 29869, 31837, 33709, + 33973, 34173, 3677, 3877, 3981, 39885, 42117, 4421, + 44221, 44245, 44693, 46157, 47309, 5005, 51461, 52037, + 55333, 55693, 56277, 58949, 6205, 62141, 62469, 6293, + 10101, 12509, 14029, 17997, 20469, 21149, 25221, 27109, + 2773, 2877, 29405, 31493, 31645, 4077, 42005, 42077, + 42469, 42501, 44013, 48653, 49349, 4997, 50101, 55405, + 56957, 58037, 59429, 60749, 61797, 62381, 62837, 6605, + 10541, 23981, 24533, 2701, 27333, 27341, 31197, 33805, + 3621, 37381, 3749, 3829, 38533, 42613, 44381, 45901, + 48517, 51269, 57725, 59461, 60045, 62029, 13805, 14013, + 15461, 16069, 16157, 18573, 2309, 23501, 28645, 3077, + 31541, 36357, 36877, 3789, 39429, 39805, 47685, 47949, + 49413, 5485, 56757, 57549, 57805, 58317, 59549, 62213, + 62613, 62853, 62933, 8909, 12941, 16677, 20333, 21541, + 24429, 26077, 26421, 2885, 31269, 33381, 3661, 40925, + 42925, 45173, 4525, 4709, 53133, 55941, 57413, 57797, + 62125, 62237, 62733, 6773, 12317, 13197, 16533, 16933, + 18245, 2213, 2477, 29757, 33293, 35517, 40133, 40749, + 4661, 49941, 62757, 7853, 8149, 8573, 11029, 13421, + 21549, 22709, 22725, 24629, 2469, 26125, 2669, 34253, + 36709, 41013, 45597, 46637, 52285, 52333, 54685, 59013, + 60997, 61189, 61981, 62605, 62821, 7077, 7525, 8781, + 10861, 15277, 2205, 22077, 28517, 28949, 32109, 33493, + 3685, 39197, 39869, 42621, 44997, 48565, 5221, 57381, + 61749, 62317, 63245, 63381, 23149, 2549, 28661, 31653, + 33885, 36341, 37053, 39517, 42805, 45853, 48997, 59349, + 60053, 62509, 63069, 6525, 1893, 20181, 2365, 24893, + 27397, 31357, 32277, 33357, 34437, 36677, 37661, 43469, + 43917, 50997, 53869, 5653, 13221, 16741, 17893, 2157, + 28653, 31789, 35301, 35821, 61613, 62245, 12405, 14517, + 17453, 18421, 3149, 3205, 40341, 4109, 43941, 46869, + 48837, 50621, 57405, 60509, 62877, 8157, 12933, 12957, + 16501, 19533, 3461, 36829, 52357, 58189, 58293, 63053, + 17109, 1933, 32157, 37701, 59005, 61621, 13029, 15085, + 16493, 32317, 35093, 5061, 51557, 62221, 20765, 24613, + 2629, 30861, 33197, 33749, 35365, 37933, 40317, 48045, + 56229, 61157, 63797, 7917, 17965, 1917, 1973, 20301, + 2253, 33157, 58629, 59861, 61085, 63909, 8141, 9221, + 14757, 1581, 21637, 26557, 33869, 34285, 35733, 40933, + 42517, 43501, 53653, 61885, 63805, 7141, 21653, 54973, + 31189, 60061, 60341, 63357, 16045, 2053, 26069, 33997, + 43901, 54565, 63837, 8949, 17909, 18693, 32349, 33125, + 37293, 48821, 49053, 51309, 64037, 7117, 1445, 20405, + 23085, 26269, 26293, 27349, 32381, 33141, 34525, 36461, + 37581, 43525, 4357, 43877, 5069, 55197, 63965, 9845, + 12093, 2197, 2229, 32165, 33469, 40981, 42397, 8749, + 10853, 1453, 18069, 21693, 30573, 36261, 37421, 42533 +}; +#define NSID_MULT_TABLE_SIZE \ + ((sizeof nsid_multiplier_table)/(sizeof nsid_multiplier_table[0])) + +void +nsid_init(void) { + struct timeval now; + pid_t mypid; + u_int16_t a1ndx, a2ndx, a3ndx, c1ndx, c2ndx, c3ndx; + int i; + + if (nsid_algorithm != 0) + return; + + gettimeofday(&now, NULL); + mypid = getpid(); + + /* Initialize the state */ + nsid_hash_state = 0; + nsid_hash((u_char *)&now, sizeof now); + nsid_hash((u_char *)&mypid, sizeof mypid); + + /* + * Select our random number generators and initial seed. + * We could really use more random bits at this point, + * but we'll try to make a silk purse out of a sows ear ... + */ + /* generator 1 */ + a1ndx = ((u_long) NSID_MULT_TABLE_SIZE * + (nsid_hash_state & 0xFFFF)) >> 16; + nsid_a1 = nsid_multiplier_table[a1ndx]; + c1ndx = (nsid_hash_state >> 9) & 0x7FFF; + nsid_c1 = 2*c1ndx + 1; + /* generator 2, distinct from 1 */ + a2ndx = ((u_long) (NSID_MULT_TABLE_SIZE - 1) * + ((nsid_hash_state >> 10) & 0xFFFF)) >> 16; + if (a2ndx >= a1ndx) + a2ndx++; + nsid_a2 = nsid_multiplier_table[a2ndx]; + c2ndx = nsid_hash_state % 32767; + if (c2ndx >= c1ndx) + c2ndx++; + nsid_c2 = 2*c2ndx + 1; + /* generator 3, distinct from 1 and 2 */ + a3ndx = ((u_long) (NSID_MULT_TABLE_SIZE - 2) * + ((nsid_hash_state >> 20) & 0xFFFF)) >> 16; + if (a3ndx >= a1ndx || a3ndx >= a2ndx) + a3ndx++; + if (a3ndx >= a1ndx && a3ndx >= a2ndx) + a3ndx++; + nsid_a3 = nsid_multiplier_table[a3ndx]; + c3ndx = nsid_hash_state % 32766; + if (c3ndx >= c1ndx || c3ndx >= c2ndx) + c3ndx++; + if (c3ndx >= c1ndx && c3ndx >= c2ndx) + c3ndx++; + nsid_c3 = 2*c3ndx + 1; + + nsid_state = ((nsid_hash_state >> 16) ^ (nsid_hash_state)) & 0xFFFF; + + /* Do the algorithm specific initialization */ + INSIST(server_options != NULL); + if (NS_OPTION_P(OPTION_USE_ID_POOL) == 0) { + /* Algorithm 1 */ + nsid_algorithm = NSID_SHUFFLE_ONLY; + nsid_vtable = memget(NSID_SHUFFLE_TABLE_SIZE * + (sizeof(u_int16_t)) ); + if (!nsid_vtable) + ns_panic(ns_log_default, 1, "memget(nsid_vtable)"); + for (i = 0; i < NSID_SHUFFLE_TABLE_SIZE; i++) { + nsid_vtable[i] = nsid_state; + nsid_state = (((u_long) nsid_a1 * nsid_state) + nsid_c1) + & 0xFFFF; + } + nsid_state2 = nsid_state; + } else { + /* Algorithm 2 */ + nsid_algorithm = NSID_USE_POOL; + nsid_pool = memget(0x10000 * (sizeof(u_int16_t))); + if (!nsid_pool) + ns_panic(ns_log_default, 1, "memget(nsid_pool)"); + for (i = 0; ; i++) { + nsid_pool[i] = nsid_state; + nsid_state = (((u_long) nsid_a1 * nsid_state) + nsid_c1) & 0xFFFF; + if (i == 0xFFFF) + break; + } + } +} + +#define NSID_RANGE_MASK (NSID_LOOKAHEAD - 1) + +#define NSID_POOL_MASK 0xFFFF /* used to wrap the pool index */ + +u_int16_t +nsid_next() { + u_int16_t id, compressed_hash; + + compressed_hash = ((nsid_hash_state >> 16) ^ (nsid_hash_state)) & + 0xFFFF; + if (nsid_algorithm == NSID_SHUFFLE_ONLY) { + u_int16_t j; + + /* + * This is the original Algorithm B + * j = ((u_long) NSID_SHUFFLE_TABLE_SIZE * nsid_state2) + * >> 16; + * + * We'll perturb it with some random stuff ... + */ + j = ((u_long) NSID_SHUFFLE_TABLE_SIZE * + (nsid_state2 ^ compressed_hash)) >> 16; + nsid_state2 = id = nsid_vtable[j]; + nsid_state = (((u_long) nsid_a1 * nsid_state) + nsid_c1) & + 0xFFFF; + nsid_vtable[j] = nsid_state; + } else if (nsid_algorithm == NSID_USE_POOL) { + u_int16_t pick; + + pick = compressed_hash & NSID_RANGE_MASK; + id = nsid_pool[(nsid_state + pick) & NSID_POOL_MASK]; + if (pick != 0) { + /* Swap two IDs to stir the pool */ + nsid_pool[(nsid_state + pick) & NSID_POOL_MASK] = + nsid_pool[nsid_state]; + nsid_pool[nsid_state] = id; + } + + /* increment the base pointer into the pool */ + if (nsid_state == 65535) + nsid_state = 0; + else + nsid_state++; + } else { + id = 0; /* silence compiler */ + ns_panic(ns_log_default, 1, "Unknown ID algorithm"); + } + + /* Now lets obfuscate ... */ + id = (((u_long) nsid_a2 * id) + nsid_c2) & 0xFFFF; + id = (((u_long) nsid_a3 * id) + nsid_c3) & 0xFFFF; + + return (id); +} + +/* Note: this function CAN'T deallocate the saved_argv[]. */ +static void +deallocate_everything(void) { + FILE *f; + + f = write_open(server_options->memstats_filename); + + ns_freestats(); + qflush(); + sq_flush(NULL); + free_addinfo(); + ns_shutdown(); + dq_remove_all(); + db_lame_destroy(); + if (local_addresses != NULL) + free_ip_match_list(local_addresses); + if (local_networks != NULL) + free_ip_match_list(local_networks); + destroyservicelist(); + destroyprotolist(); + shutdown_logging(); + evDestroy(ev); + if (conffile != NULL) + freestr(conffile); + conffile = NULL; + if (debugfile != NULL) + freestr(debugfile); + debugfile = NULL; + if (user_name != NULL) + freestr(user_name); + user_name = NULL; + if (group_name != NULL) + freestr(group_name); + group_name = NULL; + if (chroot_dir != NULL) + freestr(chroot_dir); + chroot_dir = NULL; + if (working_dir != NULL) + freestr(working_dir); + working_dir = NULL; + if (nsid_pool != NULL) + memput(nsid_pool, 0x10000 * (sizeof(u_int16_t))); + nsid_pool = NULL; + if (nsid_vtable != NULL) + memput(nsid_vtable, NSID_SHUFFLE_TABLE_SIZE * + (sizeof(u_int16_t))); + nsid_vtable = NULL; + irs_destroy(); + if (f != NULL) { + memstats(f); + (void)fclose(f); + } + if (memactive()) + abort(); +} + +static void +ns_restart(void) { + needs_restart = 1; + needs_exit = 1; +} + +static void +use_desired_debug(void) { +#ifdef DEBUG + sigset_t set; + + /* Protect against race conditions by blocking debugging signals. */ + + if (sigemptyset(&set) < 0) { + ns_error(ns_log_os, + "sigemptyset failed in use_desired_debug: %s", + strerror(errno)); + return; + } + if (sigaddset(&set, SIGUSR1) < 0) { + ns_error(ns_log_os, + "sigaddset SIGUSR1 failed in use_desired_debug: %s", + strerror(errno)); + return; + } + if (sigaddset(&set, SIGUSR2) < 0) { + ns_error(ns_log_os, + "sigaddset SIGUSR2 failed in use_desired_debug: %s", + strerror(errno)); + return; + } + if (sigprocmask(SIG_BLOCK, &set, NULL) < 0) { + ns_error(ns_log_os, + "sigprocmask to block USR1 and USR2 failed: %s", + strerror(errno)); + return; + } + setdebug(desired_debug); + if (sigprocmask(SIG_UNBLOCK, &set, NULL) < 0) + ns_error(ns_log_os, + "sigprocmask to unblock USR1 and USR2 failed: %s", + strerror(errno)); +#endif +} + +void +toggle_qrylog(void) { + qrylog = !qrylog; + ns_notice(ns_log_default, "query log %s\n", qrylog ?"on" :"off"); +} + +static void +wild(void) { + ns_panic(ns_log_default, 1, "wild need"); +} + +/* + * This is a functional interface to the global needs and options. + */ + +static void +init_needs(void) { + int need; + + for (need = 0; need < main_need_num; need++) + handlers[need] = wild; + handlers[main_need_zreload] = ns_zreload; + handlers[main_need_reload] = ns_reload; + handlers[main_need_reconfig] = ns_reconfig; + handlers[main_need_endxfer] = endxfer; + handlers[main_need_zoneload] = loadxfer; + handlers[main_need_dump] = doadump; + handlers[main_need_statsdump] = ns_stats; + handlers[main_need_statsdumpandclear] = ns_stats_dumpandclear; + handlers[main_need_exit] = exit_handler; + handlers[main_need_qrylog] = toggle_qrylog; + handlers[main_need_debug] = use_desired_debug; + handlers[main_need_restart] = ns_restart; + handlers[main_need_reap] = reapchild; + handlers[main_need_noexpired] = ns_noexpired; + handlers[main_need_tryxfer] = tryxfer; +} + +static void +handle_needs(void) { + int need, queued = 0; + + ns_debug(ns_log_default, 15, "handle_needs()"); + block_signals(); + for (need = 0; need < main_need_num; need++) + if ((needs & (1 << need)) != 0) { + INSIST_ERR(evWaitFor(ev, (void *)handle_needs, + need_waitfunc, + (void *)handlers[need], + NULL) != -1); + queued++; + } + needs = 0; + unblock_signals(); + ns_debug(ns_log_default, 15, "handle_needs(): queued %d", queued); + if (queued != 0) { + INSIST_ERR(evDo(ev, (void *)handle_needs) != -1); + return; + } + ns_panic(ns_log_default, 1, "ns_handle_needs: queued == 0"); +} + +static void +need_waitfunc(evContext ctx, void *uap, const void *tag) { + handler hand = (handler) uap; + time_t begin; + long syncdelay; + + UNUSED(tag); + + begin = time(NULL); + (*hand)(); + syncdelay = time(NULL) - begin; + + if (syncdelay > MAX_SYNCDELAY) + ns_notice(ns_log_default, "drained %d queries (delay %ld sec)", + drain_all_rcvbuf(ctx), syncdelay); +} + +void +ns_need(enum need need) { + block_signals(); + ns_need_unsafe(need); + unblock_signals(); +} + +/* Note: this function should only be called with signals blocked. */ +void +ns_need_unsafe(enum need need) { + needs |= (1 << need); +} + +static void +exit_handler(void) { + needs_exit = 1; +} + +void +ns_setoption(int option) { + ns_warning(ns_log_default, "used obsolete ns_setoption(%d)", option); +} + +void +writestream(struct qstream *sp, const u_char *msg, int msglen) { + if (sq_openw(sp, msglen + INT16SZ) == -1) { + sq_remove(sp); + return; + } + if (sq_write(sp, msg, msglen) == -1) { + sq_remove(sp); + return; + } + sq_writeh(sp, sq_flushw); +} + +static int +only_digits(const char *s) { + if (*s == '\0') + return (0); + while (*s != '\0') { + if (!isdigit(*s)) + return (0); + s++; + } + return (1); +} +#if defined(__GNUC__) && defined(__BOUNDS_CHECKING_ON) + /* Use bounds checking malloc, etc. */ +void * +memget(size_t len) { + return (malloc(len)); +} + +void +memput(void *addr, size_t len) { + free(addr); +} + +int +meminit(size_t init_max_size, size_t target_size) { + return (0); +} + +void * +memget_debug(size_t size, const char *file, int line) { + void *ptr; + ptr = __memget(size); + fprintf(stderr, "%s:%d: memget(%lu) -> %p\n", file, line, + (u_long)size, ptr); + return (ptr); +} + +void +memput_debug(void *ptr, size_t size, const char *file, int line) { + fprintf(stderr, "%s:%d: memput(%p, %lu)\n", file, line, ptr, + (u_long)size); + __memput(ptr, size); +} + +void +memstats(FILE *out) { + fputs("No memstats\n", out); +} +#endif + +#ifndef HAVE_CUSTOM +/* Standard implementation has nothing here */ +static void +custom_init(void) { + /* Noop. */ +} + +static void +custom_shutdown(void) { + /* Noop. */ +} +#endif Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_main.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_maint.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_maint.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_maint.c (revision 109985) @@ -0,0 +1,2073 @@ +#if !defined(lint) && !defined(SABER) +static const char sccsid[] = "@(#)ns_maint.c 4.39 (Berkeley) 3/2/91"; +static const char rcsid[] = "$Id: ns_maint.c,v 8.136 2002/06/26 03:27:20 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986, 1988 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1999 by Check Point Software Technologies, Inc. + * + * 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 Check Point Software Technologies Incorporated 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 CHECK POINT SOFTWARE TECHNOLOGIES + * INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL CHECK POINT SOFTWARE TECHNOLOGIES INCORPRATED + * 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 SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "port_after.h" + +#include "named.h" + +static int nxfers(struct zoneinfo *), + bottom_of_zone(struct databuf *, int); + +static void startxfer(struct zoneinfo *), + abortxfer(struct zoneinfo *), + purge_z_2(struct hashbuf *, int); +static int purge_nonglue_2(const char *, struct hashbuf *, + int, int, int); + +#ifndef HAVE_SPAWNXFER +static pid_t spawnxfer(char **, struct zoneinfo *); +#endif + + /* State of all running zone transfers */ +static struct { + pid_t xfer_pid; + int xfer_state; /* see below */ + WAIT_T xfer_status; + struct in_addr xfer_addr; +} xferstatus[MAX_XFERS_RUNNING]; + +#define XFER_IDLE 0 +#define XFER_RUNNING 1 +#define XFER_DONE 2 + + +/* + * Perform routine zone maintenance. + */ +void +zone_maint(struct zoneinfo *zp) { + gettime(&tt); + + ns_debug(ns_log_maint, 1, "zone_maint('%s'); now %lu", + zp->z_origin[0] == '\0' ? "." : zp->z_origin, + (u_long)tt.tv_sec); + +#ifdef DEBUG + if (debug >= 2) + printzoneinfo((zp - zones), ns_log_maint, 2); +#endif + + switch (zp->z_type) { + + case Z_SECONDARY: + /*FALLTHROUGH*/ +#ifdef STUBS + case Z_STUB: +#endif + if (zp->z_serial != 0 && + ((zp->z_lastupdate+zp->z_expire) < (u_int32_t)tt.tv_sec)) { + if ((zp->z_flags & Z_NOTIFY) != 0) + ns_stopnotify(zp->z_origin, zp->z_class); + /* calls purge_zone */ + do_reload(zp->z_origin, zp->z_type, zp->z_class, 0); + /* reset zone state */ + if (!haveComplained((u_long)zp, (u_long)stale)) { + ns_notice(ns_log_default, + "%s zone \"%s\" expired", + zoneTypeString(zp->z_type), + zp->z_origin); + } + zp->z_flags &= ~Z_AUTH; + zp->z_flags |= Z_EXPIRED; + zp->z_refresh = INIT_REFRESH; + zp->z_retry = INIT_REFRESH; + zp->z_serial = 0; + } + if ((zp->z_flags & (Z_NEED_RELOAD|Z_NEED_XFER|Z_QSERIAL)) != 0) + { + ns_retrytime(zp, tt.tv_sec); + break; + } + if (zp->z_flags & Z_XFER_RUNNING) { + abortxfer(zp); + /* + * Check again in 30 seconds in case the first + * abort doesn't work. + */ + if (zp->z_time != 0 && zp->z_time <= tt.tv_sec) + zp->z_time = tt.tv_sec + 30; + break; + } + /* + * If we don't have the zone loaded or dialup is off + * or we attempted a qserial_query before and the queue was + * full attempt to verify / load the zone. + */ + if ((zp->z_serial == 0) || (zp->z_flags & Z_NEED_QSERIAL) || + (zp->z_dialup == zdialup_no) || + (zp->z_dialup == zdialup_use_default && + NS_OPTION_P(OPTION_NODIALUP))) + qserial_query(zp); + else { + ns_info(ns_log_default, "Suppressed qserial_query(%s)", + *(zp->z_origin) ? zp->z_origin : "."); + ns_refreshtime(zp, tt.tv_sec); + } + break; + +#ifdef BIND_UPDATE + case Z_PRIMARY: + if ((zp->z_flags & Z_DYNAMIC) == 0) + break; + if (tt.tv_sec >= zp->z_soaincrtime && + zp->z_soaincrintvl > 0 && + zp->z_flags & Z_NEED_SOAUPDATE) { + if (incr_serial(zp) < 0) { + /* Try again later. */ + ns_error(ns_log_maint, + "error updating serial number for %s from %d", + zp->z_origin, + zp->z_serial); + zp->z_soaincrtime = 0; + (void)schedule_soa_update(zp, 0); + } + + } + if (tt.tv_sec >= zp->z_dumptime && + zp->z_dumpintvl > 0 && + zp->z_flags & Z_NEED_DUMP) { + if (zonedump(zp, ISNOTIXFR) < 0) { + /* Try again later. */ + ns_error(ns_log_maint, + "zone dump for '%s' failed, rescheduling", + zp->z_origin); + zp->z_dumptime = 0; + (void)schedule_dump(zp); + } + } + if (zp->z_maintain_ixfr_base) + ixfr_log_maint(zp); + break; +#endif /* BIND_UPDATE */ + + default: + break; + } + + if (zp->z_time != 0 && zp->z_time < tt.tv_sec) + zp->z_time = tt.tv_sec; + + sched_zone_maint(zp); +} + +static void +do_zone_maint(evContext ctx, void *uap, struct timespec due, + struct timespec inter) { + ztimer_info zti = uap; + struct zoneinfo *zp; + + UNUSED(ctx); + UNUSED(due); + UNUSED(inter); + + INSIST(zti != NULL); + + ns_debug(ns_log_maint, 1, "do_zone_maint for zone %s (class %s)", + zti->name, p_class(zti->class)); + zp = find_zone(zti->name, zti->class); + if (zp == NULL) { + ns_error(ns_log_maint, + "do_zone_maint: %s zone '%s' (class %s) is not authoritative", + zoneTypeString(zti->type), zti->name, + p_class(zti->class)); + return; + } + if (zp->z_type != zti->type) { + ns_error(ns_log_maint, + "do_zone_maint: %s zone '%s' (class %s) has changed its type", + zoneTypeString(zti->type), zti->name, + p_class(zti->class)); + return; + } + + free_zone_timerinfo(zp); + + zp->z_flags &= ~Z_TIMER_SET; + zone_maint(zp); +} + +/* + * Figure out the next maintenance time for the zone and set a timer. + */ +void +sched_zone_maint(struct zoneinfo *zp) { + time_t next_maint = (time_t)0; + ztimer_info zti; + + if (zp->z_time != 0) + next_maint = zp->z_time; +#ifdef BIND_UPDATE + if (zp->z_type == z_master && (zp->z_flags & Z_DYNAMIC) != 0) { + if (zp->z_soaincrintvl > 0 && + (next_maint == 0 || next_maint > zp->z_soaincrtime)) + next_maint = zp->z_soaincrtime; + if (zp->z_dumpintvl > 0 && + (next_maint == 0 || next_maint > zp->z_dumptime)) + next_maint = zp->z_dumptime; + } +#endif + + if (next_maint != 0) { + if (next_maint < tt.tv_sec) + next_maint = tt.tv_sec; + + if (zp->z_flags & Z_TIMER_SET) { + if (next_maint == zp->z_nextmaint) { + ns_debug(ns_log_maint, 1, + "no schedule change for zone '%s'", + zp->z_origin[0] == '\0' ? "." : + zp->z_origin); + return; + } + + if (evResetTimer(ev, zp->z_timer, + do_zone_maint, zp->z_timerinfo, + evConsTime(next_maint, 0), + evConsTime(0, 0)) < 0) { + ns_error(ns_log_maint, + "evChangeTimer failed in sched_zone_maint for zone '%s': %s", + zp->z_origin[0] == '\0' ? "." : + zp->z_origin, + strerror(errno)); + return; + } + } else { + zti = (ztimer_info)memget(sizeof *zti); + if (zti == NULL) + ns_panic(ns_log_maint, 1, + "memget failed in sched_zone_maint"); + zti->name = savestr(zp->z_origin, 1); + zti->class = zp->z_class; + zti->type = zp->z_type; + if (evSetTimer(ev, do_zone_maint, zti, + evConsTime(next_maint, 0), + evConsTime(0, 0), &zp->z_timer) < 0) { + ns_error(ns_log_maint, + "evSetTimer failed in sched_zone_maint for zone '%s': %s", + zp->z_origin[0] == '\0' ? "." : + zp->z_origin, + strerror(errno)); + return; + } + zp->z_flags |= Z_TIMER_SET; + zp->z_timerinfo = zti; + } + ns_debug(ns_log_maint, 1, + "next maintenance for zone '%s' in %lu sec", + zp->z_origin[0] == '\0' ? "." : zp->z_origin, + (u_long)(next_maint - tt.tv_sec)); + } else { + if (zp->z_flags & Z_TIMER_SET) { + free_zone_timerinfo(zp); + if (evClearTimer(ev, zp->z_timer) < 0) + ns_error(ns_log_maint, + "evClearTimer failed in sched_zone_maint for zone '%s': %s", + zp->z_origin[0] == '\0' ? "." : + zp->z_origin, + strerror(errno)); + zp->z_flags &= ~Z_TIMER_SET; + } + ns_debug(ns_log_maint, 1, + "no scheduled maintenance for zone '%s'", + zp->z_origin[0] == '\0' ? "." : zp->z_origin); + } + zp->z_nextmaint = next_maint; +} + +void +ns_cleancache(evContext ctx, void *uap, + struct timespec due, + struct timespec inter) +{ + int deleted; + + UNUSED(ctx); + UNUSED(due); + UNUSED(inter); + + gettime(&tt); + INSIST(uap == NULL); + deleted = clean_cache(hashtab, 0); + ns_info(ns_log_maint, "Cleaned cache of %d RRset%s", + deleted, (deleted==1) ? "" : "s"); +} + +void +ns_heartbeat(evContext ctx, void *uap, struct timespec due, + struct timespec inter) +{ + struct zoneinfo *zp; + + UNUSED(ctx); + UNUSED(due); + UNUSED(inter); + + gettime(&tt); + INSIST(uap == NULL); + + for (zp = zones; zp < &zones[nzones]; zp++) { + enum zonetype zt = zp->z_type; + + if ((zt == z_nil) || + (zp->z_dialup == zdialup_no) || + (zp->z_dialup == zdialup_use_default && + NS_OPTION_P(OPTION_NODIALUP))) + continue; + /* + * Perform the refresh query that was suppressed. + */ + if ((zt == z_slave || zt == z_stub) && + (zp->z_flags & + (Z_NEED_RELOAD|Z_NEED_XFER|Z_QSERIAL|Z_XFER_RUNNING) + ) == 0) { + ns_info(ns_log_default, + "Heartbeat: qserial \"%s\"", + *(zp->z_origin) ? zp->z_origin : "."); + qserial_query(zp); + } +#ifdef BIND_NOTIFY + /* + * Trigger a refresh query while the link is up by + * sending a notify. + */ + if (((zp->z_notify == notify_yes) || + (zp->z_notify == notify_explicit) || + ((zp->z_notify == notify_use_default) && + server_options->notify != notify_no)) && + (zt == z_master || zt == z_slave) && !loading && + ((zp->z_flags & Z_AUTH) != 0)) + ns_notify(zp->z_origin, zp->z_class, ns_t_soa); +#endif + } +} + + +/* + * Mark a zone "up to date" after named-xfer tells us this or we + * discover it through the qserial_*() logic. + * The caller is responsible for calling sched_zone_maint(zp). + */ +static void +markUpToDate(struct zoneinfo *zp) { + struct stat f_time; + + zp->z_flags &= ~Z_SYSLOGGED; + zp->z_lastupdate = tt.tv_sec; + ns_refreshtime(zp, tt.tv_sec); + /* + * Restore Z_AUTH in case expired, + * but only if there were no errors + * in the zone file. + */ + if ((zp->z_flags & Z_DB_BAD) == 0) { + zp->z_flags |= Z_AUTH; + zp->z_flags &= ~Z_EXPIRED; + } + if (zp->z_source) { + struct timeval t[2]; + + t[0] = tt; + t[1] = tt; + (void) utimes(zp->z_source, t); + } + /* we use "stat" to set zp->z_ftime instead of just + setting it to tt.tv_sec in order to avoid any + possible rounding problems in utimes(). */ + if (stat(zp->z_source, &f_time) != -1) + zp->z_ftime = f_time.st_mtime; + /* XXX log if stat fails? */ +} + +void +qserial_retrytime(struct zoneinfo *zp, time_t timebase) { + zp->z_time = timebase + 5 + (rand() % 25); +} + +/* + * Query for the serial number of a zone, so that we can check to see if + * we need to transfer it. If there are too many outstanding serial + * number queries, we'll try again later. + * The caller is responsible for calling sched_zone_maint(zp). + */ +void +qserial_query(struct zoneinfo *zp) { + struct qinfo *qp; + + ns_debug(ns_log_default, 1, "qserial_query(%s)", zp->z_origin); + + if (qserials_running >= server_options->serial_queries) { + qserial_retrytime(zp, tt.tv_sec); + zp->z_flags |= Z_NEED_QSERIAL; + return; + } + + qp = sysquery(zp->z_origin, zp->z_class, T_SOA, + zp->z_addr, zp->z_keys, zp->z_addrcnt, + ntohs(zp->z_port) ? zp->z_port : ns_port, + QUERY, 0); + if (qp == NULL) { + ns_debug(ns_log_default, 1, + "qserial_query(%s): sysquery FAILED", + zp->z_origin); + /* XXX - this is bad, we should do something */ + qserial_retrytime(zp, tt.tv_sec); + zp->z_flags |= Z_NEED_QSERIAL; + return; + } + qp->q_flags |= Q_ZSERIAL; + qp->q_zquery = zp; + zp->z_flags |= Z_QSERIAL; + zp->z_flags &= ~Z_NEED_QSERIAL; + zp->z_xaddrcnt = 0; + ns_refreshtime(zp, tt.tv_sec); + qserials_running++; + ns_debug(ns_log_default, 1, "qserial_query(%s) QUEUED", zp->z_origin); +} + +static int +qserv_compare(const void *a, const void *b) { + const struct qserv *qs1 = a, *qs2 = b; + u_int32_t s1 = qs1->serial, s2 = qs2->serial; + + /* Note that we sort the "best" serial numbers to the front. */ + if (s1 == s2) + return (0); + if (s1 == 0) + return (-1); + if (s2 == 0) + return (1); + if (!SEQ_GT(s1, s2)) + return (1); + assert(SEQ_GT(s1, s2)); + return (-1); +} + +void +qserial_answer(struct qinfo *qp) { + struct zoneinfo *zp = qp->q_zquery; + struct qserv *qs = NULL; + u_int32_t serial = 0; + int n, cnt = 0; + + /* Take this query out of the global quotas. */ + zp->z_flags &= ~Z_QSERIAL; + qp->q_flags &= ~Q_ZSERIAL; /* keeps us from being called twice */ + qserials_running--; + + /* Find best serial among those returned. */ + for (n = 0; n < qp->q_naddr; n++) { + qs = &qp->q_addr[n]; + ns_debug(ns_log_default, 1, "qserial_answer(%s): [%s] -> %lu", + zp->z_origin, inet_ntoa(qs->ns_addr.sin_addr), + (unsigned long)qs->serial); + /* Don't consider serials which weren't set by a response. */ + if (qs->serial == 0) + continue; + /* Count valid answers. */ + cnt++; + /* Remove from consideration serials which aren't "better." */ + if (zp->z_serial != 0 && !SEQ_GT(qs->serial, zp->z_serial)) { + if (serial == 0 && qs->serial == zp->z_serial) + serial = qs->serial; + + if (qs->serial != zp->z_serial) + ns_notice(ns_log_xfer_in, + "Zone \"%s\" (%s) SOA serial# (%lu) rcvd from [%s] is < ours (%lu)%s", + zp->z_origin, p_class(zp->z_class), + (u_long) qs->serial, + inet_ntoa(qs->ns_addr.sin_addr), + (u_long) zp->z_serial, + qp->q_naddr!=1 ? ": skipping" : ""); + qs->serial = 0; + continue; + } + if (serial == 0 || SEQ_GT(qs->serial, serial)) + serial = qs->serial; + } + + /* If we have an existing serial number, then sort by "better." */ + if (zp->z_serial != 0) { + qsort(qp->q_addr, qp->q_naddr, sizeof(struct qserv), + qserv_compare); + for (n = 0; n < qp->q_naddr; n++) { + qs = &qp->q_addr[n]; + ns_debug(ns_log_default, 1, + "qserial_answer after sort: [%s] -> %lu", + inet_ntoa(qs->ns_addr.sin_addr), + (unsigned long)qs->serial); + } + } + + /* Now see about kicking off an inbound transfer. */ + if (serial == 0) { + /* An error occurred, or the all queries timed out. */ + if (qp->q_naddr != cnt) + ns_info(ns_log_xfer_in, + "Err/TO getting serial# for \"%s\"", + zp->z_origin); + addxfer(zp); + } else if (zp->z_serial == 0 || SEQ_GT(serial, zp->z_serial)) { + ns_debug(ns_log_xfer_in, 1, + "qserial_answer: zone is out of date"); + /* Use all servers whose serials are better than ours. */ + zp->z_xaddrcnt = 0; + for (n = 0; n < qp->q_naddr; n++) { + qs = &qp->q_addr[n]; + if (qs->serial != 0) + zp->z_xaddr[zp->z_xaddrcnt++] = + qs->ns_addr.sin_addr; + } + addxfer(zp); + } else if (zp->z_serial == serial) { + ns_debug(ns_log_xfer_in, 1, + "qserial_answer: zone serial is still OK"); + markUpToDate(zp); + sched_zone_maint(zp); + } +} + +/* + * Writes TSIG key info for an address to a file, optionally opening it first. + * Returns: + * -1: Error. + * 0: No action taken. + * 1: Tsig info successfully written. + */ +static int +write_tsig_info(struct zoneinfo *zp, struct in_addr addr, char *name, int *fd) { + server_info si; + DST_KEY *dst_key = NULL; + int tsig_fd = *fd; + char tsig_str[1024], secret_buf64[172]; + u_char secret_buf[128]; + int secret_len, len; + int i; + + for (i = 0; i < zp->z_addrcnt ; i++) + if (memcmp(&addr, &zp->z_addr[i], sizeof(addr)) == 0) { + dst_key = zp->z_keys[i]; + break; + } + + if (dst_key == NULL) { + si = find_server(addr); + if (si == NULL || si->key_list == NULL || + si->key_list->first == NULL) + return(0); + dst_key = si->key_list->first->key; + } + if (tsig_fd == -1) { + *fd = tsig_fd = mkstemp(name); + if (tsig_fd < 0) { + ns_warning(ns_log_default, + "write_tsig_info: mkstemp(%s) for TSIG info failed", + name); + return(-1); + } + (void) fchown(tsig_fd, user_id, group_id); + } + + memset(secret_buf, 0, sizeof(secret_buf)); + secret_len = dst_key_to_buffer(dst_key, secret_buf, sizeof(secret_buf)); + if (secret_len == 0) + return (-1); + len = b64_ntop(secret_buf, secret_len, secret_buf64, + sizeof(secret_buf64)); + if (len == -1) + return (-1); + /* We need snprintf! */ + if (strlen(dst_key->dk_key_name) + len + sizeof("XXX.XXX.XXX.XXX") + + sizeof("123") + 5 > sizeof(tsig_str)) + return (-1); + sprintf(tsig_str, "%s\n%s\n%d\n%s\n", + inet_ntoa(addr), dst_key->dk_key_name, dst_key->dk_alg, + secret_buf64); + len = strlen(tsig_str); + if (write(tsig_fd, tsig_str, strlen(tsig_str)) != len) + return (-1); + return (1); +} + +/* + * Returns number of tsigs written or -1. + */ +static int +write_tsigs(struct zoneinfo *zp, char *tsig_name) { + struct in_addr a; + int tsig_ret; + int tsig_fd = -1; + int cnt; + int records = 0; + + for (cnt = 0; cnt < zp->z_xaddrcnt; cnt++) { + a = zp->z_xaddr[cnt]; + if (aIsUs(a) && ns_port == zp->z_port) + continue; + + tsig_ret = write_tsig_info(zp, a, tsig_name, &tsig_fd); + switch (tsig_ret) { + case -1: + goto error; + case 0: + break; + case 1: + records++; + break; + } + } + + if (tsig_fd != -1) + close(tsig_fd); + return (records); + + error: + if (tsig_fd != -1) { + unlink(tsig_name); + close(tsig_fd); + } + return (-1); +} + +#ifdef BIND_IXFR +static int +supports_ixfr(struct zoneinfo *zp) { + int cnt = 0; + for (cnt = 0; cnt < zp->z_xaddrcnt; cnt++) { + struct in_addr a; + server_info si; + + a = zp->z_xaddr[cnt]; + if (aIsUs(a) && ns_port == zp->z_port) + continue; + si = find_server(a); + + if (si != NULL && (si->flags & SERVER_INFO_SUPPORT_IXFR) != 0) + return(1); + } + return(0); +} +#endif + +/* + * Start an asynchronous zone transfer for a zone. Depends on current time + * being in tt. Caller must do a sched_zone_maint(zp) after we return. + */ +static void +startxfer(struct zoneinfo *zp) { + char *argv[NSMAX*2 + 20]; + char argv_ns[NSMAX][MAXDNAME]; + int argc = 0, argc_ns = 0, i; + pid_t pid; + u_int cnt; + char debug_str[10]; + char serial_str[10]; + char port_str[10]; + char class_str[10]; + char src_str[20]; + char tsig_name[MAXPATHLEN+1]; + int tsig_ret = 0; + + ns_debug(ns_log_default, 1, "startxfer() %s", + zp->z_origin[0] != '\0' ? zp->z_origin : "."); + + argv[argc++] = server_options->named_xfer; + DE_CONST("-z", argv[argc++]); + DE_CONST(*zp->z_origin ? zp->z_origin : ".", argv[argc++]); + DE_CONST("-f", argv[argc++]); + argv[argc++] = zp->z_source; +#ifdef BIND_IXFR + if (supports_ixfr(zp) && zp->z_ixfr_tmp != NULL) { + DE_CONST("-i", argv[argc++]); + argv[argc++] = zp->z_ixfr_tmp; + } +#endif + if (zp->z_serial != 0) { + DE_CONST("-s", argv[argc++]); + sprintf(serial_str, "%u", zp->z_serial); + argv[argc++] = serial_str; + } + if (zp->z_axfr_src.s_addr != 0 || + server_options->axfr_src.s_addr != 0) { + DE_CONST("-x", argv[argc++]); + argv[argc++] = strcpy(src_str, inet_ntoa( + (zp->z_axfr_src.s_addr != 0) ? zp->z_axfr_src : + server_options->axfr_src)); + } + DE_CONST("-C", argv[argc++]); + sprintf(class_str, "%d", zp->z_class); + argv[argc++] = class_str; + if (zp->z_flags & Z_SYSLOGGED) + DE_CONST("-q", argv[argc++]); + DE_CONST("-P", argv[argc++]); + sprintf(port_str, "%d", ntohs(zp->z_port) != 0 ? zp->z_port : ns_port); + argv[argc++] = port_str; +#ifdef STUBS + if (zp->z_type == Z_STUB) + DE_CONST("-S", argv[argc++]); +#endif +#ifdef DEBUG + if (debug) { + DE_CONST("-d", argv[argc++]); + sprintf(debug_str, "%d", debug); + argv[argc++] = debug_str; + DE_CONST("-l", argv[argc++]); + DE_CONST(_PATH_XFERDDT, argv[argc++]); + if (debug > 5) { + DE_CONST("-t", argv[argc++]); + DE_CONST(_PATH_XFERTRACE, argv[argc++]); + } + } +#endif + + if (zp->z_xaddrcnt == 0) { + for (zp->z_xaddrcnt = 0; + zp->z_xaddrcnt < zp->z_addrcnt; + zp->z_xaddrcnt++) + zp->z_xaddr[zp->z_xaddrcnt] = + zp->z_addr[zp->z_xaddrcnt]; + } + + /* + * Store TSIG keys if we have them. + */ + strcpy(tsig_name, "tsigs.XXXXXX"); + tsig_ret = write_tsigs(zp, tsig_name); + if (tsig_ret == -1) { + ns_error(ns_log_xfer_in, "unable to write tsig info: '%s'", + zp->z_origin); + return; + } + if (tsig_ret != 0) { + DE_CONST("-T", argv[argc++]); + argv[argc++] = tsig_name; + } + + /* + * Copy the server ip addresses into argv, after converting + * to ascii and saving the static inet_ntoa result. + * Also, send TSIG key info into a file for the child. + */ + for (cnt = 0; cnt < zp->z_xaddrcnt; cnt++) { + struct in_addr a; + + a = zp->z_xaddr[cnt]; + if (aIsUs(a) && ns_port == zp->z_port) { + if (!haveComplained((u_long)zp, (u_long)startxfer)) + ns_notice(ns_log_default, + "attempted to fetch zone %s from self (%s)", + zp->z_origin, inet_ntoa(a)); + continue; + } + argv[argc++] = strcpy(argv_ns[argc_ns++], inet_ntoa(a)); +#ifdef BIND_IXFR + if (zp->z_ixfr_tmp != NULL) { + server_info si = find_server(a); + + if (si != NULL && + (si->flags & SERVER_INFO_SUPPORT_IXFR) != 0) + DE_CONST("ixfr", argv[argc++]); + else + DE_CONST("axfr", argv[argc++]); + } +#endif + } + + argv[argc] = NULL; + +#ifdef DEBUG + if (debug >= 1) { + char buffer[1024]; + char *curr, *last; + int len; + + curr = buffer; + last = &buffer[sizeof buffer - 1]; /* leave room for \0 */ + for (i = 0; i < argc; i++) { + len = strlen(argv[i]); + if (curr + len + 1 >= last) { + ns_debug(ns_log_xfer_in, 1, + "xfer args debug printout truncated"); + break; + } + strncpy(curr, argv[i], len); + curr += len; + *curr = ' '; + curr++; + } + *curr = '\0'; + ns_debug(ns_log_xfer_in, 1, "%s", buffer); + } +#endif /* DEBUG */ + + gettime(&tt); + for (i = 0; i < MAX_XFERS_RUNNING; i++) + if (xferstatus[i].xfer_pid == 0) + break; + if (i == MAX_XFERS_RUNNING) { + ns_warning(ns_log_default, + "startxfer: too many xfers running"); + zp->z_time = tt.tv_sec + 10; + return; + } + + if ((pid = spawnxfer(argv, zp)) == -1) { + unlink(tsig_name); + return; + } + + xferstatus[i].xfer_state = XFER_RUNNING; + xferstatus[i].xfer_pid = pid; /* XXX - small race condition here if we + * can't hold signals */ + xferstatus[i].xfer_addr = zp->z_xaddr[0]; + ns_debug(ns_log_default, 1, "started xfer child %d", pid); + zp->z_flags &= ~Z_NEED_XFER; + zp->z_flags |= Z_XFER_RUNNING; + zp->z_xferpid = pid; + xfers_running++; + xfers_deferred--; + if (zp->z_max_transfer_time_in) + zp->z_time = tt.tv_sec + zp->z_max_transfer_time_in; + else + zp->z_time = tt.tv_sec + server_options->max_transfer_time_in; +} + +const char * +zoneTypeString(u_int type) { + static char ret[sizeof "(4294967296?)"]; /* 2^32 */ + + switch (type) { + case Z_MASTER: return ("master"); + case Z_SLAVE: return ("slave"); +#ifdef STUBS + case Z_STUB: return ("stub"); +#endif + case Z_HINT: return ("hint"); + case Z_CACHE: return ("cache"); + case Z_FORWARD: return ("forward"); + default: + sprintf(ret, "(%u?)", type); + return (ret); + } +} + +#ifdef DEBUG +void +printzoneinfo(int zonenum, int category, int level) { + struct timeval tt; + struct zoneinfo *zp = &zones[zonenum]; + + if (debug == 0) + return; + + if (!zp->z_origin) + return; + + gettime(&tt); + + ns_debug(category, level, "zone %d: %s, class %s, type %s", zonenum, + zp->z_origin[0] ? zp->z_origin : ".", + p_class(zp->z_class), zoneTypeString(zp->z_type)); + if (zp->z_source) + ns_debug(category, level, "\tsource %s", zp->z_source); + ns_debug(category, level, "\tflags %lx, serial %u, minimum %u", + (u_long)zp->z_flags, zp->z_serial, zp->z_minimum); + ns_debug(category, level, "\trefresh %u, retry %u, expire %u", + zp->z_refresh, zp->z_retry, zp->z_expire); + if (zp->z_time) + ns_debug(category, level, "\tz_time %lu (now %lu, left: %lu)", + zp->z_time, (u_long)tt.tv_sec, + (u_long)(zp->z_time - tt.tv_sec)); + else + ns_debug(category, level, "\tz_time %lu", zp->z_time); +#ifdef BIND_UPDATE + if (zp->z_type == z_master && (zp->z_flags & Z_DYNAMIC) != 0) { + ns_debug(category, level, + "\tdumpintvl %lu, soaincrintvl %lu deferupdcnt %lu", + (unsigned long)zp->z_dumpintvl, + (unsigned long)zp->z_soaincrintvl, + (unsigned long)zp->z_deferupdcnt); + if (zp->z_soaincrtime) + ns_debug(category, level, + "\tz_soaincrtime %lu (now %lu, left: %lu)", + zp->z_soaincrtime, (u_long)tt.tv_sec, + (u_long)(zp->z_soaincrtime - tt.tv_sec)); + else + ns_debug(category, level, "\tz_soaincrtime %lu", + zp->z_soaincrtime); + if (zp->z_dumptime) + ns_debug(category, level, + "\tz_dumptime %lu (now %lu, left: %lu)", + zp->z_dumptime, (u_long)tt.tv_sec, + (u_long)(zp->z_dumptime - tt.tv_sec)); + else + ns_debug(category, level, "\tz_dumptime %lu", + zp->z_dumptime); + } +#endif +} +#endif /* DEBUG */ + +/* + * Remove all cached data below dname, class independent. + */ +void +clean_cache_from(char *dname, struct hashbuf *htp) { + const char *fname; + struct databuf *dp, *pdp; + struct namebuf *np; + struct hashbuf *phtp = htp; + int root_zone = 0; + + ns_debug(ns_log_default, 1, "clean_cache_from(%s)", dname); + if ((np = nlookup(dname, &phtp, &fname, 0)) && dname == fname && + !ns_wildcard(NAME(*np))) { + for (pdp = NULL, dp = np->n_data; dp != NULL; (void)NULL) { + if (dp->d_zone == DB_Z_CACHE) + dp = rm_datum(dp, np, pdp, NULL); + else { + pdp = dp; + dp = dp->d_next; + } + } + + if (*dname == '\0') + root_zone = 1; + + if (np->n_hash != NULL || root_zone) { + struct hashbuf *h; + + if (root_zone) + h = htp; + else + h = np->n_hash; + (void)clean_cache(h, 1); + if (h->h_cnt == 0 && !root_zone) { + rm_hash(np->n_hash); + np->n_hash = NULL; + } + } + + if (!root_zone && np->n_hash == NULL && np->n_data == NULL) + (void) purge_node(htp, np); + } +} + +/* clean_cache(htp, all) + * Scan the entire cache looking for expired TTL's on nonauthoritative + * data, and remove it. if `all' is true, ignore TTL and rm everything. + * notes: + * this should be lazy and eventlib driven. + * return: + * number of deleted RRs (all=1) or RRsets (all=0). + */ +int +clean_cache(struct hashbuf *htp, int all) { + struct databuf *dp, *pdp; + struct namebuf *np, *pnp, *npn; + struct namebuf **npp, **nppend; + int deleted = 0; + + nppend = htp->h_tab + htp->h_size; + for (npp = htp->h_tab; npp < nppend; npp++) { + for (pnp = NULL, np = *npp; np != NULL; np = npn) { + again: + for (pdp = NULL, dp = np->n_data; dp != NULL; + (void)NULL) { + if (all && dp->d_zone == DB_Z_CACHE) { + dp = rm_datum(dp, np, pdp, NULL); + deleted++; + } else if (dp->d_zone == DB_Z_CACHE && + stale(dp)) { + delete_all(np, dp->d_class, dp->d_type); + deleted++; + goto again; + } else { + pdp = dp; + dp = dp->d_next; + } + } /*for(pdp)*/ + + if (np->n_hash) { + /* Call recursively to remove subdomains. */ + deleted += clean_cache(np->n_hash, all); + + /* If now empty, free it */ + if (np->n_hash->h_cnt == 0) { + rm_hash(np->n_hash); + np->n_hash = NULL; + } + } + + if (np->n_hash == NULL && np->n_data == NULL) { + npn = rm_name(np, npp, pnp); + htp->h_cnt--; + } else { + npn = np->n_next; + pnp = np; + } + } /*for(pnp)*/ + } /*for(npp)*/ + return (deleted); +} + +/* struct namebuf * + * purge_node(htp, np) + * Remove entry from cache. + * Prerequisites: + * Node is empty and has no children. + * Paramters: + * htp - root of recursive hash table this node is part of. + * np - the node to be deleted. + * Return: + * pointer to parent. + */ +struct namebuf * +purge_node(struct hashbuf *htp, struct namebuf *np) { + struct namebuf **npp, **nppend; + struct namebuf *npn, *pnp, *nnp, *parent; + struct hashbuf *phtp; + + ns_debug(ns_log_default, 3, "purge_node: cleaning cache"); + INSIST(np->n_hash == NULL && np->n_data == NULL); + + /* Walk parent hashtable looking for ourself. */ + parent = np->n_parent; + if (parent != NULL) + phtp = parent->n_hash; + else + phtp = htp; + + if (phtp == NULL) { + /* XXX why shouldn't we panic? */ + } else { + nppend = phtp->h_tab + phtp->h_size; + for (npp = phtp->h_tab; npp < nppend; npp++) { + for (pnp = NULL, nnp = *npp; nnp != NULL; nnp = npn) { + if (nnp == np) { + ns_debug(ns_log_default, 3, + "purge_node: found ourself"); + npn = rm_name(nnp, npp, pnp); + phtp->h_cnt--; + } else { + npn = nnp->n_next; + pnp = nnp; + } + } + } + } + return (parent); +} + +void +remove_zone(struct zoneinfo *zp, const char *verb) { +#ifdef BIND_UPDATE + /* + * A dynamic zone might have changed, so we + * need to dump it before removing it. + */ + if ((zp->z_flags & Z_DYNAMIC) != 0 && + ((zp->z_flags & Z_NEED_SOAUPDATE) != 0 || + (zp->z_flags & Z_NEED_DUMP) != 0)) + (void) zonedump(zp, ISNOTIXFR); +#endif + if ((zp->z_flags & Z_NOTIFY) != 0) + ns_stopnotify(zp->z_origin, zp->z_class); + if ((zp->z_flags & Z_NEED_XFER) != 0) { + zp->z_flags &= ~Z_NEED_XFER; + xfers_deferred--; + } + ns_stopxfrs(zp); + if ((zp->z_flags & Z_XFER_RUNNING) != 0) { + int i; + /* Kill and abandon the current transfer. */ + for (i = 0; i < MAX_XFERS_RUNNING; i++) { + if (xferstatus[i].xfer_pid == zp->z_xferpid) { + xferstatus[i].xfer_pid = 0; + xferstatus[i].xfer_state = XFER_IDLE; + xfers_running--; + break; + } + } + (void)kill(zp->z_xferpid, SIGTERM); + zp->z_flags &= ~(Z_XFER_RUNNING|Z_XFER_ABORTED|Z_XFER_GONE); + zp->z_xferpid = 0; + ns_need(main_need_tryxfer); + } + do_reload(zp->z_origin, zp->z_type, zp->z_class, 1); + ns_notice(ns_log_config, "%s zone \"%s\" (%s) %s", + zoneTypeString(zp->z_type), zp->z_origin, + p_class(zp->z_class), verb); + free_zone_contents(zp, 1); + memset(zp, 0, sizeof(*zp)); + zp->z_type = z_nil; /* Pedantic; memset() did it. */ + INIT_LINK(zp, z_reloadlink); + INIT_LINK(zp, z_freelink); + free_zone(zp); +} + +int +purge_nonglue(const char *dname, struct hashbuf *htp, int class, int log) { + const char *fname; + struct namebuf *np; + struct hashbuf *phtp = htp; + int root_zone = 0; + int errs = 0; + + ns_debug(ns_log_default, 1, "purge_zone(%s,%d)", dname, class); + if ((np = nlookup(dname, &phtp, &fname, 0)) && dname == fname && + !ns_wildcard(NAME(*np))) { + + if (*dname == '\0') + root_zone = 1; + + if (np->n_hash != NULL || root_zone) { + struct hashbuf *h; + + if (root_zone) + h = htp; + else + h = np->n_hash; + errs += purge_nonglue_2(dname, h, class, 0, log); + if (h->h_cnt == 0 && !root_zone) { + rm_hash(np->n_hash); + np->n_hash = NULL; + } + } + } + return (errs); +} + +static int +valid_glue(struct databuf *dp, char *name, int belowcut) { + + /* NS records are only valid glue at the zone cut */ + if (belowcut && dp->d_type == T_NS) + return(0); + + if (ISVALIDGLUE(dp)) /* T_NS/T_A/T_AAAA/T_A6 */ + return (1); + + if (belowcut) + return (0); + + /* Parent NXT record? */ + if (dp->d_type == T_NXT && !ns_samedomain((char*)dp->d_data, name) && + ns_samedomain((char*)dp->d_data, zones[dp->d_zone].z_origin)) + return (1); + + /* KEY RRset may be in the parent */ + if (dp->d_type == T_KEY) + return (1); + + /* NXT & KEY records may be signed */ + if (!belowcut && dp->d_type == T_SIG && + (SIG_COVERS(dp) == T_NXT || SIG_COVERS(dp) == T_KEY)) + return (1); + return (0); +} + +static int +purge_nonglue_2(const char *dname, struct hashbuf *htp, int class, + int belowcut, int log) +{ + struct databuf *dp, *pdp; + struct namebuf *np, *pnp, *npn; + struct namebuf **npp, **nppend; + int errs = 0; + int zonecut; + char name[MAXDNAME]; + + nppend = htp->h_tab + htp->h_size; + for (npp = htp->h_tab; npp < nppend; npp++) { + for (pnp = NULL, np = *npp; np != NULL; np = npn) { + if (!bottom_of_zone(np->n_data, class)) { + zonecut = belowcut; + for (dp = np->n_data; dp != NULL; + dp = dp->d_next) { + if (match(dp, class, ns_t_ns)) { + zonecut = 1; + break; + } + } + getname(np, name, sizeof name); + for (pdp = NULL, dp = np->n_data; + dp != NULL; + (void)NULL) { + if (dp->d_class == class && + zonecut && + !valid_glue(dp, name, belowcut)) { + if (log) + ns_error(ns_log_load, + "zone: %s/%s: non-glue record %s bottom of zone: %s/%s", + *dname ? dname : ".", + p_class(dp->d_class), + belowcut ? "below" : + "at", + *name ? name : ".", + p_type(dp->d_type)); + dp = rm_datum(dp, np, pdp, + NULL); + if (log) + errs++; + } else { + pdp = dp; + dp = dp->d_next; + } + } + if (np->n_hash) { + /* + * call recursively to clean + * subdomains + */ + errs += purge_nonglue_2(dname, + np->n_hash, + class, + zonecut || + belowcut, + log); + + /* if now empty, free it */ + if (np->n_hash->h_cnt == 0) { + rm_hash(np->n_hash); + np->n_hash = NULL; + } + } + } + + if (np->n_hash == NULL && np->n_data == NULL) { + npn = rm_name(np, npp, pnp); + htp->h_cnt--; + } else { + npn = np->n_next; + pnp = np; + } + } + } + return (errs); +} + +void +purge_zone(const char *dname, struct hashbuf *htp, int class) { + const char *fname; + struct databuf *dp, *pdp; + struct namebuf *np; + struct hashbuf *phtp = htp; + int root_zone = 0; + + ns_debug(ns_log_default, 1, "purge_zone(%s,%d)", dname, class); + if ((np = nlookup(dname, &phtp, &fname, 0)) && dname == fname && + !ns_wildcard(NAME(*np))) { + for (pdp = NULL, dp = np->n_data; dp != NULL; (void)NULL) { + if (dp->d_class == class) + dp = rm_datum(dp, np, pdp, NULL); + else { + pdp = dp; + dp = dp->d_next; + } + } + + if (*dname == '\0') + root_zone = 1; + + if (np->n_hash != NULL || root_zone) { + struct hashbuf *h; + + if (root_zone) + h = htp; + else + h = np->n_hash; + purge_z_2(h, class); + if (h->h_cnt == 0 && !root_zone) { + rm_hash(np->n_hash); + np->n_hash = NULL; + } + } + + if (!root_zone && np->n_hash == NULL && np->n_data == NULL) + (void) purge_node(htp, np); + } +} + +static void +purge_z_2(htp, class) + struct hashbuf *htp; + int class; +{ + struct databuf *dp, *pdp; + struct namebuf *np, *pnp, *npn; + struct namebuf **npp, **nppend; + + nppend = htp->h_tab + htp->h_size; + for (npp = htp->h_tab; npp < nppend; npp++) { + for (pnp = NULL, np = *npp; np != NULL; np = npn) { + if (!bottom_of_zone(np->n_data, class)) { + for (pdp = NULL, dp = np->n_data; + dp != NULL; + (void)NULL) { + if (dp->d_class == class) + dp = rm_datum(dp, np, pdp, + NULL); + else { + pdp = dp; + dp = dp->d_next; + } + } + if (np->n_hash) { + /* call recursively to rm subdomains */ + purge_z_2(np->n_hash, class); + + /* if now empty, free it */ + if (np->n_hash->h_cnt == 0) { + rm_hash(np->n_hash); + np->n_hash = NULL; + } + } + } + + if (np->n_hash == NULL && np->n_data == NULL) { + npn = rm_name(np, npp, pnp); + htp->h_cnt--; + } else { + npn = np->n_next; + pnp = np; + } + } + } +} + +static int +bottom_of_zone(struct databuf *dp, int class) { + int ret = 0; + + for ((void)NULL; dp; dp = dp->d_next) { + if (dp->d_class != class) + continue; + if (dp->d_zone == DB_Z_CACHE) + continue; + if (dp->d_rcode) /* This should not occur. */ + continue; + if (dp->d_type != T_SOA) + continue; + ret = 1; + break; + } + ns_debug(ns_log_default, 3, "bottom_of_zone() == %d", ret); + return (ret); +} + +/* + * Handle XFER limit for a nameserver. + */ + + +static int +nxfers(struct zoneinfo *zp) { + struct in_addr nsa; + int ret; + int i; + + if (zp->z_xaddrcnt != 0) + nsa = zp->z_xaddr[0]; /* first ns holds zone's xfer limit */ + else if (zp->z_addrcnt != 0) + nsa = zp->z_addr[0]; /* first ns holds zone's xfer limit */ + else + return (-1); + + ret = 0; + for (i = 0; i < MAX_XFERS_RUNNING; i++) + if (xferstatus[i].xfer_status == XFER_RUNNING && + xferstatus[i].xfer_addr.s_addr == nsa.s_addr) + ret++; + return (ret); +} + +/* + * Abort an xfer that has taken too long. + */ +static void +abortxfer(struct zoneinfo *zp) { + if (zp->z_flags & (Z_XFER_GONE|Z_XFER_ABORTED)) { + int i; + + for (i = 0; i < MAX_XFERS_RUNNING; i++) { + if (xferstatus[i].xfer_pid == zp->z_xferpid) { + xferstatus[i].xfer_pid = 0; + xferstatus[i].xfer_state = XFER_IDLE; + break; + } + } + + if (zp->z_flags & Z_XFER_GONE) + ns_warning(ns_log_default, + "zone transfer timeout for \"%s\"; pid %lu missing", + zp->z_origin, (u_long)zp->z_xferpid); + else if (kill(zp->z_xferpid, SIGKILL) == -1) + ns_warning(ns_log_default, + "zone transfer timeout for \"%s\"; kill pid %lu: %s", + zp->z_origin, (u_long)zp->z_xferpid, + strerror(errno)); + else + ns_warning(ns_log_default, +"zone transfer timeout for \"%s\"; second kill \ +pid %lu - forgetting, processes may accumulate", + zp->z_origin, (u_long)zp->z_xferpid); + + zp->z_xferpid = 0; + xfers_running--; + zp->z_flags &= ~(Z_XFER_RUNNING|Z_XFER_ABORTED|Z_XFER_GONE); + } else if (kill(zp->z_xferpid, SIGTERM) == -1) { + if (errno == ESRCH) + /* No warning on first time, it may have just exited */ + zp->z_flags |= Z_XFER_GONE; + else { + ns_warning(ns_log_default, + "zone transfer timeout for \"%s\"; pid %lu kill failed %s", + zp->z_origin, (u_long)zp->z_xferpid, + strerror(errno)); + zp->z_flags |= Z_XFER_ABORTED; + } + } else { + ns_notice(ns_log_default, + "zone transfer timeout for \"%s\"; pid %lu killed", + zp->z_origin, (u_long)zp->z_xferpid); + zp->z_flags |= Z_XFER_ABORTED; + } +} + +/* + * Process exit of xfer's. + */ +void +reapchild(void) { + int i; + pid_t pid; + WAIT_T status; + + gettime(&tt); + while ((pid = (pid_t)waitpid(-1, &status, WNOHANG)) > 0) { + for (i = 0; i < MAX_XFERS_RUNNING; i++) { + if (xferstatus[i].xfer_pid == pid) { + xferstatus[i].xfer_status = status; + xferstatus[i].xfer_state = XFER_DONE; + ns_need(main_need_endxfer); + break; + } + } + } +} + +/* + * Finish processing of of finished xfers + */ +void +endxfer() { + struct zoneinfo *zp; + int exitstatus, i; + pid_t pid; + WAIT_T status; + + gettime(&tt); + + for (i = 0; i < MAX_XFERS_RUNNING; i++) { + if (xferstatus[i].xfer_state != XFER_DONE) + continue; + pid = xferstatus[i].xfer_pid; + status = xferstatus[i].xfer_status; + exitstatus = WIFEXITED(status) ? WEXITSTATUS(status) : 0; + + for (zp = zones; zp < &zones[nzones]; zp++) { + if (zp->z_xferpid != pid) + continue; + xfers_running--; + zp->z_xferpid = 0; + zp->z_flags &= + ~(Z_XFER_RUNNING|Z_XFER_ABORTED|Z_XFER_GONE); + ns_debug(ns_log_default, 1, + "\nendxfer: child %d zone %s returned status=%d termsig=%d", + pid, zp->z_origin, exitstatus, + WIFSIGNALED(status) ? WTERMSIG(status) : -1); + if (WIFSIGNALED(status)) { + if (WTERMSIG(status) != SIGKILL) { + ns_notice(ns_log_default, + "named-xfer \"%s\" exited with signal %d", + zp->z_origin[0]?zp->z_origin:".", + WTERMSIG(status)); + } + ns_retrytime(zp, tt.tv_sec); + sched_zone_maint(zp); + } else { + switch (exitstatus) { + case XFER_UPTODATE: + markUpToDate(zp); + sched_zone_maint(zp); + break; + + case XFER_SUCCESSAXFR: + case XFER_SUCCESSAXFRIXFRFILE: + zp->z_xferpid = XFER_ISAXFR; + if (exitstatus == XFER_SUCCESSAXFRIXFRFILE) { + zp->z_xferpid = XFER_ISAXFRIXFR; + if (zp->z_ixfr_tmp != NULL) + isc_movefile( + zp->z_ixfr_tmp, + zp->z_source); + } + /* XXX should incorporate loadxfer() */ + zp->z_flags |= Z_NEED_RELOAD; + zp->z_flags &= ~Z_SYSLOGGED; + ns_need(main_need_zoneload); + break; + + case XFER_SUCCESSIXFR: + zp->z_xferpid = XFER_ISIXFR; + ns_notice(ns_log_default, + "IXFR Success %s", + zp->z_ixfr_tmp); + if (merge_logs(zp, zp->z_ixfr_tmp) >= 0) { + ns_notice(ns_log_default, + "IXFR Merge success %s", + zp->z_ixfr_tmp); + + (void)unlink(zp->z_updatelog); + (void)unlink(zp->z_ixfr_base); + isc_movefile(zp->z_ixfr_tmp, + zp->z_ixfr_base); + (void)unlink(zp->z_ixfr_tmp); + if (zonedump(zp, ISIXFR) < 0) + ns_warning(ns_log_db, + "error in write ixfr updates to zone file %s", + zp ->z_source); + ns_refreshtime(zp, tt.tv_sec); + sched_zone_maint(zp); + } else { + ns_notice(ns_log_default, + "IXFR Merge failed %s", + zp->z_ixfr_tmp); + ns_retrytime(zp, tt.tv_sec); + sched_zone_maint(zp); + } + break; + + case XFER_TIMEOUT: + if (!(zp->z_flags & Z_SYSLOGGED)) { + zp->z_flags |= Z_SYSLOGGED; + ns_notice(ns_log_default, + "zoneref: Masters for slave zone \"%s\" unreachable", + zp->z_origin); + } + ns_retrytime(zp, tt.tv_sec); + sched_zone_maint(zp); + break; + + case XFER_REFUSED: + if (!(zp->z_flags & Z_SYSLOGGED)) { + zp->z_flags |= Z_SYSLOGGED; + ns_error(ns_log_xfer_in, + "zoneref: Masters for slave zone \"%s\" REFUSED transfer", + zp->z_origin); + } + ns_retrytime(zp, tt.tv_sec); + sched_zone_maint(zp); + break; + + default: + if (!(zp->z_flags & Z_SYSLOGGED)) { + zp->z_flags |= Z_SYSLOGGED; + ns_notice(ns_log_default, + "named-xfer for \"%s\" exited %d", + zp->z_origin, + exitstatus); + } + /* FALLTHROUGH */ + case XFER_FAIL: + zp->z_flags |= Z_SYSLOGGED; + ns_retrytime(zp, tt.tv_sec); + sched_zone_maint(zp); + break; + } + break; + } + } + xferstatus[i].xfer_state = XFER_IDLE; + xferstatus[i].xfer_pid = 0; + } + tryxfer(); +} + +/* + * Try to start some xfers - new "fair scheduler" by Bob Halley @DEC (1995) + */ +void +tryxfer() { + static struct zoneinfo *zp = NULL; + static struct zoneinfo *lastzones = NULL; + static int lastnzones = 0; + struct zoneinfo *startzp, *stopzp; + + /* initialize, and watch out for changes in zones! */ + if (lastzones != zones) { + if (lastzones != NULL) + ns_debug(ns_log_default, 3, "zones changed: %p != %p", + lastzones, zones); + lastzones = zones; + zp = zones; + } + + /* did zones shrink? */ + if (lastnzones > nzones) { + ns_debug(ns_log_default, 3, "zones shrunk"); + zp = zones; + } + lastnzones = nzones; + + if (zp == zones) + stopzp = &zones[nzones-1]; + else + stopzp = zp - 1; + + ns_debug(ns_log_default, 3, + "tryxfer start zp=%p stopzp=%p def=%d running=%d", + zp, stopzp, xfers_deferred, xfers_running); + + startzp = zp; + for (;;) { + int xfers; + + if (!xfers_deferred || + xfers_running >= server_options->transfers_in) + break; + + if ((xfers = nxfers(zp)) != -1 && + xfers < server_options->transfers_per_ns && + (zp->z_flags & Z_NEED_XFER)) { + startxfer(zp); + sched_zone_maint(zp); + } + + if (zp == stopzp) { + ns_debug(ns_log_default, 3, "tryxfer stop mark"); + zp = startzp; + break; + } + + zp++; + /* wrap around? */ + if (zp == &zones[nzones]) + zp = zones; + } + ns_debug(ns_log_default, 3, "tryxfer stop zp=%p", zp); +} + +/* + * Reload zones whose transfers have completed. + */ +void +loadxfer(void) { + struct zoneinfo *zp; + u_int32_t old_serial,new_serial; + char *tmpnom; + int isixfr; + + gettime(&tt); + for (zp = zones; zp < &zones[nzones]; zp++) { + if (zp->z_flags & Z_NEED_RELOAD) { + ns_debug(ns_log_default, 1, "loadxfer() \"%s\"", + zp->z_origin[0] ? zp->z_origin : "."); + zp->z_flags &= ~(Z_NEED_RELOAD|Z_AUTH); +/* XXX this is bad, should be done in ns_zreload() for primary changes. */ + ns_stopxfrs(zp); + old_serial = zp->z_serial; + if (zp->z_xferpid == XFER_ISIXFR) { + tmpnom = zp->z_ixfr_tmp; + isixfr = ISIXFR; + } else { + tmpnom = zp->z_source; + purge_zone(zp->z_origin, hashtab, zp->z_class); + isixfr = ISNOTIXFR; + } + if (zp->z_xferpid == XFER_ISAXFRIXFR) { + tmpnom= zp->z_source; + purge_zone(zp->z_origin, hashtab, zp->z_class); + isixfr = ISNOTIXFR; + } + + if (!db_load(tmpnom, zp->z_origin, zp, NULL, isixfr)) { + zp->z_flags |= Z_AUTH; + zp->z_flags &= ~Z_EXPIRED; + if (isixfr == ISIXFR) { + new_serial= zp ->z_serial; + ns_warning(ns_log_db, "ISIXFR"); + ns_warning(ns_log_db, "error in updating ixfr data base file %s from %s", zp -> z_ixfr_base, zp ->z_ixfr_tmp); + if (zonedump(zp,ISIXFR)<0) + ns_warning(ns_log_db, "error in write ixfr updates to zone file %s", zp ->z_source); + + } + } + zp->z_xferpid = 0; + if (zp->z_flags & Z_TMP_FILE) + (void) unlink(zp->z_source); + sched_zone_maint(zp); + } + } +} + +/* + * Add this zone to the set of those needing transfers. + */ +void +addxfer(struct zoneinfo *zp) { + if (!(zp->z_flags & Z_NEED_XFER)) { + zp->z_flags |= Z_NEED_XFER; + xfers_deferred++; + tryxfer(); + } +} + +/* + * Mark one zone as requiring a reload. + * Note that it should be called with signals blocked, + * and should not allocate memory (since it can be called from a sighandler). + */ +const char * +deferred_reload_unsafe(struct zoneinfo *zp) { + INSIST(zp->z_type != z_nil); + if (!zonefile_changed_p(zp)) + return ("Zone file has not changed."); + if (LINKED(zp, z_reloadlink)) + return ("Zone is already scheduled for reloading."); + APPEND(reloadingzones, zp, z_reloadlink); + ns_need_unsafe(main_need_zreload); + return ("Zone is now scheduled for reloading."); +} + +/* + * If we've loaded this file, and the file has not been modified and contains + * no $INCLUDE, then there's no need to reload. + */ +int +zonefile_changed_p(struct zoneinfo *zp) { + struct stat sb; + + INSIST(zp->z_type != z_nil); + return ((zp->z_flags & Z_INCLUDE) != 0 || + stat(zp->z_source, &sb) == -1 || + zp->z_ftime != sb.st_mtime); +} + +int +reload_master(struct zoneinfo *zp) { + INSIST(zp->z_type == z_master); + zp->z_flags &= ~Z_AUTH; + ns_stopxfrs(zp); + /* XXX what about parent zones? */ +#ifdef BIND_UPDATE + /* + * A dynamic zone might have changed, so we + * need to dump it before reloading it. + */ + if ((zp->z_flags & Z_DYNAMIC) != 0 && + ((zp->z_flags & Z_NEED_SOAUPDATE) != 0 || + (zp->z_flags & Z_NEED_DUMP) != 0)) + (void) zonedump(zp, ISNOTIXFR); +#endif + purge_zone(zp->z_origin, hashtab, zp->z_class); + ns_debug(ns_log_config, 1, "reloading zone"); +#ifdef BIND_UPDATE + if ((zp->z_flags & Z_DYNAMIC) != 0) { + struct stat sb; + + if (stat(zp->z_source, &sb) < 0) + ns_error(ns_log_config, "stat(%s) failed: %s", + zp->z_source, strerror(errno)); + else { + if ((sb.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) != 0) + ns_warning(ns_log_config, + "dynamic zone file '%s' is writable", + zp->z_source); + } + } +#endif + if (!db_load(zp->z_source, zp->z_origin, zp, NULL, ISNOTIXFR)) + zp->z_flags |= Z_AUTH; + zp->z_refresh = 0; /* no maintenance needed */ + zp->z_time = 0; +#ifdef BIND_UPDATE + zp->z_lastupdate = 0; + if ((zp->z_flags & Z_DYNAMIC) != 0) + if (merge_logs(zp, zp->z_updatelog) == 1) + return (1); +#endif + return (0); +} + +/* + * Called by main() when main_need_zreload has been set. Should pull one + * zone off of the reloadingzones list and reload it, then if the list is + * not then empty, should turn main_need_zreload on again for the next call. + * It is not an error to call this when the reloadingzones list is empty. + */ +void +ns_zreload(void) { + struct zoneinfo *zp; + + block_signals(); + if (EMPTY(reloadingzones)) { + unblock_signals(); + return; + } + zp = HEAD(reloadingzones); + UNLINK(reloadingzones, zp, z_reloadlink); + unblock_signals(); + + reload_master(zp); + + block_signals(); + if (!EMPTY(reloadingzones)) + ns_need_unsafe(main_need_zreload); + unblock_signals(); +} + +/* + * Flush and reload configuration file and data base. + */ +void +ns_reload(void) { + ns_notice(ns_log_default, "%s %snameserver", + (reconfiging != 0) ? "reconfiguring" : "reloading", + (noexpired == 1) ? "(-noexpired) " : ""); + + INSIST(reloading == 0); + qflush(); + sq_flush(NULL); + reloading++; /* To force transfer if slave and backing up. */ + confmtime = ns_init(conffile); + time(&resettime); + reloading--; + ns_notice(ns_log_default, "Ready to answer queries."); +} + +/* + * Reload configuration, look for new or deleted zones, not changed ones + * also ignore expired zones. + */ +void +ns_noexpired(void) { + INSIST(noexpired == 0); + noexpired++; /* To ignore zones which are expired */ + ns_reconfig(); + noexpired--; +} + +/* + * Reload configuration, look for new or deleted zones, not changed ones. + */ +void +ns_reconfig(void) { + INSIST(reconfiging == 0); + reconfiging++; /* To ignore zones which aren't new or deleted. */ + ns_reload(); + reconfiging--; +} + +void +make_new_zones(void) { + struct zoneinfo *zp; + int n; + int newzones = (nzones == 0) ? INITIALZONES : NEWZONES; + + ns_debug(ns_log_config, 1, "Adding %d template zones", NEWZONES); + zp = (struct zoneinfo *) + memget((nzones + newzones) * sizeof(struct zoneinfo)); + if (zp == NULL) + panic("no memory for more zones", NULL); + memset(zp, 0, (nzones + newzones) * sizeof(struct zoneinfo)); + if (zones != NULL) { + memcpy(zp, zones, nzones * sizeof(struct zoneinfo)); + memput(zones, nzones * sizeof(struct zoneinfo)); + } + zones = zp; + block_signals(); + for (n = 0; n < newzones; n++) { + INIT_LINK(&zones[nzones], z_reloadlink); + INIT_LINK(&zones[nzones], z_freelink); + if (nzones != 0) + free_zone(&zones[nzones]); + nzones++; + } + unblock_signals(); +} + +void +free_zone(struct zoneinfo *zp) { + if (LINKED(zp, z_reloadlink)) + panic("freeing reloading zone", NULL); + if (zp->z_type != z_nil) + panic("freeing unfree zone", NULL); + APPEND(freezones, zp, z_freelink); +} + +#ifndef HAVE_SPAWNXFER +static pid_t +spawnxfer(char **argv, struct zoneinfo *zp) { + pid_t pid = (pid_t)vfork(); + + if (pid == -1) { + ns_error(ns_log_default, "xfer vfork: %s", strerror(errno)); + zp->z_time = tt.tv_sec + 10; + return (pid); + } + if (pid == 0) { + /* Child. */ + execv(server_options->named_xfer, argv); + ns_error(ns_log_default, "can't exec %s: %s", + server_options->named_xfer, strerror(errno)); + _exit(XFER_FAIL); /* Avoid duplicate buffer flushes. */ + } + return (pid); +} +#endif + +struct zoneinfo * +find_auth_zone(const char *zname, ns_class zclass) { + struct zoneinfo *zp; + struct hashbuf *htp; + struct namebuf *np; + const char *fname; + int zn; + + zp = find_zone(zname, zclass); + if (zp != NULL && + (zp->z_type == z_slave || + zp->z_type == z_master || + zp->z_type == z_stub)) + return (zp); + + htp = hashtab; + np = nlookup(zname, &htp, &fname, 0); + if (np != NULL && (zn = findMyZone(np, zclass)) != DB_Z_CACHE) + return (&zones[zn]); + + return (NULL); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_maint.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_parser.y =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_parser.y (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_parser.y (revision 109985) @@ -0,0 +1,2067 @@ +%{ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: ns_parser.y,v 8.80 2002/05/24 03:05:01 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* Global C stuff goes here. */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "port_after.h" + +#include "named.h" +#include "ns_parseutil.h" +#include "ns_lexer.h" + +#define SYM_ZONE 0x010000 +#define SYM_SERVER 0x020000 +#define SYM_KEY 0x030000 +#define SYM_ACL 0x040000 +#define SYM_CHANNEL 0x050000 +#define SYM_PORT 0x060000 + +#define SYMBOL_TABLE_SIZE 29989 /* should always be prime */ +static symbol_table symtab; + +#define AUTH_TABLE_SIZE 397 /* should always be prime */ +static symbol_table authtab = NULL; +static symbol_table channeltab = NULL; + +static zone_config current_zone; +static int should_install; + +static options current_options; +static int seen_options; +static int logged_options_error; + +static controls current_controls; + +static int seen_topology; + +static server_config current_server; +static int seen_server; + +static char *current_algorithm; +static char *current_secret; + +static log_config current_logging; +static int current_category; +static int chan_type; +static int chan_level; +static u_int chan_flags; +static int chan_facility; +static char *chan_name; +static int chan_versions; +static u_long chan_max_size; + +static log_channel lookup_channel(char *); +static void define_channel(const char *, log_channel); +static char *canonical_name(char *); + +int yyparse(); + +%} + +%union { + char * cp; + int s_int; + long num; + u_long ul_int; + u_int16_t us_int; + struct in_addr ip_addr; + ip_match_element ime; + ip_match_list iml; + rrset_order_list rol; + rrset_order_element roe; + struct dst_key * keyi; + enum axfr_format axfr_fmt; +} + +/* Lexical analyzer return values. */ +%token L_EOS +%token L_IPADDR +%token L_NUMBER +%token L_STRING +%token L_QSTRING +%token L_END_INCLUDE + +/* Include support */ +%token T_INCLUDE + +/* Items related to the "options" statement: */ +%token T_OPTIONS +%token T_DIRECTORY T_PIDFILE T_NAMED_XFER +%token T_DUMP_FILE T_STATS_FILE T_MEMSTATS_FILE +%token T_FAKE_IQUERY T_RECURSION T_FETCH_GLUE +%token T_HITCOUNT T_PREFERRED_GLUE +%token T_QUERY_SOURCE T_LISTEN_ON T_PORT T_ADDRESS +%token T_RRSET_ORDER T_ORDER T_NAME T_CLASS +%token T_CONTROLS T_INET T_UNIX T_PERM T_OWNER T_GROUP T_ALLOW +%type in_port +%type maybe_port +%type maybe_zero_port +%type maybe_wild_port +%type maybe_wild_addr +%token T_DATASIZE T_STACKSIZE T_CORESIZE +%token T_DEFAULT T_UNLIMITED +%token T_FILES T_VERSION T_HOSTNAME +%token T_HOSTSTATS T_HOSTSTATSMAX T_DEALLOC_ON_EXIT +%token T_TRANSFERS_IN T_TRANSFERS_OUT T_TRANSFERS_PER_NS +%token T_TRANSFER_FORMAT T_MAX_TRANSFER_TIME_IN +%token T_SERIAL_QUERIES T_ONE_ANSWER T_MANY_ANSWERS +%type transfer_format +%token T_NOTIFY T_EXPLICIT T_NOTIFY_INITIAL T_AUTH_NXDOMAIN +%token T_MULTIPLE_CNAMES T_USE_IXFR T_MAINTAIN_IXFR_BASE +%token T_CLEAN_INTERVAL T_INTERFACE_INTERVAL T_STATS_INTERVAL +%token T_MAX_LOG_SIZE_IXFR +%token T_HEARTBEAT T_USE_ID_POOL +%token T_MAX_NCACHE_TTL T_HAS_OLD_CLIENTS T_RFC2308_TYPE1 +%token T_LAME_TTL T_MIN_ROOTS +%token T_TREAT_CR_AS_SPACE + +/* Items used for the "logging" statement: */ +%token T_LOGGING T_CATEGORY T_CHANNEL T_SEVERITY T_DYNAMIC +%token T_FILE T_VERSIONS T_SIZE +%token T_SYSLOG T_DEBUG T_NULL_OUTPUT +%token T_PRINT_TIME T_PRINT_CATEGORY T_PRINT_SEVERITY +%type category +%type category_name channel_name facility_name +%type maybe_syslog_facility + +/* Items used for the "sortlist" statement: */ +%token T_SORTLIST + +/* Items used for the "topology" statement: */ +%token T_TOPOLOGY + +%type ordering_class +%type ordering_type +%type ordering_name +%type rrset_ordering_list +%type rrset_ordering_element + +/* ip_match_list */ +%type address_match_simple address_match_element address_name +%type address_match_list + +/* Items used for "server" statements: */ +%token T_SERVER +%token T_LONG_AXFR +%token T_BOGUS +%token T_TRANSFERS +%token T_KEYS +%token T_SUPPORT_IXFR +%token T_EDNS + +/* Items used for "zone" statements: */ +%token T_ZONE +%type optional_class +%type zone_type +%token T_IN T_CHAOS T_HESIOD +%token T_TYPE +%token T_MASTER T_SLAVE T_STUB T_RESPONSE +%token T_HINT +%token T_MASTERS T_TRANSFER_SOURCE +%token T_PUBKEY +%token T_ALSO_NOTIFY +%token T_DIALUP +%token T_FILE_IXFR +%token T_IXFR_TMP + +/* Items used for "trusted-keys" statements: */ +%token T_TRUSTED_KEYS + +/* Items used for access control lists and "allow" clauses: */ +%token T_ACL +%token T_ALLOW_UPDATE T_ALLOW_QUERY T_ALLOW_TRANSFER +%token T_ALLOW_RECURSION +%token T_BLACKHOLE + +/* Items related to the "key" statement: */ +%token T_SEC_KEY T_ALGID T_SECRET +%type key_ref +%type algorithm_id secret + +/* Items used for "size_spec" clauses: */ +%type size_spec + +/* Items used for a "check-names" clause: */ +%token T_CHECK_NAMES +%type check_names_type +%type check_names_opt +%token T_WARN T_FAIL T_IGNORE + +/* Items used for "forward" clauses: */ +%token T_FORWARD T_FORWARDERS +%token T_ONLY T_FIRST T_IF_NO_ANSWER T_IF_NO_DOMAIN + +/* Items used for yes/no responses: */ +%type yea_or_nay +%token T_YES T_TRUE T_NO T_FALSE + +/* Miscellaneous items (used in several places): */ +%type any_string + +%% +config_file: statement_list + { + if (EMPTY(current_controls)) + ns_ctl_defaults(¤t_controls); + ns_ctl_install(¤t_controls); + } + ; + +statement_list: statement + | statement_list statement + ; + +statement: include_stmt + | options_stmt L_EOS + | controls_stmt L_EOS + | logging_stmt L_EOS + | server_stmt L_EOS + | zone_stmt L_EOS + | trusted_keys_stmt L_EOS + | acl_stmt L_EOS + | key_stmt L_EOS + | L_END_INCLUDE + | error L_EOS + | error L_END_INCLUDE + ; + +include_stmt: T_INCLUDE L_QSTRING L_EOS + { + lexer_begin_file($2, NULL); + (void)freestr($2); + } + ; + +/* + * Options + */ + +options_stmt: T_OPTIONS + { + if (seen_options) + parser_error(0, "cannot redefine options"); + current_options = new_options(); + } + '{' options '}' + { + if (!seen_options) + set_options(current_options, 0); + else + free_options(current_options); + current_options = NULL; + seen_options = 1; + } + ; + +options: option L_EOS + | options option L_EOS + ; + +option: /* Empty */ + | T_HOSTNAME L_QSTRING + { + if (current_options->hostname != NULL) + (void)freestr(current_options->hostname); + current_options->hostname = $2; + } + | T_VERSION L_QSTRING + { + if (current_options->version != NULL) + (void)freestr(current_options->version); + current_options->version = $2; + } + | T_DIRECTORY L_QSTRING + { + if (current_options->directory != NULL) + (void)freestr(current_options->directory); + current_options->directory = $2; + } + | T_NAMED_XFER L_QSTRING + { + if (current_options->named_xfer != NULL) + (void)freestr(current_options->named_xfer); + current_options->named_xfer = $2; + } + | T_PIDFILE L_QSTRING + { + if (current_options->pid_filename != NULL) + (void)freestr(current_options->pid_filename); + current_options->pid_filename = $2; + } + | T_STATS_FILE L_QSTRING + { + if (current_options->stats_filename != NULL) + (void)freestr(current_options->stats_filename); + current_options->stats_filename = $2; + } + | T_MEMSTATS_FILE L_QSTRING + { + if (current_options->memstats_filename != NULL) + (void)freestr(current_options->memstats_filename); + current_options->memstats_filename = $2; + } + | T_DUMP_FILE L_QSTRING + { + if (current_options->dump_filename != NULL) + (void)freestr(current_options->dump_filename); + current_options->dump_filename = $2; + } + | T_PREFERRED_GLUE L_STRING + { + current_options->preferred_glue = + strcasecmp($2, "aaaa") ? T_A : T_AAAA; + } + | T_FAKE_IQUERY yea_or_nay + { + set_global_boolean_option(current_options, + OPTION_FAKE_IQUERY, $2); + } + | T_RECURSION yea_or_nay + { + set_global_boolean_option(current_options, + OPTION_NORECURSE, !$2); + } + | T_FETCH_GLUE yea_or_nay + { + set_global_boolean_option(current_options, + OPTION_NOFETCHGLUE, !$2); + } + | T_HITCOUNT yea_or_nay + { + set_global_boolean_option(current_options, + OPTION_HITCOUNT, $2); + } + | T_NOTIFY T_EXPLICIT + { + current_options->notify = notify_explicit; + } + | T_NOTIFY yea_or_nay + { + if ($2) + current_options->notify = notify_yes; + else + current_options->notify = notify_no; + } + | T_NOTIFY_INITIAL yea_or_nay + { + if (initial_configuration && $2) + ns_notice(ns_log_default, + "suppressing initial notifies"); + set_global_boolean_option(current_options, + OPTION_SUPNOTIFY_INITIAL, $2); + } + | T_HOSTSTATS yea_or_nay + { + set_global_boolean_option(current_options, + OPTION_HOSTSTATS, $2); + } + | T_DEALLOC_ON_EXIT yea_or_nay + { + set_global_boolean_option(current_options, + OPTION_DEALLOC_ON_EXIT, $2); + } + | T_USE_IXFR yea_or_nay + { + set_global_boolean_option(current_options, OPTION_USE_IXFR, $2); + } + | T_MAINTAIN_IXFR_BASE yea_or_nay + { + set_global_boolean_option(current_options, + OPTION_MAINTAIN_IXFR_BASE, $2); + } + | T_HAS_OLD_CLIENTS yea_or_nay + { + set_global_boolean_option(current_options, + OPTION_NORFC2308_TYPE1, $2); + set_global_boolean_option(current_options, + OPTION_NONAUTH_NXDOMAIN, !$2); + } + | T_AUTH_NXDOMAIN yea_or_nay + { + set_global_boolean_option(current_options, OPTION_NONAUTH_NXDOMAIN, + !$2); + } + | T_MULTIPLE_CNAMES yea_or_nay + { + set_global_boolean_option(current_options, + OPTION_MULTIPLE_CNAMES, $2); + } + | T_CHECK_NAMES check_names_type check_names_opt + { + current_options->check_names[$2] = (enum severity)$3; + } + | T_USE_ID_POOL yea_or_nay + { + set_global_boolean_option(current_options, + OPTION_USE_ID_POOL, $2); + } + | T_RFC2308_TYPE1 yea_or_nay + { + set_global_boolean_option(current_options, + OPTION_NORFC2308_TYPE1, !$2); + } + | T_LISTEN_ON maybe_port '{' address_match_list '}' + { + char port_string[10]; + symbol_value value; + + (void)sprintf(port_string, "%u", $2); + if (lookup_symbol(symtab, port_string, SYM_PORT, NULL)) + parser_error(0, + "cannot redefine listen-on for port %u", + ntohs($2)); + else { + add_listen_on(current_options, $2, $4); + value.pointer = NULL; + define_symbol(symtab, port_string, SYM_PORT, value, 0); + } + + } + | T_FORWARD forward_opt + | T_FORWARDERS + { + if (current_options->fwdtab) { + free_forwarders(current_options->fwdtab); + current_options->fwdtab = NULL; + } + } + '{' opt_forwarders_list '}' + | T_QUERY_SOURCE query_source + | T_TRANSFER_SOURCE maybe_wild_addr + { + current_options->axfr_src = $2; + } + | T_ALLOW_QUERY '{' address_match_list '}' + { + if (current_options->query_acl) { + parser_warning(0, + "options allow-query acl already set; skipping"); + free_ip_match_list($3); + } else + current_options->query_acl = $3; + } + | T_ALLOW_RECURSION '{' address_match_list '}' + { + if (current_options->recursion_acl) { + parser_warning(0, + "options allow-recursion acl already set; skipping"); + free_ip_match_list($3); + } else + current_options->recursion_acl = $3; + } + | T_ALLOW_TRANSFER '{' address_match_list '}' + { + if (current_options->transfer_acl) { + parser_warning(0, + "options allow-transfer acl already set; skipping"); + free_ip_match_list($3); + } else + current_options->transfer_acl = $3; + } + | T_SORTLIST '{' address_match_list '}' + { + if (current_options->sortlist) { + parser_warning(0, + "options sortlist already set; skipping"); + free_ip_match_list($3); + } else + current_options->sortlist = $3; + } + | T_ALSO_NOTIFY + { + if (current_options->also_notify) { + parser_warning(0, + "duplicate also-notify clause: overwriting"); + free_also_notify(current_options); + current_options->also_notify = NULL; + } + } + '{' opt_also_notify_list '}' + | T_BLACKHOLE '{' address_match_list '}' + { + if (current_options->blackhole_acl) { + parser_warning(0, + "options blackhole already set; skipping"); + free_ip_match_list($3); + } else + current_options->blackhole_acl = $3; + } + | T_TOPOLOGY '{' address_match_list '}' + { + if (current_options->topology) { + parser_warning(0, + "options topology already set; skipping"); + free_ip_match_list($3); + } else + current_options->topology = $3; + } + | size_clause + { + /* To get around the $$ = $1 default rule. */ + } + | transfer_clause + | T_TRANSFER_FORMAT transfer_format + { + current_options->transfer_format = $2; + } + | T_MAX_TRANSFER_TIME_IN L_NUMBER + { + current_options->max_transfer_time_in = $2 * 60; + } + | T_SERIAL_QUERIES L_NUMBER + { + current_options->serial_queries = $2; + } + | T_CLEAN_INTERVAL L_NUMBER + { + current_options->clean_interval = $2 * 60; + } + | T_INTERFACE_INTERVAL L_NUMBER + { + current_options->interface_interval = $2 * 60; + } + | T_STATS_INTERVAL L_NUMBER + { + current_options->stats_interval = $2 * 60; + } + | T_HOSTSTATSMAX L_NUMBER + { + current_options->max_host_stats = $2; + } + | T_MAX_LOG_SIZE_IXFR size_spec + { + current_options->max_log_size_ixfr = $2; + } + | T_MAX_NCACHE_TTL L_NUMBER + { + current_options->max_ncache_ttl = $2; + } + | T_LAME_TTL L_NUMBER + { + current_options->lame_ttl = $2; + } + | T_HEARTBEAT L_NUMBER + { + current_options->heartbeat_interval = $2 * 60; + } + | T_DIALUP yea_or_nay + { + set_global_boolean_option(current_options, + OPTION_NODIALUP, !$2); + } + | T_RRSET_ORDER '{' rrset_ordering_list '}' + { + if (current_options->ordering) + free_rrset_order_list(current_options->ordering); + current_options->ordering = $3; + } + | T_TREAT_CR_AS_SPACE yea_or_nay + { + set_global_boolean_option(current_options, + OPTION_TREAT_CR_AS_SPACE, $2); + } + | T_MIN_ROOTS L_NUMBER + { + if ($2 >= 1) + current_options->minroots = $2; + } + | error + ; + +/* + * Controls. + */ +controls_stmt: T_CONTROLS '{' controls '}' + ; + +controls: control L_EOS + | controls control L_EOS + ; + +control: /* Empty */ + | T_INET maybe_wild_addr T_PORT in_port + T_ALLOW '{' address_match_list '}' + { + ns_ctl_add(¤t_controls, ns_ctl_new_inet($2, $4, $7)); + } + | T_INET maybe_wild_addr + T_ALLOW '{' address_match_list '}' + T_KEYS '{' dummy_key_list '}' + { + parser_warning(0, "Ignoring BIND 9 inet control clause"); + free_ip_match_list($5); + } + | T_INET maybe_wild_addr T_PORT in_port + T_ALLOW '{' address_match_list '}' + T_KEYS '{' dummy_key_list '}' + { + parser_warning(0, "Ignoring BIND 9 inet control clause"); + free_ip_match_list($7); + } + | T_UNIX L_QSTRING T_PERM L_NUMBER T_OWNER L_NUMBER T_GROUP L_NUMBER + { +#ifndef NO_SOCKADDR_UN + ns_ctl_add(¤t_controls, ns_ctl_new_unix($2, $4, $6, $8)); +#endif + freestr($2); + } + | error + ; + +rrset_ordering_list: rrset_ordering_element L_EOS + { + rrset_order_list rol; + + rol = new_rrset_order_list(); + if ($1 != NULL) { + add_to_rrset_order_list(rol, $1); + } + + $$ = rol; + } + | rrset_ordering_list rrset_ordering_element L_EOS + { + if ($2 != NULL) { + add_to_rrset_order_list($1, $2); + } + $$ = $1; + } + ; + +ordering_class: /* nothing */ + { + $$ = C_ANY; + } + | T_CLASS any_string + { + symbol_value value; + + if (lookup_symbol(constants, $2, SYM_CLASS, &value)) + $$ = value.integer; + else { + parser_error(0, "unknown class '%s'; using ANY", $2); + $$ = C_ANY; + } + (void)freestr($2); + } + ; + +ordering_type: /* nothing */ + { + $$ = ns_t_any; + } + | T_TYPE any_string + { + int success; + + if (strcmp($2, "*") == 0) { + $$ = ns_t_any; + } else { + $$ = __sym_ston(__p_type_syms, $2, &success); + if (success == 0) { + $$ = ns_t_any; + parser_error(0, + "unknown type '%s'; assuming ANY", + $2); + } + } + (void)freestr($2); + } + +ordering_name: /* nothing */ + { + $$ = savestr("*", 1); + } + | T_NAME L_QSTRING + { + if (strcmp(".",$2) == 0 || strcmp("*.",$2) == 0) { + $$ = savestr("*", 1); + (void)freestr($2); + } else { + $$ = $2 ; + } + /* XXX Should do any more name validation here? */ + } + + +rrset_ordering_element: ordering_class ordering_type ordering_name T_ORDER L_STRING + { + enum ordering o; + + if (strlen($5) == 0) { + parser_error(0, "null order name"); + $$ = NULL ; + } else { + o = lookup_ordering($5); + if (o == unknown_order) { + o = (enum ordering)DEFAULT_ORDERING; + parser_error(0, + "invalid order name '%s'; using %s", + $5, p_order(o)); + } + + (void)freestr($5); + + $$ = new_rrset_order_element($1, $2, $3, o); + } + } + + +transfer_format: T_ONE_ANSWER + { + $$ = axfr_one_answer; + } + | T_MANY_ANSWERS + { + $$ = axfr_many_answers; + } + ; + +maybe_wild_addr: L_IPADDR { $$ = $1; } + | '*' { $$.s_addr = htonl(INADDR_ANY); } + ; + +maybe_wild_port: in_port { $$ = $1; } + | '*' { $$ = htons(0); } + ; + +query_source_address: T_ADDRESS maybe_wild_addr + { + current_options->query_source.sin_addr = $2; + } + ; + +query_source_port: T_PORT maybe_wild_port + { + current_options->query_source.sin_port = $2; + } + ; + +query_source: query_source_address + | query_source_port + | query_source_address query_source_port + | query_source_port query_source_address + ; + +maybe_port: /* nothing */ { $$ = htons(NS_DEFAULTPORT); } + | T_PORT in_port { $$ = $2; } + ; + +maybe_zero_port: /* nothing */ { $$ = htons(0); } + | T_PORT in_port { $$ = $2; } + ; + + +yea_or_nay: T_YES + { + $$ = 1; + } + | T_TRUE + { + $$ = 1; + } + | T_NO + { + $$ = 0; + } + | T_FALSE + { + $$ = 0; + } + | L_NUMBER + { + if ($1 == 1 || $1 == 0) { + $$ = $1; + } else { + parser_warning(0, + "number should be 0 or 1; assuming 1"); + $$ = 1; + } + } + ; + +check_names_type: T_MASTER + { + $$ = primary_trans; + } + | T_SLAVE + { + $$ = secondary_trans; + } + | T_RESPONSE + { + $$ = response_trans; + } + ; + +check_names_opt: T_WARN + { + $$ = warn; + } + | T_FAIL + { + $$ = fail; + } + | T_IGNORE + { + $$ = ignore; + } + ; + +forward_opt: T_ONLY + { + set_global_boolean_option(current_options, + OPTION_FORWARD_ONLY, 1); + } + | T_FIRST + { + set_global_boolean_option(current_options, + OPTION_FORWARD_ONLY, 0); + } + | T_IF_NO_ANSWER + { + parser_warning(0, "forward if-no-answer is unimplemented"); + } + | T_IF_NO_DOMAIN + { + parser_warning(0, "forward if-no-domain is unimplemented"); + } + ; + +size_clause: T_DATASIZE size_spec + { + current_options->data_size = $2; + } + | T_STACKSIZE size_spec + { + current_options->stack_size = $2; + } + | T_CORESIZE size_spec + { + current_options->core_size = $2; + } + | T_FILES size_spec + { + current_options->files = $2; + } + ; + +size_spec: any_string + { + u_long result; + + if (unit_to_ulong($1, &result)) + $$ = result; + else { + parser_error(0, "invalid unit string '%s'", $1); + /* 0 means "use default" */ + $$ = 0; + } + (void)freestr($1); + } + | L_NUMBER + { + $$ = (u_long)$1; + } + | T_DEFAULT + { + $$ = 0; + } + | T_UNLIMITED + { + $$ = ULONG_MAX; + } + ; + +transfer_clause: T_TRANSFERS_IN L_NUMBER + { + current_options->transfers_in = (u_long) $2; + } + | T_TRANSFERS_OUT L_NUMBER + { + current_options->transfers_out = (u_long) $2; + } + | T_TRANSFERS_PER_NS L_NUMBER + { + current_options->transfers_per_ns = (u_long) $2; + } + ; + +opt_forwarders_list: /* nothing */ + | forwarders_in_addr_list + ; + +forwarders_in_addr_list: forwarders_in_addr L_EOS + { + /* nothing */ + } + | forwarders_in_addr_list forwarders_in_addr L_EOS + { + /* nothing */ + } + ; + +forwarders_in_addr: L_IPADDR + { + add_global_forwarder(current_options, $1); + } + ; + +opt_also_notify_list: /* nothing */ + | also_notify_in_addr_list + ; + +also_notify_in_addr_list: also_notify_in_addr L_EOS + { + /* nothing */ + } + | also_notify_in_addr_list also_notify_in_addr L_EOS + { + /* nothing */ + } + ; + +also_notify_in_addr: L_IPADDR + { + add_global_also_notify(current_options, $1); + } + ; + +/* + * Logging + */ + +logging_stmt: T_LOGGING + { + current_logging = begin_logging(); + } + '{' logging_opts_list '}' + { + end_logging(current_logging, 1); + current_logging = NULL; + } + ; + +logging_opts_list: logging_opt L_EOS + | logging_opts_list logging_opt L_EOS + | error + ; + +logging_opt: T_CATEGORY category + { + current_category = $2; + } + '{' channel_list '}' + | T_CHANNEL channel_name + { + chan_type = log_null; + chan_flags = 0; + chan_level = log_info; + } + '{' channel_opt_list '}' + { + log_channel current_channel = NULL; + + if (lookup_channel($2) != NULL) { + parser_error(0, "can't redefine channel '%s'", $2); + } else { + switch (chan_type) { + case log_file: + current_channel = + log_new_file_channel(chan_flags, + chan_level, + chan_name, NULL, + chan_versions, + chan_max_size); + log_set_file_owner(current_channel, + user_id, group_id); + chan_name = freestr(chan_name); + break; + case log_syslog: + current_channel = + log_new_syslog_channel(chan_flags, + chan_level, + chan_facility); + break; + case log_null: + current_channel = log_new_null_channel(); + break; + default: + ns_panic(ns_log_parser, 1, + "unknown channel type: %d", + chan_type); + } + if (current_channel == NULL) + ns_panic(ns_log_parser, 0, + "couldn't create channel"); + define_channel($2, current_channel); + } + (void)freestr($2); + } + ; + +channel_severity: any_string + { + symbol_value value; + + if (lookup_symbol(constants, $1, SYM_LOGGING, &value)) { + chan_level = value.integer; + } else { + parser_error(0, "unknown severity '%s'", $1); + chan_level = log_debug(99); + } + (void)freestr($1); + } + | T_DEBUG + { + chan_level = log_debug(1); + } + | T_DEBUG L_NUMBER + { + chan_level = $2; + } + | T_DYNAMIC + { + chan_level = 0; + chan_flags |= LOG_USE_CONTEXT_LEVEL|LOG_REQUIRE_DEBUG; + } + ; + +version_modifier: T_VERSIONS L_NUMBER + { + chan_versions = $2; + } + | T_VERSIONS T_UNLIMITED + { + chan_versions = LOG_MAX_VERSIONS; + } + ; + +size_modifier: T_SIZE size_spec + { + chan_max_size = $2; + } + ; + +maybe_file_modifiers: /* nothing */ + { + chan_versions = 0; + chan_max_size = ULONG_MAX; + } + | version_modifier + { + chan_max_size = ULONG_MAX; + } + | size_modifier + { + chan_versions = 0; + } + | version_modifier size_modifier + | size_modifier version_modifier + ; + +channel_file: T_FILE L_QSTRING maybe_file_modifiers + { + chan_flags |= LOG_CLOSE_STREAM; + chan_type = log_file; + chan_name = $2; + } + ; + + +facility_name: any_string { $$ = $1; } + | T_SYSLOG { $$ = savestr("syslog", 1); } + ; + +maybe_syslog_facility: /* nothing */ { $$ = LOG_DAEMON; } + | facility_name + { + symbol_value value; + + if (lookup_symbol(constants, $1, SYM_SYSLOG, &value)) { + $$ = value.integer; + } else { + parser_error(0, "unknown facility '%s'", $1); + $$ = LOG_DAEMON; + } + (void)freestr($1); + } + ; + +channel_syslog: T_SYSLOG maybe_syslog_facility + { + chan_type = log_syslog; + chan_facility = $2; + } + ; + +channel_opt: channel_file { /* nothing to do */ } + | channel_syslog { /* nothing to do */ } + | T_NULL_OUTPUT + { + chan_type = log_null; + } + | T_SEVERITY channel_severity { /* nothing to do */ } + | T_PRINT_TIME yea_or_nay + { + if ($2) + chan_flags |= LOG_TIMESTAMP; + else + chan_flags &= ~LOG_TIMESTAMP; + } + | T_PRINT_CATEGORY yea_or_nay + { + if ($2) + chan_flags |= LOG_PRINT_CATEGORY; + else + chan_flags &= ~LOG_PRINT_CATEGORY; + } + | T_PRINT_SEVERITY yea_or_nay + { + if ($2) + chan_flags |= LOG_PRINT_LEVEL; + else + chan_flags &= ~LOG_PRINT_LEVEL; + } + ; + +channel_opt_list: channel_opt L_EOS + | channel_opt_list channel_opt L_EOS + | error + ; + +channel_name: any_string + | T_NULL_OUTPUT { $$ = savestr("null", 1); } + ; + +channel: channel_name + { + log_channel channel; + + if (current_category >= 0) { + channel = lookup_channel($1); + if (channel != NULL) { + add_log_channel(current_logging, + current_category, channel); + } else + parser_error(0, "unknown channel '%s'", $1); + } + (void)freestr($1); + } + ; + +channel_list: channel L_EOS + | channel_list channel L_EOS + | error + ; + +category_name: any_string + | T_DEFAULT { $$ = savestr("default", 1); } + | T_NOTIFY { $$ = savestr("notify", 1); } + ; + +category: category_name + { + symbol_value value; + + if (lookup_symbol(constants, $1, SYM_CATEGORY, &value)) + $$ = value.integer; + else { + parser_error(0, "invalid logging category '%s'", + $1); + $$ = -1; + } + (void)freestr($1); + } + ; + +/* + * Server Information + */ + +server_stmt: T_SERVER L_IPADDR + { + const char *ip_printable; + symbol_value value; + + ip_printable = inet_ntoa($2); + value.pointer = NULL; + if (lookup_symbol(symtab, ip_printable, SYM_SERVER, NULL)) + seen_server = 1; + else + seen_server = 0; + if (seen_server) + parser_error(0, "cannot redefine server '%s'", + ip_printable); + else + define_symbol(symtab, ip_printable, SYM_SERVER, value, + 0); + current_server = begin_server($2); + } + '{' server_info_list '}' + { + end_server(current_server, !seen_server); + } + ; + +server_info_list: server_info L_EOS + | server_info_list server_info L_EOS + ; + +server_info: T_BOGUS yea_or_nay + { + set_server_option(current_server, SERVER_INFO_BOGUS, $2); + } + | T_SUPPORT_IXFR yea_or_nay + { + set_server_option(current_server, SERVER_INFO_SUPPORT_IXFR, $2); + } + | T_TRANSFERS L_NUMBER + { + set_server_transfers(current_server, (int)$2); + } + | T_TRANSFER_FORMAT transfer_format + { + set_server_transfer_format(current_server, $2); + } + | T_KEYS '{' key_list '}' + | T_EDNS yea_or_nay + { + set_server_option(current_server, SERVER_INFO_EDNS, $2); + } + | error + ; + +/* + * Address Matching + */ + +address_match_list: address_match_element L_EOS + { + ip_match_list iml; + + iml = new_ip_match_list(); + if ($1 != NULL) + add_to_ip_match_list(iml, $1); + $$ = iml; + } + | address_match_list address_match_element L_EOS + { + if ($2 != NULL) + add_to_ip_match_list($1, $2); + $$ = $1; + } + ; + +address_match_element: address_match_simple + | '!' address_match_simple + { + if ($2 != NULL) + ip_match_negate($2); + $$ = $2; + } + | T_SEC_KEY L_STRING + { + char *key_name; + struct dst_key *dst_key; + + key_name = canonical_name($2); + if (key_name == NULL) { + parser_error(0, "can't make key name '%s' canonical", + $2); + key_name = savestr("__bad_key__", 1); + } + dst_key = find_key(key_name, NULL); + if (dst_key == NULL) { + parser_error(0, "key \"%s\" not found", key_name); + $$ = NULL; + } + else + $$ = new_ip_match_key(dst_key); + (void)freestr(key_name); + freestr($2); + } + ; + +address_match_simple: L_IPADDR + { + $$ = new_ip_match_pattern($1, 32); + } + | L_IPADDR '/' L_NUMBER + { + if ($3 < 0 || $3 > 32) { + parser_error(0, "mask bits out of range; skipping"); + $$ = NULL; + } else { + $$ = new_ip_match_pattern($1, $3); + if ($$ == NULL) + parser_error(0, + "address/mask mismatch; skipping"); + } + } + | L_NUMBER '/' L_NUMBER + { + struct in_addr ia; + + if ($1 > 255) { + parser_error(0, "address out of range; skipping"); + $$ = NULL; + } else { + if ($3 < 0 || $3 > 32) { + parser_error(0, + "mask bits out of range; skipping"); + $$ = NULL; + } else { + ia.s_addr = htonl(($1 & 0xff) << 24); + $$ = new_ip_match_pattern(ia, $3); + if ($$ == NULL) + parser_error(0, + "address/mask mismatch; skipping"); + } + } + } + | address_name + | '{' address_match_list '}' + { + char name[256]; + + /* + * We want to be able to clean up this iml later so + * we give it a name and treat it like any other acl. + */ + sprintf(name, "__internal_%p", $2); + define_acl(name, $2); + $$ = new_ip_match_indirect($2); + } + ; + +address_name: any_string + { + ip_match_list iml; + + iml = lookup_acl($1); + if (iml == NULL) { + parser_error(0, "unknown ACL '%s'", $1); + $$ = NULL; + } else + $$ = new_ip_match_indirect(iml); + (void)freestr($1); + } + ; + +/* + * Keys + */ + +key_ref: any_string + { + struct dst_key *dst_key; + char *key_name; + + key_name = canonical_name($1); + if (key_name == NULL) { + parser_error(0, "can't make key name '%s' canonical", + $1); + $$ = NULL; + } else { + dst_key = lookup_key(key_name); + if (dst_key == NULL) { + parser_error(0, "unknown key '%s'", key_name); + $$ = NULL; + } else + $$ = dst_key; + key_name = freestr(key_name); + } + (void)freestr($1); + } + ; + +key_list_element: key_ref + { + if ($1 == NULL) + parser_error(0, "empty key not added to server list "); + else + add_server_key_info(current_server, $1); + } + ; + +key_list: key_list_element L_EOS + | key_list key_list_element L_EOS + | error + ; + +dummy_key_list_element: key_ref; + +dummy_key_list: dummy_key_list_element L_EOS + | dummy_key_list dummy_key_list_element L_EOS + | error + ; + +key_stmt: T_SEC_KEY + { + current_algorithm = NULL; + current_secret = NULL; + } + any_string '{' key_definition '}' + { + struct dst_key *dst_key; + char *key_name; + + key_name = canonical_name($3); + if (key_name == NULL) { + parser_error(0, "can't make key name '%s' canonical", + $3); + } else if (lookup_key(key_name) != NULL) { + parser_error(0, "can't redefine key '%s'", key_name); + } else { + if (current_algorithm == NULL || + current_secret == NULL) { + parser_error(0, "skipping bad key '%s'", + key_name); + } else { + dst_key = new_key_info(key_name, + current_algorithm, + current_secret); + if (dst_key != NULL) { + define_key(key_name, dst_key); + if (secretkey_info == NULL) + secretkey_info = + new_key_info_list(); + add_to_key_info_list(secretkey_info, + dst_key); + } + } + } + if (key_name != NULL) + key_name = freestr(key_name); + if (current_algorithm != NULL) + current_algorithm = freestr(current_algorithm); + if (current_secret != NULL) + current_secret = freestr(current_secret); + (void)freestr($3); + } + ; + +key_definition: algorithm_id secret + { + current_algorithm = $1; + current_secret = $2; + } + | secret algorithm_id + { + current_algorithm = $2; + current_secret = $1; + } + | error + { + current_algorithm = NULL; + current_secret = NULL; + } + ; + +algorithm_id: T_ALGID any_string L_EOS { $$ = $2; } + ; + +secret: T_SECRET any_string L_EOS { $$ = $2; } + ; + +/* + * ACLs + */ + +acl_stmt: T_ACL any_string '{' address_match_list '}' + { + if (lookup_acl($2) != NULL) { + parser_error(0, "can't redefine ACL '%s'", $2); + } else + define_acl($2, $4); + (void)freestr($2); + } + ; + +/* + * Zones + */ + +zone_stmt: T_ZONE L_QSTRING optional_class + { + int sym_type; + symbol_value value; + char *zone_name; + + if (!seen_options && !logged_options_error) { + parser_error(0, + "no options statement before first zone; using previous/default"); + logged_options_error = 1; + } + sym_type = SYM_ZONE | ($3 & 0xffff); + value.pointer = NULL; + zone_name = canonical_name($2); + if (zone_name == NULL) { + parser_error(0, "can't make zone name '%s' canonical", + $2); + should_install = 0; + zone_name = savestr("__bad_zone__", 1); + } else { + if (lookup_symbol(symtab, zone_name, sym_type, NULL)) { + should_install = 0; + parser_error(0, + "cannot redefine zone '%s' class %s", + *zone_name ? zone_name : ".", + p_class($3)); + } else { + should_install = 1; + define_symbol(symtab, zone_name, sym_type, + value, 0); + } + } + (void)freestr($2); + current_zone = begin_zone(zone_name, $3); + } + optional_zone_options_list + { + end_zone(current_zone, should_install); + } + ; + +optional_zone_options_list: /* Empty */ + | '{' zone_option_list '}' + ; + +optional_class: /* Empty */ + { + $$ = C_IN; + } + | any_string + { + symbol_value value; + + if (lookup_symbol(constants, $1, SYM_CLASS, &value)) + $$ = value.integer; + else { + /* the zone validator will give the error */ + $$ = C_NONE; + } + (void)freestr($1); + } + ; + +zone_type: T_MASTER + { + $$ = Z_MASTER; + } + | T_SLAVE + { + $$ = Z_SLAVE; + } + | T_HINT + { + $$ = Z_HINT; + } + | T_STUB + { + $$ = Z_STUB; + } + | T_FORWARD + { + $$ = Z_FORWARD; + } + ; + +zone_option_list: zone_option L_EOS + | zone_option_list zone_option L_EOS + ; + +zone_option: T_TYPE zone_type + { + if (!set_zone_type(current_zone, $2)) + parser_warning(0, "zone type already set; skipping"); + } + | T_FILE L_QSTRING + { + if (!set_zone_filename(current_zone, $2)) + parser_warning(0, + "zone filename already set; skipping"); + } + | T_FILE_IXFR L_QSTRING + { + if (!set_zone_ixfr_file(current_zone, $2)) + parser_warning(0, + "zone ixfr data base already set; skipping"); + } + | T_IXFR_TMP L_QSTRING + { + if (!set_zone_ixfr_tmp(current_zone, $2)) + parser_warning(0, + "zone ixfr temp filename already set; skipping"); + } + | T_MASTERS maybe_zero_port '{' master_in_addr_list '}' + { + set_zone_master_port(current_zone, $2); + } + | T_TRANSFER_SOURCE maybe_wild_addr + { + set_zone_transfer_source(current_zone, $2); + } + | T_CHECK_NAMES check_names_opt + { + if (!set_zone_checknames(current_zone, (enum severity)$2)) + parser_warning(0, + "zone checknames already set; skipping"); + } + | T_ALLOW_UPDATE '{' address_match_list '}' + { + if (!set_zone_update_acl(current_zone, $3)) + parser_warning(0, + "zone update acl already set; skipping"); + } + | T_ALLOW_QUERY '{' address_match_list '}' + { + if (!set_zone_query_acl(current_zone, $3)) + parser_warning(0, + "zone query acl already set; skipping"); + } + | T_ALLOW_TRANSFER '{' address_match_list '}' + { + if (!set_zone_transfer_acl(current_zone, $3)) + parser_warning(0, + "zone transfer acl already set; skipping"); + } + | T_FORWARD zone_forward_opt + | T_FORWARDERS + { + struct zoneinfo *zp = current_zone.opaque; + if (zp->z_fwdtab) { + free_forwarders(zp->z_fwdtab); + zp->z_fwdtab = NULL; + } + + } + '{' opt_zone_forwarders_list '}' + | T_MAX_TRANSFER_TIME_IN L_NUMBER + { + if (!set_zone_transfer_time_in(current_zone, $2*60)) + parser_warning(0, + "zone max transfer time (in) already set; skipping"); + } + | T_MAX_LOG_SIZE_IXFR size_spec + { + set_zone_max_log_size_ixfr(current_zone, $2); + } + | T_NOTIFY T_EXPLICIT + { + set_zone_notify(current_zone, notify_explicit); + } + | T_NOTIFY yea_or_nay + { + if ($2) + set_zone_notify(current_zone, notify_yes); + else + set_zone_notify(current_zone, notify_no); + } + | T_MAINTAIN_IXFR_BASE yea_or_nay + { + set_zone_maintain_ixfr_base(current_zone, $2); + } + | T_PUBKEY L_NUMBER L_NUMBER L_NUMBER L_QSTRING + { + /* flags proto alg key */ + set_zone_pubkey(current_zone, $2, $3, $4, $5); + } + | T_PUBKEY L_STRING L_NUMBER L_NUMBER L_QSTRING + { + /* flags proto alg key */ + char *endp; + int flags = (int) strtol($2, &endp, 0); + if (*endp != '\0') + ns_panic(ns_log_parser, 1, + "Invalid flags string: %s", $2); + set_zone_pubkey(current_zone, flags, $3, $4, $5); + + } + | T_ALSO_NOTIFY '{' opt_notify_in_addr_list '}' + | T_DIALUP yea_or_nay + { + set_zone_dialup(current_zone, $2); + } + | error + ; + +master_in_addr_list: master_in_addr L_EOS + { + /* nothing */ + } + | master_in_addr_list master_in_addr L_EOS + { + /* nothing */ + } + ; + +master_in_addr: L_IPADDR + { + add_zone_master(current_zone, $1, NULL); + } + | L_IPADDR T_SEC_KEY key_ref + { + add_zone_master(current_zone, $1, $3); + } + ; + +opt_notify_in_addr_list: /* nothing */ + | notify_in_addr_list + ; + +notify_in_addr_list: notify_in_addr L_EOS + { + /* nothing */ + } + | notify_in_addr_list notify_in_addr L_EOS + { + /* nothing */ + } + ; + +notify_in_addr: L_IPADDR + { + add_zone_notify(current_zone, $1); + } + ; + +zone_forward_opt: T_ONLY + { + set_zone_boolean_option(current_zone, OPTION_FORWARD_ONLY, 1); + } + | T_FIRST + { + set_zone_boolean_option(current_zone, OPTION_FORWARD_ONLY, 0); + } + ; + +opt_zone_forwarders_list: /* nothing */ + { + set_zone_forward(current_zone); + } + | zone_forwarders_in_addr_list + ; + +zone_forwarders_in_addr_list: zone_forwarders_in_addr L_EOS + { + /* nothing */ + } + | zone_forwarders_in_addr_list zone_forwarders_in_addr L_EOS + { + /* nothing */ + } + ; + +zone_forwarders_in_addr: L_IPADDR + { + add_zone_forwarder(current_zone, $1); + } + ; + +/* + * Trusted Key statement + */ + +trusted_keys_stmt: T_TRUSTED_KEYS '{' trusted_keys_list '}' + { + } + ; +trusted_keys_list: trusted_key L_EOS + { + /* nothing */ + } + | trusted_keys_list trusted_key L_EOS + { + /* nothing */ + } + ; +trusted_key: L_STRING L_NUMBER L_NUMBER L_NUMBER L_QSTRING + { + /* name flags proto alg key */ + set_trusted_key($1, $2, $3, $4, $5); + } + | L_STRING L_STRING L_NUMBER L_NUMBER L_QSTRING + { + /* name flags proto alg key */ + char *endp; + int flags = (int) strtol($2, &endp, 0); + if (*endp != '\0') + ns_panic(ns_log_parser, 1, + "Invalid flags string: %s", $2); + set_trusted_key($1, flags, $3, $4, $5); + } + ; + +/* + * Misc. + */ + +in_port: L_NUMBER + { + if ($1 < 0 || $1 > 65535) { + parser_warning(0, + "invalid IP port number '%d'; setting port to 0", + (int)$1); + $1 = 0; + } else + $$ = htons($1); + } + ; + +any_string: L_STRING + | L_QSTRING + ; + +%% + +static char * +canonical_name(char *name) { + char canonical[MAXDNAME]; + + if (strlen(name) >= MAXDNAME) + return (NULL); + strcpy(canonical, name); + if (makename(canonical, ".", sizeof canonical) < 0) + return (NULL); + return (savestr(canonical, 0)); +} + +static void +init_acls() { + ip_match_element ime; + ip_match_list iml; + struct in_addr address; + + /* Create the predefined ACLs */ + + address.s_addr = 0U; + + /* ACL "any" */ + ime = new_ip_match_pattern(address, 0); + iml = new_ip_match_list(); + add_to_ip_match_list(iml, ime); + define_acl("any", iml); + + /* ACL "none" */ + ime = new_ip_match_pattern(address, 0); + ip_match_negate(ime); + iml = new_ip_match_list(); + add_to_ip_match_list(iml, ime); + define_acl("none", iml); + + /* ACL "localhost" */ + ime = new_ip_match_localhost(); + iml = new_ip_match_list(); + add_to_ip_match_list(iml, ime); + define_acl("localhost", iml); + + /* ACL "localnets" */ + ime = new_ip_match_localnets(); + iml = new_ip_match_list(); + add_to_ip_match_list(iml, ime); + define_acl("localnets", iml); +} + +static void +free_sym_value(int type, void *value) { + ns_debug(ns_log_parser, 99, "free_sym_value: type %06x value %p", + type, value); + type &= ~0xffff; + switch (type) { + case SYM_ACL: + free_ip_match_list(value); + break; + case SYM_KEY: + free_key_info(value); + break; + case SYM_CHANNEL: + INSIST(log_free_channel(value) == 0); + break; + default: + ns_panic(ns_log_parser, 1, + "unhandled case in free_sym_value()"); + /* NOTREACHED */ + break; + } +} + +static log_channel +lookup_channel(char *name) { + symbol_value value; + + if (lookup_symbol(channeltab, name, SYM_CHANNEL, &value)) + return ((log_channel)(value.pointer)); + return (NULL); +} + +static void +define_channel(const char *name, log_channel channel) { + symbol_value value; + + value.pointer = channel; + INSIST(log_inc_references(channel) == 0); + define_symbol(channeltab, name, SYM_CHANNEL, value, SYMBOL_FREE_VALUE); +} + +static void +define_builtin_channels() { + define_channel("default_syslog", syslog_channel); + define_channel("default_debug", debug_channel); + define_channel("default_stderr", stderr_channel); + define_channel("null", null_channel); +} + +static void +parser_setup() { + seen_options = 0; + logged_options_error = 0; + seen_topology = 0; + symtab = new_symbol_table(SYMBOL_TABLE_SIZE, NULL); + if (authtab != NULL) + free_symbol_table(authtab); + authtab = new_symbol_table(AUTH_TABLE_SIZE, free_sym_value); + if (channeltab != NULL) + free_symbol_table(channeltab); + channeltab = new_symbol_table(AUTH_TABLE_SIZE, free_sym_value); + init_acls(); + define_builtin_channels(); + INIT_LIST(current_controls); +} + +static void +parser_cleanup() { + if (symtab != NULL) + free_symbol_table(symtab); + symtab = NULL; + /* + * We don't clean up authtab here because the ip_match_lists are in + * use. + */ +} + +/* + * Public Interface + */ + +ip_match_list +lookup_acl(const char *name) { + symbol_value value; + + if (lookup_symbol(authtab, name, SYM_ACL, &value)) + return ((ip_match_list)(value.pointer)); + return (NULL); +} + +void +define_acl(const char *name, ip_match_list iml) { + symbol_value value; + + INSIST(name != NULL); + INSIST(iml != NULL); + + value.pointer = iml; + define_symbol(authtab, name, SYM_ACL, value, SYMBOL_FREE_VALUE); + ns_debug(ns_log_parser, 7, "acl %s", name); + dprint_ip_match_list(ns_log_parser, iml, 2, "allow ", "deny "); +} + +struct dst_key * +lookup_key(char *name) { + symbol_value value; + + if (lookup_symbol(authtab, name, SYM_KEY, &value)) + return ((struct dst_key *)(value.pointer)); + return (NULL); +} + +void +define_key(const char *name, struct dst_key *dst_key) { + symbol_value value; + + INSIST(name != NULL); + INSIST(dst_key != NULL); + + value.pointer = dst_key; + define_symbol(authtab, name, SYM_KEY, value, SYMBOL_FREE_VALUE); + dprint_key_info(dst_key); +} + +time_t +parse_configuration(const char *filename) { + FILE *config_stream; + struct stat sb; + + config_stream = fopen(filename, "r"); + if (config_stream == NULL) + ns_panic(ns_log_parser, 0, "can't open '%s'", filename); + if (fstat(fileno(config_stream), &sb) == -1) + ns_panic(ns_log_parser, 0, "can't stat '%s'", filename); + + lexer_setup(); + parser_setup(); + lexer_begin_file(filename, config_stream); + (void)yyparse(); + lexer_end_file(); + parser_cleanup(); + return (sb.st_mtime); +} + +void +parser_initialize(void) { + lexer_initialize(); +} + +void +parser_shutdown(void) { + if (authtab != NULL) + free_symbol_table(authtab); + if (channeltab != NULL) + free_symbol_table(channeltab); + lexer_shutdown(); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_parser.y ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_signal.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_signal.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_signal.c (revision 109985) @@ -0,0 +1,297 @@ +#if !defined(lint) && !defined(SABER) +static const char sccsid[] = "@(#)ns_main.c 4.55 (Berkeley) 7/1/91"; +static const char rcsid[] = "$Id: ns_signal.c,v 8.15 2002/05/18 01:39:15 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986, 1989, 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* Import. */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#ifdef SVR4 /* XXX */ +# include +#else +#ifndef __hpux +# include +#endif +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" +#include "named.h" + +/* Forward. */ + +static SIG_FN onhup(int); +static SIG_FN onintr(int); +static SIG_FN setdumpflg(int); +static SIG_FN setIncrDbgFlg(int); +static SIG_FN setNoDbgFlg(int); +static SIG_FN setQrylogFlg(int); +static SIG_FN setstatsflg(int); +static SIG_FN discard_pipe(int); +static SIG_FN setreapflg(int); + +/* Data. */ + +static struct { + int sig; + SIG_FN (*hand)(int); +} sighandlers[] = { +#ifdef DEBUG + { SIGUSR1, setIncrDbgFlg }, + { SIGUSR2, setNoDbgFlg }, +#endif +#if defined(SIGWINCH) && defined(QRYLOG) + { SIGWINCH, setQrylogFlg }, +#endif +#if defined(SIGXFSZ) + { SIGXFSZ, onhup }, /* Wierd DEC Hesiodism, harmless. */ +#endif + { SIGINT, setdumpflg }, + { SIGILL, setstatsflg }, + { SIGHUP, onhup }, + { SIGCHLD, setreapflg }, + { SIGPIPE, discard_pipe }, + { SIGTERM, onintr } +}; + +static sigset_t mask; +static int blocked = 0; + +/* Private. */ + +static SIG_FN +onhup(int sig) { + + UNUSED(sig); + + ns_need_unsafe(main_need_reload); +} + +static SIG_FN +onintr(int sig) { + + UNUSED(sig); + + ns_need_unsafe(main_need_exit); +} + +static SIG_FN +setdumpflg(int sig) { + + UNUSED(sig); + + ns_need_unsafe(main_need_dump); +} + +#ifdef DEBUG +static SIG_FN +setIncrDbgFlg(int sig) { + + UNUSED(sig); + + desired_debug++; + ns_need_unsafe(main_need_debug); +} + +static SIG_FN +setNoDbgFlg(int sig) { + + UNUSED(sig); + + desired_debug = 0; + ns_need_unsafe(main_need_debug); +} +#endif /*DEBUG*/ + +#if defined(QRYLOG) && defined(SIGWINCH) +static SIG_FN +setQrylogFlg(int sig) { + + UNUSED(sig); + + ns_need_unsafe(main_need_qrylog); +} +#endif /*QRYLOG && SIGWINCH*/ + +static SIG_FN +setstatsflg(int sig) { + + UNUSED(sig); + + ns_need_unsafe(main_need_statsdump); +} + +static SIG_FN +discard_pipe(int sig) { +#ifdef SIGPIPE_ONE_SHOT + int saved_errno = errno; + struct sigaction sa; + + UNUSED(sig); + + memset(&sa, 0, sizeof sa); + sa.sa_mask = mask; + sa.sa_handler = discard_pipe; + if (sigaction(SIGPIPE, &sa, NULL) < 0) + ns_error(ns_log_os, "sigaction failed in discard_pipe: %s", + strerror(errno)); + errno = saved_errno; +#else + UNUSED(sig); +#endif +} + +static SIG_FN +setreapflg(int sig) { + + UNUSED(sig); + + ns_need_unsafe(main_need_reap); +} + +/* Public. */ + +void +init_signals(void) { + size_t sh; + + /* The mask of all our handlers will block all our other handlers. */ + (void)sigemptyset(&mask); + for (sh = 0; sh < sizeof sighandlers / sizeof sighandlers[0]; sh++) + sigaddset(&mask, sighandlers[sh].sig); + + /* Install our signal handlers with that shared mask. */ + for (sh = 0; sh < sizeof sighandlers / sizeof sighandlers[0]; sh++) { + struct sigaction sa; + + memset(&sa, 0, sizeof sa); + sa.sa_mask = mask; + sa.sa_handler = sighandlers[sh].hand; + if (sigaction(sighandlers[sh].sig, &sa, NULL) < 0) + ns_error(ns_log_os, + "sigaction failed in set_signal_handler(%d): %s", + sighandlers[sh].sig, strerror(errno)); + } + /* Unblock all signals that we expect to handle. */ + if (sigprocmask(SIG_UNBLOCK, &mask, NULL) < 0) + ns_panic(ns_log_os, 1, "sigblock failed: %s", strerror(errno)); +} + +void +block_signals(void) { + INSIST(!blocked); + if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) + ns_panic(ns_log_os, 1, "sigblock failed: %s", strerror(errno)); + blocked = 1; +} + +void +unblock_signals(void) { + INSIST(blocked); + if (sigprocmask(SIG_UNBLOCK, &mask, NULL) < 0) + ns_panic(ns_log_os, 1, "sigblock failed: %s", strerror(errno)); + blocked = 0; +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_signal.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_update.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_update.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_update.c (revision 109985) @@ -0,0 +1,3064 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_update.c,v 8.104 2002/05/18 01:02:59 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1999 by Check Point Software Technologies, Inc. + * + * 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 Check Point Software Technologies Incorporated 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 CHECK POINT SOFTWARE TECHNOLOGIES + * INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL CHECK POINT SOFTWARE TECHNOLOGIES INCORPRATED + * 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 SOFTWARE. + */ + +/* + * Based on the Dynamic DNS reference implementation by Viraj Bais + * + */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "port_after.h" + +#include "named.h" + +#define WRITEABLE_MASK (S_IWUSR | S_IWGRP | S_IWOTH) + +/* XXXRTH almost all funcs. in here should be static! + map rdata_dump to db_to_textual + map rdata_expand to wire_to_db + make a textual_to_db and use it in merge_logs? + replace all this "map" stuff with the new routines (from 4.9.5 I think) + */ + +/* from ns_req.c */ + +static struct map m_opcode[] = { + { "nxdomain", NXDOMAIN }, + { "yxdomain", YXDOMAIN }, + { "nxrrset", NXRRSET }, + { "yxrrset", YXRRSET }, + { "delete", DELETE }, + { "add", ADD }, +}; +#define M_OPCODE_CNT (sizeof(m_opcode) / sizeof(struct map)) + +/* XXXRTH workaround map difficulties */ +#define M_CLASS_CNT m_class_cnt +#define M_TYPE_CNT m_type_cnt + +static const char *opcodes[] = { + "delete", + "add", + "", + "nxdomain", + "", + "", + "yxdomain", + "yxrrset", + "nxrrset", + "", + "", +}; + + +/* from db_load.c */ + +static struct map m_section[] = { + { "zone", S_ZONE }, + { "prereq", S_PREREQ }, + { "update", S_UPDATE }, + { "reserved", S_ADDT }, +}; +#define M_SECTION_CNT (sizeof(m_section) / sizeof(struct map)) + +/* Forward. */ + +static int rdata_expand(const u_char *, const u_char *, const u_char *, + u_int, size_t, u_char *, size_t); + + +static FILE * +open_transaction_log(struct zoneinfo *zp) { + FILE *fp = fopen(zp->z_updatelog, "a+"); + + if (fp == NULL) { + ns_error(ns_log_update, "can't open %s: %s", zp->z_updatelog, + strerror(errno)); + return (NULL); + } + (void) fchown(fileno(fp), user_id, group_id); + if (fseek(fp, 0L, SEEK_END) != 0) { + ns_error(ns_log_update, "can't fseek(%s, 0, SEEK_END)", + zp->z_updatelog); + fclose(fp); + return (NULL); + } + if (ftell(fp) == 0L) { + fprintf(fp, "%s", LogSignature); + zp->z_serial_ixfr_start = get_serial(zp); + } + else + zp->z_serial_ixfr_start = 0; + return (fp); +} + +static FILE * +open_ixfr_log(struct zoneinfo *zp) { + FILE *fp = fopen(zp->z_ixfr_base, "a+"); + + if (fp == NULL) { + ns_error(ns_log_update, "can't open %s: %s", zp->z_ixfr_base, + strerror(errno)); + return (NULL); + } + (void) fchown(fileno(fp), user_id, group_id); + if (fseek(fp, 0L, SEEK_END) != 0) { + ns_error(ns_log_update, "can't fseek(%s, 0, SEEK_END)", + zp->z_ixfr_base); + fclose(fp); + return (NULL); + } + if (ftell(fp) == 0L) { + fprintf(fp, "%s", LogSignature); + } + return (fp); +} + +static int +close_transaction_log(struct zoneinfo *zp, FILE *fp) { + if (fflush(fp) == EOF) { + ns_error(ns_log_update, "fflush() of %s failed: %s", + zp->z_updatelog, strerror(errno)); + return (-1); + } + if (fsync(fileno(fp)) < 0) { + ns_error(ns_log_update, "fsync() of %s failed: %s", + zp->z_updatelog, strerror(errno)); + return (-1); + } + if (fclose(fp) == EOF) { + ns_error(ns_log_update, "fclose() of %s failed: %s", + zp->z_updatelog, strerror(errno)); + return (-1); + } + return (0); +} + +static int +close_ixfr_log(struct zoneinfo *zp, FILE *fp) { + if (fflush(fp) == EOF) { + ns_error(ns_log_update, "fflush() of %s failed: %s", + zp->z_ixfr_base, strerror(errno)); + fclose(fp); + return (-1); + } + if (fsync(fileno(fp)) < 0) { + ns_error(ns_log_update, "fsync() of %s failed: %s", + zp->z_ixfr_base, strerror(errno)); + fclose(fp); + return (-1); + } + if (fclose(fp) == EOF) { + ns_error(ns_log_update, "fclose() of %s failed: %s", + zp->z_ixfr_base, strerror(errno)); + return (-1); + } + return (0); +} + +/* + * return true if 'db' had been added. + */ +static int +was_added(const ns_updque *updlist, struct databuf *dp) { + ns_updrec *rrecp; + + for (rrecp = HEAD(*updlist); rrecp != NULL; rrecp = NEXT(rrecp, r_link)) + if (rrecp->r_section == S_UPDATE && rrecp->r_dp == dp) + return (1); + return (0); +} + +/* + * return true if 'db' had been deleted. + */ +static int +was_deleted(const ns_updque *updlist, struct databuf *dp) { + ns_updrec *rrecp; + struct databuf *adp; + + + for (rrecp = HEAD(*updlist); rrecp != NULL; rrecp = NEXT(rrecp, r_link)) + if (rrecp->r_section == S_UPDATE && + rrecp->r_deldp != NULL) { + adp = rrecp->r_deldp; + do { + if (adp == dp) + return (1); + } while ((adp = adp->d_next) != NULL); + } + return (0); +} + +/* + * printupdatelog(srcaddr, updlist, hp, zp, old_serial) + * append an ascii form to the zone's transaction log file. + */ +static void +printupdatelog(struct sockaddr_in srcaddr, + const ns_updque *updlist, + HEADER *hp, + struct zoneinfo *zp, + u_int32_t old_serial) +{ + struct databuf *dp; + ns_updrec *rrecp; + int opcode; + char time[25]; + FILE *fp, *ifp; + + if (EMPTY(*updlist)) + return; + + fp = open_transaction_log(zp); + if (fp == NULL) + return; + + if (zp->z_maintain_ixfr_base == 1) { + ifp = open_ixfr_log(zp); + if (ifp == NULL) { + (void) close_transaction_log(zp, fp); + return; + } + } + else + ifp = NULL; + + sprintf(time, "at %lu", (u_long)tt.tv_sec); + fprintf(fp, "[DYNAMIC_UPDATE] id %u from %s %s (named pid %ld):\n", + ntohs(hp->id), sin_ntoa(srcaddr), time, (long)getpid()); + if (ifp) + fprintf(ifp, + "[DYNAMIC_UPDATE] id %u from %s %s (named pid %ld):\n", + ntohs(hp->id), sin_ntoa(srcaddr), time, + (long)getpid()); + for (rrecp = HEAD(*updlist); rrecp != NULL; rrecp = NEXT(rrecp, r_link)) { + INSIST(zp == &zones[rrecp->r_zone]); + switch (rrecp->r_section) { + case S_ZONE: + fprintf(fp, "zone:\torigin %s class %s serial %u\n", + zp->z_origin, p_class(zp->z_class), + old_serial); + if (ifp) + fprintf(ifp, + "zone:\torigin %s class %s serial %lu\n", + zp->z_origin, p_class(zp->z_class), + (u_long)old_serial); + break; + case S_PREREQ: + opcode = rrecp->r_opcode; + fprintf(fp, "prereq:\t{%s} %s. %s ", + opcodes[opcode], rrecp->r_dname, + p_class(zp->z_class)); + if (opcode == NXRRSET || opcode == YXRRSET) { + fprintf(fp, "%s ", p_type(rrecp->r_type)); + if ((dp = rrecp->r_dp) && dp->d_size > 0) { + dp->d_class = zp->z_class; + (void) rdata_dump(dp, fp); + } + } + fprintf(fp, "\n"); + break; + case S_UPDATE: + opcode = rrecp->r_opcode; + /* + * Translate all deletes into explict actions by + * looking at what was actually deleted from the + * zone for the ixfr log. + */ + dp = rrecp->r_deldp; + while (dp != NULL) { + if (dp->d_rcode == 0 && + !was_added(updlist, dp)) { + if (ifp) { + fprintf(ifp, + "update:\t{%s} %s. %u %s %s ", + "delete", + rrecp->r_dname, + dp->d_ttl, + p_class(dp->d_class), + p_type(dp->d_type)); + (void) rdata_dump(dp, ifp); + fprintf(ifp, "\n"); + } + } + dp = dp->d_next; + } + /* + * Only successful adds should be recorded. + * Don't add changes that are undone later. + * SOA additions performed later. + */ + if (opcode == ADD && (dp = rrecp->r_dp) != NULL && + dp->d_type != T_SOA && + (dp->d_mark & D_MARK_ADDED) != 0 && + !was_deleted(updlist, dp)) { + if (ifp) { + fprintf(ifp, "update:\t{%s} %s. ", + opcodes[opcode], rrecp->r_dname); + fprintf(ifp, "%u ", rrecp->r_ttl); + fprintf(ifp, "%s ", p_class(zp->z_class)); + fprintf(ifp, "%s ", p_type(rrecp->r_type)); + (void) rdata_dump(dp, ifp); + fprintf(ifp, "\n"); + } + } + /* Update log. */ + fprintf(fp, "update:\t{%s} %s. ", + opcodes[opcode], rrecp->r_dname); + if (opcode == ADD) + fprintf(fp, "%u ", rrecp->r_ttl); + fprintf(fp, "%s ", p_class(zp->z_class)); + if (rrecp->r_type != T_ANY) + fprintf(fp, "%s ", p_type(rrecp->r_type)); + if ((dp = rrecp->r_dp) && dp->d_size > 0) { + dp->d_class = zp->z_class; + (void) rdata_dump(dp, fp); + } + fprintf(fp, "\n"); + break; + case S_ADDT: + break; + default: + ns_panic(ns_log_update, 1, + "printupdatelog - impossible condition"); + /*NOTREACHED*/ + } + } + /* + * SOA additions must be last in this update as they + * (or [INCR_SERIAL]) terminate an IXFR chunk. Only the last SOA + * addition will be emitted for any dynamic update regardless + * of the number of SOA changes in the update. + */ + for (rrecp = HEAD(*updlist); rrecp != NULL; rrecp = NEXT(rrecp, r_link)) { + INSIST(zp == &zones[rrecp->r_zone]); + switch (rrecp->r_section) { + case S_UPDATE: + opcode = rrecp->r_opcode; + if (opcode == ADD && (dp = rrecp->r_dp) != NULL && + dp->d_type == T_SOA && + (dp->d_mark & D_MARK_ADDED) != 0 && + !was_deleted(updlist, dp)) { + if (ifp) { + fprintf(ifp, "update:\t{%s} %s. ", + opcodes[opcode], rrecp->r_dname); + fprintf(ifp, "%u ", rrecp->r_ttl); + fprintf(ifp, "%s ", p_class(zp->z_class)); + fprintf(ifp, "%s ", p_type(rrecp->r_type)); + (void) rdata_dump(dp, ifp); + fprintf(ifp, "\n[END_DELTA]\n"); + } + } + break; + default: + break; + } + } + fprintf(fp, "\n"); + (void) close_transaction_log(zp, fp); + if (ifp) + (void) close_ixfr_log(zp, ifp); +} + +static void +cancel_soa_update(struct zoneinfo *zp) { + ns_debug(ns_log_update, 3, "cancel_soa_update for %s", zp->z_origin); + zp->z_flags &= ~Z_NEED_SOAUPDATE; + zp->z_soaincrtime = 0; + zp->z_updatecnt = 0; +} + +/* + * Figure out when a SOA serial number update should happen. + * Returns non-zero if the caller should call sched_zone_maint(zp). + */ +int +schedule_soa_update(struct zoneinfo *zp, int numupdated) { + (void) gettime(&tt); + + zp->z_flags |= Z_NEED_SOAUPDATE; + + /* + * Only z_deferupdcnt updates are allowed before we force + * a serial update. + */ + zp->z_updatecnt += numupdated; + if (zp->z_updatecnt >= zp->z_deferupdcnt) { + if (zp->z_soaincrtime > tt.tv_sec) { + zp->z_soaincrtime = tt.tv_sec; + return (1); + } + } + + if (zp->z_soaincrintvl > 0) { + /* We want automatic updates in this zone. */ + if (zp->z_soaincrtime > 0) { + /* Already scheduled. */ + ns_debug(ns_log_update, 3, + "schedule_soa_update('%s'): already scheduled", + zp->z_origin); + return (0); + } else { + /* First update since the soa was last incremented. */ + zp->z_updatecnt = numupdated; + zp->z_soaincrtime = tt.tv_sec + zp->z_soaincrintvl; + /* + * Never schedule soaincrtime to occur after + * dumptime. + */ + if (zp->z_soaincrtime > zp->z_dumptime) + zp->z_soaincrtime = zp->z_dumptime; + ns_debug(ns_log_update, 3, + "schedule_soa_update('%s'): scheduled for %lu", + zp->z_origin, (u_long)zp->z_soaincrtime); + return (1); + } + } + return (0); +} + +/* + * Figure out when a zone dump should happen. + * Returns non-zero if the caller should call sched_zone_maint(zp). + */ +int +schedule_dump(struct zoneinfo *zp) { + time_t half; + + (void) gettime(&tt); + + zp->z_flags |= Z_NEED_DUMP; + + if (zp->z_dumpintvl > 0) { + /* We want automatic dumping in this zone. */ + if (zp->z_dumptime > 0) { + /* Already scheduled. */ + ns_debug(ns_log_update, 3, + "schedule_dump('%s'): already scheduled", + zp->z_origin); + return (0); + } else { + /* + * Set new dump time for dynamic zone. Use a random + * number in the last half of the dump limit; we want + * it to be substantially correct while still + * preventing dump synchronization among various + * dynamic zones. + */ + half = (zp->z_dumpintvl + 1) / 2; + zp->z_dumptime = tt.tv_sec + half + (rand() % half); + /* + * Never schedule soaincrtime to occur after + * dumptime. + */ + if (zp->z_soaincrtime > zp->z_dumptime) + zp->z_soaincrtime = zp->z_dumptime; + ns_debug(ns_log_update, 3, + "schedule_dump('%s'): scheduled for %lu", + zp->z_origin, (u_long)zp->z_dumptime); + return (1); + } + } + return (0); +} + +/* + * int + * process_prereq(rec, rcodep) + * Process one prerequisite. + * returns: + * >0 prerequisite was satisfied. + * =0 prerequisite was not satisfied, or an error occurred. + * side effects: + * sets *rcodep if an error occurs or prerequisite isn't satisfied. + */ +static int +process_prereq(ns_updrec *ur, int *rcodep, u_int16_t zclass) { + const char *dname = ur->r_dname; + u_int16_t class = ur->r_class; + u_int16_t type = ur->r_type; + u_int32_t ttl = ur->r_ttl; + struct databuf *rdp = ur->r_dp; + const char *fname; + struct hashbuf *htp; + struct namebuf *np; + struct databuf *dp; + + /* + * An element in the list might have already been + * processed if it is in the same RRset as a previous + * RRset Exists (value dependent) prerequisite. + */ + if (rdp && (rdp->d_mark & D_MARK_FOUND) != 0) { + /* Already processed. */ + return (1); + } + if (ttl != 0) { + ns_debug(ns_log_update, 1, + "process_prereq: ttl!=0 in prereq section"); + *rcodep = FORMERR; + return (0); + } + htp = hashtab; + np = nlookup(dname, &htp, &fname, 0); + /* + * Matching by wildcard not allowed here. + * We need to post check for a wildcard match. + */ + if (fname != dname || + (np != NULL && ns_wildcard(NAME(*np)) && + (dname[0] != '*' || (dname[1] != '.' && dname[1] != '\0')))) + np = NULL; + + if (class == C_ANY) { + if (rdp->d_size) { + ns_debug(ns_log_update, 1, + "process_prereq: empty rdata required in prereq section with class=ANY"); + *rcodep = FORMERR; + return (0); + } + if (type == T_ANY) { + /* Name is in use. */ + ur->r_opcode = YXDOMAIN; + if (np == NULL || np->n_data == NULL) { + /* + * Name does not exist or is + * an empty nonterminal. + */ + ns_debug(ns_log_update, 1, + "process_prereq: %s not in use", + dname); + *rcodep = NXDOMAIN; + return (0); + } + } else { + /* RRset exists (value independent). */ + int found = 0; + + ur->r_opcode = YXRRSET; + if (np != NULL) + for (dp = np->n_data; + dp && !found; + dp = dp->d_next) + if (match(dp, class, type) && + dp->d_type == type) + found = 1; + if (!found) { + ns_debug(ns_log_update, 1, + "process_prereq: RRset (%s,%s,%s) does not exist", + dname, p_type(type), p_class(zclass)); + *rcodep = NXRRSET; + return (0); + } + } + } else if (class == C_NONE) { + if (rdp->d_size) { + ns_debug(ns_log_update, 1, + "process_prereq: empty rdata required in prereq section with class=NONE"); + *rcodep = FORMERR; + return (0); + } + if (type == T_ANY) { + /* Name is not in use. */ + ur->r_opcode = NXDOMAIN; + if (np != NULL && np->n_data != NULL) { + /* + * Name exists and is not an + * empty nonterminal. + */ + ns_debug(ns_log_update, 1, + "process_prereq: %s exists", + dname); + *rcodep = YXDOMAIN; + return (0); + } + } else { + /* RRset does not exist. */ + int found = 0; + + ur->r_opcode = NXRRSET; + class = zclass; + if (np != NULL) + for (dp = np->n_data; + dp && !found; + dp = dp->d_next) + if (match(dp, class, type)) + found = 1; + if (found) { + ns_debug(ns_log_update, 1, + "process_prereq: RRset (%s,%s) exists", + dname, p_type(type)); + *rcodep = YXRRSET; + return (0); + } + } + } else if (class == zclass) { + /* + * RRset exists (value dependent). + * + * Check for RRset equality also. + */ + ns_updrec *tmp; + + ur->r_opcode = YXRRSET; + if (!rdp) { + ns_debug(ns_log_update, 1, + "process_prereq: nonempty rdata required in prereq section with class=%s", + p_class(class)); + *rcodep = FORMERR; + return (0); + } + if (np == NULL || fname != dname) { + *rcodep = NXRRSET; + return (0); + } + for (dp = np->n_data; dp; dp = dp->d_next) { + if (match(dp, class, type) && dp->d_type == type) { + int found = 0; + + for (tmp = ur; + tmp != NULL && !found; + tmp = NEXT(tmp, r_link)) { + if (tmp->r_section != S_PREREQ) + break; + if (!db_cmp(dp, tmp->r_dp)) { + tmp->r_dp->d_mark |= + D_MARK_FOUND; + found = 1; + } + } + if (!found) { + *rcodep = NXRRSET; + return (0); + } + } + } + for (tmp = ur; tmp != NULL; tmp = NEXT(tmp, r_link)) + if (tmp->r_section == S_PREREQ && + ns_samename(dname, tmp->r_dname) == 1 && + tmp->r_class == class && + tmp->r_type == type && + (ur->r_dp->d_mark & D_MARK_FOUND) == 0) { + *rcodep = NXRRSET; + return (0); + } else { + tmp->r_opcode = YXRRSET; + } + } else { + ns_debug(ns_log_update, 1, + "process_prereq: incorrect class %s", + p_class(class)); + *rcodep = FORMERR; + return (0); + } + /* Through the gauntlet, and out. */ + return (1); +} + +static int +prescan_nameok(ns_updrec *ur, int *rcodep, u_int16_t zclass, + struct zoneinfo *zp) +{ + const char *owner = ur->r_dname; + u_int16_t class = ur->r_class; + u_int16_t type = ur->r_type; + char *cp = (char *)ur->r_dp->d_data; + enum context context; + enum transport transport; + + /* We don't care about deletes */ + if (ur->r_class != zclass) + return (1); + + if (zp->z_type == Z_PRIMARY) + transport = primary_trans; + else + transport = secondary_trans; + + context = ns_ownercontext(type, transport); + if (!ns_nameok(NULL, owner, class, zp, transport, context, owner, + inaddr_any)) + goto refused; + + switch (type) { + case ns_t_soa: + context = hostname_ctx; + if (!ns_nameok(NULL, cp, class, zp, transport, context, owner, + inaddr_any)) + goto refused; + cp += strlen(cp) + 1; + context = mailname_ctx; + if (!ns_nameok(NULL, cp, class, zp, transport, context, owner, + inaddr_any)) + goto refused; + break; + case ns_t_rp: + context = mailname_ctx; + if (!ns_nameok(NULL, cp, class, zp, transport, context, owner, + inaddr_any)) + goto refused; + cp += strlen(cp) + 1; + context = domain_ctx; + if (!ns_nameok(NULL, cp, class, zp, transport, context, owner, + inaddr_any)) + goto refused; + break; + case ns_t_minfo: + context = mailname_ctx; + if (!ns_nameok(NULL, cp, class, zp, transport, context, owner, + inaddr_any)) + goto refused; + cp += strlen(cp) + 1; + context = mailname_ctx; + if (!ns_nameok(NULL, cp, class, zp, transport, context, owner, + inaddr_any)) + goto refused; + break; + case ns_t_ns: + context = hostname_ctx; + if (!ns_nameok(NULL, cp, class, zp, transport, context, owner, + inaddr_any)) + goto refused; + break; + case ns_t_cname: + case ns_t_mb: + case ns_t_mg: + case ns_t_mr: + context = domain_ctx; + if (!ns_nameok(NULL, cp, class, zp, transport, context, owner, + inaddr_any)) + goto refused; + break; + case ns_t_ptr: + context = ns_ptrcontext(owner); + if (!ns_nameok(NULL, cp, class, zp, transport, context, owner, + inaddr_any)) + goto refused; + break; + case ns_t_naptr: + /* + * Order (2) + * Preference (2) + */ + cp += 4; + /* Flags (txt) */ + cp += (*cp&0xff) + 1; + /* Service (txt) */ + cp += (*cp&0xff) + 1; + /* Pattern (txt) */ + cp += (*cp&0xff) + 1; + context = domain_ctx; + if (!ns_nameok(NULL, cp, class, zp, transport, + context, owner, inaddr_any)) + goto refused; + break; + case ns_t_srv: + cp += 4; + /* FALLTHROUGH */ + case ns_t_mx: + case ns_t_afsdb: + case ns_t_rt: + case ns_t_kx: + cp += 2; + context = hostname_ctx; + if (!ns_nameok(NULL, cp, class, zp, transport, context, owner, + inaddr_any)) + goto refused; + break; + case ns_t_px: + cp += 2; + context = domain_ctx; + if (!ns_nameok(NULL, cp, class, zp, transport, context, owner, + inaddr_any)) + goto refused; + cp += strlen(cp) + 1; + if (!ns_nameok(NULL, cp, class, zp, transport, context, owner, + inaddr_any)) + goto refused; + break; + case ns_t_sig: + /* + * Type covered (2) + * Alg (1) * + * Labels (1) + * ttl (4) + * expires (4) + * signed (4) + * footprint (2) + */ + cp += 18; + context = domain_ctx; + if (!ns_nameok(NULL, cp, class, zp, transport, context, owner, + inaddr_any)) + goto refused; + break; + case ns_t_nxt: + context = domain_ctx; + if (!ns_nameok(NULL, cp, class, zp, transport, context, owner, + inaddr_any)) + goto refused; + break; + default: + break; + } + return (1); + refused: + *rcodep = REFUSED; + return (0); +} + +/* + * int + * prescan_update(ur, rcodep) + * Process one prerequisite. + * returns: + * >0 update looks OK (format wise; who knows if it will succeed?) + * =0 update has something wrong with it. + * side effects: + * sets *rcodep if an error occurs or prerequisite isn't satisfied. + */ +static int +prescan_update(ns_updrec *ur, int *rcodep, u_int16_t zclass) { + u_int16_t class = ur->r_class; + u_int16_t type = ur->r_type; + u_int32_t ttl = ur->r_ttl; + struct databuf *rdp = ur->r_dp; + + if (class == zclass) { + if (!ns_t_rr_p(type)) { + ns_debug(ns_log_update, 1, + "prescan_update: invalid type (%s)", + p_type(type)); + *rcodep = FORMERR; + return (0); + } + if (ttl > MAXIMUM_TTL) { + ns_debug(ns_log_update, 1, + "prescan_update: invalid ttl (%u)", ttl); + *rcodep = FORMERR; + return (0); + } + } else if (class == C_ANY) { + if (ttl != 0 || rdp->d_size || + (!ns_t_rr_p(type) && type != T_ANY)) + { + ns_debug(ns_log_update, 1, + "prescan_update: formerr(#2)"); + *rcodep = FORMERR; + return (0); + } + } else if (class == C_NONE) { + if (ttl != 0 || !ns_t_rr_p(type)) { + ns_debug(ns_log_update, 1, + "prescan_update: formerr(#3) %d %s", + ttl, p_type(type)); + *rcodep = FORMERR; + return (0); + } + } else { + ns_debug(ns_log_update, 1, + "prescan_update: invalid class (%s)", + p_class(class)); + *rcodep = FORMERR; + return (0); + } + /* No format errors found. */ + return (1); +} + +/* + * int + * process_updates(updlist, rcodep, from) + * Process prerequisites and apply updates from the list to the database. + * returns: + * number of successful updates, 0 if none were successful. + * side effects: + * *rcodep gets the transaction return code. + * can schedule maintainance for zone dumps and soa.serial# increments. + */ +static int +process_updates(const ns_updque *updlist, int *rcodep, + struct sockaddr_in from) +{ + int j, n, dbflags, matches, zonenum; + int numupdated = 0, soaupdated = 0, schedmaint = 0; + u_int16_t zclass; + ns_updrec *ur; + struct databuf *dp, *savedp; + struct zoneinfo *zp; + int zonelist[MAXDNAME]; + + *rcodep = SERVFAIL; + if (EMPTY(*updlist)) + return (0); + ur = HEAD(*updlist); + if (ur->r_section == S_ZONE) { + zclass = ur->r_class; + zonenum = ur->r_zone; + zp = &zones[zonenum]; + } else { + ns_debug(ns_log_update, 1, + "process_updates: missing zone record"); + return (0); + } + + /* Process prereq records and prescan update records. */ + for (ur = HEAD(*updlist); ur != NULL; ur = NEXT(ur, r_link)) { + const char * dname = ur->r_dname; + u_int16_t class = ur->r_class; + u_int16_t type = ur->r_type; + u_int32_t ttl = ur->r_ttl; + struct databuf *rdp = ur->r_dp; + u_int section = ur->r_section; + + ns_debug(ns_log_update, 3, +"process_update: record section=%s, dname=%s, \ +class=%s, type=%s, ttl=%d, dp=%p", + p_section(section, ns_o_update), dname, + p_class(class), p_type(type), ttl, rdp); + + matches = findzone(dname, zclass, MAXDNAME, + zonelist, MAXDNAME); + ur->r_zone = 0; + for (j = 0; j < matches && !ur->r_zone; j++) + if (zonelist[j] == zonenum) + ur->r_zone = zonelist[j]; + if (!ur->r_zone || + (section != S_ADDT && type == T_SOA && + ns_samename(dname, zp->z_origin) != 1)) { + ns_debug(ns_log_update, 1, + "process_updates: record does not belong to the zone %s", + zones[zonenum].z_origin); + *rcodep = NOTZONE; + return (0); + } + + switch (section) { + case S_ZONE: + break; + case S_PREREQ: + if (!process_prereq(ur, rcodep, zclass)) + return (0); /* *rcodep has been set. */ + ns_debug(ns_log_update, 3, "prerequisite satisfied"); + break; + case S_UPDATE: + if (!prescan_update(ur, rcodep, zclass)) + return (0); /* *rcodep has been set. */ + if (!prescan_nameok(ur, rcodep, zclass, zp)) + return (0); /* *rcodep has been set. */ + ns_debug(ns_log_update, 3, "update prescan succeeded"); + break; + case S_ADDT: + break; + default: + ns_panic(ns_log_update, 1, + "process_updates: impossible section"); + /* NOTREACHED */ + } + } + + /* Now process the records in update section. */ + for (ur = HEAD(*updlist); ur != NULL; ur = NEXT(ur, r_link)) { + const char * dname = ur->r_dname; + u_int16_t class = ur->r_class; + + if (ur->r_section != S_UPDATE) + continue; + dbflags = 0; + savedp = NULL; + dp = ur->r_dp; + if (class == zp->z_class) { + /* ADD databuf dp to hash table */ + /* + * Handling of various SOA/WKS/CNAME scenarios + * is done in db_update(). + */ + ur->r_opcode = ADD; + dbflags |= DB_NODATA | DB_REPLACE; + n = db_update(dname, dp, dp, &savedp, + dbflags, hashtab, from); + if (!((n == OK) || + ((zp->z_xferpid == XFER_ISIXFR) && (n == DATAEXISTS)))) { + ns_debug(ns_log_update, 3, + "process_updates: failed to add databuf (%d)", + n); + } else { + ns_debug(ns_log_update, 3, + "process_updates: added databuf %p", + dp); + dp->d_mark = D_MARK_ADDED; + numupdated++; + if (dp->d_type == T_SOA) + soaupdated = 1; + } + } else if (class == C_ANY || class == C_NONE) { + /* + * DELETE databuf's matching dp from the hash table. + * + * handling of various SOA/NS scenarios done + * in db_update(). + */ + ur->r_opcode = DELETE; + /* + * we know we're deleting now, and db_update won't + * match with class==C_NONE, so we use the zone's + * class. + */ + if (class == C_NONE) + ur->r_dp->d_class = zp->z_class; + dbflags |= DB_DELETE; + n = db_update(dname, dp, NULL, &savedp, + dbflags, hashtab, from); + if (!((n == OK) || + ((zp->z_xferpid == XFER_ISIXFR) && (n == NODATA)))) { + ns_debug(ns_log_update, 3, + "process_updates: delete failed"); + } else { + ns_debug(ns_log_update, 3, + "process_updates: delete succeeded"); + numupdated++; + } + } + /* + * Even an addition could have caused some deletions like + * replacing old SOA or CNAME or WKS record or records of + * lower cred/clev. + * + * We need to save the deleted databuf's in case we wish to + * abort this update transaction and roll back all updates + * applied from this packet. + */ + ur->r_deldp = savedp; + } + + /* + * If we got here, things are OK, so set rcodep to indicate so. + */ + *rcodep = NOERROR; + + if (!numupdated) + return (0); + + /* + * schedule maintenance for dumps and SOA.serial# increment + * (this also sets Z_NEED_DUMP and Z_NEED_SOAUPDATE appropriately) + */ + schedmaint = 0; + if (schedule_dump(zp)) + schedmaint = 1; + if (soaupdated) { + /* + * SOA updated by this update transaction, so + * we need to set the zone serial number, stop any + * automatic updates that may be pending, and send out + * a NOTIFY message. + */ + zp->z_serial = get_serial_unchecked(zp); + cancel_soa_update(zp); + schedmaint = 1; +#ifdef BIND_NOTIFY + if (!loading) + ns_notify(zp->z_origin, zp->z_class, ns_t_soa); +#endif + } else { + if (schedule_soa_update(zp, numupdated)) + schedmaint = 1; + } + if (schedmaint) + sched_zone_maint(zp); + return (numupdated); +} + +static enum req_action +req_update_private(HEADER *hp, u_char *cp, u_char *eom, u_char *msg, + struct sockaddr_in from, struct tsig_record *in_tsig, + ns_updque *curupd) +{ + char dnbuf[MAXDNAME], *dname; + u_int zocount, prcount, upcount, adcount, class, type, dlen; + u_int32_t ttl; + int i, n, matches, zonenum, numupdated = 0; + int rcode = NOERROR; + u_int section; + u_char rdata[MAXDATA]; + struct databuf *dp, *nsp[NSMAX]; + struct zoneinfo *zp; + ns_updrec *rrecp; + int zonelist[MAXDNAME]; + u_int32_t old_serial; + DST_KEY *in_key = (in_tsig != NULL) ? in_tsig->key : NULL; + + nsp[0] = NULL; + + zocount = ntohs(hp->qdcount); + prcount = ntohs(hp->ancount); + upcount = ntohs(hp->nscount); + adcount = ntohs(hp->arcount); + + /* Process zone section. */ + ns_debug(ns_log_update, 3, "req_update: section ZONE, count %d", + zocount); + if ((n = dn_expand(msg, eom, cp, dnbuf, sizeof(dnbuf))) < 0) { + ns_debug(ns_log_update, 1, "req_update: expand name failed"); + hp->rcode = FORMERR; + return (Finish); + } + dname = dnbuf; + cp += n; + if (cp + 2 * INT16SZ > eom) { + ns_debug(ns_log_update, 1, "req_update: too short"); + hp->rcode = FORMERR; + return (Finish); + } + GETSHORT(type, cp); + GETSHORT(class, cp); + if (zocount != 1 || type != T_SOA) { + ns_debug(ns_log_update, 1, + "req_update: incorrect count or type for zone section: %d", + zocount); + hp->rcode = FORMERR; + return (Finish); + } + + matches = findzone(dname, class, 0, zonelist, MAXDNAME); + if (matches == 1) { + zonenum = zonelist[0]; + zp = &zones[zonenum]; + if (zp->z_class != (int)class || + (zp->z_type != z_master && zp->z_type != z_slave)) + matches = 0; + } + if (matches != 1) { + ns_debug(ns_log_update, 1, + "req_update: non-authoritative server for %s", + dname); + hp->rcode = NOTAUTH; + return (Finish); + } + + /* + * Begin Access Control Point + */ + + if (!ip_addr_or_key_allowed(zp->z_update_acl, from.sin_addr, in_key)) { + ns_notice(ns_log_security, + "denied update from %s for \"%s\" %s", + sin_ntoa(from), *dname ? dname : ".", p_class(class)); + nameserIncr(from.sin_addr, nssRcvdUUpd); + return (Refuse); + } + + /* + * End Access Control Point + */ + + /* we should be authoritative */ + if (!(zp->z_flags & Z_AUTH)) { + ns_debug(ns_log_update, 1, + "req_update: zone %s: Z_AUTH not set", + dname); + hp->rcode = NOTAUTH; + return (Finish); + } + + if (zp->z_type == Z_SECONDARY) { + /* + * XXX The code below is broken. + * Until fixed, we just return NOTIMPL. + */ +#if 1 + hp->rcode = ns_r_notimpl; + return (Finish); +#else + /* We are a slave for this zone, forward it to the master. */ + for (cnt = 0; cnt < zp->z_addrcnt; cnt++) + *nspp++ = savedata(zp->z_class, T_A, USE_MINIMUM, + (u_char *)&zp->z_addr[cnt].s_addr, + INT32SZ); + *nspp = NULL; + /* + * If the request came in over TCP, forward it over TCP + */ + should_use_tcp = (qsp != NULL); + if (in_tsig != NULL) { + tsig_len = ns_skiprr(eom, eom + TSIG_BUF_SIZE, + ns_s_ar, 1); + eom += tsig_len; + } + n = ns_forw(nsp, msg, eom-msg, from, qsp, dfd, &qp, + dname, class, type, NULL, should_use_tcp, NULL); + if (in_tsig != NULL) + eom -= tsig_len; + free_nsp(nsp); + switch (n) { + case FW_OK: + case FW_DUP: + return (Return); + case FW_NOSERVER: + /* should not happen */ + case FW_SERVFAIL: + hp->rcode = SERVFAIL; + return (Finish); + } +#endif + } + /* + * We are the primary master server for this zone, + * proceed further and process update packet + */ + if (!(zp->z_flags & Z_DYNAMIC)) { + ns_debug(ns_log_update, 1, + "req_update: dynamic flag not set for zone %s", + dname); + return (Refuse); + } + old_serial = get_serial(zp); + ns_debug(ns_log_update, 3, + "req_update: update request for zone %s, class %s", + zp->z_origin, p_class(class)); + rrecp = res_mkupdrec(S_ZONE, dname, class, type, 0); + rrecp->r_zone = zonenum; + + APPEND(*curupd, rrecp, r_link); + + /* + * Parse the prerequisite and update sections for format errors. + */ + for (i = 0; (u_int)i < prcount + upcount; i++) { + if ((n = dn_expand(msg, eom, cp, dnbuf, sizeof(dnbuf))) < 0) { + ns_debug(ns_log_update, 1, + "req_update: expand name failed"); + hp->rcode = FORMERR; + return (Finish); + } + dname = dnbuf; + cp += n; + if (cp + RRFIXEDSZ > eom) { + ns_debug(ns_log_update, 1, + "req_update: overrun in answer"); + hp->rcode = FORMERR; + return (Finish); + } + GETSHORT(type, cp); + GETSHORT(class, cp); + if (class > CLASS_MAX) { + ns_debug(ns_log_update, 1, + "req_update: bad class"); + hp->rcode = FORMERR; + return (Finish); + } + GETLONG(ttl, cp); + GETSHORT(dlen, cp); + n = 0; + dp = NULL; + if (dlen > 0) { + if (cp + dlen > eom) { + ns_debug(ns_log_update, 1, + "req_update: bad dlen"); + hp->rcode = FORMERR; + return (Finish); + } + n = rdata_expand(msg, eom, cp, type, dlen, + rdata, sizeof rdata); + if (n == 0 || n > MAXDATA) { + ns_debug(ns_log_update, 1, + "req_update: failed to expand record"); + hp->rcode = FORMERR; + return (Finish); + } + cp += dlen; + } + section = ((u_int)i < prcount) ? S_PREREQ : S_UPDATE; + rrecp = res_mkupdrec(section, dname, class, type, ttl); + dp = savedata(class, type, ttl, rdata, n); + dp->d_zone = zonenum; + dp->d_cred = DB_C_ZONE; + dp->d_secure = DB_S_INSECURE; /* should be UNCHECKED */ + dp->d_clev = nlabels(zp->z_origin); + /* XXX - also record in dp->d_ns, which host this came from */ + rrecp->r_dp = dp; + /* Append the current record to the end of list of records. */ + APPEND(*curupd, rrecp, r_link); + if (cp > eom) { + ns_info(ns_log_update, + "Malformed response from %s (overrun)", + inet_ntoa(from.sin_addr)); + hp->rcode = FORMERR; + return (Finish); + } + } + + /* Now process all parsed records in the prereq and update sections. */ + numupdated = process_updates(curupd, &rcode, from); + hp->rcode = rcode; + if (numupdated <= 0) { + if (rcode != NOERROR) + ns_error(ns_log_update, + "error processing update packet (%s) id %d from %s", + p_rcode(rcode), ntohs(hp->id), sin_ntoa(from)); + return (Finish); + } + + /* + * Stop any outbound zone transfers. + * (Eventlib is synchronous for this.) + */ + ns_stopxfrs(zp); + + /* Make a log of the update. */ + (void) printupdatelog(from, curupd, hp, zp, old_serial); + + return (Finish); +} + +void +free_rrecp(ns_updque *updlist, int rcode, struct sockaddr_in from) { + ns_updrec *rrecp, *first_rrecp, *next_rrecp; + struct databuf *dp, *tmpdp; + char *dname; + const char *msg; + + if (rcode == NOERROR) { + first_rrecp = HEAD(*updlist); + msg = "free_rrecp: update transaction succeeded, cleaning up"; + } else { + first_rrecp = TAIL(*updlist); + msg = "free_rrecp: update transaction aborted, rolling back"; + } + ns_debug(ns_log_update, 1, "%s", msg); + for (rrecp = first_rrecp; rrecp != NULL; rrecp = next_rrecp) { + if (rcode == NOERROR) + next_rrecp = NEXT(rrecp, r_link); + else + next_rrecp = PREV(rrecp, r_link); + UNLINK(*updlist, rrecp, r_link); + if (rrecp->r_section != S_UPDATE) { + if (rrecp->r_dp) + db_detach(&rrecp->r_dp); + INSIST(rrecp->r_deldp == NULL); + res_freeupdrec(rrecp); + continue; + } + dname = rrecp->r_dname; + dp = rrecp->r_dp; + rrecp->r_dp = NULL; + if ((dp->d_mark & D_MARK_ADDED) != 0) { + if (rcode == NOERROR) { + /* + * This databuf is now a part of hashtab, + * or has been deleted by a subsequent update. + * Either way, we must not free it. + */ + dp->d_mark &= ~D_MARK_ADDED; + } else { + /* Delete the databuf. */ + if (db_update(dname, dp, NULL, NULL, + DB_DELETE, hashtab, from) + != OK) { + ns_error(ns_log_update, + "free_rrecp: failed to delete databuf: dname=%s, type=%s", + dname, p_type(dp->d_type)); + } else { + ns_debug(ns_log_update, 3, + "free_rrecp: deleted databuf %p", + dp); + } + } + } + db_detach(&dp); + + /* Process deleted databuf's. */ + dp = rrecp->r_deldp; + rrecp->r_deldp = NULL; + while (dp != NULL) { + tmpdp = dp; + dp = dp->d_next; + tmpdp->d_next = NULL; + if (rcode != NOERROR) { + /* Add the databuf back. */ + tmpdp->d_mark &= ~D_MARK_DELETED; + if (db_update(dname, tmpdp, tmpdp, NULL, + DB_REPLACE, hashtab, from) != OK) { + ns_error(ns_log_update, + "free_rrecp: failed to add back databuf: dname=%s, type=%s", + dname, p_type(tmpdp->d_type)); + } else { + ns_debug(ns_log_update, 3, + "free_rrecp: added back databuf %p", + tmpdp); + } + } + db_detach(&tmpdp); + } + res_freeupdrec(rrecp); + } +} + +enum req_action +req_update(HEADER *hp, u_char *cp, u_char *eom, u_char *msg, + struct sockaddr_in from, struct tsig_record *in_tsig) +{ + enum req_action ret; + ns_updque curupd; + + INIT_LIST(curupd); + ret = req_update_private(hp, cp, eom, msg, from, in_tsig, &curupd); + free_rrecp(&curupd, ret == Refuse ? ns_r_refused : hp->rcode, from); + if (ret == Finish) { + hp->qdcount = hp->ancount = hp->nscount = hp->arcount = 0; + memset(msg + HFIXEDSZ, 0, (eom - msg) - HFIXEDSZ); + } + return (ret); +} + +/* + * expand rdata portion of a compressed resource record at cp into cp1 + * and return the length of the expanded rdata (length of the compressed + * rdata is "dlen"). + */ +static int +rdata_expand(const u_char *msg, const u_char *eom, const u_char *cp, + u_int type, size_t dlen, u_char *cp1, size_t size) +{ + const u_char *cpinit = cp; + const u_char *cp1init = cp1; + int n, i, n1; + + switch (type) { + case T_A: + case T_AAAA: + if ((type == T_A && dlen != INT32SZ) || + (type == T_AAAA && dlen != NS_IN6ADDRSZ)) + return (0); + /*FALLTHROUGH*/ + case T_WKS: + case T_HINFO: + case T_TXT: + case T_X25: + case T_ISDN: + case T_NSAP: + case T_LOC: + case T_KEY: + case ns_t_cert: + if (size < dlen) + return (0); + memcpy(cp1, cp, dlen); + return (dlen); + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_NS: + case T_PTR: + n = dn_expand(msg, eom, cp, (char *)cp1, size); + if (n < 0 || (u_int)n != dlen) + return (0); + return (strlen((char *)cp1) + 1); + case T_MINFO: + case T_SOA: + case T_RP: + /* Get two compressed domain names. */ + for (i = 0; i < 2; i++) { + n = dn_expand(msg, eom, cp, (char *)cp1, size); + if (n < 0) + return (0); + cp += n; + n = strlen((char *)cp1) + 1; + cp1 += n; + size -= n; + } + if (type == T_SOA) { + n = 5 * INT32SZ; + if (size < (size_t)n || cp + n > eom) + return(0); + size -= n; + memcpy(cp1, cp, n); + cp += n; + cp1 += n; + } + if (cp != cpinit + dlen) + return (0); + return (cp1 - cp1init); + case T_MX: + case T_AFSDB: + case T_RT: + case T_SRV: + /* Grab preference. */ + if (size < INT16SZ || cp + INT16SZ > eom) + return (0); + size -= INT16SZ; + memcpy(cp1, cp, INT16SZ); + cp += INT16SZ; + cp1 += INT16SZ; + + if (type == T_SRV) { + if (size < INT16SZ*2 || cp + INT16SZ*2 > eom) + return (0); + size -= INT16SZ*2; + /* Grab weight and port. */ + memcpy(cp1, cp, INT16SZ*2); + cp1 += INT16SZ*2; + cp += INT16SZ*2; + } + + /* Get name. */ + n = dn_expand(msg, eom, cp, (char *)cp1, size); + if (n < 0) + return (0); + cp += n; + n = strlen((char *)cp1) + 1; + cp1 += n; + if (cp != cpinit + dlen) + return (0); + return (cp1 - cp1init); + case T_PX: + /* Grab preference. */ + if (size < INT16SZ || cp + INT16SZ > eom) + return (0); + size -= INT16SZ; + memcpy(cp1, cp, INT16SZ); + cp += INT16SZ; + cp1 += INT16SZ; + /* Get MAP822 name. */ + n = dn_expand(msg, eom, cp, (char *)cp1, size); + if (n < 0) + return (0); + cp += n; + n = strlen((char *)cp1) + 1; + cp1 += n; + size -= n; + n = dn_expand(msg, eom, cp, (char *)cp1, size); + if (n < 0) + return (0); + cp += n; + n = strlen((char *)cp1) + 1; + cp1 += n; + if (cp != cpinit + dlen) + return (0); + return (cp1 - cp1init); + case T_SIG: + if (dlen < SIG_HDR_SIZE || size < dlen) + return (0); + memcpy(cp1, cp, SIG_HDR_SIZE); + size -= SIG_HDR_SIZE; + cp += SIG_HDR_SIZE; + cp1 += SIG_HDR_SIZE; + n = dn_expand(msg, eom, cp, (char *)cp1, size); + if (n < 0 || n + SIG_HDR_SIZE > (int)dlen) + return (0); + cp += n; + n1 = dlen - n - SIG_HDR_SIZE; + n = strlen((char *)cp1) + 1; + cp1 += n; + if ((int)size < n1) + return (0); + memcpy(cp1, cp, n1); + cp1 += n1; + return (cp1 - cp1init); + case T_NXT: + n = dn_expand(msg, eom, cp, (char *)cp1, size); + if (n < 0 || (u_int)n >= dlen) + return (0); + size -= n; + cp += n; + n1 = dlen - n; + n = strlen((char *)cp1) + 1; + cp1 += n; + /* + * The first bit of the first octet determines the format + * of the NXT record. A format for types >= 128 has not + * yet been defined, so if bit zero is set, we just copy + * what's there because we don't understand it. + */ + if ((*cp & 0x80) == 0) { + /* + * Bit zero is not set; this is an ordinary NXT + * record. The bitmap must be at least 4 octets + * because the NXT bit should be set. It should be + * less than or equal to 16 octets because this NXT + * format is only defined for types < 128. + */ + if (n1 < 4 || n1 > 16) + return (0); + } + if (n1 > (int)size) + return (0); + memcpy(cp1, cp, n1); + cp1 += n1; + return (cp1 - cp1init); + default: + if (size < dlen) + return (0); + memcpy(cp1, cp, dlen); + return (dlen); + } +} + +/* + * Print out rdata portion of a resource record from a databuf into a file. + * + * XXX - similar code in db_dump() should be replaced by a call to this + * function. + */ +void +rdata_dump(struct databuf *dp, FILE *fp) { + u_int32_t n, addr; + u_char *cp, *end; + int i, j; + const char *proto; + u_char *savecp; + char temp_base64[NS_MD5RSA_MAX_BASE64]; + u_int16_t keyflags; + u_char *sigdata, *certdata; + + cp = (u_char *)dp->d_data; + switch (dp->d_type) { + case T_A: + switch (dp->d_class) { + case C_IN: + case C_HS: + GETLONG(n, cp); + n = htonl(n); + fputs(inet_ntoa(*(struct in_addr *)&n), fp); + break; + } + if (dp->d_nstime) + fprintf(fp, ";\tNT=%d", dp->d_nstime); + break; + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_PTR: + fprintf(fp, "%s.", cp); + break; + case T_NS: + cp = (u_char *)dp->d_data; + if (cp[0] == '\0') + fprintf(fp, ".\t"); + else + fprintf(fp, "%s.", cp); + break; + case T_HINFO: + case T_ISDN: + if ((n = *cp++) != '\0') { + fprintf(fp, "\"%.*s\"", (int)n, cp); + cp += n; + } else + fprintf(fp, "\"\""); + if ((n = *cp++) != '\0') + fprintf(fp, " \"%.*s\"", (int)n, cp); + else + fprintf(fp, " \"\""); + break; + case T_SOA: + fprintf(fp, "%s.", cp); + cp += strlen((char *)cp) + 1; + fprintf(fp, " %s. ( ", cp); +#if defined(RETURNSOA) && defined(NCACHE) + if (dp->d_rcode == NXDOMAIN) + fputs(";", fp); +#endif + cp += strlen((char *)cp) + 1; + GETLONG(n, cp); + fprintf(fp, "%u", n); + GETLONG(n, cp); + fprintf(fp, " %u", n); + GETLONG(n, cp); + fprintf(fp, " %u", n); + GETLONG(n, cp); + fprintf(fp, " %u", n); + GETLONG(n, cp); + fprintf(fp, " %u )", n); +#if defined(RETURNSOA) && defined(NCACHE) + if (dp->d_rcode == NXDOMAIN) + fprintf(fp, ";%s.;NXDOMAIN;\t-$", cp); +#endif + break; + case T_MX: + case T_AFSDB: + case T_RT: + GETSHORT(n, cp); + fprintf(fp, "%u", n); + fprintf(fp, " %s.", cp); + break; + case T_SRV: + GETSHORT(n, cp); /* priority */ + fprintf(fp, "%u ", n); + GETSHORT(n, cp); /* weight */ + fprintf(fp, "%u ", n); + GETSHORT(n, cp); /* port */ + fprintf(fp, "%u ", n); + fprintf(fp, " %s.", cp); + break; + case T_PX: + GETSHORT(n, cp); + fprintf(fp, "%u", n); + fprintf(fp, " %s.", cp); + cp += strlen((char *)cp) + 1; + fprintf(fp, " %s.", cp); + break; + case T_TXT: + case T_X25: + end = (u_char *)dp->d_data + dp->d_size; + (void) putc('"', fp); + while (cp < end) { + if ((n = *cp++) != '\0') { + for (j = n; j > 0 && cp < end; j--) + if ((*cp < ' ') || (*cp > '~')) { + fprintf(fp, "\\%03d", *cp++); + } else if (*cp == '\\' || *cp =='"') { + putc('\\', fp); + putc(*cp++, fp); + } else + (void) putc(*cp++, fp); + } + if (cp != end) + fputs("\" \"", fp); + } + /* XXXVIX need to keep the segmentation (see 4.9.5). */ + (void) fputs("\"", fp); + break; + case T_NSAP: + (void) fputs(inet_nsap_ntoa(dp->d_size, dp->d_data, NULL), fp); + break; + case T_LOC: + (void) fputs(loc_ntoa(dp->d_data, NULL), fp); + break; + case T_WKS: + GETLONG(addr, cp); + addr = htonl(addr); + fputs(inet_ntoa(*(struct in_addr *)&addr), fp); + proto = protocolname((u_char)*cp); + cp += sizeof(char); + fprintf(fp, "%s ", proto); + i = 0; + while(cp < (u_char *)dp->d_data + dp->d_size) { + j = *cp++; + do { + if (j & 0200) + fprintf(fp, " %s", + servicename(i, proto)); + j <<= 1; + } while (++i & 07); + } + break; + case T_MINFO: + case T_RP: + fprintf(fp, "%s.", cp); + cp += strlen((char *)cp) + 1; + fprintf(fp, " %s.", cp); + break; + case T_KEY: + savecp = cp; /* save the beginning */ + /*>>> Flags (unsigned_16) */ + NS_GET16(keyflags,cp); + fprintf(fp, "0x%04x ", keyflags); + /*>>> Protocol (8-bit decimal) */ + fprintf(fp, "%3u ", *cp++); + /*>>> Algorithm id (8-bit decimal) */ + fprintf(fp, "%3u ", *cp++); + + /*>>> Public-Key Data (multidigit BASE64) */ + /* containing ExponentLen, Exponent, and Modulus */ + i = b64_ntop(cp, dp->d_size - (cp - savecp), + temp_base64, sizeof temp_base64); + if (i < 0) + fprintf(fp, "; BAD BASE64"); + else + fprintf(fp, "%s", temp_base64); + break; + case T_SIG: + sigdata = cp; + /* RRtype (char *) */ + NS_GET16(n,cp); + fprintf(fp, "%s ", p_type(n)); + /* Algorithm id (8-bit decimal) */ + fprintf(fp, "%d ", *cp++); + /* Labels (8-bit decimal) (not saved in file) */ + /* XXXX FIXME -- check value and print err if bad */ + cp++; + /* OTTL (u_long) */ + NS_GET32(n, cp); + fprintf(fp, "%u ", n); + /* Texp (u_long) */ + NS_GET32(n, cp); + fprintf(fp, "%s ", p_secstodate (n)); + /* Tsig (u_long) */ + NS_GET32(n, cp); + fprintf(fp, "%s ", p_secstodate (n)); + /* Kfootprint (unsigned_16) */ + NS_GET16(n, cp); + fprintf(fp, "%u ", n); + /* Signer's Name (char *) */ + fprintf(fp, "%s ", cp); + cp += strlen((char *)cp) + 1; + /* Signature (base64 of any length) */ + i = b64_ntop(cp, dp->d_size - (cp - sigdata), + temp_base64, sizeof temp_base64); + if (i < 0) + fprintf(fp, "; BAD BASE64"); + else + fprintf(fp, "%s", temp_base64); + break; + + case T_NXT: + fprintf(fp, "%s.", cp); + n = strlen ((char *)cp) + 1; + cp += n; + i = 8 * (dp->d_size - n); /* How many bits? */ + for (n = 0; n < (u_int32_t)i; n++) { + if (NS_NXT_BIT_ISSET(n, cp)) + fprintf(fp," %s",__p_type(n)); + } + break; + case ns_t_cert: + certdata = cp; + NS_GET16(n,cp); + fprintf(fp, "%d ", n); /* cert type */ + + NS_GET16(n,cp); + fprintf(fp, "%d %d ", n, *cp++); /* tag & alg */ + + /* Certificate (base64 of any length) */ + i = b64_ntop(cp, dp->d_size - (cp - certdata), + temp_base64, sizeof(temp_base64)); + if (i < 0) + fprintf(fp, "; BAD BASE64"); + else + fprintf(fp, "%s", temp_base64); + break; + case ns_t_aaaa: { + char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; + + (void) fputs(inet_ntop(AF_INET6, dp->d_data, t, sizeof t), fp); + break; + } + default: + fprintf(fp, "\\# %u", dp->d_size); + if (dp->d_size) { + fputs(" ( ", fp); + isc_puthexstring(fp, dp->d_data, dp->d_size, + 28, 48, "\n\t\t\t\t"); + fputs(" )", fp); + } + } +} + +/* + * Return the number of authoritative zones that "dname" could belong to by + * stripping up to "depth" labels from dname. Up to the first "maxzones" + * authoritative zone numbers will be stored in "zonelist", ordered + * deepest match first. + */ +int +findzone(const char *dname, int class, int depth, int *zonelist, int maxzones){ + char *tmpdname; + char tmpdnamebuf[MAXDNAME]; + char *zonename; + int tmpdnamelen, zonenamelen, zonenum, i, j, c; + int matches = 0; + int escaped, found, done; + + ns_debug(ns_log_update, 4, "findzone(dname=%s, class=%d, depth=%d, \ +zonelist=%p, maxzones=%d)", + dname, class, depth, zonelist, maxzones); +#ifdef DEBUG + if (debug >= 5) { + ns_debug(ns_log_update, 5, "zone dump:"); + for (zonenum = 1; zonenum < nzones; zonenum++) + printzoneinfo(zonenum, ns_log_update, 5); + } +#endif + + strcpy(tmpdnamebuf, dname); + tmpdname = tmpdnamebuf; + /* + * The code to handle trailing dots and escapes is adapted + * from ns_samedomain(). + */ + tmpdnamelen = strlen(tmpdname); + /* + * Ignore a trailing label separator (i.e. an unescaped dot) + * in 'tmpdname'. + */ + if (tmpdnamelen && tmpdname[tmpdnamelen-1] == '.') { + escaped = 0; + /* note this loop doesn't get executed if tmpdnamelen==1 */ + for (j = tmpdnamelen - 2; j >= 0; j--) + if (tmpdname[j] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else { + break; + } + if (!escaped) { + tmpdnamelen--; + tmpdname[tmpdnamelen] = '\0'; + } + } + + for (done = i = 0; i <= depth && !done; i++) { + for (zonenum = 1; zonenum < nzones; zonenum++) { + if (zones[zonenum].z_type == z_nil) + continue; + if (zones[zonenum].z_class != class) + continue; + zonename = zones[zonenum].z_origin; + zonenamelen = strlen(zonename); + /* + * Ignore a trailing label separator + * (i.e. an unescaped dot) in 'zonename'. + */ + if (zonenamelen && zonename[zonenamelen-1] == '.') { + escaped = 0; + for (j = zonenamelen - 2; j >= 0; j--) + if (zonename[j] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else { + break; + } + if (!escaped) + zonenamelen--; + } + + if (tmpdnamelen != zonenamelen) + continue; + ns_debug(ns_log_update, 5, + "about to strncasecmp('%s', '%s', %d)", + tmpdname, zonename, tmpdnamelen); + /* XXXRTH I'm doing a special test for zonenamelen == 0 + because I worry that some implementations of + strncasecmp might not handle comparisions where + n==0 correctly */ + if (zonenamelen == 0 || + !strncasecmp(tmpdname, zonename, tmpdnamelen)) { + ns_debug(ns_log_update, 5, "match"); + zonelist[matches++] = zonenum; + if (matches == maxzones) { + /* XXX should signal error */ + return (matches); + } + } + } + + /* + * Strip off the first label if we're not already at + * the root label. + */ + if (*tmpdname != '\0') { + for (escaped = found = 0; + (c = *tmpdname) && !found; + tmpdname++) { + if (!escaped && (c == '.')) + /* + * Note the loop increment will + * make tmpdname point past the '.' + * before the '!found' test causes + * us to exit the loop. + */ + found = 1; + + if (escaped) + escaped = 0; + else if (c == '\\') + escaped = 1; + } + } else + done = 1; + + tmpdnamelen = strlen(tmpdname); + } + ns_debug(ns_log_update, 4, + "findzone: returning %d match(es)", matches); + return (matches); +} + +/* + * reapply lost updates from log file for the zone to the zone + * + * returns -1 on error, 0 on success, 1 if dump reload needed + */ +int +merge_logs(struct zoneinfo *zp, char *logname) { + char origin[MAXDNAME], data[MAXDATA], dnbuf[MAXDNAME], sclass[3]; + char buf[BUFSIZ]; + FILE *fp; + u_int32_t serial, ttl, old_serial, new_serial; + char *dname, *cp, *cp1; + int type, class; + int i, c, section, opcode, matches, zonenum = 0, err, multiline; + int nonempty_lineno = -1, prev_pktdone = 0, cont = 0, inside_next = 0; + int id, rcode = NOERROR; + u_int32_t n; + struct map *mp; + ns_updrec *rrecp; + struct databuf *dp; + struct in_addr ina; + int zonelist[MAXDNAME]; + struct stat st; + struct sockaddr_in empty_from; + int datasize; + unsigned long l; + ns_updque curupd; + unsigned long lutmp; + + empty_from.sin_family = AF_INET; + empty_from.sin_addr.s_addr = htonl(INADDR_ANY); + empty_from.sin_port = htons(0); + + /* XXX - much of this stuff is similar to that in nsupdate.c + * getword_str() was used in nsupdate.c for reasons described there + * getword() is used here just to be consistent with db_load() + */ + + ns_debug(ns_log_update, 3, "merge_logs(%s)", logname); + + /* If there is no log file, just return. */ + if (stat(logname, &st) < 0) { + if (errno != ENOENT) + ns_error(ns_log_update, + "unexpected stat(%s) failure: %s", + logname, strerror(errno)); + return (-1); + } + fp = fopen(logname, "r"); + if (fp == NULL) { + ns_error(ns_log_update, "fopen(%s) failed: %s", + logname, strerror(errno)); + return (-1); + } + + /* + * See if we really have a log file -- it might be a zone dump + * that was in the process of being isc_movefiled, or it might + * be garbage! + */ + + if (fgets(buf, sizeof(buf), fp)==NULL) { + ns_error(ns_log_update, "fgets() from %s failed: %s", + logname, strerror(errno)); + fclose(fp); + return (-1); + } + if (strcmp(buf, DumpSignature) == 0) { + /* It's a dump; finish isc_movefile that was interrupted. */ + ns_info(ns_log_update, + "completing interrupted dump isc_movefile for %s", + zp->z_source); + fclose(fp); + if (isc_movefile(logname, zp->z_source) < 0) { + ns_error(ns_log_update, + "isc_movefile(%s,%s) failed: %s :1", + logname, zp->z_source, + strerror(errno)); + return (-1); + } + /* Finally, tell caller to reload zone. */ + return (1); + } + if (strcmp(buf, LogSignature) != 0) { + /* Not a dump and not a log; complain and then bail out. */ + ns_error(ns_log_update, "invalid log file %s", + logname); + fclose(fp); + return (-1); + } + + ns_debug(ns_log_update, 3, "merging logs for %s from %s", + zp->z_origin, logname); + lineno = 1; + INIT_LIST(curupd); + for (;;) { + err = 0; + dname = NULL; + if (!getword(buf, sizeof buf, fp, 0)) { + if (lineno == (nonempty_lineno + 1) && !(feof(fp))) { + /* + * End of a nonempty line inside an update + * packet or not inside an update packet. + */ + continue; + } + /* + * Empty line or EOF. + * + * Marks completion of current update packet. + */ + inside_next = 0; + prev_pktdone = 1; + cont = 1; + } else { + nonempty_lineno = lineno; + } + + if (!strcasecmp(buf, "[DYNAMIC_UPDATE]") || + !strcasecmp(buf, "[IXFR_UPDATE]")) { + err = 0; + rcode = NOERROR; + cp = fgets(buf, sizeof buf, fp); + if (cp != NULL) + lineno++; + if (cp == NULL || !sscanf((char *)cp, "id %d", &id)) + id = -1; + inside_next = 1; + prev_pktdone = 1; + cont = 1; + } else if (!strcasecmp(buf, "[INCR_SERIAL]")) { + /* XXXRTH not enough error checking here */ + cp = fgets(buf, sizeof buf, fp); + if (cp != NULL) + lineno++; + if (cp == NULL || + !sscanf((char *)cp, "from %u to %u", + &old_serial, &new_serial)) { + ns_error(ns_log_update, + "incr_serial problem with %s", + logname); + } else { + serial = get_serial(zp); + if (serial != old_serial) { + ns_error(ns_log_update, + "serial number mismatch (log=%u, zone=%u) in %s", old_serial, + serial, logname); + } else { + set_serial(zp, new_serial); + /* + * The zone has changed; make sure + * a dump is scheduled. + */ + (void)schedule_dump(zp); + sched_zone_maint(zp); + ns_info(ns_log_update, + "set serial to %u (log file %s)", + new_serial, logname); + } + } + prev_pktdone = 1; + cont = 1; + } else if (!strcasecmp(buf, "[END_DELTA]")) { + prev_pktdone = 1; + cont = 1; + } + if (prev_pktdone) { + if (!EMPTY(curupd)) { + n = process_updates(&curupd, &rcode, + empty_from); + free_rrecp(&curupd, rcode, empty_from); + if (n > 0) + ns_info(ns_log_update, + "successfully merged update id %d from log file %s", + id, logname); + else { + ns_error(ns_log_update, + "error merging update id %d from log file %s", + id, logname); + fclose(fp); + return(-1); + } + } + prev_pktdone = 0; + if (feof(fp)) + break; + } + if (cont) { + cont = 0; + continue; + } + if (!inside_next) + continue; + /* + * inside the same update packet, + * continue accumulating records. + */ + section = -1; + n = strlen(buf); + if (buf[n-1] == ':') + buf[--n] = '\0'; + for (mp = m_section; mp < m_section+M_SECTION_CNT; mp++) + if (!strcasecmp(buf, mp->token)) { + section = mp->val; + break; + } + ttl = 0; + type = -1; + class = zp->z_class; + n = 0; + data[0] = '\0'; + switch (section) { + case S_ZONE: + cp = fgets(buf, sizeof buf, fp); + if (!cp) + *buf = '\0'; + n = sscanf(cp, "origin %s class %s serial %lu", + origin, sclass, &lutmp); + serial = lutmp; + if (n != 3 || ns_samename(origin, zp->z_origin) != 1) + err++; + if (cp) + lineno++; + if (!err && serial != zp->z_serial) { + ns_error(ns_log_update, + "serial number mismatch in update id %d (log=%u, zone=%u) in %s", + id, serial, zp->z_serial, + logname); + inside_next = 0; + err++; + } + if (!err && inside_next) { + int success; + + dname = origin; + type = T_SOA; + class = res_nametoclass(sclass, &success); + if (!success) { + err++; + break; + } + matches = findzone(dname, class, 0, + zonelist, MAXDNAME); + if (matches) + zonenum = zonelist[0]; + else + err++; + } + break; + case S_PREREQ: + case S_UPDATE: + /* Operation code. */ + if (!getword(buf, sizeof buf, fp, 0)) { + err++; + break; + } + opcode = -1; + if (buf[0] == '{') { + n = strlen(buf); + for (i = 0; (u_int32_t)i < n; i++) + buf[i] = buf[i+1]; + if (buf[n-2] == '}') + buf[n-2] = '\0'; + } + for (mp = m_opcode; mp < m_opcode+M_OPCODE_CNT; mp++) + if (!strcasecmp(buf, mp->token)) { + opcode = mp->val; + break; + } + if (opcode == -1) { + err++; + break; + } + /* Owner's domain name. */ + if (!getword((char *)dnbuf, sizeof dnbuf, fp, 1)) { + err++; + break; + } + n = strlen((char *)dnbuf) - 1; + if (dnbuf[n] == '.') + dnbuf[n] = '\0'; + dname = dnbuf; + ttl = 0; + type = -1; + class = zp->z_class; + n = 0; + data[0] = '\0'; + (void) getword(buf, sizeof buf, fp, 1); + if (isdigit(buf[0])) { /* ttl */ + if (ns_parse_ttl(buf, &l) < 0) { + err++; + break; + } + ttl = l; + (void) getword(buf, sizeof buf, fp, 1); + } + + /* possibly class */ + if (buf[0] != '\0') { + int success; + int maybe_class; + + maybe_class = res_nametoclass(buf, &success); + if (success) { + class = maybe_class; + (void) getword(buf, + sizeof buf, + fp, 1); + } + } + /* possibly type */ + if (buf[0] != '\0') { + int success; + int maybe_type; + + maybe_type = res_nametotype(buf, &success); + + if (success) { + type = maybe_type; + (void) getword(buf, + sizeof buf, + fp, 1); + } + } + if (buf[0] != '\0') /* possibly rdata */ + /* + * Convert the ascii data 'buf' to the proper + * format based on the type and pack into + * 'data'. + * + * XXX - same as in db_load(), + * consolidation needed + */ + switch (type) { + case T_A: + if (!inet_aton(buf, &ina)) { + err++; + break; + } + n = ntohl(ina.s_addr); + cp = data; + PUTLONG(n, cp); + n = INT32SZ; + break; + case T_HINFO: + case T_ISDN: + n = strlen(buf); + data[0] = n; + memcpy(data+1, buf, n); + n++; + if (!getword(buf, sizeof buf, + fp, 0)) { + i = 0; + } else { + endline(fp); + i = strlen(buf); + } + data[n] = i; + memcpy(data+n+1, buf, i); + break; + case T_SOA: + case T_MINFO: + case T_RP: + (void) strcpy(data, buf); + cp = data + strlen(data) -1; + *(cp++) = 0; /* ditch dot */ + if (!getword((char *)cp, + sizeof data - (cp - data), + fp, 1)) { + err++; + break; + } + cp += strlen((char *)cp) -1; + *(cp++) = 0; /* ditch dot */ + if (type != T_SOA) { + n = cp - data; + break; + } + else + n = cp - data; + if (class != zp->z_class || + ns_samename(dname, zp->z_origin) != 1) { + err++; + break; + } + c = getnonblank(fp, logname, 1); + if (c == '(') { + multiline = 1; + } else { + multiline = 0; + ungetc(c, fp); + } + n = getnum(fp, logname, GETNUM_SERIAL, + &multiline); + if (getnum_error) { + err++; + break; + } + PUTLONG(n, cp); + for (i = 0; i < 4; i++) { + if (getttl(fp, logname, lineno, + &n, &multiline) <= 0) + { + err++; + break; + } + PUTLONG(n, cp); + } + if (multiline) { + c = getnonblank(fp, logname, 1); + if (c != ')') { + ungetc(c, fp); + err++; + break; + } + } + n = cp - data; + endline(fp); + break; + case T_WKS: + if (!inet_aton(buf, &ina)) { + err++; + break; + } + n = ntohl(ina.s_addr); + cp = data; + PUTLONG(n, cp); + *cp = (char)getprotocol(fp, + logname + ); + n = INT32SZ + sizeof(char); + n = getservices((int)n, data, + fp, logname); + break; + case T_NS: + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_PTR: + (void) strcpy(data, buf); + if (makename(data, origin, + sizeof(data)) == -1) { + err++; + break; + } + n = strlen(data) + 1; + break; + case T_MX: + case T_AFSDB: + case T_RT: + n = 0; + cp = buf; + while (isdigit(*cp)) + n = n * 10 + (*cp++ - '0'); + /* catch bad values */ + cp = data; + PUTSHORT((u_int16_t)n, cp); + if (!getword(buf, sizeof(buf), + fp, 1)) { + err++; + break; + } + (void) strcpy((char *)cp, buf); + if (makename((char *)cp, origin, + sizeof(data) - (cp-data)) + == -1) { + err++; + break; + } + /* advance pointer to end of data */ + cp += strlen((char *)cp) +1; + /* now save length */ + n = (cp - data); + break; + case T_PX: + n = 0; + data[0] = '\0'; + cp = buf; + while (isdigit(*cp)) + n = n * 10 + (*cp++ - '0'); + cp = data; + PUTSHORT((u_int16_t)n, cp); + for (i = 0; i < 2; i++) { + if (!getword(buf, + sizeof(buf), + fp, 0)) { + err++; + break; + } + (void) strcpy((char *)cp, + buf); + cp += strlen((char *)cp) + 1; + } + n = cp - data; + break; + case T_TXT: + case T_X25: + i = strlen(buf); + cp = data; + datasize = sizeof data; + cp1 = buf; + while (i > MAXCHARSTRING) { + if (datasize <= MAXCHARSTRING){ + ns_error(ns_log_update, + "record too big"); + fclose(fp); + return (-1); + } + datasize -= MAXCHARSTRING; + *cp++ = (char)MAXCHARSTRING; + memcpy(cp, cp1, MAXCHARSTRING); + cp += MAXCHARSTRING; + cp1 += MAXCHARSTRING; + i -= MAXCHARSTRING; + } + if (datasize < i + 1) { + ns_error(ns_log_update, + "record too big"); + fclose(fp); + return (-1); + } + *cp++ = i; + memcpy(cp, cp1, i); + cp += i; + n = cp - data; + endline(fp); + /* XXXVIX: segmented texts 4.9.5 */ + break; + case T_NSAP: + n = inet_nsap_addr(buf, + (u_char *)data, + sizeof data); + endline(fp); + break; + case T_LOC: + cp = buf + (n = strlen(buf)); + *cp = ' '; + cp++; + while ((i = getc(fp), *cp = i, + i != EOF) + && *cp != '\n' + && (n < MAXDATA)) { + cp++; + n++; + } + if (*cp == '\n') + ungetc(*cp, fp); + *cp = '\0'; + n = loc_aton(buf, (u_char *)data); + if (n == 0) { + err++; + break; + } + endline(fp); + break; + case ns_t_sig: + case ns_t_key: + case ns_t_nxt: + case ns_t_cert: + { + const char * errmsg = NULL; + int s; + + s = parse_sec_rdata(buf, sizeof(buf), + 1, + (u_char *)data, + sizeof(data), + fp, zp, dnbuf, + ttl, type, + domain_ctx, + primary_trans, + &errmsg); + if (s < 0) { + err++; + break; + } + break; + } + default: + if (strcmp(buf, "\\#") != 0) { + err++; + break; + } + if (!getword(buf, sizeof buf, fp, 0) || + !isdigit((unsigned char)buf[0])) { + err++; + break; + } + n = strtoul(buf, &cp, 10); + if (n > 0xffff || *cp != '\0') { + err++; + break; + } + multiline = 0; + i = isc_gethexstring((u_char *)data, + sizeof(data), + n, fp, &multiline); + if (i == -1) { + err++; + break; + } + if (multiline) { + c = getnonblank(fp, + zp->z_updatelog, + 1); + if (c != ')') { + ungetc(c, fp); + err++; + break; + } + multiline = 0; + } + endline(fp); + } + if (section == S_PREREQ) { + ttl = 0; + if (opcode == NXDOMAIN) { + class = C_NONE; + type = T_ANY; + n = 0; + } else if (opcode == YXDOMAIN) { + class = C_ANY; + type = T_ANY; + n = 0; + } else if (opcode == NXRRSET) { + class = C_NONE; + n = 0; + } else if (opcode == YXRRSET) { + if (n == 0) + class = C_ANY; + } + } else { /* section == S_UPDATE */ + if (opcode == DELETE) { + ttl = 0; + if (n == 0) { + class = C_ANY; + if (type == -1) + type = T_ANY; + /* WTF? C_NONE or C_ANY _must_ be the case if + * we really are to delete this. If + * C_NONE is used, according to process_updates(), + * the class is gotten from the zone's class. + * This still isn't perfect, but it will at least + * work. + * + * Question: What is so special about the class + * of the update while we are deleting?? + */ + } else /* if (zp->z_xferpid != XFER_ISIXFR) */ { + class = C_NONE; + } + } + } + break; + case S_ADDT: + default: + ns_debug(ns_log_update, 1, + "cannot interpret section: %d", section); + inside_next = 0; + err++; + } + if (err) { + ns_debug(ns_log_update, 1, + "merge of update id %d failed due to error at line %d", + id, lineno); + free_rrecp(&curupd, FORMERR, empty_from); + fclose(fp); + return(-1); + } + rrecp = res_mkupdrec(section, dname, class, type, ttl); + if (section != S_ZONE) { + dp = savedata(class, type, ttl, (u_char *)data, n); + dp->d_zone = zonenum; + dp->d_cred = DB_C_ZONE; + dp->d_clev = nlabels(zp->z_origin); + dp->d_secure = DB_S_INSECURE; /* should be UNCHECKED */ + rrecp->r_dp = dp; + } else { + rrecp->r_zone = zonenum; + } + APPEND(curupd, rrecp, r_link); + } /* for (;;) */ + INSIST(EMPTY(curupd)); + fclose(fp); + return (0); +} + + +/* + * Create a disk database to back up zones + */ +int +zonedump(struct zoneinfo *zp, int mode) { + FILE *fp; + const char *fname; + struct hashbuf *htp; + char *op; + struct stat st; + char tmp_name[MAXPATHLEN]; + int escaped; + char c; + + /* + * We must check to see if Z_NEED_SOAUPDATE is set, and if so + * we must do it. This won't be the case normally + * (when called from ns_maint()), but it is possible if we're + * exiting named. + */ + + if (zp->z_flags & Z_NEED_SOAUPDATE) { + u_int32_t serial, old_serial; + + old_serial = get_serial(zp); + serial = old_serial + 1; + if (serial == 0) + serial = 1; + set_serial(zp, serial); + } + + /* Only dump zone if there is a cache specified */ + if (zp->z_source && *(zp->z_source)) { + ns_debug(ns_log_update, 1, "zonedump(%s)", zp->z_source); + + if (strlen(zp->z_source)+strlen(DumpSuffix) >= MAXPATHLEN) { + ns_error(ns_log_update, + "filename %s too long in zonedump", + zp->z_source); + /* + * This problem won't ever get better, so we + * clear the "need dump" flag. + */ + zp->z_flags &= ~Z_NEED_DUMP; + return (-1); + } + (void)sprintf(tmp_name, "%s%s", zp->z_source, DumpSuffix); + if ((fp = write_open(tmp_name)) == NULL) { + ns_error(ns_log_update, "fopen() of %s failed: %s", + tmp_name, strerror(errno)); + return (-1); + } + fprintf(fp, "%s", DumpSignature); + op = zp->z_origin; + escaped = 0; + while (*op && (((c = *op++) != '.') || escaped)) + escaped = (c == '\\') && !escaped; + gettime(&tt); + htp = hashtab; + if (nlookup(zp->z_origin, &htp, &fname, 0) != NULL) { + if (db_dump(htp, fp, zp-zones, op) != OK) { + ns_error(ns_log_update, + "error dumping zone file %s", + zp->z_source); + (void)fclose(fp); + return (-1); + } + } + if (fflush(fp) == EOF) { + ns_error(ns_log_update, "fflush() of %s failed: %s", + tmp_name, strerror(errno)); + fclose(fp); + return (-1); + } + if (fsync(fileno(fp)) < 0) { + ns_error(ns_log_update, "fsync() of %s failed: %s", + tmp_name, strerror(errno)); + fclose(fp); + return (-1); + } + if (fclose(fp) == EOF) { + ns_error(ns_log_update, "fclose() of %s failed: %s", + tmp_name, strerror(errno)); + return (-1); + } + /* + * Try to make read only, so people will be less likely to + * edit dynamic domains. + */ + if (stat(tmp_name, &st) < 0) { + ns_error(ns_log_update, + "stat(%s) failed, pressing on: %s", + tmp_name, strerror(errno)); + } else { + zp->z_ftime = st.st_mtime; + st.st_mode &= ~WRITEABLE_MASK; + if (chmod(tmp_name, st.st_mode) < 0) + ns_error(ns_log_update, + "chmod(%s,%o) failed, pressing on: %s", + tmp_name, st.st_mode, + strerror(errno)); + } + + if (mode == ISIXFR) { + if (isc_movefile(tmp_name, zp->z_ixfr_tmp) < 0) { + ns_error(ns_log_update, + "isc_movefile(%s,%s) failed: %s :2", + tmp_name, zp->z_ixfr_tmp, + strerror(errno)); + return (-1); + } + if (chmod(zp->z_source, 0644) < 0) + ns_error(ns_log_update, + "chmod(%s,%o) failed, pressing on: %s", + zp->z_source, st.st_mode, + strerror(errno)); + if (isc_movefile(zp->z_ixfr_tmp, zp->z_source) < 0) { + ns_error(ns_log_update, + "isc_movefile(%s,%s) failed: %s :3", + zp->z_ixfr_tmp, zp->z_source, + strerror(errno)); + return (-1); + } + st.st_mode &= ~WRITEABLE_MASK; + if (chmod(zp->z_source, st.st_mode) < 0) + ns_error(ns_log_update, + "chmod(%s,%o) failed, pressing on: %s", + zp->z_source, st.st_mode, + strerror(errno)); + } else if (mode == ISNOTIXFR) { + if (isc_movefile(tmp_name, zp->z_updatelog) < 0) { + ns_error(ns_log_update, + "isc_movefile(%s,%s) failed: %s :4", + tmp_name, zp->z_updatelog, + strerror(errno)); + return (-1); + } + if (isc_movefile(zp->z_updatelog, zp->z_source) < 0) { + ns_error(ns_log_update, + "isc_movefile(%s,%s) failed: %s :5", + zp->z_updatelog, zp->z_source, + strerror(errno)); + return (-1); + } + } else { + if (isc_movefile(tmp_name, zp->z_source) < 0) { + ns_error(ns_log_update, + "isc_movefile(%s,%s) failed: %s :6", + tmp_name, zp->z_source, + strerror(errno)); + return (-1); + } + } + } else + ns_debug(ns_log_update, 1, "zonedump: no zone to dump"); + + zp->z_flags &= ~Z_NEED_DUMP; + zp->z_dumptime = 0; + return (0); +} + +struct databuf * +findzonesoa(struct zoneinfo *zp) { + struct hashbuf *htp; + struct namebuf *np; + struct databuf *dp; + const char *fname; + + htp = hashtab; + np = nlookup(zp->z_origin, &htp, &fname, 0); + if (np == NULL || fname != zp->z_origin) + return (NULL); + foreach_rr(dp, np, T_SOA, zp->z_class, zp - zones) + return (dp); + return (NULL); +} + +u_char * +findsoaserial(u_char *data) { + char *cp = (char *)data; + + cp += strlen(cp) + 1; /* Nameserver. */ + cp += strlen(cp) + 1; /* Mailbox. */ + return ((u_char *)cp); +} + +u_int32_t +get_serial_unchecked(struct zoneinfo *zp) { + struct databuf *dp; + u_char *cp; + u_int32_t ret; + + dp = findzonesoa(zp); + if (!dp) + ns_panic(ns_log_update, 1, + "get_serial_unchecked(%s): can't locate zone SOA", + zp->z_origin); + cp = findsoaserial(dp->d_data); + GETLONG(ret, cp); + return (ret); +} + +u_int32_t +get_serial(struct zoneinfo *zp) { + u_int32_t ret; + + ret = get_serial_unchecked(zp); + if (ret != zp->z_serial) + ns_panic(ns_log_update, 1, + "get_serial(%s): db and zone serial numbers differ", + zp->z_origin); + return (ret); +} + +void +set_serial(struct zoneinfo *zp, u_int32_t serial) { + struct databuf *dp; + u_char *cp; + + dp = findzonesoa(zp); + if (!dp) + ns_panic(ns_log_update, 1, + "set_serial(%s): can't locate zone SOA", + zp->z_origin); + cp = findsoaserial(dp->d_data); + PUTLONG(serial, cp); + zp->z_serial = serial; + zp->z_flags &= ~Z_NEED_SOAUPDATE; + zp->z_soaincrtime = 0; + zp->z_updatecnt = 0; +#ifdef BIND_NOTIFY + if (!loading) + ns_notify(zp->z_origin, zp->z_class, ns_t_soa); +#endif + /* + * Note: caller is responsible for scheduling a dump. + */ +} + +/* + * Increment serial number in zoneinfo structure and hash table SOA databuf + */ + +int +incr_serial(struct zoneinfo *zp) { + u_int32_t serial, old_serial; + FILE *fp, *ifp; + time_t t; + struct databuf *dp, *olddp; + unsigned char *cp; + + old_serial = get_serial(zp); + serial = old_serial + 1; + if (serial == 0) + serial = 1; + set_serial(zp, serial); + + (void) gettime(&tt); + t = (time_t)tt.tv_sec; + fp = open_transaction_log(zp); + if (fp == NULL) + return (-1); + fprintf(fp, "[INCR_SERIAL] from %u to %u %s\n", + old_serial, serial, checked_ctime(&t)); + if (close_transaction_log(zp, fp)<0) + return (-1); + if (zp->z_maintain_ixfr_base) { + ifp = open_ixfr_log(zp); + if (ifp == NULL) + return (-1); + dp = findzonesoa(zp); + if (dp) { + olddp = memget(BIND_DATASIZE(dp->d_size)); + if (olddp != NULL) { + memcpy(olddp, dp, BIND_DATASIZE(dp->d_size)); + cp = findsoaserial(olddp->d_data); + PUTLONG(old_serial, cp); + fprintf(ifp, "update: {delete} %s. %u %s %s ", + zp->z_origin, dp->d_ttl, + p_class(dp->d_class), + p_type(dp->d_type)); + (void) rdata_dump(olddp, ifp); + fprintf(ifp, "\n"); + memput(olddp, BIND_DATASIZE(dp->d_size)); + } + fprintf(ifp, "update: {add} %s. %u %s %s ", + zp->z_origin, dp->d_ttl, + p_class(dp->d_class), p_type(dp->d_type)); + (void) rdata_dump(dp, ifp); + fprintf(ifp, "\n"); + } + fprintf(ifp, "[END_DELTA]\n"); + if (close_ixfr_log(zp, ifp) < 0) + return (-1); + } + + /* + * This shouldn't happen, but we check to be sure. + */ + if (!(zp->z_flags & Z_NEED_DUMP)) { + ns_warning(ns_log_update, + "incr_serial: Z_NEED_DUMP not set for zone '%s'", + zp->z_origin); + (void)schedule_dump(zp); + } + + sched_zone_maint(zp); + + return (0); +} + +void +dynamic_about_to_exit(void) { + struct zoneinfo *zp; + + ns_debug(ns_log_update, 1, + "shutting down; dumping zones that need it"); + for (zp = zones; zp < &zones[nzones]; zp++) { + if ((zp->z_flags & Z_DYNAMIC) && + ((zp->z_flags & Z_NEED_SOAUPDATE) || + (zp->z_flags & Z_NEED_DUMP))) + (void)zonedump(zp, ISNOTIXFR); + } +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_update.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_xfr.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_xfr.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_xfr.c (revision 109985) @@ -0,0 +1,871 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_xfr.c,v 8.69 2002/06/05 03:53:49 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "port_after.h" + +#include "named.h" + +static struct qs_x_lev *sx_freelev(struct qs_x_lev *lev); + +static int sx_flush(struct qstream *qsp), + sx_addrr(struct qstream *qsp, + const char *dname, + struct databuf *dp), + sx_nsrrs(struct qstream *qsp), + sx_allrrs(struct qstream *qsp), + sx_pushlev(struct qstream *qsp, struct namebuf *np); +static struct databuf *db_next(struct databuf *dp); + +/* + * void + * ns_xfr(qsp, znp, zone, class, type, opcode, id, serial_ixfr, in_tsig) + * Initiate a concurrent (event driven) outgoing zone transfer. + */ +void +ns_xfr(struct qstream *qsp, struct namebuf *znp, + int zone, int class, int type, + int opcode, int id, u_int32_t serial_ixfr, struct tsig_record *in_tsig) +{ + server_info si; +#ifdef SO_SNDBUF + static const int sndbuf = XFER_BUFSIZE * 2; +#endif +#ifdef SO_SNDLOWAT + static const int sndlowat = XFER_BUFSIZE; +#endif + ns_deltalist *changes; + + switch (type) { + case ns_t_ixfr: + ns_info(ns_log_xfer_out, + "zone transfer (%s) of \"%s\" (%s) to %s serial %u -> %u", + p_type(type), zones[zone].z_origin, p_class(class), + sin_ntoa(qsp->s_from), serial_ixfr, + zones[zone].z_serial); + break; + case ns_t_axfr: /*FALLTHROUGH*/ +#ifdef BIND_ZXFR + case ns_t_zxfr: +#endif + ns_info(ns_log_xfer_out, + "zone transfer (%s) of \"%s\" (%s) to %s serial %u", + p_type(type), zones[zone].z_origin, p_class(class), + sin_ntoa(qsp->s_from), zones[zone].z_serial); + break; + default: + ns_warning(ns_log_xfer_out, + "unsupported XFR (type %s) of \"%s\" (%s) to %s", + p_type(type), zones[zone].z_origin, p_class(class), + sin_ntoa(qsp->s_from)); + goto abort; + } + +#ifdef SO_SNDBUF + /* + * The default seems to be 4K, and we'd like it to have enough room + * to parallelize sending the pushed data with accumulating more + * write() data from us. + */ + (void) setsockopt(qsp->s_rfd, SOL_SOCKET, SO_SNDBUF, + (const char *)&sndbuf, sizeof sndbuf); +#endif +#ifdef SO_SNDLOWAT + /* + * We don't want select() to show writability 'til we can write + * an XFER_BUFSIZE block of data. + */ + (void) setsockopt(qsp->s_rfd, SOL_SOCKET, SO_SNDLOWAT, + (const char *)&sndlowat, sizeof sndlowat); +#endif + if (sq_openw(qsp, 64*1024) == -1) { + ns_error(ns_log_xfer_out, "ns_xfr: out of memory"); + goto abort; + } + memset(&qsp->xfr, 0, sizeof qsp->xfr); + qsp->xfr.top.axfr = znp; + qsp->xfr.zone = zone; + qsp->xfr.class = class; + if (qsp->flags & STREAM_AXFRIXFR) + type = ns_t_axfr; + qsp->xfr.type = type; + qsp->xfr.id = id; + qsp->xfr.opcode = opcode; + qsp->xfr.msg = memget(XFER_BUFSIZE); + if (!qsp->xfr.msg) { + ns_error(ns_log_xfer_out, "ns_xfr: out of memory"); + goto abort; + } + qsp->xfr.eom = qsp->xfr.msg + XFER_BUFSIZE; + qsp->xfr.cp = NULL; + qsp->xfr.state = s_x_firstsoa; + zones[zone].z_numxfrs++; + qsp->flags |= STREAM_AXFR; + +#ifdef BIND_ZXFR + if (type == ns_t_zxfr) { + enum { rd = 0, wr = 1 }; + int z[2]; + pid_t p; + + if (pipe(z) < 0) { + ns_error(ns_log_xfer_out, "pipe: %s", strerror(errno)); + goto abort; + } + p = vfork(); + if (p < 0) { + ns_error(ns_log_xfer_out, "vfork: %s", strerror(errno)); + goto abort; + } + if (p == 0) { + /* Child. */ + dup2(z[rd], STDIN_FILENO); + dup2(qsp->s_rfd, STDOUT_FILENO); + execlp("gzip", "gzip", NULL); + ns_error(ns_log_xfer_out, "execlp: %s", strerror(errno)); + _exit(1); + } + ns_info(ns_log_xfer_out, "zxfr gzip pid %lu", p); + /* Parent. */ + dup2(z[wr], qsp->s_rfd); + close(z[wr]); + close(z[rd]); + + /* When a ZXFR completes, there can be no more requests. */ + qsp->flags |= STREAM_DONE_CLOSE; + } +#endif + + si = find_server(qsp->s_from.sin_addr); + if (si != NULL && si->transfer_format != axfr_use_default) + qsp->xfr.transfer_format = si->transfer_format; + else + qsp->xfr.transfer_format = server_options->transfer_format; + if (in_tsig == NULL) { + qsp->xfr.tsig_state = NULL; + qsp->xfr.tsig_size = 0; + } else { + qsp->xfr.tsig_state = memget(sizeof(ns_tcp_tsig_state)); + ns_sign_tcp_init(in_tsig->key, in_tsig->sig, in_tsig->siglen, + qsp->xfr.tsig_state); + qsp->xfr.tsig_skip = 0; + qsp->xfr.tsig_size = in_tsig->tsig_size; + } + + if (type == ns_t_ixfr) { + changes = ixfr_get_change_list(&zones[zone], serial_ixfr, + zones[zone].z_serial); + ixfr_log_maint(&zones[zone]); + if (changes != NULL) { + qsp->xfr.serial = serial_ixfr; + qsp->xfr.top.ixfr = changes; + } + else { + qsp->xfr.top.ixfr = NULL; + goto abort; + } + } else { + if (sx_pushlev(qsp, znp) < 0) { + ns_error(ns_log_xfer_out, "ns_xfr: out of memory"); + abort: + (void) shutdown(qsp->s_rfd, 2); + sq_remove(qsp); + return; + } + } + if (type != ns_t_ixfr) { + ns_debug(ns_log_default, 3, "sq_writeh sx_sendsoa (%s)", + zones[zone].z_origin); + (void) sq_writeh(qsp, sx_sendsoa); + } else { + ns_debug(ns_log_default, 3, "sq_writeh sx_send_ixfr (%s)", + zones[zone].z_origin); + (void) sq_writeh(qsp, sx_send_ixfr); + } +} + +/* + * void + * ns_stopxfrs(zp) + * Stop (abort, reset) all transfers of the zone specified by 'zp'. + */ +void +ns_stopxfrs(struct zoneinfo *zp) { + struct qstream *this, *next; + u_int zone = (u_int)(zp - zones); + + ns_debug(ns_log_default, 3, "ns_stopxfrs (%s)", zp->z_origin); + + for (this = streamq; this; this = next) { + next = this->s_next; + if (this->xfr.zone == zone) { + (void) shutdown(this->s_rfd, 2); + sq_remove(this); + } + } + INSIST(zp->z_numxfrs == 0); +} + +/* + * void + * ns_freexfr(qsp) + * Free all xfr-related dynamic data associated with qsp. + */ +void +ns_freexfr(struct qstream *qsp) { + ns_delta *dp; + ns_updrec *rp; + + if (qsp->xfr.msg != NULL) { + memput(qsp->xfr.msg, XFER_BUFSIZE); + qsp->xfr.msg = NULL; + } + if (qsp->xfr.type == ns_t_ixfr && qsp->xfr.top.ixfr != NULL) { + while ((dp = HEAD(*qsp->xfr.top.ixfr)) != NULL) { + UNLINK(*qsp->xfr.top.ixfr, dp, d_link); + while ((rp = HEAD(dp->d_changes)) != NULL) { + UNLINK(dp->d_changes, rp, r_link); + if (rp->r_dp != NULL) + db_detach(&rp->r_dp); + res_freeupdrec(rp); + } + memput(dp, sizeof *dp); + } + memput(qsp->xfr.top.ixfr, sizeof *qsp->xfr.top.ixfr); + qsp->xfr.top.ixfr = NULL; + } + while (qsp->xfr.lev) + qsp->xfr.lev = sx_freelev(qsp->xfr.lev); + if (qsp->xfr.tsig_state != NULL) { + memput(qsp->xfr.tsig_state, sizeof(ns_tcp_tsig_state)); + qsp->xfr.tsig_state = NULL; + } + zones[qsp->xfr.zone].z_numxfrs--; + qsp->flags &= ~(STREAM_AXFR | STREAM_AXFRIXFR); +} + +/* + * u_char * + * sx_newmsg(msg) + * init the header of a message, reset the compression pointers, and + * reset the write pointer to the first byte following the header. + */ +void +sx_newmsg(struct qstream *qsp) { + HEADER *hp = (HEADER *)qsp->xfr.msg; + + memset(hp, 0, HFIXEDSZ); + hp->id = htons(qsp->xfr.id); + hp->opcode = qsp->xfr.opcode; + hp->qr = 1; + hp->rcode = NOERROR; + + qsp->xfr.ptrs[0] = qsp->xfr.msg; + qsp->xfr.ptrs[1] = NULL; + + qsp->xfr.cp = qsp->xfr.msg + HFIXEDSZ; + + qsp->xfr.eom = qsp->xfr.msg + XFER_BUFSIZE; + + if (qsp->xfr.tsig_state != NULL) + qsp->xfr.eom -= TSIG_BUF_SIZE; +} + +/* + * int + * sx_flush(qsp) + * flush the intermediate buffer out to the stream IO system. + * return: + * passed through from sq_write(). + */ +static int +sx_flush(struct qstream *qsp) { + int ret; + +#ifdef DEBUG + if (debug >= 10) + res_pquery(&res, qsp->xfr.msg, qsp->xfr.cp - qsp->xfr.msg, + log_get_stream(packet_channel)); +#endif + if (qsp->xfr.tsig_state != NULL && qsp->xfr.tsig_skip == 0) { + int msglen = qsp->xfr.cp - qsp->xfr.msg; + + ns_sign_tcp(qsp->xfr.msg, &msglen, qsp->xfr.eom - qsp->xfr.msg, + NOERROR, qsp->xfr.tsig_state, + qsp->xfr.state == s_x_done); + + if (qsp->xfr.state == s_x_done) { + memput(qsp->xfr.tsig_state, sizeof(ns_tcp_tsig_state)); + qsp->xfr.tsig_state = NULL; + } + qsp->xfr.cp = qsp->xfr.msg + msglen; + + } + ret = sq_write(qsp, qsp->xfr.msg, qsp->xfr.cp - qsp->xfr.msg); + if (ret >= 0) { + qsp->xfr.cp = NULL; + qsp->xfr.tsig_skip = 0; + } + else + qsp->xfr.tsig_skip = 1; + return (ret); +} + +/* + * int + * sx_addrr(qsp, name, dp) + * add name/dp's RR to the current assembly message. if it won't fit, + * write current message out, renew the message, and then RR *must* fit. + * return: + * -1 = the sx_flush() failed so we could not queue the full message. + * 0 = one way or another, everything is fine. + * side effects: + * on success, the ANCOUNT is incremented and the pointers are advanced. + */ +static int +sx_addrr(struct qstream *qsp, const char *dname, struct databuf *dp) { + HEADER *hp = (HEADER *)qsp->xfr.msg; + u_char **edp = qsp->xfr.ptrs + sizeof qsp->xfr.ptrs / sizeof(u_char*); + int n, type; + + if (qsp->xfr.cp != NULL) { + if (qsp->xfr.transfer_format == axfr_one_answer && + sx_flush(qsp) < 0) + return (-1); + } + if (qsp->xfr.cp == NULL) + sx_newmsg(qsp); + + /* + * Add question to first answer. + */ + if (qsp->xfr.state == s_x_firstsoa && dp->d_type == T_SOA) { + n = dn_comp(dname, qsp->xfr.cp, qsp->xfr.eom - qsp->xfr.cp, + qsp->xfr.ptrs, edp); + if (n > 0 && (qsp->xfr.cp + n + INT16SZ * 2) <= qsp->xfr.eom) { + qsp->xfr.cp += n; + if (qsp->xfr.type == ns_t_zxfr) + type = ns_t_axfr; + else if ((qsp->flags & STREAM_AXFRIXFR) != 0) + type = ns_t_ixfr; + else + type = qsp->xfr.type; + PUTSHORT((u_int16_t) type, qsp->xfr.cp); + PUTSHORT((u_int16_t) qsp->xfr.class, qsp->xfr.cp); + hp->qdcount = htons(ntohs(hp->qdcount) + 1); + } + } + + n = make_rr(dname, dp, qsp->xfr.cp, qsp->xfr.eom - qsp->xfr.cp - + qsp->xfr.tsig_size, 0, qsp->xfr.ptrs, edp, 0); + if (n < 0) { + if (sx_flush(qsp) < 0) + return (-1); + if (qsp->xfr.cp == NULL) + sx_newmsg(qsp); + n = make_rr(dname, dp, qsp->xfr.cp, qsp->xfr.eom - + qsp->xfr.cp - qsp->xfr.tsig_size, + 0, qsp->xfr.ptrs, edp, 0); + INSIST(n >= 0); + } + hp->ancount = htons(ntohs(hp->ancount) + 1); + qsp->xfr.cp += n; + return (0); +} + +/* + * int + * sx_soarr(qsp) + * add the SOA RR's at the current level's top np to the assembly message. + * return: + * 0 = success + * -1 = write buffer full, cannot continue at this time + * side effects: + * if progress was made, header and pointers will be advanced. + */ +static int +sx_soarr(struct qstream *qsp) { + struct databuf *dp; + int added_soa = 0; + + foreach_rr(dp, qsp->xfr.top.axfr, T_SOA, qsp->xfr.class, + qsp->xfr.zone) { + if (sx_addrr(qsp, zones[qsp->xfr.zone].z_origin, dp) < 0) { + /* RR wouldn't fit. Bail out. */ + return (-1); + } + added_soa = 1; + break; + } + if (added_soa == 0) + ns_panic(ns_log_xfer_out, 1, "no SOA at zone top"); + if (qsp->xfr.state == s_x_firstsoa) { + foreach_rr(dp, qsp->xfr.top.axfr, T_SIG, qsp->xfr.class, + qsp->xfr.zone) + { + if (SIG_COVERS(dp) != T_SOA) + continue; + if (sx_addrr(qsp, zones[qsp->xfr.zone].z_origin, dp) < + 0) + { + /* RR wouldn't fit. Bail out. */ + return (-1); + } + } + } + return (0); +} + +/* + * int + * sx_nsrrs(qsp) + * add the NS RR's at the current level's current np to the assembly msg. + * This function also adds the SIG(NS), KEY, SIG(KEY), NXT, SIG(NXT), + * since these records are also part of the delegation (see DNSSEC). + * return: + * >1 = number of NS RRs added, note that there may be more + * 0 = success, there are no more NS RRs at this level + * -1 = write buffer full, cannot continue at this time + * side effects: + * if progress was made, header and pointers will be advanced. + * note: + * this is meant for AXFR, which includes glue as part of the answer + * sections. this is different from and incompatible with the additional + * data of a referral response. + */ +static int +sx_nsrrs(struct qstream *qsp) { + struct databuf *dp, *tdp, *gdp; + struct namebuf *gnp, *tnp, *top; + struct hashbuf *htp; + const char *fname; + int class; + + class = qsp->xfr.class; + top = qsp->xfr.top.axfr; + for ((void)NULL; + (dp = qsp->xfr.lev->dp) != NULL; + qsp->xfr.lev->dp = db_next(dp)) { + if (dp->d_class != class && class != C_ANY) + continue; + if (dp->d_rcode) + continue; + /* + * It might not be in the same zone, if we are authoritative + * for both parent and child, but it does have to be a zone. + * + * XXX: this is sort of a bug, since it means we merge the + * @ NS RRset into our parent's zone. But that is what + * db_load() does, so for now we have no choice. + */ + if (dp->d_zone == DB_Z_CACHE) + continue; + + if (dp->d_type != T_NS && dp->d_type != T_KEY && + dp->d_type != T_NXT && dp->d_type != T_SIG) + continue; + if (dp->d_type == T_SIG && ((SIG_COVERS(dp) != T_NS) && + (SIG_COVERS(dp) != T_KEY) && (SIG_COVERS(dp) != T_NXT))) + continue; + if (!(qsp->xfr.lev->flags & SXL_GLUING)) { + if (sx_addrr(qsp, qsp->xfr.lev->dname, dp) < 0) { + /* RR wouldn't fit. Bail out. */ + return (-1); + } + if (dp->d_type != T_NS) /* no glue processing */ + continue; + /* Remember we have found a zone cut */ + if (qsp->xfr.top.axfr != qsp->xfr.lev->np) + qsp->xfr.lev->flags |= SXL_ZONECUT; + } + + /* + * Glue the sub domains together by sending the address + * records for the sub domain name servers along if necessary. + * Glue is necessary if the server is in any zone delegated + * from the current (top) zone. Such a delegated zone might + * or might not be that referred to by the NS record now + * being handled. + */ + htp = hashtab; + gnp = nlookup((char *)dp->d_data, &htp, &fname, 0); + if (gnp == NULL || fname != (char *)dp->d_data) + continue; + for (tnp = gnp; + tnp != NULL && tnp != top; + tnp = tnp->n_parent) + (void)NULL; + if (tnp == NULL && NAME(*top)[0] != '\0') + continue; /* name server is not below top domain */ + for (tnp = gnp; + tnp != NULL && tnp != top; + tnp = tnp->n_parent) { + foreach_rr(tdp, tnp, T_NS, class, DB_Z_CACHE) + break; + /* If we found a zone cut, we're outta here. */ + if (tdp != NULL) + break; + } + /* If name server is not in a delegated zone, skip it. */ + if (tnp == top || (tnp == NULL && NAME(*top)[0] == '\0')) + continue; + /* Now we know glue records are needed. Send them. */ + qsp->xfr.lev->flags |= SXL_GLUING; + foreach_rr(gdp, gnp, T_A, class, DB_Z_CACHE) + if (sx_addrr(qsp, fname, gdp) < 0) { + /* + * Rats. We already sent the NS RR, too. + * Note that SXL_GLUING is being left on. + */ + return (-1); + } + /* for IPv6 glue AAAA record transfer */ + /* patched by yasuhiro@nic.ad.jp, 1999/5/23 */ + foreach_rr(gdp, gnp, T_AAAA, class, DB_Z_CACHE) + if (sx_addrr(qsp, fname, gdp) < 0) { + /* + * Rats. We already sent the NS RR, too. + * Note that SXL_GLUING is being left on. + */ + return (-1); + } + foreach_rr(gdp, gnp, ns_t_a6, class, DB_Z_CACHE) + if (sx_addrr(qsp, fname, gdp) < 0) { + /* + * Rats. We already sent the NS RR, too. + * Note that SXL_GLUING is being left on. + */ + return (-1); + } + qsp->xfr.lev->flags &= ~SXL_GLUING; + } + return (0); +} + +/* + * int + * sx_allrrs(qsp) + * add the non-(SOA,NS) RR's at the current level's current np, + * to the assembly message + * do not add the DNSSEC types KEY and NXT as the delegation check + * wrote these types out. + * return: + * >0 = number of RR's added, note that there may be more + * 0 = success, there are no more RRs at this level + * -1 = write buffer full, cannot continue at this time + * side effects: + * if progress was made, header and pointers will be advanced. + * note: + * this is meant for AXFR, which includes glue as part of the answer + * sections. this is different from and incompatible with the additional + * data of a referral response. + */ +static int +sx_allrrs(struct qstream *qsp) { + struct databuf *dp; + struct namebuf *top; + int rrcount, class; + u_int zone; + + class = qsp->xfr.class; + top = qsp->xfr.top.axfr; + zone = qsp->xfr.zone; + rrcount = 0; + for ((void)NULL; + (dp = qsp->xfr.lev->dp) != NULL; + qsp->xfr.lev->dp = db_next(dp)) { + if (dp->d_class != class && class != C_ANY) + continue; + if (dp->d_rcode) + continue; + if (dp->d_zone != zone || stale(dp)) + continue; + if (dp->d_type == T_SOA || dp->d_type == T_NS || + dp->d_type == T_NXT || dp->d_type == T_KEY) + continue; + if (dp->d_type == T_SIG && + (SIG_COVERS(dp) == T_SOA || SIG_COVERS(dp) == T_NS || + SIG_COVERS(dp) == T_KEY || SIG_COVERS(dp) == T_NXT)) + continue; + INSIST(!(qsp->xfr.lev->flags & SXL_GLUING)); + + if (sx_addrr(qsp, qsp->xfr.lev->dname, dp) < 0) { + /* RR wouldn't fit. Bail out. */ + return (-1); + } + rrcount++; + } + return (rrcount); +} + +/* + * void + * sx_sendlev(qsp) + * send all the RRs at the current level (really a domain name), and + * do a decomposed recursion to get all subdomains up to and including + * but not exceeding bottom zone cuts. + * side effects: + * advances qsp->xfr pointers. changes qsp->xfr.lev quite often. + * causes messages to be sent to a remote TCP client. changes the + * qsp->xfr.state at the end of the topmost level. changes the + * qsp->xfr.lev->state several times per domain name. + */ +void +sx_sendlev(struct qstream *qsp) { + struct qs_x_lev *lev; + + again: + lev = qsp->xfr.lev; + switch (lev->state) { + case sxl_ns: { + while (lev->dp) { + /* Was the child zone reloaded under us? */ + if ((lev->dp->d_flags & DB_F_ACTIVE) == 0) { + (void) shutdown(qsp->s_rfd, 2); + sq_remove(qsp); + return; + } + /* If we can't pack this one in, come back later. */ + if (sx_nsrrs(qsp) < 0) + return; + } + /* No more DP's for the NS RR pass on this NP. */ + if (lev->flags & SXL_ZONECUT) { + /* Zone cut, so go directly to end of level. */ + break; + } + /* No NS RR's, so it's safe to send other types. */ + lev->state = sxl_all; + lev->dp = lev->np->n_data; + if (lev->dp) + DRCNTINC(lev->dp); + goto again; + } + case sxl_all: { + while (lev->dp) { + /* Was a record updated under us? */ + if ((lev->dp->d_flags & DB_F_ACTIVE) == 0) { + (void) shutdown(qsp->s_rfd, 2); + sq_remove(qsp); + return; + } + /* If we can't pack this one in, come back later. */ + if (sx_allrrs(qsp) < 0) + return; + } + /* No more non-NS DP's for this NP, do subdomains. */ + lev->state = sxl_sub; + goto again; + } + case sxl_sub: { + struct namebuf *np; + + /* Get next in-use hash chain if we're not following one. */ + while (lev->nnp == NULL) { + /* If no, or no more subdomains, end of level. */ + if (lev->npp == NULL || lev->npp == lev->npe) + break; + lev->nnp = *lev->npp++; + } + /* If we encountered the end of the level, we're outta here. */ + if ((np = lev->nnp) == NULL) + break; + /* Next time, we'll do the following NP, or the next chain. */ + lev->nnp = np->n_next; + /* Skip our own NP if it appears as a subdom (as in root). */ + if (np != lev->np) + sx_pushlev(qsp, np); + goto again; + } + default: + abort(); + } + + /* End of level. Pop it off the stack. */ + + if ((qsp->xfr.lev = sx_freelev(lev)) == NULL) { + /* End of topmost level. */ + qsp->xfr.state = s_x_lastsoa; + sq_writeh(qsp, sx_sendsoa); + return; + } + goto again; +} + +/* + * void + * sx_sendsoa(qsp) + * send either the first or last SOA needed for an AXFR. + * side effects: + * changes qsp->xfr.state. adds RR to output buffer. + */ +void +sx_sendsoa(struct qstream *qsp) { + HEADER * hp = (HEADER *) qsp->xfr.msg; + + if (sx_soarr(qsp) == -1) + return; /* No state change, come back here later. */ + + hp->aa = 1; + + switch (qsp->xfr.state) { + case s_x_firstsoa: { + /* Next thing to do is send the zone. */ + qsp->xfr.state = s_x_zone; + sq_writeh(qsp, sx_sendlev); + break; + } + case s_x_lastsoa: { + /* Next thing to do is go back and wait for another query. */ + qsp->xfr.state = s_x_done; + (void)sx_flush(qsp); + sq_writeh(qsp, sq_flushw); + break; + } + default: { + ns_panic(ns_log_xfer_out, 1, + "unexpected state %d in sx_sendsoa", qsp->xfr.state); + } + } +} + +/* int + * sx_pushlev(qsp, np) + * manage the decomposed recursion. set up for a new level (domain). + * returns: + * 0 = success + * -1 = failure (check errno) + */ +static int +sx_pushlev(struct qstream *qsp, struct namebuf *np) { + struct qs_x_lev *new = memget(sizeof *new); + struct hashbuf *htp; + + if (!new) { + errno = ENOMEM; + return (-1); + } + memset(new, 0, sizeof *new); + new->state = sxl_ns; + new->np = np; + new->dp = np->n_data; + if (new->dp) + DRCNTINC(new->dp); + getname(np, new->dname, sizeof new->dname); + /* + * We find the subdomains by looking in the hash table for this + * domain, but the root domain needs special treatment, because + * of the following wart in the database design: + * + * The top level hash table (pointed to by the global `hashtab' + * variable) contains pointers to the namebuf's for the root as + * well as for the top-level domains below the root, in contrast + * to the usual situation where a hash table contains entries + * for domains at the same level. The n_hash member of the + * namebuf for the root domain is NULL instead of pointing to a + * hashbuf for the top-level domains. The n_parent members of + * the namebufs for the top-level domains are NULL instead of + * pointing to the namebuf for the root. + * + * We work around the wart as follows: + * + * If we are not dealing with the root zone then we just set + * htp = np->n_hash, pointing to the hash table for the current + * domain, and we walk through the hash table as usual, + * processing the namebufs for all the subdomains. + * + * If we are dealing with the root zone, then we set + * htp = hashtab, pointing to the global hash table (because + * there is no hash table associated with the root domain's + * namebuf. While we walk this hash table, we take care not to + * recursively process the entry for the root namebuf. + * + * (apb@und nov1990) + */ + htp = ((new->dname[0] == '\0') ? hashtab : np->n_hash); + if (htp) { + new->npp = htp->h_tab; + new->npe = htp->h_tab + htp->h_size; + } else { + new->npp = NULL; + new->npe = NULL; + } + new->nnp = NULL; + new->next = qsp->xfr.lev; + qsp->xfr.lev = new; + return (0); +} + +/* + * qs_x_lev * + * sx_freelev(lev) + * free the memory occupied by a level descriptor + * return: + * pointer to "next" level descriptor + */ +static struct qs_x_lev * +sx_freelev(struct qs_x_lev *lev) { + struct qs_x_lev *next = lev->next; + + if (lev->dp) + db_detach(&lev->dp); + memput(lev, sizeof *lev); + return (next); +} + +static struct databuf * +db_next(struct databuf *dp) { + struct databuf *next = dp->d_next; + + db_detach(&dp); + if (next) + DRCNTINC(next); + + return (next); +} + Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_xfr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/named.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/named.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/named.h (revision 109985) @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * $Id: named.h,v 8.32 2002/03/15 00:58:16 vixie Exp $ + */ + +/* Options. Change them at your peril. */ +#undef NXDOMAIN_ON_DENIAL +#define DEBUG +#define ADDAUTH +#define STUBS +#define RETURNSOA +#define BOGUSNS +#define TRACEROOT +#define XFRNETS +#define QRYLOG +#undef YPKLUDGE +#define RENICE +#define BIND_IXFR +#define BIND_NOTIFY +#define BIND_UPDATE +#define WANT_PIDFILE +#define FWD_LOOP +#define DOTTED_SERIAL +#define SENSIBLE_DOTS +#define ROUND_ROBIN +#define DNS_SECURITY +#undef RSAREF +#undef BSAFE +#define ALLOW_LONG_TXT_RDATA +#define STRICT_RFC2308 +#undef BIND_ZXFR +#undef LOG_TSIG_BUG +#define NOADDITIONAL +#undef FORWARD_ALLOWS /* enable allow-query for forward zones. */ + +#include +#include +#include + +#include + +#include "pathnames.h" + +#include "ns_defs.h" +#include "db_defs.h" + +#include "ns_glob.h" +#include "db_glob.h" + +#include "ns_func.h" +#include "db_func.h" Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/named.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_func.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_func.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_func.h (revision 109985) @@ -0,0 +1,530 @@ +/* + * Copyright (c) 1985, 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1999 by Check Point Software Technologies, Inc. + * + * 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 Check Point Software Technologies Incorporated 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 CHECK POINT SOFTWARE TECHNOLOGIES + * INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL CHECK POINT SOFTWARE TECHNOLOGIES INCORPRATED + * 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 SOFTWARE. + */ + +/* ns_func.h - declarations for ns_*.c's externally visible functions + * + * $Id: ns_func.h,v 8.117 2002/04/25 05:27:07 marka Exp $ + */ + +/* ++from ns_glue.c++ */ +struct in_addr ina_get(const u_char *data); +const char * sin_ntoa(struct sockaddr_in); +int ns_wouldlog(int category, int level); +void ns_debug(int, int, const char *, ...) ISC_FORMAT_PRINTF(3, 4); +void ns_info(int, const char *, ...) ISC_FORMAT_PRINTF(2, 3); +void ns_notice(int, const char *, ...) ISC_FORMAT_PRINTF(2, 3); +void ns_warning(int, const char *, ...) ISC_FORMAT_PRINTF(2, 3); +void ns_error(int, const char *, ...) ISC_FORMAT_PRINTF(2, 3); +void ns_critical(int, const char *, ...) ISC_FORMAT_PRINTF(2, 3); +void ns_panic(int, int, const char *, ...) ISC_FORMAT_PRINTF(3, 4); +void ns_assertion_failed(const char *file, int line, + assertion_type type, + const char *cond, int print_errno); +void panic(const char *, const void *); +void gettime(struct timeval *); +int nlabels(const char *); +int my_close(int); +int my_fclose(FILE *); +void * __freestr(char *); +char * __newstr(size_t, int); +char * __savestr(const char *, int); +const char * checked_ctime(const time_t *t); +const char * ctimel(long); +void * __freestr_record(char *, const char *, int); +char * __newstr_record(size_t, int, const char *, int); +char * __savestr_record(const char *, int, const char *, int); +u_char * ina_put(struct in_addr ina, u_char *data); +u_char * savebuf(const u_char *, size_t, int); +void dprintf(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3); +#ifdef DEBUG_STRINGS +char * debug_newstr(size_t, int, const char *, int); +char * debug_savestr(const char *, int, const char *, int); +void * debug_freestr(char *, const char *, int); +#define newstr(l, n) debug_newstr((l), (n), __FILE__, __LINE__) +#define savestr(s, n) debug_savestr((s), (n), __FILE__, __LINE__) +#define freestr(s) debug_freestr((s), __FILE__, __LINE__) +#else +#ifdef RECORD_STRINGS +#define newstr(l, n) __newstr_record((l), (n), __FILE__, __LINE__) +#define savestr(s, n) __savestr_record((s), (n), __FILE__, __LINE__) +#define freestr(s) __freestr_record((s), __FILE__, __LINE__) +#else +#define newstr(l, n) __newstr((l), (n)) +#define savestr(s, n) __savestr((s), (n)) +#define freestr(s) __freestr((s)) +#endif +#endif /* DEBUG_STRINGS */ +/* --from ns_glue.c-- */ + +/* ++from ns_notify.c++ */ +#ifdef BIND_NOTIFY +void ns_notify(const char *, ns_class, ns_type); +void notify_afterload(void); +void ns_unnotify(void); +void ns_stopnotify(const char *, ns_class); +#endif +/* --from ns_notify.c-- */ + +/* ++from ns_resp.c++ */ +void ns_resp(u_char *, int, struct sockaddr_in, + struct qstream *); +void prime_cache(void); +void delete_all(struct namebuf *, int, int); +int delete_stale(struct namebuf *); +struct qinfo * sysquery(const char *, int, int, + struct in_addr *, struct dst_key **keys, + int, u_int16_t, int, int); +int doupdate(u_char *, u_char *, struct databuf **, + int, int, int, u_int, struct sockaddr_in); +int send_msg(u_char *, int, struct qinfo *); +int findns(struct namebuf **, int, + struct databuf **, int *, int); +int finddata(struct namebuf *, int, int, HEADER *, + char **, int *, int *); +int add_data(struct namebuf *, + struct databuf **, + u_char *, int, int *); +int trunc_adjust(u_char *, int, int); +/* --from ns_resp.c-- */ + +/* ++from ns_req.c++ */ +int ns_get_opt(u_char *msg, u_char *eom, + u_int8_t *versionp, u_int16_t *rcodep, + u_int16_t *flagp, u_int16_t *bufsizep, + u_char **optionsp, size_t *optsizep); +int ns_add_opt(u_char *msg, u_char *cp, size_t buflen, + u_int8_t version, u_int16_t rcode, + u_int16_t size, u_int16_t flags, + u_char *options, size_t optlen); +void ns_req(u_char *, int, int, + struct qstream *, + struct sockaddr_in, + int); +void free_addinfo(void); +void free_nsp(struct databuf **); +int stale(struct databuf *); +int make_rr(const char *, struct databuf *, + u_char *, int, int, + u_char **, u_char **, int); +int doaddinfo(HEADER *, u_char *, int); +int doaddauth(HEADER *, u_char *, int, + struct namebuf *, + struct databuf *); +#ifdef BIND_NOTIFY +int findZonePri(const struct zoneinfo *, + const struct sockaddr_in); +#endif +int drop_port(u_int16_t); +/* --from ns_req.c-- */ + +/* ++from ns_xfr.c++ */ +void ns_xfr(struct qstream *qsp, struct namebuf *znp, + int zone, int class, int type, + int id, int opcode, u_int32_t serial_ixfr, + struct tsig_record *in_tsig); +void ns_stopxfrs(struct zoneinfo *); +void ns_freexfr(struct qstream *); +void sx_newmsg(struct qstream *qsp); +void sx_sendlev(struct qstream *qsp); +void sx_sendsoa(struct qstream *qsp); +/* --from ns_xfr.c-- */ + +/* ++from ns_ctl.c++ */ +void ns_ctl_initialize(void); +void ns_ctl_shutdown(void); +void ns_ctl_defaults(controls *); +void ns_ctl_add(controls *, control); +control ns_ctl_new_inet(struct in_addr, u_int, ip_match_list); +#ifndef NO_SOCKADDR_UN +control ns_ctl_new_unix(const char *, mode_t, uid_t, gid_t); +#endif +void ns_ctl_install(controls *); +/* --from ns_ctl.c-- */ + +/* ++from ns_ixfr.c++ */ +void sx_send_ixfr(struct qstream *); +int ixfr_log_maint(struct zoneinfo *); +/* --from ns_ixfr.c-- */ + +/* ++from ns_forw.c++ */ +time_t retrytime(struct qinfo *); +int ns_forw(struct databuf *nsp[], + u_char *msg, + int msglen, + struct sockaddr_in from, + struct qstream *qsp, + int dfd, + struct qinfo **qpp, + const char *dname, + int class, + int type, + struct namebuf *np, + int use_tcp, + struct tsig_record *in_tsig); +int haveComplained(u_long, u_long); +int nslookup(struct databuf *nsp[], + struct qinfo *qp, + const char *syslogdname, + const char *sysloginfo); +int qcomp(struct qserv *, struct qserv *); +void schedretry(struct qinfo *, time_t); +void unsched(struct qinfo *); +void reset_retrytimer(void); +void retrytimer(evContext ctx, void *uap, + struct timespec due, struct timespec ival); +void retry(struct qinfo *, int); +void qflush(void); +void qremove(struct qinfo *); +void ns_freeqns(struct qinfo *); +void ns_freeqry(struct qinfo *); +void freeComplaints(void); +void nsfwdadd(struct qinfo *, struct fwdinfo *); +struct qinfo * qfindid(u_int16_t); +struct qinfo * qnew(const char *, int, int, int); +/* --from ns_forw.c-- */ + +/* ++from ns_main.c++ */ +void toggle_qrylog(void); +struct in_addr net_mask(struct in_addr); +void sq_remove(struct qstream *); +void sq_flushw(struct qstream *); +void sq_flush(struct qstream *allbut); +void dq_remove_gen(time_t gen); +void dq_remove_all(void); +void sq_done(struct qstream *); +void ns_setproctitle(char *, int); +void getnetconf(int); +void nsid_init(void); +void ns_setoption(int option); +void writestream(struct qstream *, const u_char *, int); +void ns_need_unsafe(enum need); +void ns_need(enum need); +void opensocket_f(void); +void nsid_hash(u_char *, size_t); +u_int16_t nsid_next(void); +int sq_openw(struct qstream *, int); +int sq_writeh(struct qstream *, sq_closure); +int sq_write(struct qstream *, const u_char *, int); +int tcp_send(struct qinfo *); +int aIsUs(struct in_addr); +/* --from ns_main.c-- */ + +/* ++from ns_maint.c++ */ +void zone_maint(struct zoneinfo *); +void sched_zone_maint(struct zoneinfo *); +void ns_cleancache(evContext ctx, void *uap, + struct timespec due, + struct timespec inter); +void clean_cache_from(char *dname, struct hashbuf *htp); +void remove_zone(struct zoneinfo *, const char *); +void purge_zone(const char *, struct hashbuf *, int); +void loadxfer(void); +void qserial_retrytime(struct zoneinfo *, time_t); +void qserial_query(struct zoneinfo *); +void qserial_answer(struct qinfo *); +#ifdef DEBUG +void printzoneinfo(int, int, int); +#endif +void endxfer(void); +void tryxfer(void); +void addxfer(struct zoneinfo *); +void ns_zreload(void); +void ns_reload(void); +void ns_reconfig(void); +void ns_noexpired(void); +#if 0 +int reload_all_unsafe(void); +#endif +int zonefile_changed_p(struct zoneinfo *); +int reload_master(struct zoneinfo *); +const char * deferred_reload_unsafe(struct zoneinfo *); +struct namebuf * purge_node(struct hashbuf *htp, struct namebuf *np); +int clean_cache(struct hashbuf *, int); +void reapchild(void); +const char * zoneTypeString(unsigned int); +void ns_heartbeat(evContext ctx, void *uap, + struct timespec, struct timespec); +void make_new_zones(void); +void free_zone(struct zoneinfo *); +struct zoneinfo * find_auth_zone(const char *, ns_class); +int purge_nonglue(const char *dname, struct hashbuf *htp, + int class, int log); +/* --from ns_maint.c-- */ + +/* ++from ns_sort.c++ */ +void sort_response(u_char *, u_char *, int, + struct sockaddr_in *); +/* --from ns_sort.c-- */ + +/* ++from ns_init.c++ */ +void ns_refreshtime(struct zoneinfo *, time_t); +void ns_retrytime(struct zoneinfo *, time_t); +time_t ns_init(const char *); +void purgeandload(struct zoneinfo *zp); +enum context ns_ptrcontext(const char *owner); +enum context ns_ownercontext(int type, enum transport); +int ns_nameok(const struct qinfo *qry, const char *name, + int class, struct zoneinfo *zp, + enum transport, enum context, + const char *owner, + struct in_addr source); +int ns_wildcard(const char *name); +void zoneinit(struct zoneinfo *); +void do_reload(const char *, int, int, int); +void ns_shutdown(void); +/* --from ns_init.c-- */ + +/* ++from ns_ncache.c++ */ +void cache_n_resp(u_char *, int, struct sockaddr_in, + const char *, int, int); +/* --from ns_ncache.c-- */ + +/* ++from ns_udp.c++ */ +void ns_udp(void); +/* --from ns_udp.c-- */ + +/* ++from ns_stats.c++ */ +void ns_stats(void); +void ns_stats_dumpandclear(void); +void ns_freestats(void); +void ns_logstats(evContext ctx, void *uap, + struct timespec, struct timespec); +void qtypeIncr(int qtype); +struct nameser * nameserFind(struct in_addr addr, int flags); +#define NS_F_INSERT 0x0001 +#define nameserIncr(a,w) NS_INCRSTAT(a,w) /* XXX should change name. */ +/* --from ns_stats.c-- */ + +/* ++from ns_update.c++ */ +struct databuf * findzonesoa(struct zoneinfo *); +void free_rrecp(ns_updque *, int rcode, struct sockaddr_in); +int findzone(const char *, int, int, int *, int); +u_char * findsoaserial(u_char *data); +u_int32_t get_serial_unchecked(struct zoneinfo *zp); +u_int32_t get_serial(struct zoneinfo *zp); +void set_serial(struct zoneinfo *zp, u_int32_t serial); +int schedule_soa_update(struct zoneinfo *, int); +int schedule_dump(struct zoneinfo *); +int incr_serial(struct zoneinfo *zp); +int merge_logs(struct zoneinfo *zp, char *logname); +int zonedump(struct zoneinfo *zp, int isixfr); +void dynamic_about_to_exit(void); +enum req_action req_update(HEADER *hp, u_char *cp, u_char *eom, + u_char *msg, struct sockaddr_in from, + struct tsig_record *in_tsig); +void rdata_dump(struct databuf *dp, FILE *fp); +/* --from ns_update.c-- */ + +/* ++from ns_config.c++ */ +void add_to_rrset_order_list(rrset_order_list, + rrset_order_element); +const char * p_order(int); +int set_zone_ixfr_file(zone_config, char *); +int set_zone_master_port(zone_config, u_short); +int set_zone_max_log_size_ixfr(zone_config, int); +int set_zone_dialup(zone_config, int); +int set_trusted_key(const char *, const int, + const int, const int, const char *); +int set_zone_ixfr_tmp(zone_config, char *); +void free_zone_timerinfo(struct zoneinfo *); +void free_zone_contents(struct zoneinfo *, int); +struct zoneinfo * find_zone(const char *, int); +zone_config begin_zone(char *, int); +void end_zone(zone_config, int); +int set_zone_type(zone_config, int); +int set_zone_filename(zone_config, char *); +int set_zone_checknames(zone_config, enum severity); +#ifdef BIND_NOTIFY +int set_zone_notify(zone_config, enum notify value); +#endif +int set_zone_maintain_ixfr_base(zone_config, int value); +int set_zone_update_acl(zone_config, ip_match_list); +int set_zone_query_acl(zone_config, ip_match_list); +int set_zone_transfer_acl(zone_config, ip_match_list); +int set_zone_transfer_source(zone_config, struct in_addr); +int set_zone_pubkey(zone_config, const int, const int, + const int, const char *); +int set_zone_transfer_time_in(zone_config, long); +int add_zone_master(zone_config, struct in_addr, + struct dst_key *); +#ifdef BIND_NOTIFY +int add_zone_notify(zone_config, struct in_addr); +#endif +void set_zone_forward(zone_config); +void add_zone_forwarder(zone_config, struct in_addr); +void set_zone_boolean_option(zone_config, int, int); +options new_options(void); +void free_options(options); +void free_rrset_order_list(rrset_order_list); +void set_global_boolean_option(options, int, int); +listen_info_list new_listen_info_list(void); +void free_listen_info_list(listen_info_list); +void add_listen_on(options, u_short, ip_match_list); +FILE * write_open(char *filename); +void update_pid_file(void); +void set_options(options, int); +void use_default_options(void); +enum ordering lookup_ordering(const char *); +rrset_order_list new_rrset_order_list(void); +rrset_order_element new_rrset_order_element(int, int, char *, enum ordering); +ip_match_list new_ip_match_list(void); +void free_ip_match_list(ip_match_list); +ip_match_element new_ip_match_pattern(struct in_addr, u_int); +ip_match_element new_ip_match_mask(struct in_addr, struct in_addr); +ip_match_element new_ip_match_indirect(ip_match_list); +ip_match_element new_ip_match_key(struct dst_key *dst_key); +ip_match_element new_ip_match_localhost(void); +ip_match_element new_ip_match_localnets(void); +void ip_match_negate(ip_match_element); +void add_to_ip_match_list(ip_match_list, ip_match_element); +void dprint_ip_match_list(int, ip_match_list, int, + const char *, const char *); +int ip_match_address(ip_match_list, struct in_addr); +int ip_match_addr_or_key(ip_match_list, struct in_addr, + struct dst_key *key); +int ip_address_allowed(ip_match_list, struct in_addr); +int ip_addr_or_key_allowed(ip_match_list iml, + struct in_addr, + struct dst_key *key); +int ip_match_network(ip_match_list, struct in_addr, + struct in_addr); +int ip_match_key_name(ip_match_list iml, char *name); +int distance_of_address(ip_match_list, struct in_addr); +int ip_match_is_none(ip_match_list); +#ifdef BIND_NOTIFY +void free_also_notify(options); +int add_global_also_notify(options, struct in_addr); +#endif +void add_global_forwarder(options, struct in_addr); +void free_forwarders(struct fwdinfo *); +server_info find_server(struct in_addr); +server_config begin_server(struct in_addr); +void end_server(server_config, int); +void set_server_option(server_config, int, int); +void set_server_transfers(server_config, int); +void set_server_transfer_format(server_config, + enum axfr_format); +void add_server_key_info(server_config, struct dst_key *); +struct dst_key *new_key_info(char *, char *, char *); +void free_key_info(struct dst_key *); +struct dst_key *find_key(char *name, char *algorithm); +void dprint_key_info(struct dst_key *); +key_info_list new_key_info_list(void); +void free_key_info_list(key_info_list); +void add_to_key_info_list(key_info_list, struct dst_key *); +void dprint_key_info_list(key_info_list); +log_config begin_logging(void); +void add_log_channel(log_config, int, log_channel); +void open_special_channels(void); +void set_logging(log_config, int); +void end_logging(log_config, int); +void use_default_logging(void); +void init_logging(void); +void shutdown_logging(void); +void init_configuration(void); +void shutdown_configuration(void); +time_t load_configuration(const char *); +/* --from ns_config.c-- */ + +/* ++from parser.y++ */ +ip_match_list lookup_acl(const char *); +void define_acl(const char *, ip_match_list); +struct dst_key *lookup_key(char *); +void define_key(const char *, struct dst_key *); +time_t parse_configuration(const char *); +void parser_initialize(void); +void parser_shutdown(void); +/* --from parser.y-- */ + +/* ++from ns_signal.c++ */ +void init_signals(void); +void block_signals(void); +void unblock_signals(void); +/* --from ns_signal.c-- */ Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_func.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_notify.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_notify.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_notify.c (revision 109985) @@ -0,0 +1,462 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_notify.c,v 8.20 2002/04/25 05:27:12 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1994-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* Import. */ + +#include "port_before.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "port_after.h" + +#include "named.h" + +#ifdef BIND_NOTIFY + +/* Types. */ + +struct pnotify { + char * name; + ns_class class; + ns_type type; + evTimerID timer; + LINK(struct pnotify) link; +}; + +/* Forward. */ + +static void sysnotify(const char *, ns_class, ns_type); +static void sysnotify_slaves(const char *, const char *, + ns_class, ns_type, int, int *, int *); +static void sysnotify_ns(const char *, const char *, + ns_class, ns_type, int, int *, int *); +static void free_notify(struct pnotify *); +static void notify_timer(evContext, void *, + struct timespec, struct timespec); + +/* Local. */ + +static LIST(struct pnotify) pending_notifies; +static LIST(struct pnotify) loading_notifies; + +/* Public. */ + +/* + * ns_notify(dname, class, type) + * call this when a zone has changed and its slaves need to know. + */ +void +ns_notify(const char *dname, ns_class class, ns_type type) { + static const char no_room[] = "%s failed, cannot notify for zone %s"; + int delay, max_delay; + struct zoneinfo *zp; + struct pnotify *ni; + + zp = find_auth_zone(dname, class); + if (zp == NULL) { + ns_warning(ns_log_notify, + "no zone found for notify (\"%s\" %s %s)", + (dname && *dname) ? dname : ".", + p_class(class), p_type(type)); + return; + } + if (ns_samename(dname, zp->z_origin) != 1) { + ns_warning(ns_log_notify, + "notify not called with top of zone (\"%s\" %s %s)", + (dname && *dname) ? dname : ".", + p_class(class), p_type(type)); + return; + } + if ((zp->z_flags & Z_NOTIFY) != 0) { + ns_info(ns_log_notify, + "suppressing duplicate notify (\"%s\" %s %s)", + (dname && *dname) ? dname : ".", + p_class(class), p_type(type)); + return; + } + ni = memget(sizeof *ni); + if (ni == NULL) { + ns_info(ns_log_notify, no_room, "memget", dname); + return; + } + ni->name = savestr(dname, 0); + if (ni->name == NULL) { + memput(ni, sizeof *ni); + ni = NULL; + ns_info(ns_log_notify, no_room, "memget", dname); + return; + } + ni->class = class; + ni->type = type; + INIT_LINK(ni, link); + evInitID(&ni->timer); + + if (loading != 0) { + APPEND(loading_notifies, ni, link); + return; + } + + /* Delay notification for from five seconds up to fifteen minutes. */ + max_delay = MIN(nzones, 895); + max_delay = MAX(max_delay, 25); + delay = 5 + (rand() % max_delay); + if (evSetTimer(ev, notify_timer, ni, + evAddTime(evNowTime(), evConsTime(delay, 0)), + evConsTime(0, 0), &ni->timer) < 0) { + ns_error(ns_log_notify, "evSetTimer() failed: %s", + strerror(errno)); + ni->name = freestr(ni->name); + memput(ni, sizeof *ni); + return; + } + + zp->z_flags |= Z_NOTIFY; + APPEND(pending_notifies, ni, link); + ns_debug(ns_log_notify, 3, + "ns_notify(%s, %s, %s): ni %p, zp %p, delay %d", + (dname && *dname) ? dname : ".", + p_class(class), p_type(type), + ni, zp, delay); +} + +void +notify_afterload() { + struct pnotify *ni; + + INSIST(loading == 0); + while ((ni = HEAD(loading_notifies)) != NULL) { + UNLINK(loading_notifies, ni, link); + ns_notify(ni->name, ni->class, ni->type); + ni->name = freestr(ni->name); + memput(ni, sizeof *ni); + } +} + +/* + * ns_unnotify() + * call this when all pending notifies are now considered junque. + */ +void +ns_unnotify(void) { + while (!EMPTY(pending_notifies)) { + struct pnotify *ni = HEAD(pending_notifies); + + INSIST(LINKED(ni, link)); + UNLINK(pending_notifies, ni, link); + free_notify(ni); + } +} + +/* + * ns_stopnotify(const char *dname, ns_class class) + * stop notifies for this particular zone. + */ +void +ns_stopnotify(const char *dname, ns_class class) { + struct pnotify *ni; + + ni = HEAD(pending_notifies); + while (ni != NULL && + (ni->class != class || ns_samename(ni->name, dname) != 1)) + ni = NEXT(ni, link); + + if (ni != NULL) { + UNLINK(pending_notifies, ni, link); + free_notify(ni); + } +} + +/* Private. */ + +/* + * sysnotify(dname, class, type) + * cause a NOTIFY request to be sysquery()'d to each slave server + * of the zone that "dname" is within. + */ +static void +sysnotify(const char *dname, ns_class class, ns_type type) { + const char *zname; + u_int32_t zserial; + int nns, na, i; + struct zoneinfo *zp; + struct in_addr *also_addr; + + ns_debug(ns_log_notify, 3, "sysnotify(%s, %s, %s)", + dname, p_class(class), p_type(type)); + zp = find_auth_zone(dname, class); + if (zp == NULL) { + ns_warning(ns_log_notify, "sysnotify: can't find \"%s\" (%s)", + dname, p_class(class)); + return; + } + if (ns_samename(dname, zp->z_origin) != 1) { + ns_warning(ns_log_notify, "sysnotify: not auth for zone %s", + dname); + return; + } + if (zp->z_notify == notify_no || + (zp->z_notify == notify_use_default && + server_options->notify == notify_no)) + return; + if (zp->z_type != z_master && zp->z_type != z_slave) { + ns_warning(ns_log_notify, "sysnotify: %s not master or slave", + dname); + return; + } + zname = zp->z_origin; + zserial = zp->z_serial; + nns = na = 0; + if (zp->z_notify == notify_yes || + (zp->z_notify == notify_use_default && + server_options->notify == notify_yes)) + sysnotify_slaves(dname, zname, class, type, + zp - zones, &nns, &na); + + /* + * Handle any global or zone-specific also-notify clauses + */ + if (zp->z_notify_count != 0) { + /* zone-specific also notify */ + + ns_debug(ns_log_notify, 3, "zone notify ns = %d", + zp->z_notify_count); + + also_addr = zp->z_also_notify; + for (i = 0; i < zp->z_notify_count; i++) { + ns_debug(ns_log_notify, 4, "notifying %s", + inet_ntoa(*also_addr)); + sysquery(dname, class, type, also_addr, NULL, 1, + ns_port, NS_NOTIFY_OP, 0); + also_addr++; + } + nns += zp->z_notify_count; + na += zp->z_notify_count; + } else if (server_options->notify_count != 0) { + ns_debug(ns_log_notify, 4, "global notify ns = %d", + server_options->notify_count); + also_addr = server_options->also_notify; + for (i = 0; i < server_options->notify_count; i++) { + ns_debug(ns_log_notify, 3, "notifying %s", + inet_ntoa(*also_addr)); + sysquery(dname, class, type, also_addr, NULL, 1, + ns_port, ns_o_notify, 0); + also_addr++; + } + nns += server_options->notify_count; + na += server_options->notify_count; + } + + if (nns != 0 || na != 0) + ns_info(ns_log_notify, + "Sent NOTIFY for \"%s %s %s %u\" (%s); %d NS, %d A", + dname, p_class(class), p_type(type), zserial, zname, nns, na); +} + +static void +sysnotify_slaves(const char *dname, const char *zname, + ns_class class, ns_type type, + int zn, int *nns, int *na) +{ + const char *mname, *fname; + struct hashbuf *htp; + struct namebuf *np; + struct databuf *dp; + + /* + * Master. + */ + htp = hashtab; + np = nlookup(zname, &htp, &fname, 0); + if (np == NULL) { + ns_warning(ns_log_notify, + "sysnotify: found name \"%s\" but not zone", + dname); + return; + } + mname = NULL; + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (dp->d_zone == DB_Z_CACHE || !match(dp, class, ns_t_soa)) + continue; + if (dp->d_type == ns_t_sig) + continue; + if (mname) { + ns_notice(ns_log_notify, + "multiple SOA's for zone \"%s\"?", + zname); + return; + } + mname = (char *) dp->d_data; + } + if (mname == NULL) { + ns_notice(ns_log_notify, "no SOA found for zone \"%s\"", + zname); + return; + } + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (dp->d_zone == DB_Z_CACHE || !match(dp, class, ns_t_ns)) + continue; + if (dp->d_type == ns_t_sig) + continue; + if (ns_samename((char*)dp->d_data, mname) == 1) + continue; + sysnotify_ns(dname, (char *)dp->d_data, class, type, + zn, nns, na); + } +} + +static void +sysnotify_ns(const char *dname, const char *aname, + ns_class class, ns_type type, + int zn, int *nns, int *na) +{ + struct databuf *adp; + struct namebuf *anp; + const char *fname; + struct in_addr nss[NSMAX]; + struct hashbuf *htp; + int is_us, nsc, auth6, neg; + int cname = 0; + + htp = hashtab; + anp = nlookup(aname, &htp, &fname, 0); + nsc = 0; + is_us = 0; + auth6 = 0; + neg = 0; + if (anp != NULL) + for (adp = anp->n_data; adp; adp = adp->d_next) { + struct in_addr ina; + + if (adp->d_class != class) + continue; + if (adp->d_rcode == NXDOMAIN) { + neg = 1; + break; + } + if (adp->d_type == T_CNAME && adp->d_rcode == 0) { + cname = 1; + ns_error(ns_log_notify, + "NS '%s' for '%s/%s' is a CNAME", + *aname ? aname : ".", + *dname ? dname : ".", + p_class(class)); + break; + } + if ((adp->d_type == T_AAAA || adp->d_type == ns_t_a6) && + (zones[adp->d_class].z_type == z_master || + zones[adp->d_class].z_type == z_slave)) { + auth6 = 1; + continue; + } + if (!match(adp, class, T_A)) + continue; + if (adp->d_rcode) { + neg = 1; + continue; + } + if (adp->d_type == ns_t_sig) + continue; + ina = ina_get(adp->d_data); + if (aIsUs(ina)) { + is_us = 1; + continue; + } + if (nsc < NSMAX) + nss[nsc++] = ina; + } /*next A*/ + if (nsc == 0) { + if (!is_us && !cname && !auth6 && !neg && + !NS_OPTION_P(OPTION_NOFETCHGLUE)) { + struct qinfo *qp; + + qp = sysquery(aname, class, ns_t_a, NULL, NULL, 0, + ns_port, ns_o_query, 0); + if (qp != NULL) + qp->q_notifyzone = zn; + } + return; + } + sysquery(dname, class, type, nss, NULL, nsc, ns_port, ns_o_notify, 0); + (*nns)++; + *na += nsc; +} + +static void +free_notify(struct pnotify *ni) { + struct zoneinfo *zp; + + INSIST(!LINKED(ni, link)); + zp = find_auth_zone(ni->name, ni->class); + if (zp != NULL && ns_samename(ni->name, zp->z_origin) == 1) { + INSIST((zp->z_flags & Z_NOTIFY) != 0); + zp->z_flags &= ~Z_NOTIFY; + } + if (evTestID(ni->timer)) { + evClearTimer(ev, ni->timer); + evInitID(&ni->timer); + } + ni->name = freestr(ni->name); + memput(ni, sizeof *ni); +} + +static void +notify_timer(evContext ctx, void *uap, + struct timespec due, + struct timespec inter) +{ + struct pnotify *ni = uap; + + UNUSED(ctx); + UNUSED(due); + UNUSED(inter); + + INSIST(evTestID(ni->timer)); + evInitID(&ni->timer); + INSIST(LINKED(ni, link)); + UNLINK(pending_notifies, ni, link); + sysnotify(ni->name, ni->class, ni->type); + free_notify(ni); +} + +#endif /*BIND_NOTIFY*/ Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_notify.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/db_dump.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/db_dump.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/db_dump.c (revision 109985) @@ -0,0 +1,702 @@ +#if !defined(lint) && !defined(SABER) +static const char sccsid[] = "@(#)db_dump.c 4.33 (Berkeley) 3/3/91"; +static const char rcsid[] = "$Id: db_dump.c,v 8.51 2001/06/18 14:42:49 marka Exp $"; +#endif /* not lint */ + +/* + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "port_after.h" + +#include "named.h" + +#ifdef HITCOUNTS +u_int32_t db_total_hits; +#endif /* HITCOUNTS */ + +static const char *MkCredStr(int); + +static int fwd_dump(FILE *fp); + +/* + * Dump current data base in a format similar to RFC 883. + */ + +void +doadump(void) { + FILE *fp; + + ns_notice(ns_log_db, "dumping nameserver data"); + + if ((fp = write_open(server_options->dump_filename)) == NULL) + return; + gettime(&tt); +#ifdef HITCOUNTS + if (NS_OPTION_P(OPTION_HITCOUNT)) + fprintf(fp, "; Total hits: %d\n",db_total_hits); +#endif /* HITCOUNTS */ + fprintf(fp, "; Dumped at %s", ctimel(tt.tv_sec)); + if (zones != NULL && nzones != 0) + zt_dump(fp); + if (fwddata != NULL && fwddata_count != 0) + fwd_dump(fp); + fputs( +"; Note: Cr=(auth,answer,addtnl,cache) tag only shown for non-auth RR's\n", + fp); + fputs( +"; Note: NT=milliseconds for any A RR which we've used as a nameserver\n", + fp); + fprintf(fp, "; --- Cache & Data ---\n"); + if (hashtab != NULL) + (void) db_dump(hashtab, fp, DB_Z_ALL, ""); + fprintf(fp, "; --- Hints ---\n"); + if (fcachetab != NULL) + (void) db_dump(fcachetab, fp, DB_Z_ALL, ""); + (void) my_fclose(fp); + ns_notice(ns_log_db, "finished dumping nameserver data"); +} + +int +zt_dump(FILE *fp) { + struct zoneinfo *zp; + + fprintf(fp, ";; ++zone table++\n"); + for (zp = &zones[0]; zp < &zones[nzones]; zp++) { + const char *pre; + char buf[64]; + u_int cnt; + + if (!zp->z_origin) + continue; + + fprintf(fp, "; %s (type %d, class %d, source %s)\n", + zp->z_origin + ? (*zp->z_origin ? zp->z_origin : ".") + : "Nil", + zp->z_type, zp->z_class, + zp->z_source ? zp->z_source : "Nil"); + fprintf(fp, ";\ttime=%lu, lastupdate=%lu, serial=%u,\n", + (u_long)zp->z_time, (u_long)zp->z_lastupdate, + zp->z_serial); + fprintf(fp, ";\trefresh=%u, retry=%u, expire=%u, minimum=%u\n", + zp->z_refresh, zp->z_retry, + zp->z_expire, zp->z_minimum); + fprintf(fp, ";\tftime=%lu, xaddrcnt=%d, state=%04x, pid=%d\n", + (u_long)zp->z_ftime, zp->z_xaddrcnt, + zp->z_flags, (int)zp->z_xferpid); + sprintf(buf, ";\tz_addr[%d]: ", zp->z_addrcnt); + pre = buf; + for (cnt = 0; cnt < zp->z_addrcnt; cnt++) { + fprintf(fp, "%s[%s]", pre, inet_ntoa(zp->z_addr[cnt])); + pre = ", "; + } + if (zp->z_addrcnt) + fputc('\n', fp); + if (zp->z_axfr_src.s_addr != 0) + fprintf(fp, ";\tupdate source [%s]\n", + inet_ntoa(zp->z_axfr_src)); + } + fprintf(fp, ";; --zone table--\n"); + return (0); +} + +static int +fwd_dump(FILE *fp) { + int i; + + fprintf(fp, ";; ++forwarders table++\n"); + for (i = 0; i < fwddata_count; i++) { + if (fwddata[i] != NULL) + fprintf(fp,"; %s rtt=%d\n", + inet_ntoa(fwddata[i]->fwdaddr.sin_addr), + fwddata[i]->nsdata->d_nstime); + } + fprintf(fp, ";; --forwarders table--\n"); + return (0); +} + +int +db_dump(struct hashbuf *htp, FILE *fp, int zone, const char *origin) { + struct databuf *dp = NULL; + struct namebuf *np; + struct namebuf **npp, **nppend; + char dname[MAXDNAME]; + u_int32_t n; + int j, i, found_data, tab, printed_origin; + u_char *cp, *end; + const char *proto, *sep; + int16_t type; + u_int16_t keyflags; + u_char *sigdata, *certdata; + u_char *savecp; + char temp_base64[NS_MD5RSA_MAX_BASE64]; + + found_data = 0; + printed_origin = 0; + npp = htp->h_tab; + nppend = npp + htp->h_size; + while (npp < nppend) { + for (np = *npp++; np != NULL; np = np->n_next) { + if (np->n_data == NULL) + continue; + /* Blecch - can't tell if there is data here for the + * right zone, so can't print name yet + */ + found_data = 0; + /* we want a snapshot in time... */ + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + /* Is the data for this zone? */ + if (zone != DB_Z_ALL && dp->d_zone != zone) + continue; + /* XXX why are we not calling stale() here? */ + if (dp->d_zone == DB_Z_CACHE && + dp->d_ttl <= (u_int32_t)tt.tv_sec && + (dp->d_flags & DB_F_HINT) == 0) + continue; + if (!printed_origin) { + fprintf(fp, "$ORIGIN %s.\n", origin); + printed_origin++; + } + tab = 0; + if (dp->d_rcode == NXDOMAIN || + dp->d_rcode == NOERROR_NODATA) { + fputc(';', fp); + } else if (found_data == 0 || found_data == 1) { + found_data = 2; + } + if (found_data == 0 || found_data == 2) { + if (NAME(*np)[0] == '\0') { + if (origin[0] == '\0') + fprintf(fp, ".\t"); + else + fprintf(fp, ".%s.\t", origin); /* ??? */ + } else + fprintf(fp, "%s\t", NAME(*np)); + if (NAMELEN(*np) < (unsigned)8) + tab = 1; + found_data++; + } else { + (void) putc('\t', fp); + tab = 1; + } + if (dp->d_zone == DB_Z_CACHE) { + if (dp->d_flags & DB_F_HINT && + (int32_t)(dp->d_ttl - tt.tv_sec) + < DB_ROOT_TIMBUF) + fprintf(fp, "%d\t", DB_ROOT_TIMBUF); + else + fprintf(fp, "%d\t", + (int)(dp->d_ttl - tt.tv_sec)); + } else if (dp->d_ttl != USE_MINIMUM) + fprintf(fp, "%u\t", dp->d_ttl); + else + fprintf(fp, "%u\t", + zones[dp->d_zone].z_minimum); + fprintf(fp, "%s\t%s\t", + p_class(dp->d_class), + p_type(dp->d_type)); + cp = (u_char *)dp->d_data; + sep = "\t;"; + type = dp->d_type; + if (dp->d_rcode == NXDOMAIN || + dp->d_rcode == NOERROR_NODATA) { +#ifdef RETURNSOA + if (dp->d_size == 0) { +#endif + + fprintf(fp, "%s%s-$", + (dp->d_rcode == NXDOMAIN) + ?"NXDOMAIN" :"NODATA", + sep); + goto eoln; +#ifdef RETURNSOA + } else { + type = T_SOA; + } +#endif + } + /* + * Print type specific data + */ + /* XXX why are we not using ns_sprintrr() here? */ + switch (type) { + case T_A: + switch (dp->d_class) { + case C_IN: + case C_HS: + fputs(inet_ntoa(ina_get(cp)), fp); + break; + } + if (dp->d_nstime) { + fprintf(fp, "%sNT=%d", + sep, dp->d_nstime); + sep = " "; + } + break; + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_PTR: + fprintf(fp, "%s.", cp); + break; + + case T_NS: + cp = (u_char *)dp->d_data; + if (cp[0] == '\0') + fprintf(fp, ".\t"); + else + fprintf(fp, "%s.", cp); + break; + + case T_HINFO: + case T_ISDN: { + char buf[256]; + + if ((n = *cp++) != '\0') { + memcpy(buf, cp, n); buf[n] = '\0'; + fprintf(fp, "\"%.*s\"", (int)n, buf); + cp += n; + } else + fprintf(fp, "\"\""); + if ((n = *cp++) != '\0') { + memcpy(buf, cp, n); buf[n] = '\0'; + fprintf(fp, " \"%.*s\"", (int)n, buf); + } else + fprintf(fp, " \"\""); + break; + } + + case T_SOA: + fprintf(fp, "%s.", cp); + cp += strlen((char *)cp) + 1; + fprintf(fp, " %s. (\n", cp); +#if defined(RETURNSOA) + if (dp->d_rcode) + fputs(";", fp); +#endif + cp += strlen((char *)cp) + 1; + NS_GET32(n, cp); + fprintf(fp, "\t\t%u", n); + NS_GET32(n, cp); + fprintf(fp, " %u", n); + NS_GET32(n, cp); + fprintf(fp, " %u", n); + NS_GET32(n, cp); + fprintf(fp, " %u", n); + NS_GET32(n, cp); + fprintf(fp, " %u )", n); +#if defined(RETURNSOA) + if (dp->d_rcode) { + fprintf(fp,";%s.;%s%s-$",cp, + (dp->d_rcode == NXDOMAIN) ? + "NXDOMAIN" : "NODATA", + sep); + } +#endif + break; + + case T_MX: + case T_AFSDB: + case T_RT: + NS_GET16(n, cp); + fprintf(fp, "%u", n); + fprintf(fp, " %s.", cp); + break; + + case T_PX: + NS_GET16(n, cp); + fprintf(fp, "%u", n); + fprintf(fp, " %s.", cp); + cp += strlen((char *)cp) + 1; + fprintf(fp, " %s.", cp); + break; + + case T_X25: + if ((n = *cp++) != '\0') + fprintf(fp, " \"%.*s\"", (int)n, cp); + else + fprintf(fp, " \"\""); + break; + + case T_TXT: + end = (u_char *)dp->d_data + dp->d_size; + while (cp < end) { + (void) putc('"', fp); + if ((n = *cp++) != '\0') { + for (j = n ; j > 0 && cp < end ; j--) { + if (*cp == '\n' || *cp == '"' || *cp == '\\') + (void) putc('\\', fp); + (void) putc(*cp++, fp); + } + } + (void) putc('"', fp); + if (cp < end) + (void) putc(' ', fp); + } + break; + + case T_NSAP: + (void) fputs(inet_nsap_ntoa(dp->d_size, + dp->d_data, NULL), + fp); + break; + + case T_AAAA: { + char t[sizeof + "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255" + ]; + + (void) fputs(inet_ntop(AF_INET6, dp->d_data, + t, sizeof t), + fp); + break; + } + + case T_LOC: { + char t[256]; + + (void) fputs(loc_ntoa(dp->d_data, t), fp); + break; + } + + case T_NAPTR: { + u_int32_t order, preference; + + NS_GET16(order, cp); + fprintf(fp, "%u", order); + + NS_GET16(preference, cp); + fprintf(fp, "%u", preference); + + n = *cp++; + fprintf(fp, "\"%.*s\"", (int)n, cp); + cp += n; + + n = *cp++; + fprintf(fp, "\"%.*s\"", (int)n, cp); + cp += n; + + n = *cp++; + fprintf(fp, " \"%.*s\"", (int)n, cp); + cp += n; + + fprintf(fp, " %s.", cp); + + break; + } + + case T_SRV: { + u_int priority, weight, port; + + NS_GET16(priority, cp); + NS_GET16(weight, cp); + NS_GET16(port, cp); + fprintf(fp, "\t%u %u %u %s.", + priority, weight, port, cp); + break; + } + + case T_WKS: + fputs(inet_ntoa(ina_get(cp)), fp); + cp += INADDRSZ; + proto = protocolname(*cp); + cp += sizeof(char); + fprintf(fp, " %s ", proto); + i = 0; + while(cp < (u_char *)dp->d_data + dp->d_size) { + j = *cp++; + do { + if (j & 0200) + fprintf(fp, " %s", + servicename(i, proto)); + j <<= 1; + } while (++i & 07); + } + break; + + case T_MINFO: + case T_RP: + fprintf(fp, "%s.", cp); + cp += strlen((char *)cp) + 1; + fprintf(fp, " %s.", cp); + break; + + case T_KEY: + savecp = cp; /* save the beginning */ + /*>>> Flags (unsigned_16) */ + NS_GET16(keyflags,cp); + fprintf(fp, "0x%04x ", keyflags); + /*>>> Protocol (8-bit decimal) */ + fprintf(fp, "%3u ", *cp++); + /*>>> Algorithm id (8-bit decimal) */ + fprintf(fp, "%3u ", *cp++); + + /*>>> Public-Key Data (multidigit BASE64) */ + /* containing ExponentLen, Exponent, and Modulus */ + i = b64_ntop(cp, dp->d_size - (cp - savecp), + temp_base64, + sizeof temp_base64); + if (i < 0) + fprintf(fp, "; BAD BASE64"); + else + fprintf(fp, "%s", temp_base64); + break; + + case T_SIG: + sigdata = cp; + /* RRtype (char *) */ + NS_GET16(n,cp); + fprintf(fp, "%s ", p_type(n)); + /* Algorithm id (8-bit decimal) */ + fprintf(fp, "%d ", *cp++); + /* Labels (8-bit decimal) */ + fprintf(fp, "%d ", *cp++); + /* OTTL (u_long) */ + NS_GET32(n, cp); + fprintf(fp, "%u ", n); + /* Texp (u_long) */ + NS_GET32(n, cp); + fprintf(fp, "%s ", p_secstodate (n)); + /* Tsig (u_long) */ + NS_GET32(n, cp); + fprintf(fp, "%s ", p_secstodate (n)); + /* Kfootprint (unsigned_16) */ + NS_GET16(n, cp); + fprintf(fp, "%u ", n); + /* Signer's Name (char *) */ + fprintf(fp, "%s ", cp); + cp += strlen((char *)cp) + 1; + /* Signature (base64 of any length) */ + i = b64_ntop(cp, dp->d_size - (cp - sigdata), + temp_base64, + sizeof temp_base64); + if (i < 0) + fprintf(fp, "; BAD BASE64"); + else + fprintf(fp, "%s", temp_base64); + break; + + case T_NXT: + fprintf(fp, "%s.", cp); + n = strlen ((char *)cp) + 1; + cp += n; + i = 8 * (dp->d_size - n); /* How many bits? */ + for (n = 0; n < (u_int32_t)i; n++) { + if (NS_NXT_BIT_ISSET(n, cp)) + fprintf(fp," %s", p_type(n)); + } + break; + + case ns_t_cert: + certdata = cp; + NS_GET16(n,cp); + fprintf(fp, "%d ", n); /* cert type */ + + NS_GET16(n,cp); + fprintf(fp, "%d %d ", n, *cp++); /* tag & alg */ + + /* Certificate (base64 of any length) */ + i = b64_ntop(cp, + dp->d_size - (cp - certdata), + temp_base64, sizeof(temp_base64)); + if (i < 0) + fprintf(fp, "; BAD BASE64"); + else + fprintf(fp, "%s", temp_base64); + break; + + default: + fprintf(fp, "\\# %u", dp->d_size); + if (dp->d_size != 0) { + fputs(" ( ", fp); + isc_puthexstring(fp, dp->d_data, + dp->d_size, 40, 48, + "\n\t\t\t\t"); + fputs(" ) ", fp); + } + } + if (dp->d_cred < DB_C_ZONE) { + fprintf(fp, "%sCr=%s", + sep, MkCredStr(dp->d_cred)); + sep = " "; + } else { + fprintf(fp, "%sCl=%d", + sep, dp->d_clev); + sep = " "; + } + if ((dp->d_flags & DB_F_LAME) != 0) { + time_t when; + getname(np, dname, sizeof(dname)); + when = db_lame_find(dname, dp); + if (when != 0 && when > tt.tv_sec) { + fprintf(fp, "%sLAME=%ld", + sep, when - tt.tv_sec); + sep = " "; + } + } + + eoln: + if (dp->d_addr.s_addr != htonl(0)) { + fprintf(fp, "%s[%s]", + sep, inet_ntoa(dp->d_addr)); + sep = " "; + } +#ifdef HITCOUNTS + if (NS_OPTION_P(OPTION_HITCOUNT)) { + fprintf(fp, "%shits=%d", sep, dp->d_hitcnt); + sep=" "; + } +#endif /* HITCOUNTS */ + putc('\n', fp); + } + } + } + if (ferror(fp)) + return (NODBFILE); + + npp = htp->h_tab; + nppend = npp + htp->h_size; + while (npp < nppend) { + for (np = *npp++; np != NULL; np = np->n_next) { + if (np->n_hash == NULL) + continue; + getname(np, dname, sizeof(dname)); + if (db_dump(np->n_hash, fp, zone, dname) == NODBFILE) + return (NODBFILE); + } + } + return (OK); +} + +static const char * +MkCredStr(int cred) { + static char badness[20]; + + switch (cred) { + case DB_C_ZONE: return "zone"; + case DB_C_AUTH: return "auth"; + case DB_C_ANSWER: return "answer"; + case DB_C_ADDITIONAL: return "addtnl"; + case DB_C_CACHE: return "cache"; + default: break; + } + sprintf(badness, "?%d?", cred); + return (badness); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/db_dump.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/db_func.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/db_func.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/db_func.h (revision 109985) @@ -0,0 +1,211 @@ +/* + * Copyright (c) 1985, 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1999 by Check Point Software Technologies, Inc. + * + * 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 Check Point Software Technologies Incorporated 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 CHECK POINT SOFTWARE TECHNOLOGIES + * INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL CHECK POINT SOFTWARE TECHNOLOGIES INCORPRATED + * 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 SOFTWARE. + */ + +/* db_proc.h - prototypes for functions in db_*.c + * + * $Id: db_func.h,v 8.46 2001/06/18 14:42:51 marka Exp $ + */ + +/* ++from db_update.c++ */ +int db_update(const char *name, + struct databuf *odp, + struct databuf *newdp, + struct databuf **savedpp, + int flags, + struct hashbuf *htp, + struct sockaddr_in from); +int db_cmp(const struct databuf *, const struct databuf *); +int findMyZone(struct namebuf *np, int class); +void fixttl(struct databuf *dp); +/* --from db_update.c-- */ + +/* ++from db_save.c++ */ +struct namebuf * savename(const char *, int); +struct databuf * savedata(int, int, u_int32_t, u_char *, int); +struct hashbuf * savehash(struct hashbuf *); +/* --from db_save.c-- */ + +/* ++from db_dump.c++ */ +int db_dump(struct hashbuf *, FILE *, int, const char *), + zt_dump(FILE *); +void doadump(void); +/* --from db_dump.c-- */ + +/* ++from db_load.c++ */ +int makename_ok(char *name, const char *origin, int class, + struct zoneinfo *zp, + enum transport transport, + enum context context, + const char *owner, const char *filename, + int lineno, int size); +void endline(FILE *); +int getword(char *, size_t, FILE *, int); +int getttl(FILE *, const char *, int, u_int32_t *, int *); +int getnum(FILE *, const char *, int, int *); +int db_load(const char *, const char *, struct zoneinfo *, + const char *, int); +int getnonblank(FILE *, const char *, int); +int getservices(int, char *, FILE *, const char *); +char getprotocol(FILE *, const char *); +int makename(char *, const char *, int); +void db_err(int, char *, int, const char *, int); +int parse_sec_rdata(char *inp, int inp_len, int inp_full, + u_char *data, int data_len, + FILE *fp, struct zoneinfo *zp, + char *domain, u_int32_t ttl, + int type, enum context context, + enum transport transport, + const char **errmsg); +/* --from db_load.c-- */ + +/* ++from db_glue.c++ */ +void buildservicelist(void); +void destroyservicelist(void); +void buildprotolist(void); +void destroyprotolist(void); +void getname(struct namebuf *, char *, int); +int servicenumber(const char *); +int protocolnumber(const char *); +int get_class(const char *); +u_int nhash(const char *); +const char * protocolname(int); +const char * servicename(u_int16_t, const char *); +struct databuf * rm_datum(struct databuf *, + struct namebuf *, + struct databuf *, + struct databuf **); +struct namebuf * rm_name(struct namebuf *, + struct namebuf **, + struct namebuf *); +void rm_hash(struct hashbuf *); +void db_detach(struct databuf **); +void db_lame_add(char *zone, char *server, time_t when); +time_t db_lame_find(char *zone, struct databuf *dp); +void db_lame_clean(void); +void db_lame_destroy(void); +/* --from db_glue.c-- */ + +/* ++from db_lookup.c++ */ +struct namebuf * nlookup(const char *, struct hashbuf **, + const char **, int); +struct namebuf * np_parent(struct namebuf *); +int match(struct databuf *, int, int), + nxtmatch(const char *, struct databuf *, + struct databuf *), + rrmatch(const char *, struct databuf *, + struct databuf *); +/* --from db_lookup.c-- */ + +/* ++from db_ixfr.c++ */ +ns_deltalist * ixfr_get_change_list(struct zoneinfo *, u_int32_t, + u_int32_t); +int ixfr_have_log(struct zoneinfo *, u_int32_t, + u_int32_t); +/* --from db_ixfr.c++ */ + +/* ++from db_sec.c++ */ +int add_trusted_key(const char *name, const int flags, + const int proto, const int alg, + const char *str); +int db_set_update(char *name, struct databuf *dp, + void **state, int flags, + struct hashbuf **htp, + struct sockaddr_in from, + int *rrcount, int line, + const char *file); +/* --from db_sec.c-- */ + +/* ++from db_tsig.c++ */ +const char * tsig_alg_name(int value); +int tsig_alg_value(char *name); +struct dst_key * tsig_key_from_addr(struct in_addr addr); +struct tsig_record * new_tsig(struct dst_key *key, u_char *sig, int siglen); +void free_tsig(struct tsig_record *tsig); +/* --from db_tsig.c-- */ Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/db_func.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/db_ixfr.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/db_ixfr.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/db_ixfr.c (revision 109985) @@ -0,0 +1,983 @@ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: db_ixfr.c,v 8.31 2002/01/02 04:47:10 marka Exp $"; +#endif + +/* + * Portions Copyright (c) 1999 by Check Point Software Technologies, Inc. + * + * 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 Check Point Software Technologies Incorporated 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 CHECK POINT SOFTWARE TECHNOLOGIES + * INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL CHECK POINT SOFTWARE TECHNOLOGIES INCORPRATED + * 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 SOFTWARE. + */ + +/* + * Manage ixfr transaction log + */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#include "named.h" + +#define DBIXFR_ERROR (-1) +#define DBIXFR_FOUND_RR 2 +#define DBIXFR_END 3 + +static int ixfr_getdelta(struct zoneinfo *, FILE *, const char *, char *, + ns_updque *, u_int32_t *, u_int32_t *); + +ns_deltalist * +ixfr_get_change_list(struct zoneinfo *zp, + u_int32_t from_serial, u_int32_t to_serial) +{ + FILE * fp = NULL; + u_int32_t old_serial, new_serial; + char origin[MAXDNAME]; + ns_deltalist *dlhead = NULL; + int ret; + ns_updrec *uprec; + ns_delta *dl; + + if (SEQ_GT(from_serial, to_serial)) + return (NULL); + + dlhead = memget(sizeof(*dlhead)); + if (dlhead == NULL) + return (NULL); + INIT_LIST(*dlhead); + + if ((fp = fopen(zp->z_ixfr_base, "r")) == NULL) { + ns_warning(ns_log_db, "%s: %s", + zp->z_ixfr_base, strerror(errno)); + goto cleanup; + } + strcpy(origin, zp->z_origin); + lineno = 1; + old_serial = new_serial = 0; + + for (;;) { + dl = memget(sizeof *dl); + if (dl == NULL) { + ns_warning(ns_log_db, + "ixfr_get_change_list: out of memory"); + goto cleanup; + } + INIT_LINK(dl, d_link); + INIT_LIST(dl->d_changes); + ret = ixfr_getdelta(zp, fp, zp->z_ixfr_base, origin, + &dl->d_changes, &old_serial, &new_serial); + switch (ret) { + case DBIXFR_ERROR: + ns_warning(ns_log_db, "Logical error in %s: unlinking", + zp->z_ixfr_base); + if (fp != NULL) { + (void) my_fclose(fp); + fp = NULL; + } + unlink(zp->z_ixfr_base); + goto cleanup; + + case DBIXFR_FOUND_RR: + ns_debug(ns_log_default, 4, + "ixfr_getdelta DBIXFR_FOUND_RR (%s)", + zp->z_origin); + if (EMPTY(*dlhead)) { + /* skip updates prior to the one we want */ + uprec = HEAD(dl->d_changes); + INSIST(uprec != NULL); + if (SEQ_LT(uprec->r_zone, from_serial) || + SEQ_GT(uprec->r_zone, to_serial)) + { + while ((uprec = HEAD(dl->d_changes)) != NULL) { + UNLINK(dl->d_changes, uprec, r_link); + + if (uprec->r_dp != NULL) + db_detach(&uprec->r_dp); + res_freeupdrec(uprec); + } + memput(dl, sizeof *dl); + break; + } + else if (uprec->r_zone > from_serial) { + /* missed the boat */ + ns_debug(ns_log_default, 3, + "ixfr_getdelta first SOA is %d, asked for %d (%s)", + uprec->r_zone, + from_serial, + zp->z_origin); + goto cleanup; + } + } + ns_debug(ns_log_default, 4, + "adding to change list (%s)", + zp->z_origin); + APPEND(*dlhead, dl, d_link); + break; + + case DBIXFR_END: + ns_debug(ns_log_default, 4, + "ixfr_getdelta DBIXFR_END (%s)", + zp->z_origin); + (void) my_fclose(fp); + memput(dl, sizeof *dl); + return (dlhead); + + default: + (void) my_fclose(fp); + if (dl != NULL) + memput(dl, sizeof *dl); + return (NULL); + } + } + + cleanup: + if (fp != NULL) + (void) my_fclose(fp); + + while ((dl = HEAD(*dlhead)) != NULL) { + UNLINK(*dlhead, dl, d_link); + while ((uprec = HEAD(dl->d_changes)) != NULL) { + UNLINK(dl->d_changes, uprec, r_link); + + if (uprec->r_dp != NULL) + db_detach(&uprec->r_dp); + uprec->r_dp = NULL; + res_freeupdrec(uprec); + } + memput(dl, sizeof *dl); + } + memput(dlhead, sizeof *dlhead); + return (NULL); +} + +/* + * int ixfr_have_log(struct zoneinfo *zp,u_int32_t from_serial, + * u_int32_t to_serial) + * + * verify that ixfr transaction log contains changes + * from from_serial to to_serial + * + * returns: + * 0 = serial number is up to date + * 1 = transmission is possible + * -1 = error while opening the ixfr transaction log + * -2 = error in parameters + * -3 = logical error in the history file + */ +int +ixfr_have_log(struct zoneinfo *zp, u_int32_t from_serial, u_int32_t to_serial) +{ + FILE *fp; + u_int32_t old_serial = 0, new_serial = 0; + u_int32_t last_serial = 0; + u_int32_t first_serial = 0; + char buf[BUFSIZ]; + char *cp; + struct stat st; + int nonempty_lineno = -1, prev_pktdone = 0, cont = 0, + inside_next = 0; + int err; + int first = 0; + int rval = 0; + int id, rcode = NOERROR; + if (SEQ_GT(from_serial, to_serial)) + return (-2); + if (from_serial == to_serial) + return (0); + /* If there is no log file, just return. */ + if (zp->z_ixfr_base == NULL || zp->z_updatelog == NULL) + return (-1); + if (zp->z_serial_ixfr_start > 0) { + if (from_serial >= zp->z_serial_ixfr_start) + return (1); + } + if (stat(zp->z_ixfr_base, &st) < 0) { + if (errno != ENOENT) + ns_error(ns_log_db, + "unexpected stat(%s) failure: %s", + zp->z_ixfr_base, strerror(errno)); + return (-1); + } + if ((fp = fopen(zp->z_ixfr_base, "r")) == NULL) { + ns_warning(ns_log_db, "%s: %s", + zp->z_ixfr_base, strerror(errno)); + return (-1); + } + if (fgets(buf, sizeof(buf), fp) == NULL) { + ns_error(ns_log_update, "fgets() from %s failed: %s", + zp->z_ixfr_base, strerror(errno)); + fclose(fp); + return (-1); + } + if (strcmp(buf, LogSignature) != 0) { + ns_error(ns_log_update, "invalid log file %s", + zp->z_ixfr_base); + fclose(fp); + return (-3); + } + lineno = 1; + first = 1; + for (;;) { + if (getword(buf, sizeof buf, fp, 0)) { + nonempty_lineno = lineno; + } else { + if (lineno == (nonempty_lineno + 1)) + continue; + inside_next = 0; + prev_pktdone = 1; + cont = 1; + } + if (!strcasecmp(buf, "[DYNAMIC_UPDATE]") || + !strcasecmp(buf, "[IXFR_UPDATE]")) { + err = 0; + rcode = NOERROR; + cp = fgets(buf, sizeof buf, fp); + if (cp != NULL) + lineno++; + if (cp == NULL || !sscanf((char *) cp, "id %d", &id)) + id = -1; + inside_next = 1; + prev_pktdone = 1; + cont = 1; + } else if (!strcasecmp(buf, "serial")) { + cp = fgets(buf, sizeof buf, fp); + if (cp != NULL) + lineno++; + if (sscanf((char *) cp, "%u", &old_serial)) { + if (first == 1) { + first = 0; + first_serial = old_serial; + } + last_serial = old_serial; + if (from_serial >= old_serial) { + rval = 1; + } + } + prev_pktdone = 1; + cont = 1; + } else if (!strcasecmp(buf, "[INCR_SERIAL]")) { + /* XXXRTH not enough error checking here */ + cp = fgets(buf, sizeof buf, fp); + if (cp != NULL) + lineno++; + if (cp == NULL || + sscanf((char *) cp, "from %u to %u", + &old_serial, &new_serial) != 2) { + rval = -3; + break; + } else if (from_serial >= old_serial) { + if (first == 1) { + first = 0; + first_serial = old_serial; + } + last_serial = old_serial; + rval = 1; + } + } + if (prev_pktdone) { + prev_pktdone = 0; + if (feof(fp)) + break; + } + } + fclose(fp); + if (last_serial +1 < zp->z_serial) { + ns_warning(ns_log_db, + "%s: File Deleted. Found gap between serial:" + " %d and current serial: %d", + zp->z_ixfr_base, last_serial, zp->z_serial); + (void) unlink(zp->z_ixfr_base); + rval = -3; + } + if (from_serial < first_serial || from_serial > last_serial) + rval = -3; + if (rval == 1) + zp->z_serial_ixfr_start = first_serial; + return (rval); +} + +/* from db_load.c */ + +static struct map m_section[] = { + {"zone", S_ZONE}, + {"prereq", S_PREREQ}, + {"update", S_UPDATE}, + {"reserved", S_ADDT}, +}; +#define M_SECTION_CNT (sizeof(m_section) / sizeof(struct map)) + +/* from ns_req.c */ + +static struct map m_opcode[] = { + {"nxdomain", NXDOMAIN}, + {"yxdomain", YXDOMAIN}, + {"nxrrset", NXRRSET}, + {"yxrrset", YXRRSET}, + {"delete", DELETE}, + {"add", ADD}, +}; +#define M_OPCODE_CNT (sizeof(m_opcode) / sizeof(struct map)) + +/* XXXRTH workaround map difficulties */ +#define M_CLASS_CNT m_class_cnt +#define M_TYPE_CNT m_type_cnt + +/* + * read a line from the history of a zone. + * + * returns: + * + * DBIXFR_ERROR = an error occured + * DBIXFR_FOUND_RR = a rr encountered + * DBIXFR_END = end of file + */ +static int +ixfr_getdelta(struct zoneinfo *zp, FILE *fp, const char *filename, char *origin, + ns_updque *listuprec, u_int32_t *old_serial, + u_int32_t *new_serial) +{ + char data[MAXDATA], dnbuf[MAXDNAME], sclass[3]; + char *dname, *cp, *cp1; + char buf[MAXDATA]; + long unsigned lutmp; + u_int32_t serial = 0, ttl; + u_int32_t current_serial = 0; + int nonempty_lineno = -1, prev_pktdone = 0, cont = 0, + inside_next = 0; + int id; + int i, c, section, opcode, matches, zonenum, err, multiline; + int type, class; + u_int32_t n; + enum transport transport; + struct map *mp; + int zonelist[MAXDNAME]; + struct in_addr ina; + int datasize; + ns_updrec * rrecp; + u_long l; + +#define ERRTO(msg) if (1) { errtype = msg; goto err; } else (void)NULL + + err = 0; + transport = primary_trans; + lineno = 1; + zonenum = 0; + + /* + * Look for serial if "first" call othewise use new_serial to + * for current_serial. + */ + if (*old_serial == *new_serial && *old_serial == 0) + current_serial = 0; + else + current_serial = *new_serial; + + for (;;) { + dname = NULL; + if (!getword(buf, sizeof buf, fp, 0)) { + if (lineno == (nonempty_lineno + 1) && !(feof(fp))) { + /* + * End of a nonempty line inside an update + * packet or not inside an update packet. + */ + continue; + } + /* + * Empty line or EOF. + */ + if (feof(fp)) + break; + inside_next = 0; + cont = 1; + } else { + nonempty_lineno = lineno; + } + + if (!strcasecmp(buf, "[DYNAMIC_UPDATE]") || + !strcasecmp(buf, "[IXFR_UPDATE]")) { + cp = fgets(buf, sizeof buf, fp); + if (cp != NULL) + lineno++; + if (cp == NULL || !sscanf((char *) cp, "id %d", &id)) + id = -1; + inside_next = 1; + cont = 1; + } else if (!strcasecmp(buf, "[INCR_SERIAL]")) { + /* XXXRTH not enough error checking here */ + cp = fgets(buf, sizeof buf, fp); + if (cp != NULL) + lineno++; + if (cp == NULL || + sscanf((char *) cp, "from %u to %u", + old_serial, new_serial) != 2) { + ns_error(ns_log_update, + "incr_serial problem with %s", + zp->z_updatelog); + } else { + serial = get_serial(zp); + } + cont = 1; + } else if (!strcasecmp(buf, "[END_DELTA]")) { + prev_pktdone = 1; + cont = 1; + lineno++; + } + if (prev_pktdone) { + if (!EMPTY(*listuprec)) { + n++; + return (DBIXFR_FOUND_RR); + } + prev_pktdone = 0; + } + if (cont) { + cont = 0; + continue; + } + if (!inside_next) + continue; + /* + * inside the same update packet, continue accumulating + * records. + */ + section = -1; + n = strlen(buf); + if (buf[n - 1] == ':') + buf[--n] = '\0'; + for (mp = m_section; mp < m_section + M_SECTION_CNT; mp++) + if (!strcasecmp(buf, mp->token)) { + section = mp->val; + break; + } + ttl = 0; + type = -1; + class = zp->z_class; + n = 0; + data[0] = '\0'; + opcode = -1; + switch (section) { + case S_ZONE: + cp = fgets(buf, sizeof buf, fp); + if (!cp) + *buf = '\0'; + n = sscanf(cp, "origin %s class %s serial %lu", + origin, sclass, &lutmp); + serial = lutmp; + if (current_serial == 0) + current_serial = serial; + else if (current_serial != serial) { + ns_debug(ns_log_update, 1, + "%s:line %d serial # askew %d %d", + filename, lineno, serial, + current_serial); + current_serial = serial; + err++; + } + if (n != 3 || ns_samename(origin, zp->z_origin) != 1) + err++; + if (cp) + lineno++; + if (!err && inside_next) { + int success; + + dname = origin; + type = T_SOA; + class = res_nametoclass(sclass, &success); + if (!success) { + err++; + break; + } + matches = findzone(dname, class, 0, + zonelist, MAXDNAME); + if (matches) + zonenum = zonelist[0]; + else + err++; + } + break; + case S_PREREQ: + case S_UPDATE: + /* Operation code. */ + if (!getword(buf, sizeof buf, fp, 0)) { + err++; + break; + } + if (buf[0] == '{') { + n = strlen(buf); + for (i = 0; (u_int32_t) i < n; i++) + buf[i] = buf[i + 1]; + if (buf[n - 2] == '}') + buf[n - 2] = '\0'; + } + for (mp = m_opcode; mp < m_opcode + M_OPCODE_CNT; mp++) + if (!strcasecmp(buf, mp->token)) { + opcode = mp->val; + break; + } + if (opcode == -1) { + err++; + break; + } + /* Owner's domain name. */ + if (!getword((char *) dnbuf, sizeof dnbuf, fp, 0)) { + err++; + break; + } + n = strlen((char *) dnbuf) - 1; + if (dnbuf[n] == '.') + dnbuf[n] = '\0'; + dname = dnbuf; + ttl = 0; + type = -1; + class = zp->z_class; + n = 0; + data[0] = '\0'; + (void) getword(buf, sizeof buf, fp, 1); + if (isdigit(buf[0])) { /* ttl */ + if (ns_parse_ttl(buf, &l) < 0) { + err++; + break; + } + ttl = l; + (void) getword(buf, sizeof buf, fp, 1); + } + /* possibly class */ + if (buf[0] != '\0') { + int success; + int maybe_class; + + maybe_class = res_nametoclass(buf, &success); + if (success) { + class = maybe_class; + (void) getword(buf, sizeof buf, fp, 1); + } + } + /* possibly type */ + if (buf[0] != '\0') { + int success; + int maybe_type; + + maybe_type = res_nametotype(buf, &success); + + if (success) { + type = maybe_type; + (void) getword(buf, sizeof buf, fp, 1); + } + } + if (buf[0] != '\0') /* possibly rdata */ + /* + * Convert the ascii data 'buf' to the proper + * format based on the type and pack into + * 'data'. + * + * XXX - same as in db_load(), consolidation + * needed + */ + switch (type) { + case T_A: + if (!inet_aton(buf, &ina)) { + err++; + break; + } + n = ntohl(ina.s_addr); + cp = data; + PUTLONG(n, cp); + n = INT32SZ; + break; + case T_HINFO: + case T_ISDN: + n = strlen(buf); + data[0] = n; + memcpy(data + 1, buf, n); + n++; + if (!getword(buf, sizeof buf, fp, 0)) { + i = 0; + } else { + endline(fp); + i = strlen(buf); + } + data[n] = i; + n++; + memcpy(data + n + 1, buf, i); + n += i; + break; + case T_SOA: + case T_MINFO: + case T_RP: + (void) strcpy(data, buf); + cp = data + strlen(data) + 1; + if (!getword((char *) cp, + sizeof data - (cp - data), + fp, 1)) { + err++; + break; + } + cp += strlen((char *) cp) + 1; + if (type != T_SOA) { + n = cp - data; + break; + } + if (class != zp->z_class || + ns_samename(dname, zp->z_origin) != 1) { + err++; + break; + } + c = getnonblank(fp, zp->z_updatelog, 0); + if (c == '(') { + multiline = 1; + } else { + multiline = 0; + ungetc(c, fp); + } + n = getnum(fp, zp->z_updatelog, GETNUM_SERIAL, + &multiline); + if (getnum_error) { + err++; + break; + } + if (opcode == ADD) + *new_serial = n; + current_serial = n; + PUTLONG(n, cp); + for (i = 0; i < 4; i++) { + if (!getword(buf, sizeof buf, fp, 1)) { + err++; + break; + } + if (ns_parse_ttl(buf, &l) < 0) { + err++; + break; + } + n = l; + PUTLONG(n, cp); + } + if (multiline) { + c = getnonblank(fp, zp->z_updatelog, 1); + if (c != ')') { + ungetc(c, fp); + err++; + break; + } + } + endline(fp); + n = cp - data; + break; + case T_WKS: + if (!inet_aton(buf, &ina)) { + err++; + break; + } + n = ntohl(ina.s_addr); + cp = data; + PUTLONG(n, cp); + *cp = (char) getprotocol(fp, zp->z_updatelog); + n = INT32SZ + sizeof(char); + n = getservices((int) n, data, + fp, zp->z_updatelog); + break; + case T_NS: + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_PTR: + (void) strcpy(data, buf); + if (makename(data, origin, + sizeof(data)) == -1) { + err++; + break; + } + n = strlen(data) + 1; + break; + case T_MX: + case T_AFSDB: + case T_RT: + n = 0; + cp = buf; + while (isdigit(*cp)) + n = n * 10 + (*cp++ - '0'); + /* catch bad values */ + cp = data; + PUTSHORT((u_int16_t) n, cp); + if (!getword(buf, sizeof(buf), fp, 1)) { + err++; + break; + } + (void) strcpy((char *) cp, buf); + if (makename((char *) cp, origin, + sizeof(data) - (cp - data)) == -1) + { + err++; + break; + } + /* advance pointer to end of data */ + cp += strlen((char *) cp) + 1; + /* now save length */ + n = (cp - data); + break; + case T_PX: + n = 0; + data[0] = '\0'; + cp = buf; + while (isdigit(*cp)) + n = n * 10 + (*cp++ - '0'); + cp = data; + PUTSHORT((u_int16_t) n, cp); + for (i = 0; i < 2; i++) { + if (!getword(buf, sizeof(buf), fp, 0)) + { + err++; + break; + } + (void) strcpy((char *) cp, buf); + cp += strlen((char *) cp) + 1; + } + n = cp - data; + break; + case T_TXT: + case T_X25: + i = strlen(buf); + cp = data; + datasize = sizeof data; + cp1 = buf; + while (i > MAXCHARSTRING) { + if (datasize <= MAXCHARSTRING) { + ns_error(ns_log_update, + "record too big"); + return (-1); + } + datasize -= MAXCHARSTRING; + *cp++ = (char)MAXCHARSTRING; + memcpy(cp, cp1, MAXCHARSTRING); + cp += MAXCHARSTRING; + cp1 += MAXCHARSTRING; + i -= MAXCHARSTRING; + } + if (datasize < i + 1) { + ns_error(ns_log_update, + "record too big"); + return (-1); + } + *cp++ = i; + memcpy(cp, cp1, i); + cp += i; + n = cp - data; + endline(fp); + /* XXXVIX: segmented texts 4.9.5 */ + break; + case T_NSAP: + n = inet_nsap_addr(buf, (u_char *) data, + sizeof data); + endline(fp); + break; + case T_LOC: + cp = buf + (n = strlen(buf)); + *cp = ' '; + cp++; + while ((i = getc(fp), *cp = i, i != EOF) + && *cp != '\n' && (n < MAXDATA)) + { + cp++; + n++; + } + if (*cp == '\n') + ungetc(*cp, fp); + *cp = '\0'; + n = loc_aton(buf, (u_char *) data); + if (n == 0) { + err++; + break; + } + endline(fp); + break; + case ns_t_sig: + case ns_t_nxt: + case ns_t_key: + case ns_t_cert:{ + const char *errmsg = NULL; + + n = parse_sec_rdata(buf, sizeof(buf), 1, + (u_char *) data, + sizeof(data), + fp, zp, dname, ttl, + type, domain_ctx, + transport, &errmsg); + if (errmsg) { + err++; + endline(fp); + n = 0; + } + break; + } + default: + if (strcmp(buf, "\\#") != 0) { + err++; + break; + } + if (!getword(buf, sizeof buf, fp, 0) || + !isdigit((unsigned char)buf[0])) { + err++; + break; + } + n = strtoul(buf, &cp, 10); + if (n > 0xffff || *cp != '\0') { + err++; + break; + } + multiline = 0; + i = isc_gethexstring((u_char *)data, + sizeof(data), n, fp, + &multiline); + if (i == -1) { + err++; + break; + } + if (multiline) { + c = getnonblank(fp, zp->z_updatelog, 1); + if (c != ')') { + ungetc(c, fp); + err++; + break; + } + multiline = 0; + } + endline(fp); + } + if (section == S_PREREQ) { + ttl = 0; + if (opcode == NXDOMAIN) { + class = C_NONE; + type = T_ANY; + n = 0; + } else if (opcode == YXDOMAIN) { + class = C_ANY; + type = T_ANY; + n = 0; + } else if (opcode == NXRRSET) { + class = C_NONE; + n = 0; + } else if (opcode == YXRRSET) { + if (n == 0) + class = C_ANY; + } + } else {/* section == S_UPDATE */ + if (opcode == DELETE) { + if (n == 0) { + class = C_ANY; + if (type == -1) + type = T_ANY; + } else { + class = zp->z_class; + } + } + } + break; + case S_ADDT: + default: + ns_debug(ns_log_update, 1, + "cannot interpret section: %d", section); + inside_next = 0; + err++; + } + if (err) { + inside_next = 0; + ns_debug(ns_log_update, 1, + "merge of update id %d failed due to error at line %d", + id, lineno); + return (DBIXFR_ERROR); + } + rrecp = res_mkupdrec(section, dname, class, type, ttl); + if (section != S_ZONE) { + struct databuf *dp; + dp = savedata(class, type, ttl, (u_char *) data, n); + dp->d_zone = zonenum; + dp->d_cred = DB_C_ZONE; + dp->d_clev = nlabels(zp->z_origin); + rrecp->r_dp = dp; + rrecp->r_opcode = opcode; + } else { + rrecp->r_zone = zonenum; + rrecp->r_opcode = opcode; + } + + /* remove add/delete pairs */ + if (section == S_UPDATE) { + ns_updrec *arp; + int foundmatch; + + arp = TAIL(*listuprec); + foundmatch = 0; + while (arp) { + if (arp->r_section == S_UPDATE && + ((arp->r_opcode == DELETE && + opcode == ADD) || + (opcode == DELETE && + arp->r_opcode == ADD)) && + arp->r_dp->d_type == rrecp->r_dp->d_type && + arp->r_dp->d_class == rrecp->r_dp->d_class && + arp->r_dp->d_ttl == rrecp->r_dp->d_ttl && + ns_samename(arp->r_dname, dname) == 1 && + db_cmp(arp->r_dp, rrecp->r_dp) == 0) { + db_detach(&rrecp->r_dp); + db_detach(&arp->r_dp); + UNLINK(*listuprec, arp, r_link); + res_freeupdrec(arp); + res_freeupdrec(rrecp); + foundmatch = 1; + break; + } + arp = PREV(arp, r_link); + } + if (foundmatch) + continue; + } + + APPEND(*listuprec, rrecp, r_link); + /* Override zone number with current zone serial number */ + rrecp->r_zone = serial; + } + + if (err) + return (DBIXFR_ERROR); + + return (DBIXFR_END); +} + Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/db_ixfr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/db_load.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/db_load.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/db_load.c (revision 109985) @@ -0,0 +1,2749 @@ +#if !defined(lint) && !defined(SABER) +static const char sccsid[] = "@(#)db_load.c 4.38 (Berkeley) 3/2/91"; +static const char rcsid[] = "$Id: db_load.c,v 8.121 2001/11/12 21:22:22 marka Exp $"; +#endif /* not lint */ + +/* + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * Load zone from ASCII file on local host. Format similar to RFC 883. + */ + +/* Import. */ + +#include "port_before.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#include "named.h" + +/* Forward. */ + +static int gettoken(FILE *, const char *); +static int getcharstring(char *, char *, int, int, int, FILE *, + const char *); +static int genname(char *, int, const char *, char *, int); +static int getmlword(char *, size_t, FILE *, int); +static int getallwords(char *, size_t, FILE *, int); +static u_int32_t wordtouint32(char *); +static void fixup_soa(const char *fn, struct zoneinfo *zp); +static int get_nxt_types(u_char *, FILE *, const char *); + +static int parse_sig_rr(char *, int, u_char *, int, FILE *, + struct zoneinfo *, char *, u_int32_t , + enum context, enum transport, + const char **); +static int parse_key_rr(char *, int, u_char *, int, FILE *, + const char **); + +static int parse_cert_rr(char *, int, u_char *, int, FILE *, + const char **); +static int parse_nxt_rr(char *, u_char *, int, FILE *, + struct zoneinfo *, char *, enum context, + enum transport, const char **); + + +static int wordtouint32_error = 0; +static int empty_token = 0; +static int getmlword_nesting = 0; + +/* Global. */ + +static int clev; /* a zone deeper in a hierarchy has more credibility */ + +/* + * Parser token values + */ +#define CURRENT 1 +#define DOT 2 +#define AT 3 +#define DNAME 4 +#define INCLUDE 5 +#define ORIGIN 6 +#define GENERATE 7 +#define DEFAULTTTL 8 +#define ERRTOK 9 + +#define MAKENAME_OK(N) \ + do { \ + if (!makename_ok(N, origin, class, zp, \ + transport, context, \ + domain, filename, lineno, \ + data_size - ((u_char*)N - data))) { \ + errs++; \ + sprintf(buf, "bad name \"%s\"", N); \ + goto err; \ + } \ + } while (0) + +#define MAKENAME_OKZP(N, SI) \ + do { \ + if (!makename_ok(N, zp->z_origin, zp->z_class, zp, \ + transport, context, \ + domain, zp->z_source, lineno, \ + SI - ((u_char*)N - data))) { \ + errs++; \ + sprintf(buf, "bad name \"%s\"", N); \ + goto err; \ + } \ + } while (0) + +#define RANGE(x, min, max) \ + (((x) > (max)) ? (max) : (((x) < (min)) ? (min) : (x))) + +/* Public. */ + +/* int + * db_load(filename, in_origin, zp, def_domain, isixfr) + * load a database from `filename' into zone `zp'. append `in_origin' + * to all nonterminal domain names in the file. `def_domain' is the + * default domain for include files or NULL for zone base files. + * returns: + * -1 = can't open file + * 0 = success + * >0 = number of errors encountered + */ +int +db_load(const char *filename, const char *in_origin, + struct zoneinfo *zp, const char *def_domain, int isixfr) +{ + static int read_soa, read_ns, rrcount; + static u_int32_t default_ttl, default_warn; + static struct filenames { + struct filenames *next; + char *name; + } *filenames, *fn; + + const char *errtype = "Database"; + char *cp; + char domain[MAXDNAME], origin[MAXDNAME], tmporigin[MAXDNAME]; + char buf[MAXDATA]; + char genlhs[MAXDNAME], genrhs[MAXDNAME]; + u_char data[MAXDATA]; + unsigned int data_size = sizeof(data); + int c, someclass, class, type, dbflags, dataflags, multiline = 0; + int slineno, i, errs, didinclude, ininclude, escape, success; + u_int32_t ttl, n, serial; + u_long tmplong; + struct databuf *dp; + FILE *fp; + struct stat sb; + struct in_addr ina; + enum transport transport; + enum context context; + struct sockaddr_in empty_from; + int genstart, genend, genstep; + char *thisfile; + void *state = NULL; + int loggenerr; + + empty_from.sin_family = AF_INET; + empty_from.sin_addr.s_addr = htonl(INADDR_ANY); + empty_from.sin_port = htons(0); + +/* + * We use an 'if' inside of the 'do' below because otherwise the Solaris + * compiler detects that the 'while' is never executed because of the 'goto' + * and complains. + */ +#define ERRTO(msg) do { if (1) { errtype = msg; goto err; } } while (0) +#define ERRTOZ(msg) do { if (1) { errtype = msg; buf[0] = '\0'; goto err; } } while (0) + + switch (zp->z_type) { + case Z_PRIMARY: + /* Any updates should be saved before we attempt to reload. */ + INSIST((zp->z_flags & (Z_NEED_DUMP|Z_NEED_SOAUPDATE)) == 0); + case Z_HINT: + if (filename == NULL) { + ns_error(ns_log_load, + "Required filename not specified for Hint zone"); + zp->z_flags |= Z_DB_BAD; + zp->z_ftime = 0; + return (0); + } + transport = primary_trans; + break; + case Z_SECONDARY: + case Z_STUB: + transport = secondary_trans; + break; + case Z_CACHE: + transport = response_trans; + break; + default: + transport = response_trans; /*guessing*/ + break; + } + errs = 0; + didinclude = 0; + ininclude = (def_domain != NULL); + if (!ininclude) { + rrcount = 0; + read_soa = 0; + read_ns = 0; + default_ttl = USE_MINIMUM; + default_warn = 1; + clev = nlabels(in_origin); + filenames = NULL; + zp->z_minimum = USE_MINIMUM; + } + ttl = default_ttl; + + ns_debug(ns_log_load, 1, "db_load(%s, %s, %d, %s, %s)", + filename, in_origin, zp - zones, + def_domain ? def_domain : "Nil", isixfr ? "IXFR" : "Normal"); + + fn = (struct filenames *)memget(sizeof *filenames); + if (fn == NULL) + ns_panic(ns_log_db, 0, "db_load: memget failed"); + thisfile = fn->name = savestr(filename, 1); + fn->next = filenames; + filenames = fn; + + strcpy(origin, in_origin); + if ((fp = fopen(filename, "r")) == NULL) { + ns_warning(ns_log_load, "db_load could not open: %s: %s", + filename, strerror(errno)); + zp->z_ftime = 0; + if (ininclude) + return (-1); + errs = -1; + goto cleanup; + } + if (zp->z_type == Z_HINT) { + dbflags = DB_NODATA | DB_NOHINTS; + dataflags = DB_F_HINT; +#ifdef STUBS + } else if (zp->z_type == Z_STUB && clev == 0) { + dbflags = DB_NODATA | DB_NOHINTS; + dataflags = DB_F_HINT; +#endif + } else { + dbflags = DB_NODATA; + dataflags = 0; + } + gettime(&tt); + if (fstat(fileno(fp), &sb) < 0) { + ns_warning(ns_log_load, "fstat failed: %s: %s", + filename, strerror(errno)); + sb.st_mtime = (int)tt.tv_sec; + } + slineno = lineno; + lineno = 1; + if (def_domain) + strcpy(domain, def_domain); + else + domain[0] = '\0'; + class = zp->z_class; + zp->z_flags &= ~(Z_INCLUDE|Z_DB_BAD); + while ((c = gettoken(fp, filename)) != EOF) { + switch (c) { + case INCLUDE: + if (isixfr) { + c = ERRTOK; + break; + } + if (!getword(buf, sizeof buf, fp, 0)) + /* file name*/ + break; + if (!getword(tmporigin, sizeof(tmporigin), fp, 1)) + strcpy(tmporigin, origin); + else { + if (makename(tmporigin, origin, + sizeof(tmporigin)) == -1) + ERRTO("$INCLUDE makename failed"); + endline(fp); + } + didinclude = 1; + i = db_load(buf, tmporigin, zp, domain, ISNOTIXFR); + errs += (i == -1) ? 1 : i; + continue; + + case ORIGIN: + (void) strcpy(buf, origin); + if (!getword(origin, sizeof(origin), fp, 1)) + break; + ns_debug(ns_log_load, 3, "db_load: origin %s, buf %s", + origin, buf); + if (makename(origin, buf, sizeof(origin)) == -1) + ERRTO("$ORIGIN makename failed"); + ns_debug(ns_log_load, 3, "db_load: origin now %s", + origin); + continue; + + case GENERATE: + if (!getword(buf, sizeof(buf), fp, 0)) + ERRTOZ("$GENERATE missing RANGE"); + n = sscanf(buf, "%d-%d/%d", &genstart, &genend, + &genstep); + if (n != 2 && n != 3) + ERRTO("$GENERATE invalid range"); + if (n == 2) + genstep = 1; + if ((genend < genstart) || (genstart < 0) || + (genstep < 0)) + ERRTO("$GENERATE invalid range"); + if (!getword(genlhs, sizeof(genlhs), fp, 2)) + ERRTOZ("$GENERATE missing LHS"); + if (!getword(buf, sizeof(buf), fp, 0)) + ERRTOZ("GENERATE missing TYPE"); + type = res_nametotype(buf, &success); + if (success == 0 || type == ns_t_any) { + ns_info(ns_log_load, + "%s: Line %d: $GENERATE unknown type: %s.", + filename, lineno, buf); + errs++; + endline(fp); + continue; + } + switch (type) { + case ns_t_ns: + case ns_t_ptr: + case ns_t_cname: + case ns_t_a: + case ns_t_aaaa: + break; + default: + ERRTO("$GENERATE unsupported type"); + } + if (!getword(genrhs, sizeof(genrhs), fp, 2)) + ERRTOZ("$GENERATE missing RHS"); + loggenerr = 1; + for (i = genstart; i <= genend; i += genstep) { + if (genname(genlhs, i, origin, domain, + sizeof domain) == -1) + ERRTOZ("$GENERATE genname LHS failed"); + if (!ns_samedomain(domain, zp->z_origin)) { + /* Log first per $GENERATE. */ + if (loggenerr) { + ns_info(ns_log_load, + "%s:%d: $GENERATE LHS out of zone (ignored)", + filename, lineno); + loggenerr = 0; + } + continue; + } + context = ns_ownercontext(type, transport); + if (!ns_nameok(NULL, domain, class, zp, transport, + context, domain, inaddr_any)) { + strcpy(buf, domain); + ERRTO("$GENERATE owner name error"); + } + switch (type) { + case ns_t_ns: + case ns_t_ptr: + case ns_t_cname: + if (genname(genrhs, i, origin, (char *)data, + sizeof data) == -1) + ERRTOZ("$GENERATE genname RHS failed"); + switch (type) { + case ns_t_ns: + context = hostname_ctx; + break; + case ns_t_ptr: + context = ns_ptrcontext(domain); + break; + case ns_t_cname: + context = domain_ctx; + break; + } + if (!ns_nameok(NULL, (char *)data, class, zp, + transport, context, + domain, inaddr_any)) { + strncpy(buf, domain, sizeof(buf)); + buf[sizeof(buf)-1] = '\0'; + ERRTO("$GENERATE name error"); + } + n = strlen((char *)data) + 1; + break; + case ns_t_a: + case ns_t_aaaa: + if (genname(genrhs, i, NULL, (char *)data, + sizeof data) == -1) + ERRTOZ("$GENERATE genname RHS failed"); + strncpy(buf, (char*)data, sizeof(buf)); + buf[sizeof(buf)-1] = '\0'; + switch (type) { + case ns_t_a: + if (!inet_aton(buf, &ina)) + ERRTO("IP Address"); + (void) ina_put(ina, data); + n = NS_INT32SZ; + break; + case ns_t_aaaa: + if (inet_pton(AF_INET6, buf, data) <= 0) + ERRTO("IPv6 Address"); + n = NS_IN6ADDRSZ; + break; + } + break; + default: + ERRTOZ("$GENERATE unsupported context"); + } + dp = savedata(class, type, (u_int32_t)ttl, + (u_char *)data, (int)n); + dp->d_zone = zp - zones; + dp->d_flags = dataflags; + dp->d_cred = DB_C_ZONE; + dp->d_clev = clev; + c = db_set_update(domain, dp, &state, dbflags, + (dataflags & DB_F_HINT) != 0 ? + &fcachetab : &hashtab, + empty_from, &rrcount, lineno, + filename); + if (c != OK) { + if (c == CNAMEANDOTHER || c == NONGLUE) + errs++; + } + db_detach(&dp); + } + endline(fp); + continue; + + case DNAME: + if (!getword(domain, sizeof(domain), fp, 1)) + break; + if (makename(domain, origin, sizeof(domain)) == -1) + ERRTO("ownername makename failed"); + goto gotdomain; + + case DEFAULTTTL: + if (getttl(fp, filename, lineno, &n, + &multiline) <= 0 || n > MAXIMUM_TTL) { + ERRTO("$TTL bad TTL value"); + } + ttl = default_ttl = n; + continue; + + case AT: + (void) strcpy(domain, origin); + goto gotdomain; + + case DOT: + domain[0] = '\0'; + /* FALLTHROUGH */ + case CURRENT: + gotdomain: + if (!getword(buf, sizeof buf, fp, 0)) { + if (c == CURRENT) + continue; + break; + } + if (ns_parse_ttl(buf, &tmplong) < 0) { + if (zp->z_type == z_master && + default_warn && + (default_ttl == USE_MINIMUM)) { + ns_warning(ns_log_load, + "Zone \"%s\" (file %s): %s", + zp->z_origin, filename, + "No default TTL ($TTL ) set, using SOA minimum instead"); + default_warn = 0; + } + ttl = (u_int32_t)default_ttl; + } else { + ttl = tmplong; + if (ttl > MAXIMUM_TTL) { + ns_info(ns_log_load, + "%s: Line %d: TTL > %u; converted to 0", + filename, lineno, MAXIMUM_TTL); + ttl = 0; + } + if (zp->z_type == Z_CACHE) { + /* + * This allows the cache entry to age + * while sitting on disk (powered off). + */ + if (ttl > max_cache_ttl) + ttl = max_cache_ttl; + ttl += sb.st_mtime; + } + if (!getword(buf, sizeof buf, fp, 0)) + break; + } + + /* Parse class (IN, etc) */ + someclass = res_nametoclass(buf, &success); + if (success && someclass != zp->z_class) { + ns_info(ns_log_load, + "%s: Line %d: wrong class: %s.", + filename, lineno, + p_class(someclass)); + errs++; + break; + } + if (success && someclass != C_ANY) { + class = someclass; + (void) getword(buf, sizeof buf, fp, 0); + } + + /* Parse RR type (A, MX, etc) */ + type = res_nametotype(buf, &success); + if (success == 0 || type == ns_t_any) { + ns_info(ns_log_load, + "%s: Line %d: Unknown type: %s.", + filename, lineno, buf); + errs++; + break; + } + if (ttl == USE_MINIMUM) + ttl = zp->z_minimum; + context = ns_ownercontext(type, transport); + if (!ns_nameok(NULL, domain, class, zp, transport, context, + domain, inaddr_any)) { + errs++; + ns_notice(ns_log_load, + "%s:%d: owner name error", + filename, lineno); + break; + } + context = domain_ctx; + switch (type) { + case ns_t_key: + case ns_t_sig: + case ns_t_nxt: + case ns_t_cert: + /* + * Don't do anything here for these types -- + * they read their own input separately later. + */ + goto dont_get_word; + + case ns_t_soa: + case ns_t_minfo: + case ns_t_rp: + case ns_t_ns: + case ns_t_cname: + case ns_t_mb: + case ns_t_mg: + case ns_t_mr: + case ns_t_ptr: + escape = 1; + break; + case ns_t_a: + case ns_t_md: + case ns_t_mf: + case ns_t_null: + case ns_t_hinfo: + case ns_t_mx: + case ns_t_txt: + case ns_t_afsdb: + case ns_t_x25: + case ns_t_isdn: + case ns_t_rt: + case ns_t_nsap: + case ns_t_nsap_ptr: + case ns_t_px: + case ns_t_gpos: + case ns_t_aaaa: + case ns_t_loc: + case ns_t_eid: + case ns_t_nimloc: + case ns_t_srv: + case ns_t_atma: + case ns_t_naptr: + case ns_t_kx: + case ns_t_dname: + case ns_t_sink: + escape = 0; + break; + case ns_t_opt: + case ns_t_tkey: + case ns_t_tsig: + case ns_t_ixfr: + case ns_t_axfr: + case ns_t_mailb: + case ns_t_maila: + case ns_t_any: + case ns_t_zxfr: + escape = 0; + ns_info(ns_log_load, + "%s: Line %d: meta type: %s.", + filename, lineno, p_type(type)); + errs++; + break; + case ns_t_a6: /* not implemented */ + default: + escape = 1; + break; + } + if (!getword(buf, sizeof buf, fp, escape)) + break; + ns_debug(ns_log_load, 3, + "d='%s', c=%d, t=%d, ttl=%u, data='%s'", + domain, class, type, ttl, buf); + /* + * Convert the ascii data 'buf' to the proper format + * based on the type and pack into 'data'. + */ + dont_get_word: + switch (type) { + case ns_t_a: + if (!inet_aton(buf, &ina)) + ERRTO("IP Address"); + (void) ina_put(ina, data); + n = NS_INT32SZ; + break; + + case ns_t_soa: + context = hostname_ctx; + goto soa_rp_minfo; + case ns_t_rp: + case ns_t_minfo: + context = mailname_ctx; + /* FALLTHROUGH */ + soa_rp_minfo: + (void) strcpy((char *)data, buf); + + MAKENAME_OK((char *)data); + cp = (char *)(data + strlen((char *)data) + 1); + if (!getword(cp, + (sizeof data) - + (cp - (char*)data), + fp, 1)) + ERRTO("Domain Name"); + if (type == ns_t_rp) + context = domain_ctx; + else + context = mailname_ctx; + MAKENAME_OK(cp); + cp += strlen((char *)cp) + 1; + if (type != ns_t_soa) { + n = cp - (char *)data; + break; + } + if (ns_samename(zp->z_origin, domain) != 1) { + errs++; + ns_error(ns_log_load, + "%s:%d: SOA for \"%s\" not at zone top \"%s\"", + filename, lineno, domain, + zp->z_origin); + } + c = getnonblank(fp, filename, 0); + if (c == '(') { + multiline = 1; + } else { + multiline = 0; + ungetc(c, fp); + } + serial = zp->z_serial; + zp->z_serial = getnum(fp, filename, + GETNUM_SERIAL, + &multiline); + if (getnum_error) + errs++; + n = (u_int32_t) zp->z_serial; + PUTLONG(n, cp); + if (serial != 0 && + SEQ_GT(serial, zp->z_serial)) { + ns_notice(ns_log_load, + "%s:%d: WARNING: new serial number < old (%lu < %lu)", + filename , lineno, + (unsigned long)zp->z_serial, + (unsigned long)serial); + } + if (getttl(fp, filename, lineno, &n, + &multiline) <= 0) { + errs++; + n = INIT_REFRESH; + } + PUTLONG(n, cp); + zp->z_refresh = RANGE(n, MIN_REFRESH, + MAX_REFRESH); + if (zp->z_type == Z_SECONDARY +#if defined(STUBS) + || zp->z_type == Z_STUB +#endif + ) { + ns_refreshtime(zp, MIN(sb.st_mtime, + tt.tv_sec)); + sched_zone_maint(zp); + } +#ifdef BIND_UPDATE + if ((zp->z_type == Z_PRIMARY) && + (zp->z_flags & Z_DYNAMIC)) + if ((u_int32_t)zp->z_soaincrintvl > + zp->z_refresh/3) { + ns_info(ns_log_load, + "zone soa update time truncated to 1/3rd of refresh time"); + zp->z_soaincrintvl = + zp->z_refresh / 3; + } +#endif + + if (getttl(fp, filename, lineno, &n, + &multiline) <= 0) { + errs++; + n = INIT_REFRESH; + } + PUTLONG(n, cp); + zp->z_retry = RANGE(n, MIN_RETRY, MAX_RETRY); + if (getttl(fp, filename, lineno, + &n, &multiline) <= 0) { + errs++; + n = INIT_REFRESH; + } + PUTLONG(n, cp); + zp->z_expire = RANGE(n, zp->z_refresh, + MAX_EXPIRE); + if (getttl(fp, filename, lineno, &n, + &multiline) <= 0) { + errs++; + n = 120; + } + PUTLONG(n, cp); + if (n > MAXIMUM_TTL) { + ns_info(ns_log_load, + "%s: Line %d: SOA minimum TTL > %u; converted to 0", + filename, lineno, MAXIMUM_TTL); + zp->z_minimum = 0; + } else + zp->z_minimum = n; + if (ttl == USE_MINIMUM) + ttl = n; + n = cp - (char *)data; + if (multiline) { + buf[0] = getnonblank(fp, filename, 1); + buf[1] = '\0'; + if (buf[0] != ')') + ERRTO("SOA \")\""); + multiline = 0; + endline(fp); + } + read_soa++; + if (zp->z_type == Z_PRIMARY) + fixup_soa(filename, zp); + break; + + case ns_t_wks: + /* Address */ + if (!inet_aton(buf, &ina)) + ERRTO("WKS IP Address"); + (void) ina_put(ina, data); + /* Protocol */ + data[INADDRSZ] = getprotocol(fp, filename); + /* Services */ + n = getservices(NS_INT32SZ + sizeof(char), + (char *)data, fp, filename); + break; + + case ns_t_ns: + if (ns_samename(zp->z_origin, domain) == 1) + read_ns++; + context = hostname_ctx; + goto cname_etc; + case ns_t_cname: + case ns_t_mb: + case ns_t_mg: + case ns_t_mr: + context = domain_ctx; + goto cname_etc; + case ns_t_ptr: + context = ns_ptrcontext(domain); + cname_etc: + (void) strcpy((char *)data, buf); + MAKENAME_OK((char *)data); + n = strlen((char *)data) + 1; + break; + + case ns_t_naptr: + /* Order Preference Flags Service Replacement Regexp */ + n = 0; + cp = buf; + /* Order */ + while (isdigit(*cp)) + n = n * 10 + (*cp++ - '0'); + /* catch bad values */ + if (cp == buf || n > 65535) + ERRTO("NAPTR Order"); + cp = (char *)data; + PUTSHORT((u_int16_t)n, cp); + + /* Preference */ + n = getnum(fp, filename, GETNUM_NONE, + &multiline); + if (getnum_error || n > 65536) + ERRTO("NAPTR Preference"); + PUTSHORT((u_int16_t)n, cp); + + /* Flags */ + if (!getword(buf, sizeof buf, fp, 0)) + ERRTO("NAPTR Flags"); + n = strlen(buf); + if (n > 255) + ERRTO("NAPTR Flags too big"); + *cp++ = n; + memcpy(cp, buf, (int)n); + cp += n; + + /* Service Classes */ + if (!getword(buf, sizeof buf, fp, 0)) + ERRTO("NAPTR Service Classes"); + n = strlen(buf); + if (n > 255) + ERRTO("NAPTR Service Classes too big"); + *cp++ = n; + memcpy(cp, buf, (int)n); + cp += n; + + /* Pattern */ + if (!getword(buf, sizeof buf, fp, 0)) + ERRTO("NAPTR Pattern"); + n = strlen(buf); + if (n > 255) + ERRTO("NAPTR Pattern too big"); + *cp++ = n; + memcpy(cp, buf, (int)n); + cp += n; + + /* Replacement */ + if (!getword(buf, sizeof buf, fp, 1)) + ERRTO("NAPTR Replacement"); + n = strlen(buf); + if (n > data_size - ((u_char *)cp - data)) + ERRTO("NAPTR Replacement too big"); + (void) strcpy((char *)cp, buf); + context = domain_ctx; + MAKENAME_OK(cp); + /* advance pointer to end of data */ + cp += strlen((char *)cp) +1; + + /* now save length */ + n = (cp - (char *)data); + break; + + + case ns_t_mx: + case ns_t_afsdb: + case ns_t_rt: + case ns_t_srv: + n = 0; + cp = buf; + while (isdigit(*cp)) + n = n * 10 + (*cp++ - '0'); + /* catch bad values */ + if ((cp == buf) || (n > 65535)) + ERRTO("Priority"); + cp = (char *)data; + PUTSHORT((u_int16_t)n, cp); + + if (type == ns_t_srv) { + n = getnum(fp, filename, GETNUM_NONE, + &multiline); + if (getnum_error || n > 65536) + ERRTO("SRV RR"); + PUTSHORT((u_int16_t)n, cp); + + n = getnum(fp, filename, GETNUM_NONE, + &multiline); + if (getnum_error || n > 65536) + ERRTO("SRV RR"); + PUTSHORT((u_int16_t)n, cp); + } + + if (!getword(buf, sizeof buf, fp, 1)) + ERRTO("Domain Name"); + (void) strcpy((char *)cp, buf); + context = hostname_ctx; + MAKENAME_OK(cp); + /* advance pointer to end of data */ + cp += strlen((char *)cp) +1; + + /* now save length */ + n = (cp - (char *)data); + break; + + case ns_t_px: + context = domain_ctx; + n = 0; + data[0] = '\0'; + cp = buf; + while (isdigit(*cp)) + n = n * 10 + (*cp++ - '0'); + /* catch bad values */ + if ((cp == buf) || (n > 65535)) + ERRTO("PX Priority"); + cp = (char *)data; + PUTSHORT((u_int16_t)n, cp); + + if (!getword(buf, sizeof buf, fp, 0)) + ERRTO("PX Domain1"); + (void) strcpy((char *)cp, buf); + MAKENAME_OK(cp); + /* advance pointer to next field */ + cp += strlen((char *)cp) + 1; + if (!getword(buf, sizeof buf, fp, 0)) + ERRTO("PX Domain2"); + (void) strcpy((char *)cp, buf); + MAKENAME_OK(cp); + /* advance pointer to end of data */ + cp += strlen((char *)cp) + 1; + + /* now save length */ + n = (cp - (char *)data); + break; + + case ns_t_hinfo: + n = getcharstring(buf, (char *)data, type, + 2, 2, fp, filename); + if (n == 0) + ERRTO("HINFO RR"); + break; + + case ns_t_isdn: + n = getcharstring(buf, (char *)data, type, + 1, 2, fp, filename); + if (n == 0) + ERRTO("ISDN RR"); + break; + + case ns_t_txt: + n = getcharstring(buf, (char *)data, type, + 1, 0, fp, filename); + if (n == 0) + ERRTO("TXT RR"); + break; + + + case ns_t_x25: + n = getcharstring(buf, (char *)data, type, + 1, 1, fp, filename); + if (n == 0) + ERRTO("X25 RR"); + break; + + case ns_t_nsap: + if (buf[0] != '0' || + (buf[1] != 'x' && buf[1] != 'X')) + ERRTO("NSAP RR: no leading 0x"); + n = inet_nsap_addr(buf, (u_char *)data, + sizeof data); + if (n == 0) + ERRTO("NSAP RR"); + endline(fp); + break; + + case ns_t_aaaa: + if (inet_pton(AF_INET6, buf, data) <= 0) + ERRTO("IPv4 Address"); + n = NS_IN6ADDRSZ; + endline(fp); + break; + + case ns_t_nxt: + case ns_t_key: + case ns_t_cert: + case ns_t_sig: { + const char *errmsg = NULL; + int ret; + if (ttl == USE_MINIMUM) /* no ttl set */ + ttl = 0; + ret = parse_sec_rdata(buf, sizeof(buf), 0, + data, sizeof(data), + fp, zp, domain, ttl, + type, domain_ctx, + transport, &errmsg); + if (ret < 0) { + errtype = errmsg; + goto err; + } + else + n = ret; + break; + } + + + case ns_t_loc: + cp = buf + (n = strlen(buf)); + *cp = ' '; + cp++; + n++; + while ((i = getc(fp), *cp = i, i != EOF) + && *cp != '\n' + && (n < MAXDATA)) { + cp++; n++; + } + if (*cp == '\n') /* leave \n for getword */ + ungetc(*cp, fp); + *cp = '\0'; + /* now process the whole line */ + n = loc_aton(buf, (u_char *)data); + if (n == 0) + goto err; + endline(fp); + break; + + default: + if (strcmp(buf, "\\#") != 0) + goto err; + if (!getword(buf, sizeof buf, fp, 0) || + !isdigit((unsigned char)buf[0])) + ERRTO("opaque length"); + n = strtoul(buf, &cp, 10); + if (n > 0xffff || *cp != '\0') + ERRTO("opaque length"); + multiline = 0; + i = isc_gethexstring(data, sizeof(data), n, fp, + &multiline); + if (i == -1) + ERRTO("opaque data read failed"); + if (multiline) { + buf[0] = getnonblank(fp, filename, 1); + buf[1] = '\0'; + if (buf[0] != ')') + ERRTO("\")\" expected"); + multiline = 0; + } + endline(fp); + } + /* + * Ignore data outside the zone. + */ + if (zp->z_type != Z_CACHE && + !ns_samedomain(domain, zp->z_origin)) + { + ns_info(ns_log_load, + "%s:%d: data \"%s\" outside zone \"%s\" (ignored)", + filename, lineno, domain, + zp->z_origin); + continue; + } + if (ttl == USE_MINIMUM) /* no ttl set */ + ttl = 0; + dp = savedata(class, type, (u_int32_t)ttl, + (u_char *)data, (int)n); + dp->d_zone = zp - zones; + dp->d_flags = dataflags; + dp->d_cred = DB_C_ZONE; + dp->d_clev = clev; + c = db_set_update(domain, dp, &state, dbflags, + (dataflags & DB_F_HINT) != 0 ? + &fcachetab : &hashtab, + empty_from, &rrcount, lineno, + filename); + if (c == CNAMEANDOTHER || c == NONGLUE) + errs++; + db_detach(&dp); + continue; + + case ERRTOK: + break; + } + err: + errs++; + ns_notice(ns_log_load, "%s:%d: %s error near (%s)", + filename, empty_token ? (lineno - 1) : lineno, + errtype, buf); + if (!empty_token) + endline(fp); + } + c = db_set_update(NULL, NULL, &state, dbflags, + (dataflags & DB_F_HINT) ? &fcachetab : &hashtab, + empty_from, &rrcount, lineno, filename); + if (c != OK) { + if (c == CNAMEANDOTHER || c == NONGLUE) + errs++; + } + + (void) my_fclose(fp); + lineno = slineno; + if (!ininclude) { + if (didinclude) { + zp->z_flags |= Z_INCLUDE; + zp->z_ftime = 0; + } else + zp->z_ftime = sb.st_mtime; + zp->z_lastupdate = sb.st_mtime; + if (zp->z_type != Z_CACHE && zp->z_type != Z_HINT) { + const char *msg = NULL; + + if (read_soa == 0) + msg = "no SOA RR found"; + else if (read_soa != 1) + msg = "multiple SOA RRs found"; + else if (read_ns == 0) + msg = "no NS RRs found at zone top"; + else if (!rrcount) + msg = "no relevant RRs found"; + if (msg != NULL) { + errs++; + ns_warning(ns_log_load, + "Zone \"%s\" (file %s): %s", + zp->z_origin, filename, msg); + } + } + errs += purge_nonglue(zp->z_origin, + (dataflags & DB_F_HINT) ? fcachetab : + hashtab, zp->z_class, + zp->z_type == z_master); + cleanup: + while (filenames) { + fn = filenames; + filenames = filenames->next; + fn->name = freestr(fn->name); + memput(fn, sizeof *fn); + } + if (errs != 0) { + if (errs != -1) + ns_error(ns_log_load, + "%s zone \"%s\" (%s) rejected due to errors (serial %u)", + zoneTypeString(zp->z_type), + zp->z_origin, + p_class(zp->z_class), zp->z_serial); + if ((zp->z_flags & Z_NOTIFY) != 0) + ns_stopnotify(zp->z_origin, zp->z_class); + do_reload(zp->z_origin, zp->z_type, zp->z_class, + loading); + } else + ns_info(ns_log_load, + "%s zone \"%s\" (%s) loaded (serial %u)", + zoneTypeString(zp->z_type), zp->z_origin, + p_class(zp->z_class), zp->z_serial); + } + if (errs != 0) { + zp->z_flags |= Z_DB_BAD; + zp->z_ftime = 0; + } +#ifdef BIND_NOTIFY + if (errs == 0 && (!ininclude) && (initial_configuration == 0 || + !NS_OPTION_P(OPTION_SUPNOTIFY_INITIAL)) && + (zp->z_type == z_master || zp->z_type == z_slave)) + ns_notify(zp->z_origin, zp->z_class, ns_t_soa); +#endif + return (errs); +} + +void +db_err(int err, char *domain, int type, const char *filename, int lineno) { + if (filename != NULL && err == CNAMEANDOTHER) + ns_warning(ns_log_load, "%s:%d:%s: CNAME and OTHER data error", + filename, lineno, domain); + if (err != DATAEXISTS) + ns_debug(ns_log_load, 1, "update failed %s %d", + domain, type); +} + +static int +gettoken(FILE *fp, const char *src) { + int c; + char op[32]; + + for (;;) { + c = getc(fp); + top: + switch (c) { + case EOF: + return (EOF); + + case '$': + if (getword(op, sizeof op, fp, 0)) { + if (!strcasecmp("include", op)) + return (INCLUDE); + if (!strcasecmp("origin", op)) + return (ORIGIN); + if (!strcasecmp("generate", op)) + return (GENERATE); + if (!strcasecmp("ttl", op)) + return (DEFAULTTTL); + } + ns_notice(ns_log_db, + "%s:%d: Unknown $ option: $%s", + src, lineno, op); + return (ERRTOK); + + case ';': + while ((c = getc(fp)) != EOF && c != '\n') + ; + goto top; + + case ' ': + case '\t': + return (CURRENT); + + case '.': + return (DOT); + + case '@': + return (AT); + + case '\n': + lineno++; + continue; + + case '\r': + if (NS_OPTION_P(OPTION_TREAT_CR_AS_SPACE) != 0) + return (CURRENT); + + default: + (void) ungetc(c, fp); + return (DNAME); + } + } +} + +/* int + * getword(buf, size, fp, preserve) + * get next word, skipping blanks & comments. + * '\' '\n' outside of "quotes" is considered a blank. + * parameters: + * buf - destination + * size - of destination + * fp - file to read from + * preserve - should we preserve \ before \\ and \.? + * if preserve == 2, then keep all \ + * return value: + * 0 = no word; perhaps EOL or EOF; lineno was incremented. + * 1 = word was read + */ +int +getword(char *buf, size_t size, FILE *fp, int preserve) { + char *cp = buf; + int c, spaceok, once; + + empty_token = 0; /* XXX global side effect. */ + once = 0; + while ((c = getc(fp)) != EOF) { + once++; + if (c == ';') { + /* Comment. Skip to end of line. */ + while ((c = getc(fp)) != EOF && c != '\n') + (void)NULL; + c = '\n'; + } + if (c == '\n') { + /* + * Unescaped newline. It's a terminator unless we're + * already midway into a token. + */ + if (cp != buf) + ungetc(c, fp); + else + lineno++; + break; + } + if (c == '"') { + /* "Quoted string." Gather the whole string here. */ + while ((c = getc(fp)) != EOF && c!='"' && c!='\n') { + if (c == '\\') { + if ((c = getc(fp)) == EOF) + c = '\\'; + if (preserve) + switch (c) { + default: + if (preserve == 1) + break; + case '\\': + case '.': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (cp >= buf+size-1) + break; + *cp++ = '\\'; + } + if (c == '\n') + lineno++; + } + if (cp >= buf+size-1) + break; + *cp++ = c; + } + /* + * Newline string terminators are + * not token terminators. + */ + if (c == '\n') { + lineno++; + break; + } + /* Sample following character, check for terminator. */ + if ((c = getc(fp)) != EOF) + ungetc(c, fp); + if (c == EOF || isspace(c)) { + *cp = '\0'; + return (1); + } + continue; + } + spaceok = 0; + if (c == '\\') { + /* Do escape processing. */ + if ((c = getc(fp)) == EOF) + c = '\\'; + if (preserve) + switch (c) { + default: + if (preserve == 1) + break; + case '\\': + case '#': + case '.': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (cp >= buf+size-1) + break; + *cp++ = '\\'; + } + if (c == ' ' || c == '\t') + spaceok++; + } + if (isspace(c) && !spaceok) { + /* Blank of some kind. Skip run. */ + while (isspace(c = getc(fp)) && c != '\n') + (void)NULL; + ungetc(c, fp); + /* Blank means terminator if the token is nonempty. */ + if (cp != buf) /* Trailing whitespace */ + break; + continue; /* Leading whitespace */ + } + if (cp >= buf + size - 1) + break; + *cp++ = (char)c; + } + *cp = '\0'; + if (cp == buf) + empty_token = 1; + if (!once) + lineno++; + return (cp != buf); +} + +/* + * int + * getttl(fp, fn, ln, ttl, multiline) + * read a word from the file and parse it as a TTL. + * return: + * 1 ttl found + * 0 word not read (EOF or EOL?) + * -1 word read but it wasn't a ttl + * side effects: + * *ttl is written if the return value is to be 1. + */ +int +getttl(FILE *fp, const char *fn, int lineno, u_int32_t *ttl, int *multiline) { + char buf[MAXDATA]; + u_long tmp; + int ch; + int len; + + while (!feof(fp) && !getword(buf, sizeof buf, fp, 0) && *multiline) + (void)NULL; + len = strlen(buf); + if (*multiline && len && buf[len-1] == ')') { + buf[len-1] = '\0'; + *multiline = 0; + } + if (ns_parse_ttl(buf, &tmp) < 0) { + ns_notice(ns_log_db, "%s:%d: expected a TTL, got \"%s\"", + fn, lineno, buf); + return (-1); + } + if (*multiline) { + ch = getnonblank(fp, fn, 1); + if (ch == EOF) + return (-1); + if (ch == ';') + endline(fp); + else + ungetc(ch, fp); + } + *ttl = (u_int32_t)tmp; + return (1); +} + +/* Get multiline words. Same parameters as getword. Handles any + number of leading ('s or )'s in the words it sees. + FIXME: We kludge recognition of ( and ) for multiline input. + Each paren must appear at the start of a (blank-separated) word, + which is particularly counter-intuitive for ). Good enough for now, + until Paul rewrites the parser. (gnu@toad.com, oct96) +*/ +static int +getmlword(char *buf, size_t size, FILE *fp, int preserve) { + char *p; + + do { + while (!getword (buf, size, fp, preserve)) { + /* No more words on this line. See if doing the + multiline thing. */ + if (!getmlword_nesting) { /* Nope... */ + ungetc('\n', fp); /* Push back newline */ + lineno--; /* Unbump the lineno */ + empty_token = 0; /* Undo this botch */ + return 0; + } + if (feof(fp) || ferror(fp)) + return 0; /* Error, no terminating ')' */ + /* Continue reading til we get a word... */ + } + while ('(' == *buf) { + /* Word starts with paren. Multiline mode. + Move the rest of the word down over the paren. */ + getmlword_nesting++; + p = buf; + while (0 != (p[0]=p[1])) p++; + } + while (')' == *buf) { + getmlword_nesting--; + p = buf; + while (0 != (p[0]=p[1])) p++; + } + } while (buf[0] == 0); /* loop til we get a non-( non-) word */ + + return 1; /* Got a word... */ +} + +/* Get all the remaining words on a line, concatenated into one big + long (not too long!) string, with the whitespace squeezed out. + This routine, like getword(), does not swallow the newline if words seen. + This routine, unlike getword(), never swallows the newline if no words. + Parameters are the same as getword(). Result is: + 0 got no words at all + 1 got one or more words + -1 got too many words, they don't all fit; or missing close paren +*/ +static int +getallwords(char *buf, size_t size, FILE *fp, int preserve) { + char *runningbuf = buf; + int runningsize = size; + int len; + + while (runningsize > 0) { + if (!getmlword (runningbuf, runningsize, fp, preserve)) { + return runningbuf!=buf; /* 1 or 0 */ + } + len = strlen(runningbuf); + runningbuf += len; + runningsize -= len; + } + return -1; /* Error, String too long */ +} + +int +getnum(FILE *fp, const char *src, int opt, int *multiline) { + int c, n; + int seendigit = 0; + int seendecimal = 0; + int m = 0; + int allow_dots = 0; + + getnum_error = 0; +#ifdef DOTTED_SERIAL + if (opt & GETNUM_SERIAL) + allow_dots++; +#endif + for (n = 0; (c = getc(fp)) != EOF; ) { + if (isspace(c)) { + if (c == '\n') { + if (*multiline) + lineno++; + else if (!seendigit) + goto eol; + } + if (seendigit) + break; + continue; + } + if (c == ';') { + while ((c = getc(fp)) != EOF && c != '\n') + ; + if (c == '\n') { + if (*multiline) + lineno++; + else if (!seendigit) + goto eol; + } + if (seendigit) + break; + continue; + } + if (getnum_error) + continue; + if (!isdigit(c)) { + if (c == ')' && seendigit) { + (void) ungetc(c, fp); + break; + } + if (seendigit && (opt & GETNUM_SCALED) && + strchr("KkMmGg", c) != NULL) { + switch (c) { + case 'K': case 'k': + n *= 1024; + break; + case 'M': case 'm': + n *= (1024 * 1024); + break; + case 'G': case 'g': + n *= (1024 * 1024 * 1024); + break; + } + break; + } + if (seendecimal || c != '.' || !allow_dots) { + ns_notice(ns_log_db, + "%s:%d: expected a number", + src, lineno); + getnum_error = 1; + } else { + if (!seendigit) + n = 1; +#ifdef SENSIBLE_DOTS + n *= 10000; +#else + n *= 1000; +#endif + seendigit = 1; + seendecimal = 1; + } + continue; + } +#ifdef SENSIBLE_DOTS + if (seendecimal) + m = m * 10 + (c - '0'); + else + n = n * 10 + (c - '0'); +#else + n = n * 10 + (c - '0'); +#endif + seendigit = 1; + } + if (getnum_error) + return (0); + if (m > 9999) { + ns_info(ns_log_db, + "%s:%d: number after the decimal point exceeds 9999", + src, lineno); + getnum_error = 1; + return (0); + } + if (seendecimal) { + ns_info(ns_log_db, + "%s:%d: decimal serial number interpreted as %d", + src, lineno, n+m); + } + return (n + m); + + eol: + ns_error(ns_log_db, "%s:%d: unexpected end of line", src, lineno); + getnum_error = 1; + (void) ungetc(c, fp); + return (0); +} + +#ifndef BIND_UPDATE +static +#endif +int +getnonblank(FILE *fp, const char *src, int multiline) { + int c; + + while ((c = getc(fp)) != EOF) { + if (isspace(c)) { + if (c == '\n') { + if (multiline) + lineno++; + else + goto eol; + } + continue; + } + if (c == ';') { + while ((c = getc(fp)) != EOF && c != '\n') + ; + if (c == '\n') { + if (multiline) + lineno++; + else + goto eol; + } + continue; + } + return (c); + } + ns_info(ns_log_db, "%s:%d: unexpected EOF", src, lineno); + return (EOF); + eol: + ns_error(ns_log_db, "%s:%d: unexpected end of line", src, lineno); + /* don't ungetc(c, fp); as the caller will do this. */ + return(c); +} + +/* + * Replace all single "$"'s in "name" with "it". + * ${delta} will add delta to "it" before printing. + * ${delta,width} will change print width as well, zero fill is implied + * ${delta,width,radix} will change radix as well, can be d, o, x, X. + * i.e. ${0,2,X} will produce a two digit hex (upper case) with zero fill. + * Append "origin" to name if required and validate result with makename. + * To get a "$" or "{" in the output use \ before it. + * Return 0 on no error or -1 on error. + * Resulting name stored in "buf". + */ + +static int +genname(char *name, int it, const char *origin, char *buf, int size) { + char *bp = buf; + char *eom = buf + size; + char *cp; + char numbuf[32]; + char fmt[32]; + int delta = 0; + int width; + + while (*name) { + if (*name == '$') { + if (*(++name) == '$') { + /* should be deprecated. how? */ + if (bp >= eom) + return (-1); + *bp++ = *name++; + } else { + strcpy(fmt, "%d"); + if (*name == '{') { + switch (sscanf(name, "{%d,%d,%1[doxX]}", &delta, &width, numbuf)) { + case 1: + break; + case 2: + sprintf(fmt, "%%0%dd", width); + break; + case 3: + sprintf(fmt, "%%0%d%c", width, numbuf[0]); + break; + default: + return (-1); + } + while (*name && *name++ != '}') { + continue; + } + } + sprintf(numbuf, fmt, it + delta); + cp = numbuf; + while (*cp) { + if (bp >= eom) + return (-1); + *bp++ = *cp++; + } + } + } else if (*name == '\\') { + if (*(++name) == '\0') { + if (bp >= eom) + return (-1); + *bp++ = '\\'; + } else { + switch (*name) { + case '\\': + case '.': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (bp >= eom) + return (-1); + *bp++ = '\\'; + default: + if (bp >= eom) + return (-1); + *bp++ = *name++; + } + } + } else { + if (bp >= eom) + return (-1); + *bp++ = *name++; + } + } + if (bp >= eom) + return (-1); + *bp = '\0'; + return (origin == NULL ? 0 : makename(buf, origin, size)); +} + + +/* + * Take name and fix it according to following rules: + * "." means root. + * "@" means current origin. + * "name." means no changes. + * "name" means append origin. + */ +int +makename(char *name, const char *origin, int size) { + int n; + u_char domain[MAXCDNAME]; + + switch (ns_name_pton(name, domain, sizeof(domain))) { + case -1: + return (-1); + case 1: /* FULLY QUALIFIED */ + break; + case 0: /* UNQUALIFIED */ + if (strcmp(name, "@") == 0) /* must test raw name */ + domain[0] = 0; + if ((n = dn_skipname(domain, domain+sizeof(domain))) == -1) + return (-1); + /* step back over root, append origin */ + switch (ns_name_pton(origin, domain+n-1, sizeof(domain)-n+1)) { + case -1: + return (-1); + case 0: + case 1: + break; + } + break; + } + if (ns_name_ntop(domain, name, size) == -1) + return (-1); + if (name[0] == '.') /* root */ + name[0] = '\0'; + return (0); +} + +int +makename_ok(char *name, const char *origin, int class, struct zoneinfo *zp, + enum transport transport, enum context context, + const char *owner, const char *filename, int lineno, int size) +{ + int ret = 1; + + if (makename(name, origin, size) == -1) { + ns_info(ns_log_db, "%s:%d: makename failed", + filename, lineno); + return (0); + } + if (!ns_nameok(NULL, name, class, zp, transport, context, owner, + inaddr_any)) { + ns_info(ns_log_db, "%s:%d: database naming error", + filename, lineno); + ret = 0; + } + return (ret); +} + +void +endline(FILE *fp) { + int c; + + while ((c = getc(fp)) != '\0') { + if (c == '\n') { + (void) ungetc(c,fp); + break; + } else if (c == EOF) { + break; + } + } +} + +#define MAXPORT 1024 +#define MAXLEN 24 + +#ifndef BIND_UPDATE +static +#endif +char +getprotocol(FILE *fp, const char *src) { + int k; + char b[MAXLEN]; + + (void) getword(b, sizeof(b), fp, 0); + + k = protocolnumber(b); + if (k == -1) + ns_info(ns_log_db, "%s:%d: unknown protocol: %s.", + src, lineno, b); + return ((char) k); +} + +#ifndef BIND_UPDATE +static +#endif +int +getservices(int offset, char *data, FILE *fp, const char *src) { + int j, ch, k, maxl, bracket; + char bm[MAXPORT/8]; + char b[MAXLEN]; + + for (j = 0; j < MAXPORT/8; j++) + bm[j] = 0; + maxl = 0; + bracket = 0; + while (getword(b, sizeof(b), fp, 0) || bracket) { + if (feof(fp) || ferror(fp)) + break; + if (strlen(b) == 0) + continue; + if (b[0] == '(') { + bracket++; + continue; + } + if (b[0] == ')') { + bracket = 0; + while ((ch = getc(fp)) != EOF && ch != '\n') + (void)NULL; + if (ch == '\n') + lineno++; + break; + } + k = servicenumber(b); + if (k == -1) { + ns_info(ns_log_db, + "%s:%d: Unknown service '%s'", + src, lineno, b); + continue; + } + if ((k < MAXPORT) && (k)) { + bm[k/8] |= (0x80>>(k%8)); + if (k > maxl) + maxl = k; + } else { + ns_info(ns_log_db, + "%s:%d: port no. (%d) too big", + src, lineno, k); + } + } + if (bracket) + ns_info(ns_log_db, "%s:%d: missing close paren", + src, lineno); + maxl = maxl/8+1; + memcpy(data+offset, bm, maxl); + return (maxl+offset); +} + +/* + * Converts a word to a u_int32_t. Error if any non-numeric + * characters in the word, except leading or trailing white space. + */ +static u_int32_t +wordtouint32(buf) + char *buf; +{ + u_long result; + u_int32_t res2; + char *bufend; + + wordtouint32_error = 0; + result = strtoul(buf, &bufend, 0); + if (bufend == buf) + wordtouint32_error = 1; + else + while ('\0' != *bufend) { + if (isspace(*bufend)) + bufend++; + else { + wordtouint32_error = 1; + break; + } + } + /* Check for truncation between u_long and u_int32_t */ + res2 = result; + if (res2 != result) + wordtouint32_error = 1; + return (res2); +} + +static int +getcharstring(char *buf, char *data, int type, + int minfields, int maxfields, + FILE *fp, const char *src) +{ + int nfield = 0, done = 0, n = 0, i; + char *b = buf; + + do { + nfield++; + i = strlen(buf); +#ifdef ALLOW_LONG_TXT_RDATA + b = buf; + if (type == ns_t_txt || type == ns_t_x25) { + while (i > MAXCHARSTRING + && n + MAXCHARSTRING + 1 < MAXDATA) { + data[n] = (char)MAXCHARSTRING; + memmove(data + n + 1, b, MAXCHARSTRING); + n += MAXCHARSTRING + 1; + b += MAXCHARSTRING; + i -= MAXCHARSTRING; + } + } +#endif /* ALLOW_LONG_TXT_RDATA */ + if (i > MAXCHARSTRING) { + ns_info(ns_log_db, + "%s:%d: RDATA field %d too long", + src, lineno -1, nfield); + return (0); + } + if (n + i + 1 > MAXDATA) { + ns_info(ns_log_db, + "%s:%d: total RDATA too long", + src, lineno -1); + return (0); + } + data[n] = i; + memmove(data + n + 1, b, (int)i); + n += i + 1; + done = (maxfields && nfield >= maxfields); + } while (!done && getword(buf, MAXDATA, fp, 0)); + + if (nfield < minfields) { + ns_info(ns_log_db, + "%s:%d: expected %d RDATA fields, only saw %d", + src, lineno -1, minfields, nfield); + return (0); + } + + if (done) + endline(fp); + + return (n); +} + + +/* + * get_nxt_types(): Read the list of types in the NXT record. + * + * Data is the array where the bit flags are stored; it must + * contain at least ns_t_any/NS_NXT_BITS bytes. + * FP is the input FILE *. + * Filename is the sourcefile + * + * The result is how many bytes are significant in the result. + * ogud@tis.com 1995 + */ +static int +get_nxt_types(u_char *data, FILE *fp, const char *filename) { + char b[MAXLABEL]; /* Not quite the right size, but good enough */ + int maxtype=0; + int success; + int type; + int errs = 0; + + memset(data, 0, NS_NXT_MAX/NS_NXT_BITS+1); + + while (getmlword(b, sizeof(b), fp, 0)) { + if (feof(fp) || ferror(fp)) + break; + if (strlen(b) == 0 || b[0] == '\n') + continue; + + /* Parse RR type (A, MX, etc) */ + type = res_nametotype((char *)b, &success); + if ((!success) || type == ns_t_any) { + errs++; + ns_info(ns_log_db, + "%s: Line %d: Unknown type: %s in NXT record.", + filename, lineno, b); + continue; + } + NS_NXT_BIT_SET(type, data); + if (type > maxtype) + maxtype = type; + } + if (errs) + return (0); + else + return (maxtype/NS_NXT_BITS+1); +} + +/* sanity checks PRIMARY ONLY */ +static void +fixup_soa(const char *fn, struct zoneinfo *zp) { + /* Sanity: give enough time for the zone to transfer (retry). */ + if (zp->z_expire < (zp->z_refresh + zp->z_retry)) + ns_notice(ns_log_db, + "%s: WARNING SOA expire value is less than SOA refresh+retry (%u < %u+%u)", + fn, zp->z_expire, zp->z_refresh, zp->z_retry); + + /* Sanity. */ + if (zp->z_expire < (zp->z_refresh + 10 * zp->z_retry)) + ns_warning(ns_log_db, +"%s: WARNING SOA expire value is less than refresh + 10 * retry \ +(%u < (%u + 10 * %u))", + fn, zp->z_expire, zp->z_refresh, zp->z_retry); + + /* + * Sanity: most hardware/telco faults are detected and fixed within + * a week, secondaries should continue to operate for this time. + * (minimum of 4 days for long weekends) + */ + if (zp->z_expire < (7 * 24 * 3600)) + ns_warning(ns_log_db, + "%s: WARNING SOA expire value is less than 7 days (%u)", + fn, zp->z_expire); + + /* + * Sanity: maximum down time if we havn't talked for six months + * war must have broken out. + */ + if (zp->z_expire > ( 183 * 24 * 3600)) + ns_warning(ns_log_db, + "%s: WARNING SOA expire value is greater than 6 months (%u)", + fn, zp->z_expire); + + /* Sanity. */ + if (zp->z_refresh < (zp->z_retry * 2)) + ns_warning(ns_log_db, + "%s: WARNING SOA refresh value is less than 2 * retry (%u < %u * 2)", + fn, zp->z_refresh, zp->z_retry); +} + +/* this function reads in the sig record rdata from the input file and + * returns the following codes + * > 0 length of the recrod + * ERR_EOF end of file + * + */ + +static int +parse_sig_rr(char *buf, int buf_len, u_char *data, int data_size, + FILE *fp, struct zoneinfo *zp, char *domain, u_int32_t ttl, + enum context domain_ctx, enum transport transport, + const char **errmsg) +{ +/* The SIG record looks like this in the db file: + Name Cl SIG RRtype Algid [OTTL] Texp Tsig Kfoot Signer Sig + + where: Name and Cl are as usual + SIG is a keyword + RRtype is a char string + ALGid is 8 bit u_int + Labels is 8 bit u_int + OTTL is 32 bit u_int (optionally present) + Texp is YYYYMMDDHHMMSS + Tsig is YYYYMMDDHHMMSS + Kfoot is 16-bit unsigned decimal integer + Signer is a char string + Sig is 64 to 319 base-64 digits + A missing OTTL is detected by the magnitude of the Texp value + that follows it, which is larger than any u_int. + The Labels field in the binary RR does not appear in the + text RR. + + It's too crazy to run these pages of SIG code at the right + margin. I'm exdenting them for readability. +*/ + u_int32_t sig_type; + int dateerror; + int siglen, success; + u_char *cp; + u_int32_t al, la, n; + u_int32_t signtime, exptime, timetilexp; + u_int32_t origTTL; + enum context context; + time_t now; + const char *errtype = "SIG error"; + int i, my_buf_size = MAXDATA, errs = 0; + + + /* The TTL gets checked against the Original TTL, + and bounded by the signature expiration time, which + are both under the signature. We can't let TTL drift + based on the SOA record. If defaulted, fix it now. + (It's not clear to me why USE_MINIMUM isn't eliminated + before putting ALL RR's into the database. -gnu@toad.com) */ + if (ttl == USE_MINIMUM) + ttl = zp->z_minimum; + + i = 0; + data[i] = '\0'; + + getmlword_nesting = 0; /* KLUDGE err recovery */ + + /* RRtype (char *) + * if old style inp will contain the next token + *copy that into buffer, otherwise read from file + */ + if (buf && buf_len == 0) + if (!getmlword((char*)buf, my_buf_size, fp, 0)) + ERRTO("SIG record doesn't specify type"); + sig_type = res_nametotype(buf, &success); + if (!success || sig_type == ns_t_any) { + /* + * We'll also accept a numeric RR type, + * for signing RR types that this version + * of named doesn't yet understand. + * In the ns_t_any case, we rely on wordtouint32 + * to fail when scanning the string "ANY". + */ + sig_type = wordtouint32 (buf); + if (wordtouint32_error || sig_type > 0xFFFF) + ERRTO("Unknown RR type in SIG record"); + } + cp = &data[i]; + PUTSHORT((u_int16_t)sig_type, cp); + i += 2; + + /* Algorithm id (8-bit decimal) */ + if (!getmlword(buf, my_buf_size, fp, 0)) + ERRTO("Missing algorithm ID"); + al = wordtouint32(buf); + if (0 == al || wordtouint32_error || 255 <= al) + ERRTO("Bad algorithm number"); + data[i] = (u_char) al; + i++; + + /* + * Labels (8-bit decimal) + */ + if (!getmlword(buf, my_buf_size, fp, 0)) + ERRTO("Missing label count"); + la = wordtouint32(buf); + if (wordtouint32_error || 255 <= la || + (0 == la && *domain != '\0')) + ERRTO("Bad label count number"); + data[i] = (u_char) la; + i++; + + /* + * OTTL (optional u_int32_t) and + * Texp (u_int32_t date) + */ + if (!getmlword(buf, my_buf_size, fp, 0)) + ERRTO("OTTL and expiration time missing"); + /* + * See if OTTL is missing and this is a date. + * This relies on good, silent error checking + * in ns_datetosecs. + */ + exptime = ns_datetosecs(buf, &dateerror); + if (!dateerror) { + /* Output TTL as OTTL */ + origTTL = ttl; + cp = &data[i]; + PUTLONG (origTTL, cp); + i += 4; + } else { + /* Parse and output OTTL; scan TEXP */ + origTTL = wordtouint32(buf); + if (wordtouint32_error || (origTTL > 0x7fffffffU)) + ERRTO("Original TTL value bad"); + cp = &data[i]; + PUTLONG(origTTL, cp); + i += 4; + if (!getmlword(buf, my_buf_size, fp, 0)) + ERRTO("Expiration time missing"); + exptime = ns_datetosecs(buf, &dateerror); + } + if (dateerror || exptime > 0x7fffffff || exptime <= 0) + ERRTO("Invalid expiration time"); + cp = &data[i]; + PUTLONG(exptime, cp); + i += 4; + + /* Tsig (u_int32_t) */ + if (!getmlword(buf, my_buf_size, fp, 0)) + ERRTO("Missing signature time"); + signtime = ns_datetosecs(buf, &dateerror); + if (0 == signtime || dateerror) + ERRTO("Invalid signature time"); + cp = &data[i]; + PUTLONG(signtime, cp); + i += 4; + + /* Kfootprint (unsigned_16) */ + if (!getmlword(buf, my_buf_size, fp, 0)) + ERRTO("Missing key footprint"); + n = wordtouint32(buf); + if (wordtouint32_error || n >= 0x0ffff) + ERRTO("Invalid key footprint"); + cp = &data[i]; + PUTSHORT((u_int16_t)n, cp); + i += 2; + + /* Signer's Name */ + if (!getmlword((char*)buf, my_buf_size, fp, 0)) + ERRTO("Missing signer's name"); + cp = &data[i]; + strcpy((char *)cp, buf); + context = domain_ctx; + MAKENAME_OKZP((char *)cp, data_size); + i += strlen((char *)cp) + 1; + + /* + * Signature (base64 of any length) + * We don't care what algorithm it uses or what + * the internal structure of the BASE64 data is. + */ + if (!getallwords(buf, my_buf_size, fp, 0)) { + siglen = 0; + } else { + cp = &data[i]; + siglen = b64_pton(buf, (u_char*)cp, data_size - i); + if (siglen < 0) + ERRTO("Signature block bad"); + } + + /* set total length and we're done! */ + n = i + siglen; + + /* + * Check signature time, expiration, and adjust TTL. Note + * that all time values are in GMT (UTC), *not* local time. + */ + + now = time (0); /* need to find a better place for this XXX ogud */ + /* Don't let bogus name servers increase the signed TTL */ + if (ttl > origTTL) + ERRTO("TTL is greater than signed original TTL"); + + /* Don't let bogus signers "sign" in the future. */ + if (signtime > (u_int32_t)now) + ERRTO("signature time is in the future"); + + /* Ignore received SIG RR's that are already expired. */ + if (exptime <= (u_int32_t)now) + ERRTO("expiration time is in the past"); + + /* Lop off the TTL at the expiration time. */ + timetilexp = exptime - now; + if (timetilexp < ttl) { + ns_debug(ns_log_load, 1, + "shrinking expiring %s SIG TTL from %d to %d", + p_secstodate(exptime), ttl, timetilexp); + ttl = timetilexp; + } + + /* + * Check algorithm-ID and key structure, for + * the algorithm-ID's that we know about. + */ + switch (al) { + case NS_ALG_MD5RSA: + if (siglen == 0) + ERRTO("No key for RSA algorithm"); + if (siglen < 1) + ERRTO("Signature too short"); + if (siglen > (NS_MD5RSA_MAX_BITS + 7) / 8) + ERRTO("Signature too long"); + break; + + case NS_ALG_DH: + if (siglen < 1) + ERRTO("DH Signature too short"); + break; /* need more tests here */ + + case NS_ALG_DSA: + if (siglen < NS_DSA_SIG_SIZE) + ERRTO("DSS Signature too short"); + else if (siglen > NS_DSA_SIG_SIZE) + ERRTO("DSS Signature too long "); + break; /* need more tests here */ + + case NS_ALG_EXPIRE_ONLY: + if (siglen != 0) + ERRTO( + "Signature supplied to expire-only algorithm"); + break; + case NS_ALG_PRIVATE_OID: + if (siglen == 0) + ERRTO("No ObjectID in key"); + break; + default: + ERRTO("UNKOWN SIG algorithm"); + } + + /* Should we complain about algorithm-ID's that we + don't understand? It may help debug some obscure + cases, but in general we should accept any RR whether + we could cryptographically process it or not; it + may be being published for some newer DNS clients + to validate themselves. */ + + endline(fp); /* flush the rest of the line */ + + return (n); + err: + *errmsg = errtype; + return (-1); +} + +static int +parse_nxt_rr(char *buf, u_char *data, int data_size, FILE *fp, + struct zoneinfo *zp, char *domain, enum context context, + enum transport transport, const char **errmsg) +{ + + /* The NXT record looks like: + Name Cl NXT nextname RRT1 RRT2 MX A SOA ... + + where: Name and Cl are as usual + NXT is a keyword + nextname is the next valid name in the zone after "Name". + All names between the two are known to be nonexistent. + RRT's... are a series of RR type names, which indicate that + RR's of these types are published for "Name", and + that no RR's of any other types are published for "Name". + + When a NXT record is cryptographically signed, it proves the + nonexistence of an RR (actually a whole set of RR's). + */ + int n, errs = 0, i; + u_char *cp; +/* char *origin = zp->z_origin; + int class = zp->z_class; */ + *errmsg = "NXT name error"; + + (void) strcpy((char *)data, buf); + MAKENAME_OKZP((char *)data, data_size); + n = strlen((char *)data) + 1; + cp = n + data; + i = get_nxt_types(cp, fp, zp->z_source); + if( i > 0) + return (n + i); + *errmsg = "NXT type error"; + err: + return (-1); +} + + +static int +parse_cert_rr(char *buf, int buf_len, u_char *data, int data_size, + FILE *fp, const char **errmsg) +{ + /* Cert record looks like: + * Type Key_tag Alg Cert + * Type: certification type number (16) + * Key_tag: tag of corresponding KEY RR (16) + * Alg: algorithm of the KEY RR (8) + * Cert: base64 enocded block + */ + u_char *cp; + u_int32_t cert_type, key_tag, alg; + const char *errtype = "CERT parse error"; + int certlen, i, n, success; + + i = 0; + cp = &data[i]; + cert_type = sym_ston(__p_cert_syms, buf, &success); + if (!success) { + cert_type = wordtouint32(buf); + if (wordtouint32_error || cert_type > 0xFFFF) + ERRTO("CERT type out of range"); + } + if (i + INT16SZ > data_size) + ERRTO("CERT no space"); + PUTSHORT((u_int16_t)cert_type, cp); + i += INT16SZ; + + if (!getmlword((char*)buf, buf_len, fp, 0)) + ERRTO("CERT doesn't specify type"); + + key_tag = wordtouint32(buf); + if (wordtouint32_error || key_tag > 0xFFFF) + ERRTO("CERT KEY tag out of range"); + + if (i + INT16SZ > data_size) + ERRTO("CERT no space"); + PUTSHORT((u_int16_t)key_tag, cp); + i += INT16SZ; + + if (!getmlword(buf, buf_len, fp, 0)) + ERRTO("CERT missing algorithm ID"); + + alg = sym_ston(__p_key_syms, buf, &success); + if (!success) { + alg = wordtouint32(buf); + if (wordtouint32_error || alg > 0xFF) + ERRTO("CERT KEY alg out of range"); + } + if (i + 1 > data_size) + ERRTO("CERT no space"); + data[i++] = (u_char)alg; + + if (!getallwords(buf, buf_len, fp, 0)) { + certlen = 0; + } + else { + cp = &data[i]; + certlen = b64_pton(buf, (u_char*)cp, data_size - i); + if (certlen < 0) + ERRTO("CERT blob has encoding error"); + } + /* set total length */ + n = i + certlen; + return (n); + err: + *errmsg = errtype; + return (-1); + +} + +static int +parse_key_rr(char *buf, int buf_len, u_char *data, int data_size, + FILE *fp, const char **errmsg) +{ + /* The KEY record looks like this in the db file: + * Name Cl KEY Flags Proto Algid PublicKeyData + * where: + * Name,Cl per usual + * KEY RR type + * Flags 4 digit hex value (unsigned_16) + * Proto 8 bit u_int + * Algid 8 bit u_int + * PublicKeyData + * a string of base64 digits, + * skipping any embedded whitespace. + */ + u_int32_t al, pr; + int nk, klen,i, n; + u_int32_t keyflags; + const char *errtype = "KEY error"; + u_char *cp, *expstart; + u_int expbytes, modbytes; + + i = n = 0; + data[i] = '\0'; + cp = data; + getmlword_nesting = 0; /* KLUDGE err recov. */ + + /*>>> Flags (unsigned_16) */ + keyflags = wordtouint32(buf); + if (wordtouint32_error || 0xFFFF < keyflags) + ERRTO("KEY flags error"); + if (keyflags & NS_KEY_RESERVED_BITMASK) + ERRTO("KEY Reserved Flag Bit"); + PUTSHORT(keyflags, cp); + + /*>>> Protocol (8-bit decimal) */ + if (!getmlword((char*)buf, buf_len, fp, 0)) + ERRTO("KEY Protocol Field"); + pr = wordtouint32(buf); + if (wordtouint32_error || 255 < pr) + ERRTO("KEY Protocol Field"); + *cp++ = (u_char) pr; + + /*>>> Algorithm id (8-bit decimal) */ + if (!getmlword((char*)buf, buf_len, fp, 0)) + ERRTO("KEY Algorithm ID"); + al = wordtouint32(buf); + if (wordtouint32_error || 0 == al || 255 == al || 255 < al) + ERRTO("KEY Algorithm ID"); + *cp++ = (u_char) al; + + /*>>> Extended KEY flag field in bytes 5 and 6 */ + if (NS_KEY_EXTENDED_FLAGS & keyflags) { + u_int32_t keyflags2; + + if (!getmlword((char*)buf, buf_len, fp, 0)) + ERRTO("KEY Flags Field"); + keyflags2 = wordtouint32(buf); + if (wordtouint32_error || 0xFFFF < keyflags2) + ERRTO("Extended key flags error"); + if (keyflags2 & NS_KEY_RESERVED_BITMASK2) + ERRTO("KEY Reserved Flag2 Bit"); + PUTSHORT(keyflags2, cp); + } + + /*>>> Public Key data is in BASE64. + * We don't care what algorithm it uses or what + * the internal structure of the BASE64 data is. + */ + if (!getallwords(buf, MAXDATA, fp, 0)) + klen = 0; + else { + /* Convert from BASE64 to binary. */ + klen = b64_pton(buf, (u_char*)cp, + data_size - (cp - data)); + if (klen < 0) + ERRTO("KEY Public Key"); + } + + /* set total length */ + n = klen + (cp - data); + + /* + * Now check for valid key flags & algs & etc, from the RFC. + */ + + if (NS_KEY_TYPE_NO_KEY == (keyflags & NS_KEY_TYPEMASK)) + nk = 1; /* No-key */ + else + nk = 0; /* have a key */ + + if ((keyflags & (NS_KEY_NAME_TYPE | NS_KEY_TYPEMASK)) == + (NS_KEY_NAME_ZONE | NS_KEY_TYPE_CONF_ONLY)) + /* Zone key must have Auth bit set. */ + ERRTO("KEY Zone Key Auth. bit"); + + if (al == 0 && nk == 0) + ERRTO("KEY Algorithm"); + if (al != 0 && pr == 0) + ERRTO("KEY Protocols"); + + if (nk == 1 && klen != 0) + ERRTO("KEY No-Key Flags Set"); + + if (nk == 0 && klen == 0) + ERRTO("KEY Type Spec'd"); + + /* + * Check algorithm-ID and key structure, for the algorithm-ID's + * that we know about. + */ + switch (al) { + case NS_ALG_MD5RSA: + if (klen == 0) + break; + expstart = cp; + expbytes = *expstart++; + if (expbytes == 0) + GETSHORT(expbytes, expstart); + + if (expbytes < 1) + ERRTO("Exponent too short"); + if (expbytes > (NS_MD5RSA_MAX_BITS + 7) / 8) + ERRTO("Exponent too long"); + if (*expstart == 0) + ERRTO("Exponent w/ 0"); + + modbytes = klen - (expbytes + (expstart - cp)); + if (modbytes < (NS_MD5RSA_MIN_BITS + 7) / 8) + ERRTO("Modulus too short"); + if (modbytes > (NS_MD5RSA_MAX_BITS + 7) / 8) + ERRTO("Modulus too long"); + if (*(expstart+expbytes) == 0) + ERRTO("Modulus starts w/ 0"); + break; + + case NS_ALG_DH: { + u_char *dh_cp; + u_int16_t dh_len, plen, glen, ulen; + + dh_cp = (u_char *)cp; + GETSHORT(plen, dh_cp); + if(plen < 16) + ERRTO("DH short plen"); + dh_len = 2 + plen; + if(dh_len > klen) + ERRTO("DH plen > klen"); + + GETSHORT(glen, dh_cp); + if(glen <= 0 || glen > plen) + ERRTO("DH glen bad"); + dh_len = 2 + glen; + if(dh_len > klen) + ERRTO("DH glen > klen"); + + GETSHORT(ulen, dh_cp); + if(ulen <= 0 || ulen > plen) + ERRTO("DH ulen bad"); + dh_len = 2 + ulen; + if(dh_len > klen) + ERRTO("DH ulen > klen"); + else if (dh_len < klen) + ERRTO("DH *len < klen"); + break; + } + + case NS_ALG_DSA: { + u_int8_t t; + + if ( klen == 0) + break; + t = *cp; + if (t > 8) + ERRTO("DSA T value"); + if (klen != (1 + 20 + 3 *(64+8*t))) + ERRTO("DSA length"); + break; + } + + case NS_ALG_PRIVATE_OID: + if (klen == 0) + ERRTO("No ObjectID in key"); + break; + default: + ERRTO("Unknown Key algorithm"); + } + + endline(fp); /* flush the rest of the line */ + return (n); + err: + *errmsg = errtype; + return (-1); +} /*T_KEY*/ + +/* + * function to invoke DNSSEC specific parsing routines. + * this is simpler than copying these complicated blocks into the + * multiple souce files that read files (ixfr, nsupdate etc..). + * this code should be in a library rather than in this file but + * what the heck for now (ogud@tislabs.com) + */ +int +parse_sec_rdata(char *buf, int buf_len, int buf_full, u_char *data, + int data_size, FILE *fp, struct zoneinfo *zp, + char *domain, u_int32_t ttl, int type, enum context context, + enum transport transport, const char **errmsg) +{ + int ret = -1; + + getmlword_nesting = 0; /* KLUDGE err recov. */ + if (!buf_full && buf && buf_len != 0) /* check if any data in buf */ + if (!getmlword(buf, buf_len, fp, 1)) { + *errmsg = "unexpected end of input"; + goto err; + } + + switch (type) { + case ns_t_sig: + ret = parse_sig_rr(buf, buf_len, data, data_size, fp, zp, + domain, ttl, context, transport, errmsg); + break; + case ns_t_key: + ret = parse_key_rr(buf, buf_len, data, data_size, fp, errmsg); + break; + case ns_t_nxt: + ret = parse_nxt_rr(buf, data, data_size, fp, zp, + domain, context, transport, errmsg); + break; + case ns_t_cert: + ret = parse_cert_rr(buf, buf_len, data, data_size, fp, errmsg); + break; + default: + ret = -1; + *errmsg = "parse_sec_rdata():Unsupported SEC type type"; + goto err; + } + return (ret); + err: + endline(fp); + return (ret); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/db_load.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/db_lookup.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/db_lookup.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/db_lookup.c (revision 109985) @@ -0,0 +1,341 @@ +#if !defined(lint) && !defined(SABER) +static const char sccsid[] = "@(#)db_lookup.c 4.18 (Berkeley) 3/21/91"; +static const char rcsid[] = "$Id: db_lookup.c,v 8.27 2001/06/18 14:42:55 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * Table lookup routines. + */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "named.h" + +/* + * Lookup 'name' and return a pointer to the namebuf; + * NULL otherwise. If 'insert', insert name into tables. + * Wildcard lookups are handled. + */ +struct namebuf * +nlookup(const char *name, struct hashbuf **htpp, + const char **fname, int insert) +{ + struct namebuf *np; + const char *cp; + int c; + u_int hval; + struct hashbuf *htp; + struct namebuf *parent = NULL; + int escaped = 0; + + htp = *htpp; + hval = 0; + *fname = "???"; + for (cp = name; (c = *cp++) != 0; (void)NULL) { + if (!escaped && (c == '.')) { + parent = np = nlookup(cp, htpp, fname, insert); + if (np == NULL) + return (NULL); + if (*fname != cp) + return (np); + if ((htp = np->n_hash) == NULL) { + if (!insert) { + if (ns_wildcard(NAME(*np))) + *fname = name; + return (np); + } + htp = savehash((struct hashbuf *)NULL); + np->n_hash = htp; + } + *htpp = htp; + break; + } + + HASHIMILATE(hval, c); + if (escaped) + escaped = 0; + else if (c == '\\') + escaped = 1; + } + cp--; + /* + * Lookup this label in current hash table. + */ + for (np = htp->h_tab[hval % htp->h_size]; + np != NULL; + np = np->n_next) { + if (np->n_hashval == hval && + ((size_t)NAMELEN(*np) == (size_t)(cp - name)) && + (strncasecmp(name, NAME(*np), cp - name) == 0)) { + *fname = name; + return (np); + } + } + if (!insert) { + /* + * Look for wildcard in this hash table. + * Don't use a cached "*" name as a wildcard, + * only authoritative. + */ + hval = ('*' & HASHMASK) % htp->h_size; + for (np = htp->h_tab[hval]; np != NULL; np = np->n_next) { + if (ns_wildcard(NAME(*np)) && + np->n_data && np->n_data->d_zone != 0) { + *fname = name; + return (np); + } + } + return (parent); + } + np = savename(name, cp - name); + np->n_parent = parent; + np->n_hashval = hval; + hval %= htp->h_size; + np->n_next = htp->h_tab[hval]; + htp->h_tab[hval] = np; + /* Increase hash table size. */ + if (++htp->h_cnt > (htp->h_size * AVGCH_NLOOKUP)) { + *htpp = savehash(htp); + if (parent == NULL) { + if (htp == hashtab) { + hashtab = *htpp; + } else { + fcachetab = *htpp; + } + } + else + parent->n_hash = *htpp; + htp = *htpp; + } + *fname = name; + return (np); +} + +/* struct namebuf * + * np_parent(struct namebuf *np) + * Find the "parent" namebuf of np. + * This is tricky since the parent of "com" is "" and both are stored + * in the same hashbuf. + * See also: + * the AXFR wart description in ns_axfr.c + */ +struct namebuf * +np_parent(struct namebuf *np) { + struct hashbuf *htp; + struct namebuf *np2; + + if (np->n_parent != NULL || NAME(*np)[0] == '\0') + return (np->n_parent); + + /* Try to figure out if np is pointing into the cache or hints. */ + /* Try the cache first. */ + htp = hashtab; + try_again: + /* Search the hash chain that np should be part of. */ + for (np2 = htp->h_tab[np->n_hashval % htp->h_size]; + np2 != NULL; + np2 = np2->n_next) + { + if (np == np2) { /* found it! */ + /* "" hashes into the first bucket */ + for (np = htp->h_tab[0]; np != NULL; np = np->n_next) { + if (NAME(*np)[0] == '\0') + /* found the root namebuf */ + return (np); + } + /* there are no RR's with a owner name of "." yet */ + return (NULL); + } + } + /* Try the hints. */ + if (htp == hashtab) { + htp = fcachetab; + goto try_again; + } + ns_debug(ns_log_db, 1, "np_parent(0x%lx) couldn't find namebuf", + (u_long)np); + return (NULL); /* XXX shouldn't happen */ +} + +/* int + * match(dp, class, type) + * Does data record `dp' match the class and type? + * return value: + * boolean + */ +int +match(struct databuf *dp, int class, int type) { + if (dp->d_class != class && class != C_ANY) + return (0); + if (dp->d_type != type && dp->d_type != T_SIG && type != T_ANY) + return (0); + if (type != T_SIG && dp->d_type == T_SIG && (int)SIG_COVERS(dp) != type) + return (0); + return (1); +} + +/* static int + * nxtlower(name, dp) + * Is the NXT/SIG NXT record 'lower'? + * return value: + * boolean + */ +static int +nxtlower(const char *name, struct databuf *dp) { + /* An NXT is a lower NXT iff the SOA bit is set in the bitmap */ + if (dp->d_type == T_NXT) { + u_char *nxtbitmap = dp->d_data + strlen((char *)dp->d_data) + 1; + return (NS_NXT_BIT_ISSET(T_SOA, nxtbitmap) ? 1 : 0); + } + /* If it's not an NXT, it's a SIG NXT. An NXT record must be signed + * by the zone, so the signer name must be the same as the owner. + */ + return (ns_samename(name, (char *)dp->d_data + SIG_HDR_SIZE) != 1 ? 0 : 1); +} + +/* int + * nxtmatch(name, dp1, dp2) + * Do NXT/SIG NXT records `dp1' and `dp2' belong to the same NXT set? + * return value: + * boolean + */ +int +nxtmatch(const char *name, struct databuf *dp1, struct databuf *dp2) { + int dp1_lower, dp2_lower; + int type1, type2; + + if (dp1->d_type == ns_t_sig) + type1 = SIG_COVERS(dp1); + else + type1 = dp1->d_type; + if (dp2->d_type == ns_t_sig) + type2 = SIG_COVERS(dp2); + else + type2 = dp2->d_type; + + if (type1 != ns_t_nxt || type2 != ns_t_nxt) + return (0); + dp1_lower = nxtlower(name, dp1); + dp2_lower = nxtlower(name, dp2); + return (dp1_lower == dp2_lower); +} + +/* int + * rrmatch(name, dp1, dp2) + * Do data records `dp1' and `dp2' match in class and type? + * If both are NXTs, do they belong in the same NXT set? + * If both are SIGs, do the covered types match? + * If both are SIG NXTs, do the covered NXTs belong in the same set? + * Why is DNSSEC so confusing? + * return value: + * boolean + */ +int +rrmatch(const char *name, struct databuf *dp1, struct databuf *dp2) { + if (dp1->d_class != dp2->d_class && + dp1->d_class != C_ANY && dp2->d_class != C_ANY) + return(0); + if (dp1->d_type != dp2->d_type && + dp1->d_type != T_ANY && dp2->d_type != T_ANY) + return(0); + if (dp1->d_type == T_NXT) + return(nxtmatch(name, dp1, dp2)); + if (dp1->d_type != T_SIG) + return(1); + if (SIG_COVERS(dp1) == SIG_COVERS(dp2)) { + if (SIG_COVERS(dp1) == ns_t_nxt) + return(nxtmatch(name, dp1, dp2)); + else + return(1); + } + return(0); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/db_lookup.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/db_update.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/db_update.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/db_update.c (revision 109985) @@ -0,0 +1,1002 @@ +#if !defined(lint) && !defined(SABER) +static const char sccsid[] = "@(#)db_update.c 4.28 (Berkeley) 3/21/91"; +static const char rcsid[] = "$Id: db_update.c,v 8.50 2001/10/24 23:53:09 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986, 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "named.h" + +/* int + * isRefByNS(name, htp) + * recurse through all of `htp' looking for NS RR's that refer to `name'. + * returns: + * nonzero if at least one such NS RR exists + * cautions: + * this is very expensive; probably you only want to use on fcachetab. + */ +static int +isRefByNS(const char *name, struct hashbuf *htp) { + struct namebuf *np; + struct databuf *dp; + + for (np = htp->h_tab[0]; np != NULL; np = np->n_next) { + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if ((dp->d_class == C_ANY || + dp->d_class == C_IN || + dp->d_class == C_HS) && + dp->d_type == T_NS && + !dp->d_rcode && + ns_samename(name, (const char *)dp->d_data) == 1) { + return (1); + } + } + if (np->n_hash && isRefByNS(name, np->n_hash)) + return (1); + } + return (0); +} + + +/* int + * findMyZone(struct namebuf *np, int class) + * surf the zone cuts and find this zone the hard way + * return value: + * zone number or DB_Z_CACHE if it's outside a zone + * interesting cases: + * DEC.COM SOA (primary) + * CRL.DEC.COM NS (in primary) + * if you start at CRL.. here, you find the DEC.COM zone + * if you start at NS.CRL.. here, you're in the cache + * DEC.COM SOA (primary) + * CRL.DEC.COM NS (in primary) + * CRL.DEC.COM SOA (slave) + * CRL.DEC.COM NS (in slave) + * if you start at CRL.. here, you find the CRL.DEC.COM zone + * if you start at NS.CRL.. here, you're in the CRL.. zone + */ +int +findMyZone(struct namebuf *np, int class) { + for ((void)NULL; np; np = np_parent(np)) { + struct databuf *dp; + + /* if we encounter an SOA, we're in its zone (which can be + * the cache or an authoritative zone, depending). + */ + for (dp = np->n_data; dp; dp = dp->d_next) + if (match(dp, class, T_SOA) && dp->d_type == T_SOA) + return (dp->d_zone); + + /* if we find an NS at some node without having seen an SOA + * (above), then we're out in the cache somewhere. + */ + for (dp = np->n_data; dp; dp = dp->d_next) + if (match(dp, class, T_NS) && dp->d_type == T_NS) + return (DB_Z_CACHE); + } + + /* The cache has not yet been primed. */ + return (DB_Z_CACHE); +} + +/* int + * db_update(name, odp, newdp, savedpp, flags, htp, from) + * update data base node at `name'. `flags' controls the action. + * side effects: + * inverse query tables modified, if we're using them. + * return value: + * OK - success + * NONAME - name doesn't exist + * AUTH - you can't do that + * DATAEXISTS - there's something there and DB_NODATA was specified + * NODATA - there's no data, and (DB_DELETE or DB_MEXIST) was spec'd + * + * Policy: How to add data if one more RR is -ve data + * + * NEND NOERROR_NODATA + * NXD NXDOMAIN + * + * match + * old + * Data NEND NXD + * Data Merge Data Data + * new NEND NEND NEND NEND + * NXD NXD NXD NXD + * + * no match + * old + * Data NEND NXD + * Data Merge Merge Data + * new NEND Merge Merge NEND + * NXD NXD NXD NXD + * + */ +/* XXX: this code calls nlookup, which can create namebuf's. if this code + * has to exit with a fatal error, it should scan from the new np upward + * and for each node which has no children and no data it should remove + * the namebuf. design notes: (1) there's no harm in doing this even if + * success occurred; (2) stopping on the first nonremovable np is optimal; + * the code for removal should be taken out of clean_cache() and made + * general enough for this use, and for clean_cache()'s continued use. + * vix, 21jul94 + */ +int +db_update(const char *name, + struct databuf *odp, struct databuf *newdp, + struct databuf **savedpp, + int flags, struct hashbuf *htp, struct sockaddr_in from) +{ + struct databuf *dp, *pdp; + struct namebuf *np; + int zn, isHintNS; + int check_ttl = 0; + int deleted_something = 0; + const char *fname; +#ifdef BIND_UPDATE + int found_other_ns = 0; + struct databuf *tmpdp; +#endif + + ns_debug(ns_log_db, 3, "db_update(%s, %p, %p, %p, 0%o, %p)%s", + name, odp, newdp, savedpp, flags, htp, + (odp && (odp->d_flags&DB_F_HINT)) ? " hint" : ""); + np = nlookup(name, &htp, &fname, newdp != NULL); + if (np == NULL || fname != name) + return (NONAME); + + if (newdp && zones[newdp->d_zone].z_type == Z_PRIMARY) + check_ttl = 1; + + /* don't let nonauthoritative updates write in authority zones */ + if (newdp && ((zn = findMyZone(np, newdp->d_class)) != DB_Z_CACHE) && +#ifdef STUBS + (zones[zn].z_type != Z_STUB) && +#endif + (flags & DB_NOTAUTH)) { + int foundRR = 0; + + /* + * Don't generate the warning if the update + * would have been harmless (identical data). + */ + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (!db_cmp(dp, newdp)) { + foundRR++; + break; + } + } + if (!foundRR) + ns_debug(ns_log_db, 5, + "[%s].%d update? to auth zone \"%s\" (%s)", + inet_ntoa(from.sin_addr), + ntohs(from.sin_port), + zones[zn].z_origin, + name); + return (AUTH); + } + + if (newdp && zn && !(flags & DB_NOTAUTH)) { + if (nlabels(zones[zn].z_origin) > newdp->d_clev) { + if ((!ISVALIDGLUE(newdp) && + zones[newdp->d_zone].z_type == Z_PRIMARY) || + (newdp->d_type == T_NS && + !ns_samename(name, zones[zn].z_origin))) { + ns_info(ns_log_db, + "domain %s %s record in zone %s should be in zone %s", + name, p_type(newdp->d_type), + zones[newdp->d_zone].z_origin, + zones[zn].z_origin); + return (NONGLUE); + } else + ns_debug(ns_log_db, 5, + "attempted update child zone %s, %s %s", + zones[zn].z_origin, name, + p_type(newdp->d_type)); + return (AUTH); + } + } + + /* some special checks for root NS' A RR's */ + isHintNS = isRefByNS(name, fcachetab); +#ifdef DEPRECATED + if (newdp && isHintNS && newdp->d_type == T_A) { + /* upgrade credibility of additional data for rootsrv addrs */ + if (newdp->d_cred == DB_C_ADDITIONAL) { + ns_debug(ns_log_db, 3, + "upgrading credibility for A RR (%s)", + name); + /* XXX: should copy NS RR's, but we really just want + * to prevent deprecation later so this will do. + */ + newdp->d_cred = DB_C_ANSWER; + newdp->d_clev = 0; + } + } +#endif + + /* Reflect certain updates in hint cache also... */ + /* Don't stick data we are authoritative for in hints. */ + if (!(flags & DB_NOHINTS) && + (flags & DB_PRIMING) && + (odp != NULL) && + (htp != fcachetab) && + (DB_Z_SPECIAL(odp->d_zone)) && + !(odp->d_flags & DB_F_HINT) && + (!newdp || !newdp->d_rcode) && + ((name[0] == '\0' && odp->d_type == T_NS) || + (odp->d_type == T_A && isHintNS) + ) + ) + { + ns_debug(ns_log_db, 3, "db_update: hint '%s' %u", + name, odp->d_ttl); + dp = savedata(odp->d_class, odp->d_type, odp->d_ttl, + odp->d_data, odp->d_size); + dp->d_zone = DB_Z_CACHE; + dp->d_flags = DB_F_HINT; + dp->d_cred = DB_C_CACHE; + dp->d_secure = odp->d_secure; /* BEW - this should be ok */ + dp->d_clev = 0; + if (db_update(name, + dp, dp, NULL, + (flags|DB_NOHINTS), + fcachetab, from) + != OK) + ns_debug(ns_log_db, 3, + "db_update: hint %p freed", dp); + db_detach(&dp); + } + + if (odp != NULL) { + int foundRR = 0; + + pdp = NULL; + for (dp = np->n_data; dp != NULL; ) { + if (!rrmatch(name, dp, odp)) { + /* {class,type} doesn't match. these are + * the aggregation cases. + */ + /* Check that CNAMEs are only accompanied by + * Secure DNS RR's (KEY, SIG, and NXT). + */ + if (((dp->d_type == T_CNAME && + odp->d_type != T_KEY && + odp->d_type != T_SIG && + odp->d_type != T_NXT) || + (odp->d_type == T_CNAME && + dp->d_type != T_KEY && + dp->d_type != T_SIG && + dp->d_type != T_NXT)) && + odp->d_class == dp->d_class && + /* XXXRTH d_mark removed in 4.9.5, + but still here for dynamic + update */ + odp->d_mark == dp->d_mark && + !dp->d_rcode && + !odp->d_rcode && +#ifdef BIND_UPDATE + /* updating a CNAME with another CNAME is permitted */ + (dp->d_type != T_CNAME || + odp->d_type != T_CNAME) && +#endif + zones[odp->d_zone].z_type != Z_CACHE) { + ns_info(ns_log_db, + "%s has CNAME and other data (invalid)", + name); + if (zones[odp->d_zone].z_type == + Z_PRIMARY) + return (CNAMEANDOTHER); + goto skip; + } + if (!newdp || newdp->d_class != dp->d_class) + goto skip; + + /* if the new data is authorative + * remove any data for this domain with + * the same class that isn't as credable + */ + if (newdp->d_cred == DB_C_ZONE && + newdp->d_cred > dp->d_cred) + /* better credibility and the old datum + * was not from a zone file. remove + * the old datum. + */ + goto delete; + +#if 0 /* caught by findMyZone() now. */ + /* if we have authoritative data for a + * node, don't add in other data. + */ + if (dp->d_cred == DB_C_ZONE && + newdp->d_cred < dp->d_cred) + return (AUTH); +#endif + + /* if the new data is authoritative + * but isn't as credible, reject it. + */ + if (newdp->d_cred == DB_C_ZONE && + dp->d_cred == DB_C_ZONE) { + /* Both records are from a zone file. + * If their credibility levels differ, + * we're dealing with a zone cut. The + * record with lower clev is from the + * upper zone's file and is therefore + * glue. + */ + + /* BEW/OG: we see no reason to override + * these rules with new security based + * rules. + */ + if (newdp->d_clev < dp->d_clev) { + if (!ISVALIDGLUE(newdp)) { + ns_info(ns_log_db, + "domain %s %s record in zone %s should be in zone %s, ignored", + name, p_type(newdp->d_type), + zones[newdp->d_zone].z_origin, + zones[dp->d_zone].z_origin); + } + return (AUTH); + } + if (newdp->d_clev > dp->d_clev) { + if (!ISVALIDGLUE(dp)) { + ns_info(ns_log_db, + "domain %s %s record in zone %s should be in zone %s, deleted", + name, p_type(dp->d_type), + zones[dp->d_zone].z_origin, + zones[newdp->d_zone].z_origin); + } + goto delete; + } + } + + /* process NXDOMAIN */ + /* policy */ + if (newdp->d_rcode == NXDOMAIN) { + if (dp->d_cred < DB_C_AUTH && + newdp->d_secure >= dp->d_secure) + goto delete; + else + return (DATAEXISTS); + } + + if (dp->d_rcode == NXDOMAIN) + goto delete; + + /* process NOERROR_NODATA */ + /* NO PROCESSING REQUIRED */ + + goto skip; + } /*if {class,type} did not match*/ + + /* + * {type,class} did match. This is the replace case. + */ + ns_debug(ns_log_db, 5, + "db_update: flags = %#x, sizes = %d, %d (cmp %d)", + flags, odp->d_size, dp->d_size, + db_cmp(dp, odp)); + if (newdp) { + ns_debug(ns_log_db, 4, +"credibility for %s is %d(%d)(sec %d) from [%s].%d, is %d(%d)(sec %d) in cache", + *name ? name : ".", + newdp->d_cred, + newdp->d_clev, + newdp->d_secure, + inet_ntoa(from.sin_addr), + ntohs(from.sin_port), + dp->d_cred, + dp->d_secure, + dp->d_clev); + if ((newdp->d_secure > dp->d_secure) || + (newdp->d_secure == dp->d_secure && + (newdp->d_cred > dp->d_cred))) + { + /* better credibility / security. + * remove the old datum. + */ + goto delete; + } + if ((newdp->d_secure < dp->d_secure) || + (newdp->d_secure == dp->d_secure && + (newdp->d_cred < dp->d_cred))) + { + /* credibility / security is worse. + * ignore it. + */ + return (AUTH); + } + /* BEW/OG: from above, we know the security + * levels are the same. + */ + if (newdp->d_cred == DB_C_ZONE && + dp->d_cred == DB_C_ZONE ) { + /* Both records are from a zone file. + * If their credibility levels differ, + * we're dealing with a zone cut. The + * record with lower clev is from the + * upper zone's file and is therefore + * glue. + */ + + /* XXX - Tricky situation here is you + * have 2 zones a.b.c and sub.a.b.c + * being served by the same server. + * named will send NS records for + * sub.a.b.c during zone transfer of + * a.b.c zone. If we're slave for + * both zones, and we reload zone + * a.b.c, we'll get the NS records + * (and possibly A records to go with + * them?) for sub.a.b.c as part of the + * a.b.c zone transfer. But we've + * already got a more credible record + * from the sub.a.b.c zone. So we want + * to ignore the new record, but we + * shouldn't syslog because there's + * nothing the user can do to prevent + * the situation. Perhaps we should + * only complain when we are primary? + */ + + if (newdp->d_clev < dp->d_clev) { + if (!ISVALIDGLUE(newdp)) { + ns_info(ns_log_db, + "domain %s %s record in zone %s should be in zone %s, ignored", + name, p_type(newdp->d_type), + zones[newdp->d_zone].z_origin, + zones[dp->d_zone].z_origin); + } + return (AUTH); + } + if (newdp->d_clev > dp->d_clev) { + if (!ISVALIDGLUE(dp)) { + ns_info(ns_log_db, + "domain %s %s record in zone %s should be in zone %s, deleted", + name, p_type(dp->d_type), + zones[dp->d_zone].z_origin, + zones[newdp->d_zone].z_origin); + } + goto delete; + } + } + + /* credibility is the same. + * let it aggregate in the normal way. + */ + + /* + * if the new or old RR is -ve, delete old. + */ + if (dp->d_rcode || newdp->d_rcode) { + /* XXX: how can a zone rr be neg? */ + if (dp->d_cred != DB_C_ZONE) + goto delete; + else + return (DATAEXISTS); + } + + /* + * Some RR types should not be aggregated. + */ + if (dp->d_type == T_SOA) { +#ifdef BIND_UPDATE + u_int32_t dp_ser, ndp_ser; + u_char *dp_cp, *ndp_cp; + + dp_cp = findsoaserial(dp->d_data); + ndp_cp = findsoaserial(newdp->d_data); + GETLONG(dp_ser, dp_cp); + GETLONG(ndp_ser, ndp_cp); + + if (SEQ_GT(ndp_ser, dp_ser)) + goto delete; + else + return (SERIAL); +#else + goto delete; +#endif /*BIND_UPDATE*/ + } + if (dp->d_type == T_WKS && + !memcmp(dp->d_data, newdp->d_data, + INT32SZ + sizeof(u_char))) + goto delete; + if (dp->d_type == T_CNAME && + !NS_OPTION_P(OPTION_MULTIPLE_CNAMES) && + db_cmp(dp, odp) != 0) { + if ((flags & DB_REPLACE) == 0 && + zones[dp->d_zone].z_type == + Z_PRIMARY) { + ns_warning(ns_log_db, + "%s has multiple CNAMES", + name); + return (CNAMEANDOTHER); + } else + goto delete; + } +#if 0 +/* BEW - this _seriously_ breaks DNSSEC. Is it necessary for dynamic update? */ +#ifdef BIND_UPDATE + if (dp->d_type == T_SIG) + /* + * Type covered has already been + * checked. + */ + goto delete; +#endif +#endif + if (dp->d_type == T_NXT) { + goto delete; + } + if (dp->d_type == T_SIG && + SIG_COVERS(dp) == T_NXT) { + struct sig_record *sr1, *sr2; + + sr1 = (struct sig_record *) dp->d_data; + sr2 = (struct sig_record *) + newdp->d_data; + if (sr1->sig_alg_n == sr2->sig_alg_n) + goto delete; + } + if (check_ttl) { + if (newdp->d_ttl != dp->d_ttl) + ns_warning(ns_log_db, + "%s %s %s differing ttls: corrected", + name[0]?name:".", + p_class(dp->d_class), + p_type(dp->d_type)); + if (newdp->d_ttl > dp->d_ttl) { + newdp->d_ttl = dp->d_ttl; + } else { + dp->d_ttl = newdp->d_ttl; + } + } + } + if ((flags & DB_NODATA) && !db_cmp(dp, odp)) { + /* Refresh ttl if cache entry. */ + if (dp->d_zone == DB_Z_CACHE) { + if (odp->d_zone != DB_Z_CACHE) { + /* Changing cache->auth. */ + dp->d_zone = odp->d_zone; + dp->d_ttl = odp->d_ttl; + ns_debug(ns_log_db, 4, + "db_update: cache entry now in auth zone"); + return (DATAEXISTS); + } + fixttl(odp); + if (odp->d_ttl > dp->d_ttl) + dp->d_ttl = odp->d_ttl; + ns_debug(ns_log_db, 3, + "db_update: new ttl %u +%lu", + dp->d_ttl, + (u_long)(dp->d_ttl - tt.tv_sec) + ); + } + return (DATAEXISTS); + } + /* + * If the old databuf has some data, check that the + * data matches that in the new databuf. + */ + if (odp->d_size > 0) + if (db_cmp(dp, odp)) + goto skip; + if (odp->d_clev < dp->d_clev) + goto skip; + if ((odp->d_secure < dp->d_secure) || + ((odp->d_secure == dp->d_secure) && + (odp->d_cred < dp->d_cred))) + goto skip; +#ifdef BIND_UPDATE + if (ns_samename(name, zones[dp->d_zone].z_origin) == 1 + && newdp == NULL) { + /* do not delete SOA or NS records as a set */ + /* XXXRTH isn't testing d_size unnecessary? */ + if ((odp->d_size == 0) && + (odp->d_class == C_ANY) && + (odp->d_type == T_ANY || + odp->d_type == T_SOA || + odp->d_type == T_NS) && + (dp->d_type == T_SOA || + dp->d_type == T_NS)) + goto skip; + /* XXXRTH I added this to prevent SOA deletion + I'm using the same style of comparison as + the other code in this section. Do we + really need to look at dp->d_type here? + We're in the "match" section... */ + if ((odp->d_type == T_SOA) && + (dp->d_type == T_SOA)) + goto skip; + /* do not delete the last NS record + for the zone */ + if ((odp->d_type == T_NS) && + (dp->d_type == T_NS)) { + found_other_ns = 0; + for (tmpdp = np->n_data; + tmpdp && !found_other_ns; + tmpdp = tmpdp->d_next) + if ((tmpdp->d_type == T_NS) && + (tmpdp != dp)) + found_other_ns = 1; + if (!found_other_ns) { + ns_debug(ns_log_db, 3, + "cannot delete last remaining NS record for zone %s", + name); + goto skip; + } + } + } +#endif + + foundRR = 1; + if (flags & DB_DELETE) { + delete: +#ifdef BIND_UPDATE + /* + * XXX assume here that savedpp!=NULL iff. db_update + * has been called by the dyanmic update code. + * Maybe a new flag is more appropriate? + */ + if (savedpp != NULL) + foundRR = 1; +#endif + deleted_something = 1; + dp = rm_datum(dp, np, pdp, savedpp); + } else { + skip: pdp = dp; + dp = dp->d_next; + } + } + if (!foundRR) { + if (flags & DB_DELETE) + return (NODATA); + if (flags & DB_MEXIST) + return (NODATA); + } + } + if (newdp == NULL) { + if (deleted_something) { + while (np->n_data == NULL && np->n_hash == NULL) { + np = purge_node(htp, np); + if (np == NULL) + break; + } + } + return (OK); + } + /* XXX: empty nodes bypass credibility checks above; should check + * response source address here if flags&NOTAUTH. + */ + fixttl(newdp); + ns_debug(ns_log_db, 3, "db_update: adding%s %p", + (newdp->d_flags&DB_F_HINT) ? " hint":"", newdp); + + if (newdp->d_zone == DB_Z_CACHE && + (newdp->d_flags & DB_F_HINT) == 0) + newdp->d_addr = from.sin_addr; + + /* Add to end of list, generally preserving order */ + newdp->d_next = NULL; + if ((dp = np->n_data) == NULL) { + DRCNTINC(newdp); + if (newdp->d_flags & DB_F_ACTIVE) + panic("db_update: DB_F_ACTIVE set", NULL); + newdp->d_flags |= DB_F_ACTIVE; + np->n_data = newdp; + return (OK); + } + while (dp->d_next != NULL) { + if ((flags & DB_NODATA) && !db_cmp(dp, newdp)) + return (DATAEXISTS); + dp = dp->d_next; + } + if ((flags & DB_NODATA) && !db_cmp(dp, newdp)) + return (DATAEXISTS); + DRCNTINC(newdp); + if (newdp->d_flags & DB_F_ACTIVE) + panic("db_update: DB_F_ACTIVE set", NULL); + newdp->d_flags |= DB_F_ACTIVE; + dp->d_next = newdp; + return (OK); +} + +void +fixttl(struct databuf *dp) { + if (dp->d_zone == DB_Z_CACHE && (dp->d_flags & DB_F_HINT) == 0) { + if (dp->d_ttl <= (u_int32_t)tt.tv_sec) + return; + else if (dp->d_ttl < (u_int32_t)tt.tv_sec+min_cache_ttl) + dp->d_ttl = (u_int32_t)tt.tv_sec+min_cache_ttl; + else if (dp->d_ttl > (u_int32_t)tt.tv_sec+max_cache_ttl) + dp->d_ttl = (u_int32_t)tt.tv_sec+max_cache_ttl; + } +} + +/* + * Compare type, class and data from databufs for equivalence. + * All domain names in RR's must be compared case-insensitively. + * Return 0 if equivalent, nonzero otherwise. + */ +int +db_cmp(const struct databuf *dp1, const struct databuf *dp2) { + const u_char *cp1, *cp2; + int len, len2; + + /* XXXDYNUP- should be changed to + if (!match(dp1, dp2->d_type, dp2->d_class) */ + if (dp1->d_type != dp2->d_type || dp1->d_class != dp2->d_class) + return (1); + /* XXXDYNUP - should be changed to (dp1->d_size != dp2->d_size && + dp1->d_size != 0 && dp2->d_size != 0) */ + if (dp1->d_size != dp2->d_size) + return (1); + /* d_mark is only used for dynamic updates currently */ +#ifndef BIND_UPDATE + if (dp1->d_mark != dp2->d_mark) + return (1); /* old and new RR's are distinct */ +#endif + if (dp1->d_rcode && dp2->d_rcode) + return ((dp1->d_rcode == dp1->d_rcode)?0:1); + if (dp1->d_rcode || dp2->d_rcode) + return (1); + + switch (dp1->d_type) { + + case T_A: + case T_WKS: + case T_NULL: + case T_NSAP: + case T_AAAA: + case T_LOC: + case T_KEY: + /* Only binary data */ + return (memcmp(dp1->d_data, dp2->d_data, dp1->d_size)); + + case T_NS: + case T_CNAME: + case T_PTR: + case T_MB: + case T_MG: + case T_MR: + /* Only a domain name */ + if (ns_samename((const char *)dp1->d_data, + (const char *)dp2->d_data) == 1) + return (0); + else + return (1); + + case T_SIG: + /* Binary data, a domain name, more binary data */ + if (dp1->d_size < NS_SIG_SIGNER) + return (1); + if (memcmp(dp1->d_data, dp2->d_data, NS_SIG_SIGNER)) + return (1); + len = NS_SIG_SIGNER + + strlen((const char *)dp1->d_data + NS_SIG_SIGNER); + if (ns_samename((const char *)dp1->d_data + NS_SIG_SIGNER, + (const char *)dp2->d_data + NS_SIG_SIGNER) != 1) + return (1); + return (memcmp(dp1->d_data + len, + dp2->d_data + len, + dp1->d_size - len)); + + case T_NXT: + /* First a domain name, then binary data */ + if (ns_samename((const char *)dp1->d_data, + (const char *)dp2->d_data) != 1) + return (1); + len = strlen((const char *)dp1->d_data)+1; + return (memcmp(dp1->d_data + len, + dp2->d_data + len, + dp1->d_size - len)); + + case T_HINFO: + case T_ISDN: + cp1 = dp1->d_data; + cp2 = dp2->d_data; + len = *cp1; + len2 = *cp2; + if (len != len2) + return (1); + if (strncasecmp((const char *)++cp1, (const char *)++cp2, len)) + return (1); + cp1 += len; + cp2 += len; + len = *cp1; + len2 = *cp2; + if (len != len2) + return (1); + return (strncasecmp((const char *)++cp1, (const char *)++cp2, + len)); + + case T_SOA: + case T_MINFO: + case T_RP: + if (ns_samename((const char *)dp1->d_data, + (const char *)dp2->d_data) != 1) + return (1); + cp1 = dp1->d_data + strlen((const char *)dp1->d_data) + 1; + cp2 = dp2->d_data + strlen((const char *)dp2->d_data) + 1; + if (ns_samename((const char *)cp1, (const char *)cp2) != 1) + return (1); + if (dp1->d_type != T_SOA) + return (0); + cp1 += strlen((const char *)cp1) + 1; + cp2 += strlen((const char *)cp2) + 1; + return (memcmp(cp1, cp2, INT32SZ * 5)); + + case T_NAPTR: { + int t1,t2; + + if (dp1->d_size != dp2->d_size) + return (1); + cp1 = dp1->d_data; + cp2 = dp2->d_data; + + /* Order */ + if (*cp1++ != *cp2++ || *cp1++ != *cp2++) + return (1); + + /* Preference */ + if (*cp1++ != *cp2++ || *cp1++ != *cp2++) + return (1); + + /* Flags */ + t1 = *cp1++; t2 = *cp2++; + if (t1 != t2 || memcmp(cp1, cp2, t1)) + return (1); + cp1 += t1; cp2 += t2; + + /* Services */ + t1 = *cp1++; t2 = *cp2++; + if (t1 != t2 || memcmp(cp1, cp2, t1)) + return (1); + cp1 += t1; cp2 += t2; + + /* Regexp */ + t1 = *cp1++; t2 = *cp2++; + if (t1 != t2 || memcmp(cp1, cp2, t1)) + return (1); + cp1 += t1; cp2 += t2; + + /* Replacement */ + if (ns_samename((const char *)cp1, (const char *)cp2) != 1) + return (1); + + /* they all checked out! */ + return (0); + } + + case T_MX: + case T_AFSDB: + case T_RT: + case T_SRV: + cp1 = dp1->d_data; + cp2 = dp2->d_data; + if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* cmp prio */ + return (1); + if (dp1->d_type == T_SRV) { + if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* weight */ + return (1); + if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* port */ + return (1); + } + if (ns_samename((const char *)cp1, (const char *)cp2) != 1) + return (1); + return (0); + + case T_PX: + cp1 = dp1->d_data; + cp2 = dp2->d_data; + if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* cmp prio */ + return (1); + if (ns_samename((const char *)cp1, (const char *)cp2) != 1) + return (1); + cp1 += strlen((const char *)cp1) + 1; + cp2 += strlen((const char *)cp2) + 1; + if (ns_samename((const char *)cp1, (const char *)cp2) != 1) + return (1); + return (0); + + case T_TXT: + case T_X25: + if (dp1->d_size != dp2->d_size) + return (1); + return (memcmp(dp1->d_data, dp2->d_data, dp1->d_size)); + + default: + return (1); + } +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/db_update.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_glue.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_glue.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_glue.c (revision 109985) @@ -0,0 +1,469 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_glue.c,v 8.24 2002/01/07 02:54:37 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996-2000 by Internet Software Consortium, Inc. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "port_after.h" + +#include "named.h" + +/* + * IP address from unaligned octets. + */ +struct in_addr +ina_get(const u_char *data) { + struct in_addr ret; + u_int32_t i; + + GETLONG(i, data); + ina_ulong(ret) = htonl(i); + return (ret); +} + +/* + * IP address to unaligned octets. + */ +u_char * +ina_put(struct in_addr ina, u_char *data) { + PUTLONG(ntohl(ina_ulong(ina)), data); + return (data); +} + +/* + * IP address to presentation format. + */ +const char * +sin_ntoa(struct sockaddr_in sin) { + static char ret[sizeof "[111.222.333.444].55555"]; + + sprintf(ret, "[%s].%u", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); + return (ret); +} + +/* + * Logging Support + */ + +int +ns_wouldlog(int category, int level) { + if (log_ctx_valid) + return (log_check(log_ctx, category, level)); + return (0); +} + +void +ns_debug(int category, int level, const char *format, ...) { + va_list args; + + if (!log_ctx_valid) + return; + va_start(args, format); + log_vwrite(log_ctx, category, log_debug(level), format, args); + va_end(args); +} + +void +ns_info(int category, const char *format, ...) { + va_list args; + + if (!log_ctx_valid) + return; + va_start(args, format); + log_vwrite(log_ctx, category, log_info, format, args); + va_end(args); +} + +void +ns_notice(int category, const char *format, ...) { + va_list args; + + if (!log_ctx_valid) + return; + va_start(args, format); + log_vwrite(log_ctx, category, log_notice, format, args); + va_end(args); +} + +void +ns_warning(int category, const char *format, ...) { + va_list args; + + if (!log_ctx_valid) + return; + va_start(args, format); + log_vwrite(log_ctx, category, log_warning, format, args); + va_end(args); +} + +void +ns_error(int category, const char *format, ...) { + va_list args; + + if (!log_ctx_valid) + return; + va_start(args, format); + log_vwrite(log_ctx, category, log_error, format, args); + va_end(args); +} + +void +ns_critical(int category, const char *format, ...) { + va_list args; + + if (!log_ctx_valid) + return; + va_start(args, format); + log_vwrite(log_ctx, category, log_critical, format, args); + va_end(args); +} + +void +ns_panic(int category, int dump_core, const char *format, ...) { + va_list args; + + if (!log_ctx_valid) + return; + va_start(args, format); + log_vwrite(log_ctx, category, log_critical, format, args); + va_end(args); + va_start(args, format); + log_vwrite(log_ctx, ns_log_panic, log_critical, format, args); + va_end(args); + if (dump_core) + abort(); + else + exit(1); +} + +void +ns_assertion_failed(const char *file, int line, assertion_type type, + const char *cond, int print_errno) +{ + ns_panic(ns_log_insist, 1, "%s:%d: %s(%s)%s%s failed.", + file, line, assertion_type_to_text(type), cond, + (print_errno) ? ": " : "", + (print_errno) ? strerror(errno) : ""); +} + +/* + * XXX This is for compatibility and should eventually be removed. + */ +void +panic(const char *msg, const void *arg) { + ns_panic(ns_log_default, 1, msg, arg); +} + +/* + * How many labels in this name? + * Note: the root label is not included in the count. + */ +int +nlabels(const char *dname) { + int count, i, found, escaped; + const char *tmpdname, *end_tmpdname; + int tmpdnamelen, c; + + INSIST(dname != NULL); + + count = 0; + tmpdname = dname; + tmpdnamelen = strlen(tmpdname); + /* + * Ignore a trailing label separator (i.e. an unescaped dot) + * in 'tmpdname'. + */ + if (tmpdnamelen && tmpdname[tmpdnamelen-1] == '.') { + escaped = 0; + /* note this loop doesn't get executed if tmpdnamelen==1 */ + for (i = tmpdnamelen - 2; i >= 0; i--) + if (tmpdname[i] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else + break; + if (!escaped) + tmpdnamelen--; + } + + end_tmpdname = tmpdname + tmpdnamelen; + + while(tmpdname != end_tmpdname) { + count++; + /* + * Strip off the first label if we're not already at + * the root label. + */ + for (escaped = found = 0; + (tmpdname != end_tmpdname) && !found; + tmpdname++) { + c = *tmpdname; + if (!escaped && (c == '.')) + found = 1; + + if (escaped) + escaped = 0; + else if (c == '\\') + escaped = 1; + } + } + + ns_debug(ns_log_default, 12, "nlabels of \"%s\" -> %d", dname, count); + return (count); +} + +/* + * Get current system time and put it in a global. + */ +void +gettime(struct timeval *ttp) { + if (gettimeofday(ttp, NULL) < 0) + ns_error(ns_log_default, "gettimeofday: %s", strerror(errno)); +} + +/* + * This is useful for tracking down lost file descriptors. + */ +int +my_close(int fd) { + int s; + + do { + errno = 0; + s = close(fd); + } while (s < 0 && errno == EINTR); + + /* + * Tru64 UNIX V5.1 can return a spurious EINVAL after connect() + * failures. + */ + if (s < 0 && errno != EBADF && errno != EINVAL) + ns_info(ns_log_default, "close(%d) failed: %s", fd, + strerror(errno)); + else + ns_debug(ns_log_default, 3, "close(%d) succeeded", fd); + return (s); +} + +/* + * This is useful for tracking down lost file descriptors. + */ +int +my_fclose(FILE *fp) { + int fd = fileno(fp), + s = fclose(fp); + + if (s < 0) + ns_info(ns_log_default, "fclose(%d) failed: %s", fd, + strerror(errno)); + else + ns_debug(ns_log_default, 3, "fclose(%d) succeeded", fd); + return (s); +} + +/* + * Save a counted buffer and return a pointer to it. + */ +u_char * +savebuf(const u_char *buf, size_t len, int needpanic) { + u_char *bp = (u_char *)memget(len); + + if (bp == NULL) { + if (needpanic) + panic("savebuf: memget failed (%s)", strerror(errno)); + else + return (NULL); + } + memcpy(bp, buf, len); + return (bp); +} + +char * +__newstr(size_t len, int needpanic) { + return (__newstr_record(len, needpanic, __FILE__, __LINE__)); +} + +char * +__savestr(const char *str, int needpanic) { + return (__savestr_record(str, needpanic, __FILE__, __LINE__)); +} + +void * +__freestr(char *str) { + __freestr_record(str, __FILE__, __LINE__); + return (NULL); +} + +#ifdef DEBUG_STRINGS +char * +debug_newstr(size_t len, int needpanic, const char *file, int line) { + size_t size; + + size = len + 3; /* 2 length bytes + NUL. */ + printf("%s:%d: newstr %d\n", file, line, size); + return (__newstr_record(len, needpanic, file, line)); +} + +char * +debug_savestr(const char *str, int needpanic, const char *file, int line) { + size_t len; + + len = strlen(str); + len += 3; /* 2 length bytes + NUL. */ + printf("%s:%d: savestr %d %s\n", file, line, len, str); + return (__savestr_record(str, needpanic, file, line)); +} + +void +debug_freestr(char *str, const char *file, int line) { + u_char *buf, *bp; + size_t len; + + buf = (u_char *)str - 2/*Len*/; + bp = buf; + NS_GET16(len, bp); + len += 3; /* 2 length bytes + NUL. */ + printf("%s:%d: freestr %d %s\n", file, line, len, str); + __freestr_record(str, file, line); + return (NULL); +} +#endif /* DEBUG_STRINGS */ + +/* + * Return a counted string buffer big enough for a string of length 'len'. + */ +char * +__newstr_record(size_t len, int needpanic, const char *file, int line) { + u_char *buf, *bp; + + REQUIRE(len <= 65536); + + buf = (u_char *)__memget_record(2/*Len*/ + len + 1/*Nul*/, file, line); + if (buf == NULL) { + if (needpanic) + panic("savestr: memget failed (%s)", strerror(errno)); + else + return (NULL); + } + bp = buf; + NS_PUT16(len, bp); + return ((char *)bp); +} + +/* + * Save a NUL terminated string and return a pointer to it. + */ +char * +__savestr_record(const char *str, int needpanic, const char *file, int line) { + char *buf; + size_t len; + + len = strlen(str); + if (len > 65536) { + if (needpanic) + ns_panic(ns_log_default, 1, + "savestr: string too long"); + else + return (NULL); + } + buf = __newstr_record(len, needpanic, file, line); + memcpy(buf, str, len + 1); + return (buf); +} + +void * +__freestr_record(char *str, const char *file, int line) { + u_char *buf, *bp; + size_t len; + + buf = (u_char *)str - 2/*Len*/; + bp = buf; + NS_GET16(len, bp); + __memput_record(buf, 2/*Len*/ + len + 1/*Nul*/, file, line); + return (NULL); +} + +const char * +checked_ctime(const time_t *t) { + const char *ctime_result; + + ctime_result = ctime(t); + if (ctime_result == NULL) { + ns_error(ns_log_default, "ctime() returned NULL!"); + ctime_result = "\n"; + } + + return (ctime_result); +} + +/* + * Since the fields in a "struct timeval" are longs, and the argument to ctime + * is a pointer to a time_t (which might not be a long), here's a bridge. + */ +const char * +ctimel(long l) { + time_t t = (time_t)l; + + return (checked_ctime(&t)); +} + +#ifdef ultrix +/* + * Some library routines in libc need to be able to see the res_send + * and res_close symbols with out __ prefix otherwise we get multiply + * defined symbol errors when linking named. + */ + +#undef res_send +int res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) { + return __res_send(buf, buflen, ans, anssiz); +} +#undef _res_close +void _res_close(void) { + __res_close(); +} +#endif Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_glue.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_init.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_init.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_init.c (revision 109985) @@ -0,0 +1,590 @@ +#if !defined(lint) && !defined(SABER) +static const char sccsid[] = "@(#)ns_init.c 4.38 (Berkeley) 3/21/91"; +static const char rcsid[] = "$Id: ns_init.c,v 8.76 2001/12/19 01:41:51 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986, 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "port_after.h" + +#include "named.h" + +#ifdef DEBUG +static void content_zone(int, int); +#endif + +/* + * Set new refresh time for zone. Use a random number in the last half of + * the refresh limit; we want it to be substantially correct while still + * preventing slave synchronization. + */ +void +ns_refreshtime(struct zoneinfo *zp, time_t timebase) { + u_long refresh = (zp->z_refresh > 0) ? zp->z_refresh : INIT_REFRESH; + time_t half = (refresh + 1) / 2; + + if (zp->z_flags & Z_NEEDREFRESH) { + zp->z_flags &= ~Z_NEEDREFRESH; + zp->z_time = timebase; + } else + zp->z_time = timebase + half + (rand() % half); +} + +/* + * Set new retry time for zone. + */ +void +ns_retrytime(struct zoneinfo *zp, time_t timebase) { + + zp->z_flags &= ~Z_NEEDREFRESH; + zp->z_time = timebase + zp->z_retry; +} + +/* + * Read configuration file and save it as internal state. + */ +time_t +ns_init(const char *conffile) { + struct zoneinfo *zp; + static int loads = 0; /* number of times loaded */ + time_t mtime; + + ns_debug(ns_log_config, 1, "ns_init(%s)", conffile); + gettime(&tt); + + if (loads == 0) { + /* Init zone data. */ + zones = NULL; + INIT_LIST(freezones); + INIT_LIST(reloadingzones); + nzones = 0; + make_new_zones(); + + /* Init cache. */ + zones[0].z_type = z_cache; + zones[0].z_origin = savestr("", 1); + + /* 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); + + /* Init other misc stuff. */ + dst_init(); + init_configuration(); + } else { + /* Mark previous zones as not yet found in boot file. */ + block_signals(); + for (zp = &zones[1]; zp < &zones[nzones]; zp++) + if (zp->z_type != z_nil) { + zp->z_flags &= ~Z_FOUND; + if (LINKED(zp, z_reloadlink)) + UNLINK(reloadingzones, zp, + z_reloadlink); + } + unblock_signals(); + } + +#ifdef DEBUG + if (debug >= 3) { + ns_debug(ns_log_config, 3, "content of zones before loading"); + content_zone(nzones - 1, 3); + } +#endif + + mtime = load_configuration(conffile); + + /* Erase all old zones that were not found. */ + for (zp = &zones[0]; zp < &zones[nzones]; zp++) { + if (zp->z_type == z_cache) + continue; + if (zp->z_type != z_nil && (zp->z_flags & Z_FOUND) == 0) + remove_zone(zp, "removed"); + } + /* Reload parent zones of zones removed */ + for (zp = &zones[0]; zp < &zones[nzones]; zp++) { + if (zp->z_type == z_cache) + continue; + if (zp->z_type != z_nil && + (zp->z_flags & Z_PARENT_RELOAD) != 0) { + zp->z_flags &= ~Z_PARENT_RELOAD; + purgeandload(zp); + } + } + +#ifdef DEBUG + if (debug >= 2) { + ns_debug(ns_log_config, 2, "content of zones after loading"); + content_zone(nzones-1, 2); + } +#endif + + ns_debug(ns_log_config, 1, "exit ns_init()"); + loads++; + return (mtime); +} + +void +zoneinit(struct zoneinfo *zp) { + struct stat sb; + int result; + + /* + * 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 + * immediately. + */ + if (zp->z_source == NULL) + return; + result = stat(zp->z_source, &sb); + if (result != -1) { + ns_stopxfrs(zp); + purge_zone(zp->z_origin, hashtab, zp->z_class); + } + if (result == -1 || + db_load(zp->z_source, zp->z_origin, zp, NULL, ISNOTIXFR)) + { + /* + * Set zone to be refreshed immediately. + */ + zp->z_refresh = INIT_REFRESH; + zp->z_retry = INIT_REFRESH; + if ((zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING)) == 0) { + zp->z_time = tt.tv_sec; + sched_zone_maint(zp); + } + } else { + zp->z_flags |= Z_AUTH; + zp->z_flags &= ~(Z_NEED_RELOAD|Z_EXPIRED); + ns_refreshtime(zp, tt.tv_sec); + sched_zone_maint(zp); + } +} + +/* + * Purge the zone and reload all parent zones. This needs to be done when + * we unload a zone, since the child zone will have stomped the parent's + * delegation to that child when it was first loaded. + */ +void +do_reload(const char *domain, int type, int class, int mark) { + struct zoneinfo *zp; + + ns_debug(ns_log_config, 1, "do_reload: %s %d %d %d", + *domain ? domain : ".", type, class, mark); + + /* + * Check if the zone has changed type. If so, we might not need to + * do any purging or parent reloading. + * + * If the new zone is a master zone, then it will have purged the + * old data and loaded, so we don't need to do anything. + * + * If the new zone is a slave or stub zone and has successfully loaded, + * then we don't need to do anything either. + * + * NOTE: we take care not to match ourselves. + */ + zp = find_zone(domain, class); + if (zp != NULL && + ((type != z_master && zp->z_type == z_master) || + (type != z_slave && zp->z_type == z_slave && zp->z_serial != 0) || + (type != z_stub && zp->z_type == z_stub && zp->z_serial != 0))) + return; + + /* + * Clean up any leftover data. + */ + ns_stopxfrs(zp); + if (type == z_hint || (type == z_stub && *domain == 0)) + purge_zone(domain, fcachetab, class); + else + purge_zone(domain, hashtab, class); + + /* + * Reload + */ + while (*domain) { + const char *s; + int escaped; + + /* + * XXX this is presentation level hair and belongs elsewhere. + */ + escaped = 0; + for (s = domain; *s != '\0'; s++) { + if (!escaped) { + if (*s == '.') + break; + else if (*s == '\\') + escaped = 1; + } else + escaped = 0; + } + + if (*s != '\0') + domain = s + 1; /* skip label and its separator */ + else + domain = ""; /* root zone */ + + zp = find_zone(domain, class); + if (zp != NULL) { + ns_debug(ns_log_config, 1, "do_reload: matched %s", + *domain ? domain : "."); + if (mark) + zp->z_flags |= Z_PARENT_RELOAD; + else + purgeandload(zp); + break; + } + } +} + +void +purgeandload(struct zoneinfo *zp) { + +#ifdef BIND_UPDATE + /* + * A dynamic zone might have changed, so we + * need to dump it before removing it. + */ + if (zp->z_type == Z_PRIMARY && + (zp->z_flags & Z_DYNAMIC) != 0 && + ((zp->z_flags & Z_NEED_SOAUPDATE) != 0 || + (zp->z_flags & Z_NEED_DUMP) != 0)) + (void) zonedump(zp, ISNOTIXFR); +#endif + ns_stopxfrs(zp); + + if (zp->z_type == Z_HINT) + purge_zone(zp->z_origin, fcachetab, zp->z_class); + else + purge_zone(zp->z_origin, hashtab, zp->z_class); + + zp->z_flags &= ~Z_AUTH; + + switch (zp->z_type) { + case Z_SECONDARY: + case Z_STUB: + zoneinit(zp); + break; + case Z_PRIMARY: + if (db_load(zp->z_source, zp->z_origin, zp, 0, ISNOTIXFR) == 0) + zp->z_flags |= Z_AUTH; + break; + case Z_HINT: + case Z_CACHE: + (void)db_load(zp->z_source, zp->z_origin, zp, 0, ISNOTIXFR); + break; + } +} + +#ifdef DEBUG +/* prints out the content of zones */ +static void +content_zone(int end, int level) { + int i; + + for (i = 0; i <= end; i++) { + printzoneinfo(i, ns_log_config, level); + } +} +#endif + +enum context +ns_ptrcontext(owner) + const char *owner; +{ + if (ns_samedomain(owner, "in-addr.arpa") || + ns_samedomain(owner, "ip6.int")) + return (hostname_ctx); + return (domain_ctx); +} + +enum context +ns_ownercontext(type, transport) + int type; + enum transport transport; +{ + enum context context = domain_ctx; + + switch (type) { + case T_A: + case T_WKS: + case T_MX: + switch (transport) { + case update_trans: + case primary_trans: + case secondary_trans: + context = owner_ctx; + break; + case response_trans: + context = hostname_ctx; + break; + default: + panic("impossible condition in ns_ownercontext()", + NULL); + } + break; + case T_MB: + case T_MG: + context = mailname_ctx; + break; + default: + /* Nothing to do. */ + break; + } + return (context); +} + +int +ns_nameok(const struct qinfo *qry, const char *name, int class, + struct zoneinfo *zp, enum transport transport, + enum context context, + const char *owner, + struct in_addr source) +{ + enum severity severity = not_set; + int ok = 1; + + if (zp != NULL) + severity = zp->z_checknames; + if (severity == not_set) + severity = server_options->check_names[transport]; + + if (severity == ignore) + return (1); + switch (context) { + case domain_ctx: + ok = (class != C_IN) || res_dnok(name); + break; + case owner_ctx: + ok = (class != C_IN) || res_ownok(name); + break; + case mailname_ctx: + ok = res_mailok(name); + break; + case hostname_ctx: + ok = res_hnok(name); + break; + default: + ns_panic(ns_log_default, 1, + "unexpected context %d in ns_nameok", (int)context); + } + if (!ok) { + char *q, *s, *o; + + if (source.s_addr == INADDR_ANY) + s = savestr(transport_strings[transport], 0); + else { + s = newstr(strlen(transport_strings[transport]) + + sizeof " from [000.000.000.000] for [000.000.000.000]", 0); + if (s != NULL) { + if (transport == response_trans && qry != NULL) { + if ((qry->q_flags & Q_PRIMING) != 0) { + sprintf(s, "%s from [%s] for priming", + transport_strings[transport], + inet_ntoa(source)); + } else if ((qry->q_flags & Q_ZSERIAL) != 0) { + sprintf(s, "%s from [%s] for soacheck", + transport_strings[transport], + inet_ntoa(source)); + } else if ((qry->q_flags & Q_SYSTEM) != 0) { + sprintf(s, "%s from [%s] for sysquery", + transport_strings[transport], + inet_ntoa(source)); + } else { + q=strdup(inet_ntoa(qry->q_from.sin_addr)); + sprintf(s, "%s from [%s] for [%s]", + transport_strings[transport], + inet_ntoa(source), + q != NULL ? q : "memget failed"); + free(q); + } + } else { + sprintf(s, "%s from [%s]", + (transport == response_trans) + ? "query" + : transport_strings[transport], + inet_ntoa(source)); + } + } + } + if (ns_samename(owner, name) == 1) + o = savestr("", 0); + else { + const char *t = (*owner == '\0') ? "." : owner; + + o = newstr(strlen(t) + sizeof " (owner \"\")", 0); + if (o) + sprintf(o, " (owner \"%s\")", t); + } + /* + * We use log_write directly here to avoid duplicating + * the message formatting and arguments. + */ + log_write(log_ctx, ns_log_default, + (transport != response_trans) || + (o == NULL) || (s == NULL) || + ( (qry != NULL) && + (qry->q_flags & (Q_PRIMING|Q_ZSERIAL)) ) ? + log_warning : log_info, + "%s name \"%s\"%s %s (%s) is invalid - %s", + context_strings[context], + name, o != NULL ? o : "[memget failed]", + p_class(class), + s != NULL ? s : "[memget failed]", + (severity == fail) ? + "rejecting" : "proceeding anyway"); + if (severity == warn) + ok = 1; + if (s != NULL) + (void)freestr(s); + if (o != NULL) + (void)freestr(o); + } + return (ok); +} + +int +ns_wildcard(const char *name) { + if (*name != '*') + return (0); + return (*++name == '\0'); +} + +void +ns_shutdown() { + struct zoneinfo *zp; + +#ifdef BIND_NOTIFY + ns_unnotify(); +#endif + /* Erase zones. */ + for (zp = &zones[0]; zp < &zones[nzones]; zp++) { + if (zp->z_type) { + if (zp->z_type != z_hint && zp->z_type != z_cache) { + ns_stopxfrs(zp); + purge_zone(zp->z_origin, hashtab, zp->z_class); + } else if (zp->z_type == z_hint) + purge_zone(zp->z_origin, fcachetab, + zp->z_class); + free_zone_contents(zp, 1); + } + } + + /* Erase the cache. */ + clean_cache(hashtab, 1); + hashtab->h_cnt = 0; /* ??? */ + rm_hash(hashtab); + hashtab = NULL; + clean_cache(fcachetab, 1); + fcachetab->h_cnt = 0; /* ??? */ + rm_hash(fcachetab); + fcachetab = NULL; + + if (zones != NULL) + memput(zones, nzones * sizeof *zones); + zones = NULL; + + freeComplaints(); + shutdown_configuration(); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_init.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_lexer.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_lexer.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_lexer.h (revision 109985) @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#ifndef _NS_LEXER_H +#define _NS_LEXER_H + +/* + * Note: and "ns_parseutil.h" must be included + * before this file is included. + */ + +#define LEX_MAX_IDENT_SIZE 1024 + +#define SYM_CLASS 0x01 +#define SYM_CATEGORY 0x02 +#define SYM_LOGGING 0x04 +#define SYM_SYSLOG 0x08 + +int parser_warning(int, const char *, ...) ISC_FORMAT_PRINTF(2, 3); +int parser_error(int, const char *, ...) ISC_FORMAT_PRINTF(2, 3); +void yyerror(const char *); +void lexer_begin_file(const char *, FILE *); +void lexer_end_file(void); +int yylex(void); +void lexer_initialize(void); +void lexer_setup(void); +void lexer_shutdown(void); + +extern symbol_table constants; + +#endif /* !_NS_LEXER_H */ Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_lexer.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_parseutil.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_parseutil.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_parseutil.c (revision 109985) @@ -0,0 +1,243 @@ +/* + * Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* Global C stuff goes here. */ + + +#include "port_before.h" + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "port_after.h" + +#include "named.h" +#include "ns_parseutil.h" + + +/* + * Symbol Table + */ + +symbol_table +new_symbol_table(int size_guess, free_function free_value) { + symbol_table st; + + st = (symbol_table)memget(sizeof (struct symbol_table)); + if (st == NULL) + panic("memget failed in new_symbol_table()", NULL); + st->table = (symbol_entry *)memget(size_guess * sizeof *st->table); + if (st->table == NULL) + panic("memget failed in new_symbol_table()", NULL); + memset(st->table, 0, size_guess * sizeof (symbol_entry)); + st->size = size_guess; /* size_guess should be prime */ + st->free_value = free_value; + return (st); +} + +void +free_symbol(symbol_table st, symbol_entry ste) { + ste->key = freestr(ste->key); + if (ste->flags & SYMBOL_FREE_VALUE) + (st->free_value)(ste->type, ste->value.pointer); +} + +void +free_symbol_table(symbol_table st) { + int i; + symbol_entry ste, ste_next; + + for (i = 0; i < st->size; i++) { + for (ste = st->table[i]; ste != NULL; ste = ste_next) { + ste_next = ste->next; + free_symbol(st, ste); + memput(ste, sizeof *ste); + } + } + memput(st->table, st->size * sizeof (symbol_entry)); + memput(st, sizeof *st); +} + +void +dprint_symbol_table(int level, symbol_table st) { + int i; + symbol_entry ste; + + for (i = 0; i < st->size; i++) { + for (ste = st->table[i]; ste != NULL; ste = ste->next) + ns_debug(ns_log_parser, level, + "%7d: (%s: %d %p/%d %04x) ", + i, ste->key, ste->type, ste->value.pointer, + ste->value.integer, ste->flags); + } +} + +/* + * P. J. Weinberger's hash function, adapted from p. 436 of + * _Compilers: Principles, Techniques, and Tools_, Aho, Sethi + * and Ullman, Addison-Wesley, 1986, ISBN 0-201-10088-6. + */ +static int +symbol_hash(const char *key, int prime) { + const char *s; + unsigned int h = 0; + unsigned int g; + int c; + + for (s = key; *s != '\0'; s++) { + c = *s; + if (isascii(c) && isupper(c)) + c = tolower(c); + h = ( h << 4 ) + c; + if ((g = ( h & 0xf0000000 )) != 0) { + h = h ^ (g >> 24); + h = h ^ g; + } + } + return (h % prime); +} + +int +lookup_symbol(symbol_table st, const char *key, int type, + symbol_value *value) { + int hash; + symbol_entry ste; + + hash = symbol_hash(key, st->size); + for (ste = st->table[hash]; ste != NULL; ste = ste->next) + if ((type == 0 || ste->type == type) && + strcasecmp(ste->key, key) == 0) + break; + if (ste != NULL) { + if (value != NULL) + *value = ste->value; + return (1); + } + return (0); +} + +void +define_symbol(symbol_table st, const char *key, int type, symbol_value value, + unsigned int flags) { + int hash; + symbol_entry ste; + + hash = symbol_hash(key, st->size); + for (ste = st->table[hash]; ste != NULL; ste = ste->next) + if ((type == 0 || ste->type == type) && + strcasecmp(ste->key, key) == 0) + break; + if (ste == NULL) { + ste = (symbol_entry)memget(sizeof *ste); + if (ste == NULL) + panic("memget failed in define_symbol()", NULL); + ste->key = savestr(key, 1); + ste->type = type; + ste->value = value; + ste->flags = flags; + ste->next = st->table[hash]; + st->table[hash] = ste; + } else { + ns_debug(ns_log_parser, 7, "redefined symbol %s type %d", + key, type); + free_symbol(st, ste); + ste->key = savestr(key, 1); + ste->value = value; + ste->flags = flags; + } +} + +void +undefine_symbol(symbol_table st, char *key, int type) { + int hash; + symbol_entry prev_ste, ste; + + hash = symbol_hash(key, st->size); + for (prev_ste = NULL, ste = st->table[hash]; + ste != NULL; + prev_ste = ste, ste = ste->next) + if ((type == 0 || ste->type == type) && + strcasecmp(ste->key, key) == 0) + break; + if (ste != NULL) { + free_symbol(st, ste); + if (prev_ste != NULL) + prev_ste->next = ste->next; + else + st->table[hash] = ste->next; + memput(ste, sizeof *ste); + } +} + +/* + * Conversion Routines + */ + +int +unit_to_ulong(char *in, u_long *out) { + int c, units_done = 0; + u_long result = 0L; + + INSIST(in != NULL); + + for (; (c = *in) != '\0'; in++) { + if (units_done) + return (0); + if (isdigit(c)) { + result *= 10; + result += (c - '0'); + } else { + switch (c) { + case 'k': + case 'K': + result *= 1024; + units_done = 1; + break; + case 'm': + case 'M': + result *= (1024*1024); + units_done = 1; + break; + case 'g': + case 'G': + result *= (1024*1024*1024); + units_done = 1; + break; + default: + return (0); + } + } + } + + *out = result; + return (1); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_parseutil.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_parseutil.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_parseutil.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_parseutil.h (revision 109985) @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#ifndef _NS_PARSEUTIL_H +#define _NS_PARSEUTIL_H + +/* + * Symbol Table + */ + +#define SYMBOL_FREE_VALUE 0x02 + +typedef union symbol_value { + void *pointer; + int integer; +} symbol_value; + +typedef void (*free_function)(int, void *); + +typedef struct symbol_entry { + char *key; + int type; + symbol_value value; + unsigned int flags; + struct symbol_entry *next; +} *symbol_entry; + +typedef struct symbol_table { + int size; + symbol_entry *table; + free_function free_value; +} *symbol_table; + +symbol_table new_symbol_table(int, free_function); +void free_symbol(symbol_table, symbol_entry); +void free_symbol_table(symbol_table); +void dprint_symbol_table(int, symbol_table); +int lookup_symbol(symbol_table, const char *, int, + symbol_value *); +void define_symbol(symbol_table, const char *, int, + symbol_value, unsigned int); +void undefine_symbol(symbol_table, char *, int type); + +/* + * Conversion Routines + */ + +int unit_to_ulong(char *, u_long *); + +#endif /* !_NS_PARSEUTIL_H */ Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_parseutil.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_sort.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_sort.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_sort.c (revision 109985) @@ -0,0 +1,414 @@ +#if !defined(lint) && !defined(SABER) +static const char sccsid[] = "@(#)ns_sort.c 4.10 (Berkeley) 3/3/91"; +static const char rcsid[] = "$Id: ns_sort.c,v 8.8 2001/09/25 04:50:22 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986, 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * Sorting should really be handled by the resolver, but: + * 1) There are too many brain dead resolvers out there that can't be replaced. + * 2) It would be a pain to individually configure all those resolvers anyway. + * + * Here's the scoop: + * + * To enable address sorting in responses, you need to supply the sortlist + * statement in the config file. The sortlist statement takes an + * address match list and interprets it even more specially than the + * topology statement does. + * + * Each top level statement in the sortlist must itself be an explicit + * address match list with one or two elements. The first element + * (which may be an IP address, an IP prefix, an ACL name or nested + * address match list) of each top level list is checked against the + * source address of the query until a match is found. + * + * Once the source address of the query has been matched, if the top level + * statement contains only one element, the actual primitive element that + * matched the source address is used to select the address in the response + * to move to the beginning of the response. If the statement is a list + * of two elements, then the second element is treated like the address + * match list in a topology statement. Each top level element is assigned + * a distance and the address in the response with the minimum distance is + * moved to the beginning of the response. + * + * In the following example, any queries received from any of the addresses + * of the host itself will get responses preferring addresses on any of + * the locally connected networks. Next most preferred are addresses on + * the 192.168.1/24 network, and after that either the 192.168.2/24 or + * 192.168.3/24 network with no preference shown between these two networks. + * Queries received from a host on the 192.168.1/24 network will prefer + * other addresses on that network to the 192.168.2/24 and 192.168.3/24 + * networks. Queries received from a host on the 192.168.4/24 or the + * 192.168.5/24 network will only prefer other addresses on their + * directly connected networks. + * + * sortlist { + * { + * localhost; + * { + * localnets; + * 192.168.1/24; + * { 192,168.2/24; 192.168.3/24; }; + * }; + * }; + * { + * 192.168.1/24; + * { + * 192.168.1/24; + * { 192.168.2/24; 192.168.3/24; }; + * }; + * }; + * { + * 192.168.2/24; + * { + * 192.168.2/24; + * { 192.168.1/24; 192.168.3/24; }; + * }; + * }; + * { + * 192.168.3/24; + * { + * 192.168.3/24; + * { 192.168.1/24; 192.168.2/24; }; + * }; + * }; + * { + * { 192.168.4/24; 192.168.5/24; }; + * }; + * }; + * + * + * The following example will give reasonable behaviour for the local host + * and hosts on directly connected networks. It is similar to the behavior + * of the address sort in BIND 4.9.x. Responses sent to queries from the + * local host will favor any of the directly connected networks. Responses + * sent to queries from any other hosts on a directly connected network will + * prefer addresses on that same network. Responses to other queries will + * not be sorted. + * + * sortlist { + * { localhost; localnets; }; + * { localnets; }; + * }; + * + * XXX - it wouldb e nice to have an ACL called "source" that matched the + * source address of a query so that a host could be configured to + * automatically prefer itself, and an ACL called "sourcenet", that + * would return the primitive IP match element that matched the source + * address so that you could do: + * { localnets; { sourcenet; { other stuff ...}; }; + * and automatically get similar behaviour to what you get with: + * { localnets; }; + * + */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "named.h" + +static int sort_rr(u_char *cp, u_char *eom, int ancount, ip_match_list iml); + +static int ip_match_address_elt(ip_match_list, struct in_addr, + ip_match_element *); + +void +sort_response(u_char *cp, u_char *eom, int ancount, struct sockaddr_in *from) { + struct in_addr address; + struct ip_match_element imelement; + ip_match_element imetl, imematch, imeprimitive; + struct ip_match_list imlist; + ip_match_list iml; + int indirect, matched; + + if (server_options->sortlist == NULL) + return; + + if (from->sin_family != AF_INET) + return; + + address = from->sin_addr; + + for (imetl = server_options->sortlist->first; imetl != NULL; + imetl = imetl->next) { + if (imetl->type == ip_match_indirect) + imematch = imetl->u.indirect.list->first; + else + /* + * allow a bare pattern as a top level statement + * and treat it like {pattern;}; + */ + imematch = imetl; + + switch (imematch->type) { + case ip_match_pattern: + indirect = 0; + break; + case ip_match_indirect: + indirect = 1; + break; + case ip_match_localhost: + imematch->u.indirect.list = local_addresses; + indirect = 1; + break; + case ip_match_localnets: + imematch->u.indirect.list = local_networks; + indirect = 1; + break; + default: + indirect = 0; + panic("unexpected ime type in ip_match_address()", + NULL); + } + if (indirect) { + imeprimitive = NULL; + matched = ip_match_address_elt(imematch->u.indirect.list, + address, &imeprimitive); + if (matched >= 0) { + if (imematch->flags & IP_MATCH_NEGATE) + /* Don't sort */ + return; + } else + continue; + } else { + if (ina_onnet(address, imematch->u.direct.address, + imematch->u.direct.mask)) { + if (imematch->flags & IP_MATCH_NEGATE) + /* Don't sort */ + return; + else + imeprimitive = imematch; + } else + continue; + } + if (imetl != imematch && imematch->next != NULL) { + /* + * Not a bare pattern at the top level, but a two + * element list + */ + switch (imematch->next->type) { + case ip_match_pattern: + case ip_match_localhost: + case ip_match_localnets: + imelement = *(imematch->next); + imelement.next = NULL; + iml = &imlist; + iml->first = iml->last = &imelement; + break; + case ip_match_indirect: + iml = imematch->next->u.indirect.list; + break; + default: + iml = NULL; + panic("unexpected ime type in ip_match_address()", + NULL); + } + } else if (imeprimitive) { + imelement = *imeprimitive; + imelement.next = NULL; + iml = &imlist; + iml->first = iml->last = &imelement; + } else { + /* Don't sort because we'd just use "any" */ + return; + } + sort_rr(cp, eom, ancount, iml); + break; + } + + return; +} + +static int +sort_rr(u_char *cp, u_char *eom, int ancount, ip_match_list iml) { + int type, class, dlen, n, c, distance, closest = 0; + struct in_addr inaddr; + u_char *rr1 = NULL, *rrbest = NULL, *cpstart; + + rr1 = NULL; + cpstart = cp; + for (c = ancount; c > 0; --c) { + n = dn_skipname(cp, eom); + if (n < 0) + return (1); /* bogus, stop processing */ + cp += n; + if (cp + QFIXEDSZ > eom) + return (1); + GETSHORT(type, cp); + GETSHORT(class, cp); + cp += INT32SZ; + GETSHORT(dlen, cp); + if (dlen > eom - cp) + return (1); /* bogus, stop processing */ + switch (type) { + case T_A: + switch (class) { + case C_IN: + case C_HS: + memcpy((char *)&inaddr, cp, INADDRSZ); + /* Find the address with the minimum distance */ + if (rr1 == NULL) { + rr1 = cp; + rrbest = cp; + closest = distance_of_address(iml, inaddr); + } else { + distance = distance_of_address(iml, inaddr); + if (distance < closest) { + rrbest = cp; + closest = distance; + } + } + break; + } + break; + } + cp += dlen; + } + if (rr1 != rrbest && rr1 != NULL) { + memcpy((char *)&inaddr, rrbest, INADDRSZ); + memcpy(rrbest, rr1, INADDRSZ); + memcpy(rr1, (char *)&inaddr, INADDRSZ); + } + return (0); +} + +/* + * Just like ip_match_address(), but also returns a pointer to the primitive + * element that matched. + */ + +static int +ip_match_address_elt(ip_match_list iml, struct in_addr address, + ip_match_element *imep) { + ip_match_element ime; + int ret; + int indirect; + + INSIST(iml != NULL); + for (ime = iml->first; ime != NULL; ime = ime->next) { + switch (ime->type) { + case ip_match_pattern: + indirect = 0; + break; + case ip_match_indirect: + indirect = 1; + break; + case ip_match_localhost: + ime->u.indirect.list = local_addresses; + indirect = 1; + break; + case ip_match_localnets: + ime->u.indirect.list = local_networks; + indirect = 1; + break; + default: + indirect = 0; + panic("unexpected ime type in ip_match_address()", + NULL); + } + if (indirect) { + ret = ip_match_address_elt(ime->u.indirect.list, + address, imep); + if (ret >= 0) { + if (ime->flags & IP_MATCH_NEGATE) + ret = (ret) ? 0 : 1; + return (ret); + } + } else { + if (ina_onnet(address, ime->u.direct.address, + ime->u.direct.mask)) { + *imep = ime; + if (ime->flags & IP_MATCH_NEGATE) + return (0); + else + return (1); + } + } + } + return (-1); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_sort.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_stats.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_stats.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_stats.c (revision 109985) @@ -0,0 +1,452 @@ +#if !defined(lint) && !defined(SABER) +static const char sccsid[] = "@(#)ns_stats.c 4.10 (Berkeley) 6/27/90"; +static const char rcsid[] = "$Id: ns_stats.c,v 8.34 2001/08/09 13:17:21 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef HAVE_GETRUSAGE /* XXX */ +#include +#include +#endif + +#include "named.h" + +static u_long typestats[T_ANY+1]; +static void nameserStats(FILE *); +static u_int32_t ns_stats_cnt = 0; +static int ns_stats_disabled = 0; + +void +ns_stats_dumpandclear() { + time_t timenow = time(NULL); + FILE *f; + + ns_stats(); + if (!(f = fopen(server_options->stats_filename, "a"))) { + ns_notice(ns_log_statistics, "cannot open stat file, \"%s\"", + server_options->stats_filename); + } + if (f != NULL) { + (void) fchown(fileno(f), user_id, group_id); + fprintf(f, "+++ Host Statistics Cleared +++ (%ld) %s", + (long)timenow, checked_ctime(&timenow)); + (void) my_fclose(f); + } + ns_freestats(); +} + +void +ns_stats() { + time_t timenow = time(NULL); + FILE *f; + int i; + + ns_notice(ns_log_statistics, "dumping nameserver stats"); + + if (!(f = fopen(server_options->stats_filename, "a"))) { + ns_notice(ns_log_statistics, "cannot open stat file, \"%s\"", + server_options->stats_filename); + return; + } + (void) fchown(fileno(f), user_id, group_id); + + fprintf(f, "+++ Statistics Dump +++ (%ld) %s", + (long)timenow, checked_ctime(&timenow)); + fprintf(f, "%ld\ttime since boot (secs)\n", + (long)(timenow - boottime)); + fprintf(f, "%ld\ttime since reset (secs)\n", + (long)(timenow - resettime)); + + /* query type statistics */ + fprintf(f, "%lu\tUnknown query types\n", (u_long)typestats[0]); + for (i = 1; i < T_ANY+1; i++) + fprintf(f, "%lu\t%s queries\n", typestats[i], p_type(i)); + + /* name server statistics */ + nameserStats(f); + + fprintf(f, "--- Statistics Dump --- (%ld) %s", + (long)timenow, checked_ctime(&timenow)); + (void) my_fclose(f); + + /* Now do the memory statistics file */ + if (!(f = fopen(server_options->memstats_filename, "a"))) { + ns_notice(ns_log_statistics, "cannot open memstat file, \"%s\"", + server_options->memstats_filename); + return; + } + (void) fchown(fileno(f), user_id, group_id); + + fprintf(f, "+++ Memory Statistics Dump +++ (%ld) %s", + (long)timenow, checked_ctime(&timenow)); + + fprintf(f, "%ld\ttime since boot (secs)\n", + (long)(timenow - boottime)); + fprintf(f, "%ld\ttime since reset (secs)\n", + (long)(timenow - resettime)); + + fprintf(f, "++ Memory Statistics ++\n"); + memstats(f); + fprintf(f, "-- Memory Statistics --\n"); + + fprintf(f, "--- Memory Statistics Dump --- (%ld) %s", + (long)timenow, checked_ctime(&timenow)); + (void) my_fclose(f); + + ns_notice(ns_log_statistics, "done dumping nameserver stats"); +} + +void +qtypeIncr(qtype) + int qtype; +{ + if (qtype < T_A || qtype > T_ANY) + qtype = 0; /* bad type */ + typestats[qtype]++; +} + +static tree *nameserTree; +static int nameserInit; + +static FILE *nameserStatsFile; +static const char *statNames[nssLast] = { + "RR", /* sent us an answer */ + "RNXD", /* sent us a negative response */ + "RFwdR", /* sent us a response we had to fwd */ + "RDupR", /* sent us an extra answer */ + "RFail", /* sent us a SERVFAIL */ + "RFErr", /* sent us a FORMERR */ + "RErr", /* sent us some other error */ + "RAXFR", /* sent us an AXFR */ + "RLame", /* sent us a lame delegation */ + "ROpts", /* sent us some IP options */ + "SSysQ", /* sent them a sysquery */ + "SAns", /* sent them an answer */ + "SFwdQ", /* fwdd a query to them */ + "SDupQ", /* sent them a retry */ + "SErr", /* sent failed (in sendto) */ + "RQ", /* sent us a query */ + "RIQ", /* sent us an inverse query */ + "RFwdQ", /* sent us a query we had to fwd */ + "RDupQ", /* sent us a retry */ + "RTCP", /* sent us a query using TCP */ + "SFwdR", /* fwdd a response to them */ + "SFail", /* sent them a SERVFAIL */ + "SFErr", /* sent them a FORMERR */ + "SNaAns", /* sent them a non autoritative answer */ + "SNXD", /* sent them a negative response */ + "RUQ", /* sent us an unapproved query */ + "RURQ", /* sent us an unapproved recursive query */ + "RUXFR", /* sent us an unapproved AXFR or IXFR */ + "RUUpd", /* sent us an unapproved update */ + }; + +/* + * Note that addresses in network byte order always have the high byte first. + * XXX - this is horribly IPv4 dependent, but it's performance critical. + */ +static int +nameserCompar(const tree_t t1, const tree_t t2) { + u_char *p1 = (u_char *)t1, *p2 = (u_char *)t2; + int i; + + for (i = INADDRSZ; i > 0; i--) { + u_char c1 = *p1++, c2 = *p2++; + + if (c1 < c2) + return (-1); + if (c1 > c2) + return (1); + } + return (0); +} + +struct nameser * +nameserFind(addr, flags) + struct in_addr addr; + int flags; +{ + struct nameser dummy; + struct nameser *ns; + + if (!nameserInit) { + tree_init(&nameserTree); + nameserInit++; + ns_stats_cnt = 0; + ns_stats_disabled = 0; + } + + dummy.addr = addr; + ns = (struct nameser *)tree_srch(&nameserTree, nameserCompar, + (tree_t)&dummy); + if (ns == NULL && (flags & NS_F_INSERT) != 0) { + if (server_options->max_host_stats != 0 && + ns_stats_cnt > server_options->max_host_stats) { + if (!ns_stats_disabled) + ns_notice(ns_log_statistics, + "ns_stats_disabled: %s reached", + "host-statistics-max"); + ns_stats_disabled = 1; + return (NULL); + } + ns = (struct nameser *)memget(sizeof(struct nameser)); + if (ns == NULL) { + nomem: if (!haveComplained((u_long)nameserFind, 0)) + ns_notice(ns_log_statistics, + "nameserFind: memget failed; %s", + strerror(errno)); + return (NULL); + } + memset(ns, 0, sizeof *ns); + ns->addr = addr; + if (!tree_add(&nameserTree, nameserCompar, (tree_t)ns, NULL)) { + int save = errno; + memput(ns, sizeof *ns); + errno = save; + goto nomem; + } + ns_stats_cnt++; + } + return (ns); +} + +static void +nameserStatsOut(f, stats) + FILE *f; + u_long stats[]; +{ + int i; + const char *pre = "\t"; + + for (i = 0; i < (int)nssLast; i++) { + fprintf(f, "%s%lu", pre, (u_long)stats[i]); + pre = ((i+1) % 5) ? " " : " "; + } + fputc('\n', f); +} + +static void +nameserStatsHdr(f) + FILE *f; +{ + int i; + const char *pre = "\t"; + + fprintf(f, "(Legend)\n"); + for (i = 0; i < (int)nssLast; i++) { + fprintf(f, "%s%s", pre, + statNames[i] ? statNames[i] : ""); + pre = ((i+1) % 5) ? "\t" : "\n\t"; + } + fputc('\n', f); +} + +static int +nameserStatsTravUAR(t) + tree_t t; +{ + struct nameser *ns = (struct nameser *)t; + + fprintf(nameserStatsFile, "[%s]\n", /* : rtt %u */ + inet_ntoa(ns->addr) /*, ns->rtt*/ ); + nameserStatsOut(nameserStatsFile, ns->stats); + return (1); +} + +static void +nameserStats(f) + FILE *f; +{ + nameserStatsFile = f; + fprintf(f, "++ Name Server Statistics ++\n"); + nameserStatsHdr(f); + fprintf(f, "(Global)\n"); + nameserStatsOut(f, globalStats); + if (NS_OPTION_P(OPTION_HOSTSTATS)) { + tree_trav(&nameserTree, nameserStatsTravUAR); + if (ns_stats_disabled) + fprintf(f, "++ Host Statistics Incomplete ++\n"); + } + fprintf(f, "-- Name Server Statistics --\n"); + nameserStatsFile = NULL; +} + +void +ns_logstats(evContext ctx, void *uap, struct timespec due, + struct timespec inter) +{ + char buffer[1024]; + char buffer2[32], header[128]; + time_t timenow = time(NULL); + int i; +#ifdef HAVE_GETRUSAGE + struct rusage usage, childu; +#endif /*HAVE_GETRUSAGE*/ + +#ifdef HAVE_GETRUSAGE +# define tv_float(tv) ((tv).tv_sec + ((tv).tv_usec / 1000000.0)) + + UNUSED(ctx); + UNUSED(uap); + UNUSED(due); + UNUSED(inter); + + getrusage(RUSAGE_SELF, &usage); + getrusage(RUSAGE_CHILDREN, &childu); + + /* + * Get around a stupid compiler bug in gcc on solaris. + * There is a problem if three or more doubles are passed to + * sprintf. + * + */ + sprintf(buffer, "CPU=%gu/%gs CHILDCPU=", tv_float(usage.ru_utime), + tv_float(usage.ru_stime)); + sprintf(header, "%gu/%gs", tv_float(childu.ru_utime), + tv_float(childu.ru_stime)); + ns_info(ns_log_statistics, "USAGE %lu %lu %s%s", (u_long)timenow, + (u_long)boottime, buffer, header); +# undef tv_float +#endif /*HAVE_GETRUSAGE*/ + + sprintf(header, "NSTATS %lu %lu", (u_long)timenow, (u_long)boottime); + strcpy(buffer, header); + + for (i = 0; i < T_ANY+1; i++) { + if (typestats[i]) { + sprintf(buffer2, " %s=%lu", p_type(i), typestats[i]); + if (strlen(buffer) + strlen(buffer2) > + sizeof(buffer) - 1) { + ns_info(ns_log_statistics, "%s", buffer); + strcpy(buffer, header); + } + strcat(buffer, buffer2); + } + } + ns_info(ns_log_statistics, "%s", buffer); + + sprintf(header, "XSTATS %lu %lu", (u_long)timenow, (u_long)boottime); + strcpy(buffer, header); + for (i = 0; i < (int)nssLast; i++) { + sprintf(buffer2, " %s=%lu", + statNames[i]?statNames[i]:"?", (u_long)globalStats[i]); + if (strlen(buffer) + strlen(buffer2) > sizeof(buffer) - 1) { + ns_info(ns_log_statistics, "%s", buffer); + strcpy(buffer, header); + } + strcat(buffer, buffer2); + } + ns_info(ns_log_statistics, "%s", buffer); +} + +static void +nameserFree(void *uap) { + struct nameser *ns = uap; + + memput(ns, sizeof *ns); +} + +void +ns_freestats(void) { + if (nameserTree == NULL) + return; + tree_mung(&nameserTree, nameserFree); + nameserInit = 0; + ns_stats_cnt = 0; + ns_stats_disabled = 0; +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_stats.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/Makefile (revision 109985) @@ -0,0 +1,133 @@ +## Copyright (c) 1996-2000 by Internet Software Consortium +## +## 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. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM 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 +## SOFTWARE. + +# $Id: Makefile,v 8.51 2000/12/23 08:02:53 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g -Wall + +#(net2 and its descendents) +SYSTYPE = freebsd +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +EXE= +YACC = yacc -d +SYSLIBS = -ll -lutil +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +DESTETC= /etc +DESTRUN= /var/run +AR= ar cru +INSTALL= install +STRIP=-s +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin + +PS=ps +LDFLAGS= +CFLAGS= ${CDEBUG} +CPPFLAGS= -I${PORTINCL} -I${INCL} ${DEFS} + +VER= LOCAL-`date +%y%m%d.%H%M%S` +HOSTNAMECMD= hostname || uname -n + +PROG= named +HDRS= db_defs.h db_glob.h ns_defs.h ns_glob.h named.h pathnames.h +SRCS= db_dump.c db_load.c db_lookup.c db_save.c db_update.c \ + db_glue.c db_ixfr.c db_sec.c db_tsig.c \ + ns_parser.c ns_lexer.c ns_parseutil.c ns_ctl.c \ + ns_forw.c ns_init.c ns_main.c ns_maint.c ns_req.c \ + ns_resp.c ns_stats.c ns_ncache.c ns_xfr.c ns_glue.c \ + ns_udp.c ns_config.c ns_update.c ns_ixfr.c ns_signal.c \ + ns_sort.c ns_notify.c +OBJS= db_dump.${O} db_load.${O} db_lookup.${O} db_save.${O} db_update.${O} \ + db_glue.${O} db_ixfr.${O} db_sec.${O} db_tsig.${O} \ + ns_parser.${O} ns_lexer.${O} ns_parseutil.${O} ns_ctl.${O} \ + ns_forw.${O} ns_init.${O} ns_main.${O} ns_maint.${O} ns_req.${O} \ + ns_resp.${O} ns_stats.${O} ns_ncache.${O} ns_xfr.${O} ns_glue.${O} \ + ns_udp.${O} ns_config.${O} ns_update.${O} ns_ixfr.${O} ns_signal.${O} \ + ns_sort.${O} ns_notify.${O} + +all: ${PROG}${EXE} + +${PROG}${EXE}: pathnames.h ${OBJS} ${LIBBIND} Makefile tmp_version.${O} + ${CC} ${CDEBUG} ${LDFLAGS} ${BOUNDS} -o ${PROG}${EXE} ${OBJS} \ + tmp_version.${O} ${LIBBIND} ${SYSLIBS} + +ns_parser.c ns_parser.h: ns_parser.y + ${YACC} ns_parser.y + mv y.tab.c ns_parser.c + mv y.tab.h ns_parser.h + +tmp_version.${O}: tmp_version.c + +tmp_version.c: version.c Makefile ../Makefile ${SRCS} ${HDRS} + (u=$${USER-root} d=`pwd` h=`${HOSTNAMECMD}` t=`date`; \ + sed -e "s|%WHEN%|$${t}|" -e "s|%VERSION%|"${VER}"|" \ + -e "s|%WHOANDWHERE%|$${u}@$${h}:$${d}|" \ + < version.c > tmp_version.c); sleep 1 + +pathnames.h: ${TOP}/.settings Makefile pathtemplate.h + rm -f pathnames.h + sed -e "s|%DESTSBIN%|${DESTSBIN}|" \ + -e "s|%DESTEXEC%|${DESTEXEC}|" \ + -e "s|%DESTETC%|${DESTETC}|" \ + -e "s|%DESTRUN%|${DESTRUN}|" \ + < pathtemplate.h > pathnames.h + +ns_signal.${O}: ns_signal.c + ${CC} ${CPPFLAGS} ${CFLAGS} -c $*.c + +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c + +distclean: clean + rm -f ns_parser.c ns_parser.h + +clean: FRC + rm -f ${PROG}${EXE} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + rm -f tmp_version.c tmp_version.${O} + rm -f pathnames.h y.tab.h y.tab.c + +depend: ${SRCS} pathnames.h + mkdep ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${DEFS} ${SRCS} + +${DESTDIR}${DESTSBIN}: + mkdir -p ${DESTDIR}${DESTSBIN} + +install: ${DESTDIR}${DESTSBIN} ${PROG}${EXE} + ${INSTALL} ${STRIP} -c ${INSTALL_EXEC} -m 755 ${PROG}${EXE} ${DESTDIR}${DESTSBIN}/${PROG}${EXE} + +links: FRC + @ln -s SRC/*.[chy] SRC/test .; rm -f ns_parser.[ch] + +tags: FRC + ctags ${SRCS} *.h + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/db_glob.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/db_glob.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/db_glob.h (revision 109985) @@ -0,0 +1,104 @@ +/* + * from db.h 4.16 (Berkeley) 6/1/90 + * $Id: db_glob.h,v 8.14 2000/04/21 06:54:02 vixie Exp $ + */ + +/* + * Copyright (c) 1985, 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * Global variables for data base routines. + */ + + /* ONE_WEEK maximum ttl */ +DECL u_int max_cache_ttl INIT(7*24*60*60); + + /* no minimum ttl */ +DECL u_int min_cache_ttl INIT(0); + + /* current line number */ +DECL int lineno INIT(0); + + /* root hash table */ +DECL struct hashbuf *hashtab INIT(NULL); + + /* hash table of cache read from file */ +DECL struct hashbuf *fcachetab INIT(NULL); + + /* state of ns_reload() and ns_reconfig(). */ +DECL int reloading INIT(0); +DECL int reconfiging INIT(0); +DECL int noexpired INIT(0); + +DECL const int hashsizes[] +#ifdef MAIN_PROGRAM + = { 2, 11, 113, 337, 977, 2053, 4073, 8011, 16001, 99887, 0 } +#endif + ; Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/db_glob.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/ns_udp.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/ns_udp.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/ns_udp.c (revision 109985) @@ -0,0 +1,124 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_udp.c,v 8.9 2000/04/21 06:54:13 vixie Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "named.h" + +void +ns_udp() { +#if defined(CHECK_UDP_SUM) || defined(FIX_UDP_SUM) + struct nlist nl[2]; + int fd; + int sum; + u_long res, offset; + + nl[0].n_name = UDPSUM; + nl[1].n_name = 0; + + if (nlist(KSYMS, nl)) { + ns_debug(ns_log_default, 1, "ns_udp: nlist (%s,%s) failed", + KSYMS, UDPSUM); + return; + } + + ns_debug(ns_log_default, 1, "ns_udp: %s %d %lu (%ld)", + nl[0].n_name, nl[0].n_type, nl[0].n_value, nl[0].n_value); + + if (!nl[0].n_type) + return; + + if ((fd = open(KMEM, O_RDWR, 0)) < 0) { + ns_debug(ns_log_default, 1, "ns_udp: open %s failed: %s", KMEM, + strerror(errno)); + return; + } + + offset = nl[0].n_value; +#ifdef KMAP + offset &= ((~0UL)>>1); +#endif + + res = lseek(fd, offset, SEEK_SET); + if (res != offset) { + ns_debug(ns_log_default, 1, "ns_udp: lseek %lu failed %lu: %s", + offset, res, strerror(errno)); + goto cleanup; + } + + if (read(fd, &sum, sizeof(sum)) != sizeof(sum)) { + ns_debug(ns_log_default, 1, "ns_udp: read failed: %s", + strerror(errno)); + goto cleanup; + } + + ns_debug(ns_log_default, 1, "ns_udp: %d", sum); + if (sum == 0) { +#ifdef FIX_UDP_SUM + sum = 1; + lseek(fd, offset, SEEK_SET); + if (res != offset) { + ns_debug(ns_log_default, 1, + "ns_udp: lseek %lu failed %lu: %s", + offset, res, strerror(errno)); + goto cleanup; + } + if (write(fd, &sum, sizeof(sum)) != sizeof(sum)) { + ns_debug(ns_log_default, 1, "ns_udp: write failed: %s", + strerror(errno)); + goto cleanup; + } + ns_warning(ns_log_default, "ns_udp: check sums turned on"); +#else + ns_panic(ns_log_default, 0, + "ns_udp: checksums NOT turned on, exiting"); +#endif + } +cleanup: + close(fd); +#endif +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/ns_udp.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/pathtemplate.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/pathtemplate.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/pathtemplate.h (revision 109985) @@ -0,0 +1,78 @@ +/* + * $Id: pathtemplate.h,v 8.6 2000/04/21 06:54:15 vixie Exp $ + */ + +/* + * Copyright (c) 1996-2000 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include + +#ifndef _PATH_CONF +#define _PATH_CONF "%DESTETC%/named.conf" +#endif + +#ifndef _PATH_DEBUG +#define _PATH_DEBUG "named.run" +#endif + +#ifndef _PATH_DUMPFILE +#define _PATH_DUMPFILE "named_dump.db" +#endif + +#ifndef _PATH_NAMED +#define _PATH_NAMED "%DESTSBIN%/named" +#endif + +#ifndef _PATH_PIDFILE +#define _PATH_PIDFILE "%DESTRUN%/named.pid" +#endif + +#ifndef _PATH_NDCSOCK +#ifdef NEED_SECURE_DIRECTORY +#define _PATH_NDCSOCK "%DESTRUN%/ndc.d/ndc" +#else +#define _PATH_NDCSOCK "%DESTRUN%/ndc" +#endif +#endif + +#ifndef _PATH_STATS +#define _PATH_STATS "named.stats" +#endif + +#ifndef _PATH_MEMSTATS +#define _PATH_MEMSTATS "named.memstats" +#endif + +#ifndef _PATH_TMPXFER +#define _PATH_TMPXFER "xfer.ddt.XXXXXX" +#endif + +#ifndef _PATH_XFER +#define _PATH_XFER "%DESTEXEC%/named-xfer" +#endif + +#ifndef _PATH_XFERTRACE +#define _PATH_XFERTRACE "xfer.trace" +#endif + +#ifndef _PATH_XFERDDT +#define _PATH_XFERDDT "xfer.ddt" +#endif + +#ifndef _PATH_DEVNULL +#define _PATH_DEVNULL "/dev/null" +#endif Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/pathtemplate.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/test/named.conf =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/test/named.conf (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/test/named.conf (revision 109985) @@ -0,0 +1,45 @@ +// This is a configuration file for named (from BIND 8.1 or later). +// It would normally be installed as /etc/named.conf. + +options { +// directory "/var/named"; + check-names master warn; /* default. */ + datasize 20M; + deallocate-on-exit yes; + listen-on { 10.0.0.53; }; +}; + +zone "localhost" IN { + type master; + file "localhost.zone"; + check-names fail; + allow-update { none; }; + allow-transfer { any; }; +}; + +zone "0.0.127.in-addr.arpa" IN { + type master; + file "127.0.0.zone"; + check-names fail; + allow-update { none; }; + allow-transfer { any; }; +}; + +zone "." IN { + type hint; + file "root.hint"; +}; + +logging { + channel xfer-log { + file "/var/tmp/bind-xfer.log" versions unlimited size 10m; + print-category yes; + print-severity yes; + print-time yes; + severity info; + }; + category xfer-in { xfer-log; }; + category xfer-out { xfer-log; }; + category notify { xfer-log; }; + category load { xfer-log; }; +}; Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/test/named.conf ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/test/127.0.0.zone =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/test/127.0.0.zone (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/test/127.0.0.zone (revision 109985) @@ -0,0 +1,11 @@ +$ORIGIN 0.0.127.in-addr.arpa. + +@ 1D IN SOA localhost. root.localhost. ( + 42 ; serial (d. adams) + 3H ; refresh + 15M ; retry + 1W ; expiry + 1D ) ; minimum + + 1D IN NS localhost. +1 1D IN PTR localhost. Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/test/127.0.0.zone ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/test/localhost.zone =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/test/localhost.zone (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/test/localhost.zone (revision 109985) @@ -0,0 +1,10 @@ +$ORIGIN localhost. +@ 1D IN SOA @ root ( + 42 ; serial (d. adams) + 3H ; refresh + 15M ; retry + 1W ; expiry + 1D ) ; minimum + + 1D IN NS @ + 1D IN A 127.0.0.1 Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/test/localhost.zone ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/test/root.hint =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/test/root.hint (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/test/root.hint (revision 109985) @@ -0,0 +1,37 @@ + +; <<>> DiG 2.2 <<>> @192.5.5.241 +; (1 server found) +;; res options: init recurs defnam dnsrch +;; got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10 +;; flags: qr aa rd; QUERY: 1, ANSWER: 9, AUTHORITY: 0, ADDITIONAL: 9 +;; QUERY SECTION: +;; ., type = NS, class = IN + +;; ANSWER SECTION: +. 6D IN NS C.ROOT-SERVERS.NET. +. 6D IN NS D.ROOT-SERVERS.NET. +. 6D IN NS E.ROOT-SERVERS.NET. +. 6D IN NS I.ROOT-SERVERS.NET. +. 6D IN NS F.ROOT-SERVERS.NET. +. 6D IN NS G.ROOT-SERVERS.NET. +. 6D IN NS A.ROOT-SERVERS.NET. +. 6D IN NS H.ROOT-SERVERS.NET. +. 6D IN NS B.ROOT-SERVERS.NET. + +;; ADDITIONAL SECTION: +C.ROOT-SERVERS.NET. 5w6d16h IN A 192.33.4.12 +D.ROOT-SERVERS.NET. 5w6d16h IN A 128.8.10.90 +E.ROOT-SERVERS.NET. 5w6d16h IN A 192.203.230.10 +I.ROOT-SERVERS.NET. 5w6d16h IN A 192.36.148.17 +F.ROOT-SERVERS.NET. 5w6d16h IN A 192.5.5.241 +G.ROOT-SERVERS.NET. 5w6d16h IN A 192.112.36.4 +A.ROOT-SERVERS.NET. 5w6d16h IN A 198.41.0.4 +H.ROOT-SERVERS.NET. 5w6d16h IN A 128.63.2.53 +B.ROOT-SERVERS.NET. 5w6d16h IN A 128.9.0.107 + +;; Total query time: 8 msec +;; FROM: wisdom.home.vix.com to SERVER: 192.5.5.241 +;; WHEN: Fri Nov 22 00:08:05 1996 +;; MSG SIZE sent: 17 rcvd: 312 + Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/test/root.hint ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named/version.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named/version.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named/version.c (revision 109985) @@ -0,0 +1,89 @@ +/* + * @(#)Version.c 4.9 (Berkeley) 7/21/90 + * $Id: version.c,v 8.3 1999/01/02 06:05:14 vixie Exp $ + */ + +#ifndef lint +char sccsid[] = "@(#)named %VERSION% %WHEN% %WHOANDWHERE%"; +char rcsid[] = "$Id: version.c,v 8.3 1999/01/02 06:05:14 vixie Exp $"; +#endif /* not lint */ + +char Version[] = "named %VERSION% %WHEN%\n\t%WHOANDWHERE%"; +char ShortVersion[] = "%VERSION%"; + +#ifdef COMMENT + +SCCS/s.Version.c: + +D 4.8.3 90/06/27 17:05:21 bloom 37 35 00031/00028/00079 +Version distributed with 4.3 Reno tape (June 1990) + +D 4.8.2 89/09/18 13:57:11 bloom 35 34 00020/00014/00087 +Interim fixes release + +D 4.8.1 89/02/08 17:12:15 karels 34 33 00026/00017/00075 +branch for 4.8.1 + +D 4.8 88/07/09 14:27:00 karels 33 28 00043/00031/00049 +4.8 is here! + +D 4.7 87/11/20 13:15:52 karels 25 24 00000/00000/00062 +4.7.3 beta + +D 4.6 87/07/21 12:15:52 karels 25 24 00000/00000/00062 +4.6 declared stillborn + +D 4.5 87/02/10 12:33:25 kjd 24 18 00000/00000/00062 +February 1987, Network Release. Child (bind) grows up, parent (kevin) leaves home. + +D 4.4 86/10/01 10:06:26 kjd 18 12 00020/00017/00042 +October 1, 1986 Network Distribution + +D 4.3 86/06/04 12:12:18 kjd 12 7 00015/00028/00044 +Version distributed with 4.3BSD + +D 4.2 86/04/30 20:57:16 kjd 7 1 00056/00000/00016 +Network distribution Freeze and one more version until 4.3BSD + +D 1.1 86/04/30 19:30:00 kjd 1 0 00016/00000/00000 +date and time created 86/04/30 19:30:00 by kjd + +code versions: + +Makefile + Makefile 4.14 (Berkeley) 2/28/88 +db.h + db.h 4.13 (Berkeley) 2/17/88 +db_dump.c + db_dump.c 4.20 (Berkeley) 2/17/88 +db_load.c + db_load.c 4.26 (Berkeley) 2/28/88 +db_lookup.c + db_lookup.c 4.14 (Berkeley) 2/17/88 +db_reload.c + db_reload.c 4.15 (Berkeley) 2/28/88 +db_save.c + db_save.c 4.13 (Berkeley) 2/17/88 +db_update.c + db_update.c 4.16 (Berkeley) 2/28/88 +ns_forw.c + ns_forw.c 4.26 (Berkeley) 3/28/88 +ns_init.c + ns_init.c 4.23 (Berkeley) 2/28/88 +ns_main.c + Copyright (c) 1986 Regents of the University of California.\n\ + ns_main.c 4.30 (Berkeley) 3/7/88 +ns_maint.c + ns_maint.c 4.23 (Berkeley) 2/28/88 +ns_req.c + ns_req.c 4.32 (Berkeley) 3/31/88 +ns_resp.c + ns_resp.c 4.50 (Berkeley) 4/7/88 +ns_sort.c + ns_sort.c 4.3 (Berkeley) 2/17/88 +ns_stats.c + ns_stats.c 4.3 (Berkeley) 2/17/88 +newvers.sh + newvers.sh 4.4 (Berkeley) 3/28/88 + +#endif /* COMMENT */ Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named/version.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/ndc/ndc.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/ndc/ndc.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/ndc/ndc.c (revision 109985) @@ -0,0 +1,910 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ndc.c,v 1.22 2002/06/24 07:28:55 marka Exp $"; +#endif /* not lint */ + +/* + * Portions Copyright (c) 1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" +#include "pathnames.h" +#ifndef PATH_SEP +#define PATH_SEP '/' +#endif + +typedef union { + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif +} sockaddr_t; + +typedef void (*closure)(void *, const char *, int); + +static const char * program = "amnesia"; +static enum { e_channel, e_signals } mode = e_channel; +static const char * channel = _PATH_NDCSOCK; +static const char helpfmt[] = "\t%-16s\t%s\n"; +static const char * pidfile = _PATH_PIDFILE; +static sockaddr_t client, server; +static int quiet = 0, tracing = 0, silent = 0, client_set = 0; +static int debug = 0, errors = 0, doneflag, exitflag; +static int logger_show = 1; +static evContext ev; +static char cmd[1000]; +static const char * named_path = _PATH_NAMED; + +static int slashcmd(void); +static void slashhelp(void); +static int builtincmd(void); +static void command(void); +static int running(int, pid_t *); +static void command_channel(void); +static void channel_loop(const char *, int, closure, void *); +static void getpid_closure(void *, const char *, int); +static void banner(struct ctl_cctx *, void *, const char *, u_int); +static void done(struct ctl_cctx *, void *, const char *, u_int); +static void logger(enum ctl_severity, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3); +static void command_signals(void); +static void stop_named(pid_t); +static void start_named(const char *, int); +static int fgetpid(const char *, pid_t *); +static int get_sockaddr(const char *, sockaddr_t *); +static size_t impute_addrlen(const struct sockaddr *); +static void vtrace(const char *, va_list); +static void trace(const char *, ...) ISC_FORMAT_PRINTF(1, 2); +static void result(const char *, ...) ISC_FORMAT_PRINTF(1, 2); +static void fatal(const char *, ...) ISC_FORMAT_PRINTF(1, 2); +static void verror(const char *, va_list) ISC_FORMAT_PRINTF(1, 0); +static void error(const char *, ...) ISC_FORMAT_PRINTF(1, 2); + +static void +usage(const char *fmt, ...) { + va_list args; + + va_start(args, fmt); + fprintf(stderr, "%s: usage error: ", program); + vfprintf(stderr, fmt, args); + fputc('\n', stderr); + va_end(args); + fatal("usage: %s \ +[-l localsock] [-c channel] [-p pidfile] [-n namedpath] \ +[-dqst] [command [args]]\n\ +", + program); +} + +/* Public. */ + +int +main(int argc, char *argv[]) { + char *p; + int ch; + + if ((program = strrchr(argv[0], PATH_SEP)) != NULL) + program++; + else + program = argv[0]; + while ((ch = getopt(argc, argv, "c:p:l:n:dqst")) != -1) { + switch (ch) { + case 'c': + channel = optarg; + mode = e_channel; + break; + case 'p': + pidfile = optarg; + mode = e_signals; + break; + case 'l': + if (!get_sockaddr(optarg, &client)) + usage("bad local socket (%s)", optarg); + client_set++; + break; + case 'n': + named_path = optarg; + break; + case 'd': + tracing++; + debug++; + break; + case 'q': + quiet++; + break; + case 's': + silent++; + break; + case 't': + tracing++; + break; + default: + usage("unrecognized command option (%c)", ch); + /* NOTREACHED */ + } + } + if (mode != e_channel && client_set) + usage("the -l flag is only valid for control channels"); + if (mode == e_channel) { + if (!get_sockaddr(channel, &server)) + usage("bad channel name (%s)", channel); + if (evCreate(&ev) < 0) + fatal("evCreate - %s", strerror(errno)); + } + *(p = cmd) = '\0'; + for (argc -= optind, argv += optind; + argc > 0; + argc--, argv++) { + size_t t = strlen(*argv); + + if ((p - cmd) + t + 2 > sizeof cmd) + usage("command too long"); + strcpy(p, *argv); + p += t; + if (argv[1] != NULL) + *p++ = ' '; + *p = '\0'; + } + if (cmd[0] != '\0') { + command(); + } else { + if (!quiet) + result("Type help -or- /h if you need help."); + for (exitflag = 0; !exitflag; (void)NULL) { + if (!quiet) { + printf("%s> ", program); + fflush(stdout); + } + if (!fgets(cmd, sizeof cmd, stdin)) { + if (!quiet) + result("EOF"); + exitflag++; + continue; + } + if (cmd[strlen(cmd) - 1] == '\n') + cmd[strlen(cmd) - 1] = '\0'; + if (cmd[0] == '\0') + continue; + if (slashcmd()) + continue; + command(); + } + } + if (mode == e_channel) + evDestroy(ev); + exit(errors != 0); +} + +/* Private. */ + +static int +slashcmd(void) { + if (strncasecmp(cmd, "/help", strlen(cmd)) == 0) + slashhelp(); + else if (strncasecmp(cmd, "/exit", strlen(cmd)) == 0) + exitflag++; + else if (strncasecmp(cmd, "/trace", strlen(cmd)) == 0) + result("tracing now %s", + (tracing = !tracing) ? "on" : "off"); + else if (strncasecmp(cmd, "/debug", strlen(cmd)) == 0) + result("debugging now %s", + (debug = !debug) ? "on" : "off"); + else if (strncasecmp(cmd, "/quiet", strlen(cmd)) == 0) + result("%s is now %s", program, + (quiet = !quiet) ? "quiet" : "noisy"); + else if (strncasecmp(cmd, "/silent", strlen(cmd)) == 0) + result("%s is now %s", program, + (silent = !silent) + ? "silent" : "gregarious"); + else + return (0); + return (1); +} + +static void +slashhelp(void) { + printf(helpfmt, "/h(elp)", "this text"); + printf(helpfmt, "/e(xit)", "leave this program"); + printf(helpfmt, "/t(race)", + "toggle tracing (protocol and system events)"); + printf(helpfmt, "/d(ebug)", + "toggle debugging (internal program events)"); + printf(helpfmt, "/q(uiet)", + "toggle quietude (prompts and results)"); + printf(helpfmt, "/s(ilent)", + "toggle silence (suppresses nonfatal errors)"); +} + +struct argv { + int argc; + char **argv; + int error; +}; + +static char hexdigits[] = "0123456789abcdef"; + +static void +getargs_closure(void *arg, const char *msg, int flags) { + struct argv *argv = arg; + int len; + int i; + const char *cp, *cp2; + char *tp, c; + + UNUSED(flags); + + if (argv->error) + return; + + if (argv->argc == -1) { + i = atoi(msg + 4); + if (i < 1) { + argv->error = 1; + return; + } + argv->argc = i; + argv->argv = calloc((i+1), sizeof(char*)); + return; + } + len = 0; + cp = msg + 4; + while (*cp != NULL) { + c = *cp; + if (c == '%') { + cp2 = strchr(hexdigits, cp[1]); + if (cp2 == NULL) { + argv->error = 1; + return; + } + c = (cp2-hexdigits) << 4; + cp2 = strchr(hexdigits, cp[2]); + if (cp2 == NULL) { + argv->error = 1; + return; + } + c += (cp2-hexdigits); + cp += 2; + } + if (!isalnum((unsigned)c)) { + switch (c) { + case '+': case '-': case '=': case '/': case '.': + break; + default: + len++; + } + } + len++; + cp++; + } + i = 0; + while (argv->argv[i] != NULL) + i++; + if (i >= argv->argc) { + argv->error = 1; + return; + } + argv->argv[i] = malloc(len + 1); + if (argv->argv[i] == NULL) { + argv->error = 1; + return; + } + cp = msg + 4; + tp = argv->argv[i]; + while (*cp != NULL) { + c = *cp; + if (c == '%') { + cp2 = strchr(hexdigits, cp[1]); + if (cp2 == NULL) { + argv->error = 1; + return; + } + c = (cp2-hexdigits) << 4; + cp2 = strchr(hexdigits, cp[2]); + if (cp2 == NULL) { + argv->error = 1; + return; + } + c += (cp2-hexdigits); + cp += 2; + } + if (!isalnum((unsigned)c)) { + switch (c) { + case '+': case '-': case '=': case '/': case '.': + break; + default: + *tp = '\\'; + } + } + *tp++ = c; + cp++; + } +} + +static int +get_args(char **restp) { + struct argv argv; + int len, i; + char *rest, *p; + int result = 1; + + argv.argc = -1; + argv.argv = NULL; + argv.error = 0; + + channel_loop("args", 1, getargs_closure, &argv); + if (argv.error) { + result = 0; + goto err; + } + len = 0; + for (i = 1 ; i < argv.argc && argv.argv[i] != NULL; i++) + len += strlen(argv.argv[i]) + 1; + rest = malloc(len); + if (rest == NULL) { + result = 0; + goto err; + } + p = rest; + for (i = 1 ; i < argv.argc && argv.argv[i] != NULL; i++) { + strcpy(p, argv.argv[i]); + p += strlen(argv.argv[i]); + *p++ = ' '; + } + if (p != rest) + p[-1] = '\0'; + *restp = rest; + + err: + if (argv.argv) { + for (i = 0 ; i < argv.argc && argv.argv[i] != NULL; i++) + free(argv.argv[i]); + free(argv.argv); + } + return (result); +} + +static void +exec_closure(void *arg, const char *msg, int flags) { + int *result = arg; + UNUSED(flags); + if (atoi(msg) == 250) + *result = 1; +} + +static int +try_exec(int local_quiet) { + int good = 0; + pid_t pid; + + channel_loop("exec", 1, exec_closure, &good); + + if (good) { + sleep(3); + if (!running(0, &pid)) + error("name server has not restarted (yet?)"); + else if (!local_quiet) + result("new pid is %ld", (long)pid); + } + return (good); +} + +static int +builtincmd(void) { + static const char spaces[] = " \t"; + char *rest, *syscmd; + pid_t pid; + int save_quiet = quiet; + int len; + int freerest = 0; + + quiet = 1; + + len = strcspn(cmd, spaces); + rest = cmd + len; + if (*rest != '\0') + rest += strspn(rest, spaces); + if (*rest == '\0' && !strncasecmp(cmd, "restart", len)) { + if (try_exec(save_quiet)) + return (1); + freerest = get_args(&rest); + } + syscmd = malloc(strlen(named_path) + sizeof " " + strlen(rest)); + if (syscmd == NULL) + fatal("malloc() failed - %s", strerror(errno)); + strcpy(syscmd, named_path); + if (*rest != '\0') { + strcat(syscmd, " "); + strcat(syscmd, rest); + } + if (freerest) + free(rest); + if (strncasecmp(cmd, "start", len) == 0) { + if (running(debug, &pid)) + error("name server already running? (pid %ld)", + (long)pid); + else + start_named(syscmd, save_quiet); + quiet = save_quiet; + free(syscmd); + return (1); + } else if (strncasecmp(cmd, "restart", len) == 0) { + if (!running(debug, &pid)) + error("name server was not running (warning only)"); + else + stop_named(pid); + start_named(syscmd, save_quiet); + quiet = save_quiet; + free(syscmd); + return (1); + } + quiet = save_quiet; + free(syscmd); + return (0); +} + +static void +builtinhelp(void) { + const char *fmt; + + switch (mode) { + case e_channel: + fmt = "(builtin) %s - %s\n"; + break; + case e_signals: + fmt = helpfmt; + break; + default: + abort(); + } + printf(fmt, "start", "start the server"); + printf(fmt, "restart", "stop server if any, start a new one"); +} + +static void +command(void) { + if (builtincmd()) + return; + switch (mode) { + case e_channel: + command_channel(); + break; + case e_signals: + command_signals(); + break; + default: + abort(); + } +} + +static int +running(int show, pid_t *pidp) { + pid_t pid; + + switch (mode) { + case e_channel: + pid = 0; + channel_loop("getpid", show, getpid_closure, &pid); + if (pid != 0) { + if (tracing) + result("pid %ld is running", (long)pid); + *pidp = pid; + return (1); + } + break; + case e_signals: + if (fgetpid(pidfile, pidp)) { + if (tracing) + result("pid %ld is running", (long)pid); + return (1); + } + break; + default: + abort(); + } + if (show) + error("pid not valid or server not running"); + return (0); +} + +static void +getpid_closure(void *uap, const char *text, int flags) { + pid_t *pidp = uap; + const char *cp; + + flags = flags; + if ((cp = strchr(text, '<')) != NULL) { + long l = 0; + char ch; + + while ((ch = *++cp) != '\0' && ch != '>' && isdigit(ch)) + l *= 10, l += (ch - '0'); + if (ch == '>') { + *pidp = (pid_t)l; + return; + } + } + error("response does not contain pid (%s)", text); +} + +static void +command_channel(void) { + int helping = (strcasecmp(cmd, "help") == 0); + int save_quiet = quiet; + + if (helping) { + quiet = 0; + builtinhelp(); + } + channel_loop(cmd, !quiet, NULL, NULL); + quiet = save_quiet; +} + +struct args { + const char *cmd; + closure cl; + void *ua; +}; + +static void +channel_loop(const char *cmdtext, int show, closure cl, void *ua) { + struct ctl_cctx *ctl; + struct sockaddr *client_addr; + struct args a; + evEvent e; + int save_logger_show = logger_show; + + if (!client_set) + client_addr = NULL; + else + client_addr = (struct sockaddr *)&client; + a.cmd = cmdtext; + a.cl = cl; + a.ua = ua; + logger_show = show; + trace("command '%s'", cmdtext); + ctl = ctl_client(ev, client_addr, impute_addrlen(client_addr), + (struct sockaddr *)&server, + impute_addrlen((struct sockaddr *)&server), + banner, &a, 15, logger); + if (ctl == NULL) { + if (show) + error("cannot connect to command channel (%s)", + channel); + } else { + doneflag = 0; + while (evGetNext(ev, &e, EV_WAIT) == 0) + if (evDispatch(ev, e) < 0 || doneflag) + break; + ctl_endclient(ctl); + } + logger_show = save_logger_show; +} + +static void +banner(struct ctl_cctx *ctl, void *uap, const char *msg, u_int flags) { + struct args *a = uap; + + if (msg == NULL) { + trace("EOF"); + doneflag = 1; + return; + } + trace("%s", msg); + if ((flags & CTL_MORE) != 0) + return; + if (ctl_command(ctl, a->cmd, strlen(a->cmd), done, a) < 0) { + error("ctl_command failed - %s", strerror(errno)); + doneflag = 1; + } +} + +static void +done(struct ctl_cctx *ctl, void *uap, const char *msg, u_int flags) { + struct args *a = uap; + + UNUSED(ctl); + + if (msg == NULL) { + trace("EOF"); + doneflag = 1; + return; + } + if (!tracing && !quiet && strlen(msg) > 4) + result("%s", msg + 4); + trace("%s", msg); + if (a->cl) + (a->cl)(a->ua, msg, flags); + if ((flags & CTL_MORE) == 0) + doneflag = 1; +} + +static void +logger(enum ctl_severity ctlsev, const char *format, ...) { + va_list args; + + va_start(args, format); + switch (ctlsev) { + case ctl_debug: + /* FALLTHROUGH */ + case ctl_warning: + if (debug) + vtrace(format, args); + break; + case ctl_error: + if (logger_show) + verror(format, args); + break; + default: + va_end(args); + abort(); + } + va_end(args); +} + +static struct cmdsig { + const char * cmd; + int sig; + const char * help; +} cmdsigs[] = { + { "dumpdb", SIGINT, "dump cache database to a file" }, + { "reload", SIGHUP, "reload configuration file" }, + { "stats", SIGILL, "dump statistics to a file" }, + { "trace", SIGUSR1, "increment trace level" }, + { "notrace", SIGUSR2, "turn off tracing" }, +#ifdef SIGWINCH + { "querylog", SIGWINCH, "toggle query logging" }, + { "qrylog", SIGWINCH, "alias for querylog" }, +#endif + { NULL, 0, NULL } +}; + +static void +command_signals(void) { + struct cmdsig *cmdsig; + pid_t pid; + + if (strcasecmp(cmd, "help") == 0) { + printf(helpfmt, "help", "this output"); + printf(helpfmt, "status", "check for running server"); + printf(helpfmt, "stop", "stop the server"); + builtinhelp(); + for (cmdsig = cmdsigs; cmdsig->cmd != NULL; cmdsig++) + printf(helpfmt, cmdsig->cmd, cmdsig->help); + } else if (strcasecmp(cmd, "status") == 0) { + if (!fgetpid(pidfile, &pid)) + error("pid not valid or server not running"); + else + result("pid %ld is running", (long)pid); + } else if (strcasecmp(cmd, "stop") == 0) { + if (!fgetpid(pidfile, &pid)) + error("name server not running"); + else + stop_named(pid); + } else { + for (cmdsig = cmdsigs; cmdsig->cmd != NULL; cmdsig++) + if (strcasecmp(cmd, cmdsig->cmd) == 0) + break; + if (cmdsig->cmd == NULL) + error("unrecognized command (%s)", cmd); + else if (!fgetpid(pidfile, &pid)) + error("can't get pid (%s)", pidfile); + else if (kill(pid, cmdsig->sig) < 0) + error("kill() failed - %s", strerror(errno)); + else + trace("pid %ld sig %d OK", (long)pid, cmdsig->sig); + } +} + +static void +stop_named(pid_t pid) { + int n; + + trace("stopping named (pid %ld)", (long)pid); + switch (mode) { + case e_signals: + if (kill(pid, SIGTERM) < 0) { + error("kill(%ld, SIGTERM) failed - %s", + (long)pid, strerror(errno)); + return; + } + trace("SIGTERM ok, waiting for death"); + break; + case e_channel: + channel_loop("stop", tracing, NULL, NULL); + break; + default: + abort(); + } + for (n = 0; n < 10; n++) { + if (kill(pid, 0) != 0) { + trace("named (pid %ld) is dead", (long)pid); + return; + } + sleep(1); + } + error("named (pid %ld) didn't die", (long)pid); +} + +static void +start_named(const char *syscmd, int local_quiet) { + pid_t pid; + + if (system(syscmd) != 0) + error("could not start new name server (%s)", syscmd); + else { + sleep(3); + if (!running(0, &pid)) + error("name server has not started (yet?)"); + else if (!local_quiet) + result("new pid is %ld", (long)pid); + } +} + +static int +fgetpid(const char *f, pid_t *pid) { + FILE *fp; + int try; + long t; + + for (try = 0; try < 5; try++) { + trace("pidfile is \"%s\" (try #%d)", f, try + 1); + if ((fp = fopen(f, "r")) == NULL) + trace("pid file (%s) unavailable - %s", + f, strerror(errno)); + else if (fscanf(fp, "%ld\n", &t) != 1) + trace("pid file (%s) format is bad", f); + else if (*pid = (pid_t)t, fclose(fp), kill(*pid, 0) < 0) + trace("pid file (%s) contains unusable pid (%d) - %s", + f, *pid, strerror(errno)); + else { + trace("pid is %ld", (long)*pid); + return (1); + } + sleep(1); + } + trace("pid not found"); + return (0); +} + +static int +get_sockaddr(const char *name, sockaddr_t *addr) { + char *slash; + +#ifndef NO_SOCKADDR_UN + if (name[0] == '/') { + memset(&addr->un, '\0', sizeof addr->un); + addr->un.sun_family = AF_UNIX; + strncpy(addr->un.sun_path, name, sizeof addr->un.sun_path - 1); + addr->un.sun_path[sizeof addr->un.sun_path - 1] = '\0'; + } else +#endif + if ((slash = strrchr(name, '/')) != NULL) { + char *ibuf = malloc(slash - name + 1); + if (!ibuf) + usage("no memory for IP address (%s)", name); + memcpy(ibuf, name, slash - name); + ibuf[slash - name] = '\0'; + memset(&addr->in, '\0', sizeof addr->in); + if (!inet_pton(AF_INET, ibuf, &addr->in.sin_addr)) + usage("bad ip address (%s)", name); + if ((addr->in.sin_port = htons(atoi(slash+1))) == 0) + usage("bad ip port (%s)", slash+1); + addr->in.sin_family = AF_INET; + free (ibuf); + } else { + return (0); + } + return (1); +} + +static size_t +impute_addrlen(const struct sockaddr *sa) { + if (sa == NULL) + return (0); + switch (sa->sa_family) { + case AF_INET: + return (sizeof(struct sockaddr_in)); +#ifndef NO_SOCKADDR_UN + case AF_UNIX: + return (sizeof(struct sockaddr_un)); +#endif + default: + abort(); + } + /*NOTREACHED*/ +} + +static void +vtrace(const char *fmt, va_list ap) { + if (tracing) { + fprintf(stdout, "%s: [", program); + vfprintf(stdout, fmt, ap); + fputs("]\n", stdout); + } +} + +static void +trace(const char *fmt, ...) { + va_list args; + + va_start(args, fmt); + vtrace(fmt, args); + va_end(args); +} + +static void +result(const char *fmt, ...) { + va_list args; + + va_start(args, fmt); + vfprintf(stdout, fmt, args); + fputc('\n', stdout); + va_end(args); +} + +static void +fatal(const char *fmt, ...) { + va_list args; + + va_start(args, fmt); + fprintf(stderr, "%s: fatal error: ", program); + vfprintf(stderr, fmt, args); + fputc('\n', stderr); + va_end(args); + exit(1); +} + +static void +verror(const char *fmt, va_list ap) { + fprintf(stderr, "%s: error: ", program); + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); + errors++; +} + +static void +error(const char *fmt, ...) { + va_list args; + + va_start(args, fmt); + if (silent) + vtrace(fmt, args); + else + verror(fmt, args); + va_end(args); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/ndc/ndc.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/ndc/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/ndc/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/ndc/Makefile (revision 109985) @@ -0,0 +1,96 @@ +## Copyright (c) 1996,1999 by Internet Software Consortium +## +## 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. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM 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 +## SOFTWARE. + +# $Id: Makefile,v 1.17 2000/12/23 08:02:54 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g -Wall + +#(net2 and its descendents) +SYSTYPE = freebsd +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +LEX = lex -I +SYSLIBS = -ll -lutil +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +AR= ar cru +INSTALL= install +STRIP=-s +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin +PS=ps + +LDFLAGS= +CFLAGS= ${CDEBUG} +CPPFLAGS= -I${PORTINCL} -I${INCL} ${DEFS} + +PROG= ndc +SRCS= ${PROG}.c +OBJS= ${PROG}.${O} +HDRS= pathnames.h + +all: ${PROG}${EXE} + +${PROG}${EXE}: ${HDRS} ${OBJS} ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} ${BOUNDS} -o ${PROG}${EXE} ${OBJS} ${LIBBIND} ${SYSLIBS} + +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c + +pathnames.h: ${TOP}/.settings Makefile ../named/pathtemplate.h + rm -f pathnames.h + sed -e "s|%DESTSBIN%|${DESTSBIN}|" \ + -e "s|%DESTEXEC%|${DESTEXEC}|" \ + -e "s|%DESTETC%|${DESTETC}|" \ + -e "s|%DESTRUN%|${DESTRUN}|" \ + < ../named/pathtemplate.h > pathnames.h + +distclean: clean + +clean: FRC + rm -f ${PROG}${EXE} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + rm -f pathnames.h + +depend: ${SRCS} pathnames.h + mkdep ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${SRCS} + +${DESTDIR}${DESTSBIN}: + mkdir -p ${DESTDIR}${DESTSBIN} + +install: ${DESTDIR}${DESTSBIN} ${PROG}${EXE} + ${INSTALL} ${INSTALL_EXEC} ${STRIP} -c -m 755 ${PROG}${EXE} ${DESTDIR}${DESTSBIN}/${PROG}${EXE} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +tags: FRC + ctags ${SRCS} *.h + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Property changes on: vendor/bind/8.3.4/contrib/bind/bin/ndc/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/nslookup/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/nslookup/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/nslookup/Makefile (revision 109985) @@ -0,0 +1,98 @@ +## Copyright (c) 1996,1999 by Internet Software Consortium +## +## 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. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM 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 +## SOFTWARE. + +# $Id: Makefile,v 8.28 2002/05/21 00:44:59 marka Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g -Wall + +#(net2 and its descendents) +SYSTYPE = freebsd +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +EXE= +LEX = lex -I +SYSLIBS =-lutil +LIBL=-ll +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +STRIP=-s +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin + +LDFLAGS= +DEFS= -D_PATH_HELPFILE=\"${DESTHELP}/nslookup.help\" +CFLAGS= ${CDEBUG} +CPPFLAGS= -I${PORTINCL} -I${INCL} ${DEFS} + +PROG= nslookup +CSRCS= main.c getinfo.c debug.c send.c skip.c list.c subr.c +SRCS= ${CSRCS} commands.l +OBJS= main.${O} getinfo.${O} debug.${O} send.${O} skip.${O} list.${O} \ + subr.${O} commands.${O} + +all: ${PROG}${EXE} + +${PROG}${EXE}: ${OBJS} ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} ${BOUNDS} -o ${PROG}${EXE} ${OBJS} \ + ${LIBBIND} ${LIBL} ${SYSLIBS} + +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c + +distclean: clean + rm -f commands.c + +clean: FRC + rm -f ${PROG}${EXE} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + rm -f lex.yy.c lex.yy.o + +depend: ${SRCS} + mkdep ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${DEFS} ${CSRCS} + +${DESTDIR}${DESTHELP}: + mkdir -p ${DESTDIR}${DESTHELP} + +${DESTDIR}${DESTBIN}: + mkdir -p ${DESTDIR}${DESTBIN} + +install: ${DESTDIR}${DESTBIN} ${DESTDIR}${DESTHELP} ${PROG}${EXE} + ${INSTALL} ${STRIP} -c ${INSTALL_EXEC} -m 755 ${PROG}${EXE} ${DESTDIR}${DESTBIN}/${PROG}${EXE} + ${INSTALL} -c ${INSTALL_LIB} -m 444 nslookup.help ${DESTDIR}${DESTHELP}/ + +links: FRC + @set -e; ln -s SRC/*.[chl] SRC/nslookup.help . + +tags: FRC + ctags ${CSRCS} *.h + +commands.c: commands.l + ${LEX} -t $< > $@ || rm $@ + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Property changes on: vendor/bind/8.3.4/contrib/bind/bin/nslookup/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/nslookup/commands.l =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/nslookup/commands.l (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/nslookup/commands.l (revision 109985) @@ -0,0 +1,220 @@ +%{ + +/* + * Copyright (c) 1985 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +#ifndef lint +static char sccsid[] = "@(#)commands.l 5.13 (Berkeley) 7/24/90"; +#endif /* not lint */ + +/* + ******************************************************************************* + * + * commands.l + * + * Andrew Cherenson CS298-26 Fall 1985 + * + * Lex input file for the nslookup program command interpreter. + * When a sequence is recognized, the associated action + * routine is called. The action routine may need to + * parse the string for additional information. + * + * Recognized commands: (identifiers are shown in uppercase) + * + * server NAME - set default server to NAME, using default server + * lserver NAME - set default server to NAME, using initial server + * finger [NAME] - finger the optional NAME + * exit - exit the program + * root - set default server to the root + * ls NAME - list the domain NAME + * view FILE - sorts and view the file with more + * set OPTION - set an option + * help - print help information + * ? - print help information + * NAME - print info about the host/domain NAME + * using default server. + * NAME1 NAME2 - as above, but use NAME2 as server + * + * + * yylex Results: + * 0 upon end-of-file. + * 1 after each command. + * + ******************************************************************************* + */ + +#include "port_before.h" +#include +#include +#include "port_after.h" +#include +#include "res.h" + +extern char rootServerName[]; +extern void PrintHelp(); +extern void ViewList(char *); + +%} +WS [ \t] +FLET [:A-Za-z0-9.*\\_] +LET [:A-Za-z0-9.*_] +NAME [:A-Za-z0-9.*=_/-] +%% +^{WS}*server{WS}+{LET}{NAME}*{WS}*$ { + /* + * 0 == use current server to find + * the new one. + * 1 == use original server to find + * the new one. + */ + SetDefaultServer((char*)yytext, 0); + return(1); + } +^{WS}*lserver{WS}+{LET}{NAME}*{WS}*$ { + SetDefaultServer((char*)yytext, 1); + return(1); + } +^{WS}*exit{WS}*$ { + return(0); + } +^{WS}*root{WS}*$ { + SetDefaultServer(rootServerName, 1); + return(1); + } +^{WS}*finger({WS}+{LET}{NAME}*)?{WS}+>>?{WS}*{NAME}+{WS}*$ { + /* + * 2nd arg. + * 0 == output to stdout + * 1 == output to file + */ + Finger((char*)yytext, 1); + return(1); + } +^{WS}*finger({WS}+{LET}{NAME}*)?{WS}*$ { + Finger((char*)yytext, 0); + return(1); + } +^{WS}*ls{WS}+(("-a"|"-d"|"-h"|"-m"|"-s"){WS}+)?{LET}{NAME}*{WS}+>>?{WS}+{NAME}+{WS}*$ { + /* + * 2nd arg. + * 0 == output to stdout + * 1 == output to file + */ + ListHosts((char*)yytext, 1); + return(1); + } +^{WS}*ls{WS}+(("-a"|"-d"|"-h"|"-m"|"-s"){WS}+)?{LET}{NAME}*{WS}*$ { + ListHosts((char*)yytext, 0); + return(1); + } +^{WS}*ls{WS}+-t{WS}+({LET}{NAME}*{WS}+)?{LET}{NAME}*{WS}+>>?{WS}+{NAME}+{WS}*$ { + /* + * 2nd arg. + * 0 == output to stdout + * 1 == output to file + */ + ListHostsByType((char*)yytext, 1); + return(1); + } +^{WS}*ls{WS}+-t{WS}+({LET}{NAME}*{WS}+)?{LET}{NAME}*{WS}*$ { + ListHostsByType((char*)yytext, 0); + return(1); + } +^{WS}*set{WS}+{NAME}+{WS}*$ { + SetOption((char*)yytext); + return(1); + } +^{WS}*help{WS}*$ { + PrintHelp(); + return(1); + } +^{WS}*"?"{WS}*$ { + extern void PrintHelp(); + + PrintHelp(); + return(1); + } +^{WS}*{FLET}{NAME}*{WS}+>>?{WS}*{NAME}+{WS}*$ { + /* + * 0 == output to stdout + * 1 == output to file + */ + LookupHost((char*)yytext, 1); + return(1); + } +^{WS}*{FLET}{NAME}*{WS}*$ { + LookupHost((char*)yytext, 0); + return(1); + } +^{WS}*{FLET}{NAME}*{WS}+{LET}{NAME}*{WS}+>>?{WS}*{NAME}+{WS}*$ { + /* + * 0 == output to stdout + * 1 == output to file + */ + LookupHostWithServer((char*)yytext, 1); + return(1); + } +^{WS}*{FLET}{NAME}*{WS}+{LET}{NAME}*{WS}*$ { + LookupHostWithServer((char*)yytext, 0); + return(1); + } +^{WS}*\n { + return(1); + } +^.*\n { + printf("Unrecognized command: %s", + (char*)yytext); + return(1); + } +\n { ; } +%% Property changes on: vendor/bind/8.3.4/contrib/bind/bin/nslookup/commands.l ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/nslookup/getinfo.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/nslookup/getinfo.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/nslookup/getinfo.c (revision 109985) @@ -0,0 +1,1104 @@ +/* + * Copyright (c) 1985, 1989 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +#ifndef lint +static const char sccsid[] = "@(#)getinfo.c 5.26 (Berkeley) 3/21/91"; +static const char rcsid[] = "$Id: getinfo.c,v 8.27 2002/05/22 04:06:57 marka Exp $"; +#endif /* not lint */ + +/* + ****************************************************************************** + * + * getinfo.c -- + * + * Routines to create requests to name servers + * and interpret the answers. + * + * Adapted from 4.3BSD BIND gethostnamadr.c + * + ****************************************************************************** + */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#include + +#include "res.h" + +static char *addr_list[MAXADDRS + 1]; +static int addr_len[MAXADDRS + 1]; +static int addr_type[MAXADDRS + 1]; + +static char *host_aliases[MAXALIASES]; +static int host_aliases_len[MAXALIASES]; +static u_char hostbuf[MAXDNAME]; + +typedef struct { + char *name; + char *domain[MAXDOMAINS]; + int numDomains; + char *address[MAXADDRS]; + char len[MAXADDRS]; + char type[MAXADDRS]; + int numAddresses; +} ServerTable; + +ServerTable server[MAXSERVERS]; + +typedef union { + HEADER qb1; + u_char qb2[64*1024]; +} querybuf; + +typedef union { + int32_t al; + char ac; +} align; + +#define GetShort(cp) ns_get16(cp); cp += INT16SZ; + + +/* + ****************************************************************************** + * + * GetAnswer -- + * + * Interprets an answer packet and retrieves the following + * information: + * + * Results: + * SUCCESS the info was retrieved. + * NO_INFO the packet did not contain an answer. + * NONAUTH non-authoritative information was found. + * ERROR the answer was malformed. + * Other errors returned in the packet header. + * + ****************************************************************************** + */ + +static int +GetAnswer(union res_sockaddr_union *nsAddrPtr, int queryType, + char *msg, int msglen, Boolean iquery, HostInfo *hostPtr, + Boolean isServer, Boolean merge) +{ + register HEADER *headerPtr; + register const u_char *cp; + querybuf answer; + char **aliasPtr; + u_char *eom, *bp; + char **addrPtr; + int *lenPtr; + int *typePtr; + char *namePtr; + char *dnamePtr; + int type, class; + int qdcount, ancount, arcount, nscount, buflen; + int origClass = 0; + int numAliases = 0; + int numAddresses = 0; + int n, i, j, k, l, m; + int dlen; + int status; + int numServers; + size_t s; + Boolean haveAnswer; + Boolean printedAnswers = FALSE; + int oldAliases; + char **newAliases; + int oldServers; + ServerInfo **newServers; + int oldAddresses; + AddrInfo **newAddresses; + + + /* + * If the hostPtr was used before, free up the calloc'd areas. + */ + if (!merge) + FreeHostInfoPtr(hostPtr); + + status = SendRequest(nsAddrPtr, (u_char *)msg, msglen, (u_char *) &answer, + sizeof(answer), &n); + + if (status != SUCCESS) { + if (res.options & RES_DEBUG2) + printf("SendRequest failed\n"); + return (status); + } + eom = (u_char *) &answer + n; + + headerPtr = (HEADER *) &answer; + + if (headerPtr->rcode != NOERROR) { + return (headerPtr->rcode); + } + + qdcount = ntohs(headerPtr->qdcount); + ancount = ntohs(headerPtr->ancount); + arcount = ntohs(headerPtr->arcount); + nscount = ntohs(headerPtr->nscount); + + /* + * If there are no answer, n.s. or additional records + * then return with an error. + */ + if (ancount == 0 && nscount == 0 && arcount == 0) { + return (NO_INFO); + } + + + bp = hostbuf; + buflen = sizeof(hostbuf); + cp = (u_char *) &answer + HFIXEDSZ; + + /* Skip over question section. */ + while (qdcount-- > 0) { + n = dn_skipname(cp, eom); + if (n < 0) + return (ERROR); + cp += n + QFIXEDSZ; + if (cp > eom) + return (ERROR); + } + + aliasPtr = host_aliases; + addrPtr = addr_list; + lenPtr = addr_len; + typePtr = addr_type; + haveAnswer = FALSE; + + /* + * Scan through the answer resource records. + * Answers for address query types are saved. + * Other query type answers are just printed. + */ + if (ancount != 0) { + + if (headerPtr->ad) + printf("Answer crypto-validated by server:\n"); + + if (!isServer && !headerPtr->aa) { + printf("Non-authoritative answer:\n"); + } + + if (queryType != T_A && queryType != T_AAAA && /* A6? */ + !(iquery && queryType == T_PTR)) { + while (--ancount >= 0 && cp < eom) { + if ((cp = Print_rr(cp, (u_char *)&answer, + eom, stdout)) == NULL) { + return(ERROR); + } + } + printedAnswers = TRUE; + } else { + while (--ancount >= 0 && cp < eom) { + n = dn_expand(answer.qb2, eom, cp, (char *)bp, buflen); + if (n < 0) + return(ERROR); + cp += n; + if (cp + 3 * INT16SZ + INT32SZ > eom) + return (ERROR); + type = GetShort(cp); + class = GetShort(cp); + cp += INT32SZ; /* skip TTL */ + dlen = GetShort(cp); + if (cp + dlen > eom) + return (ERROR); + if (type == T_CNAME) { + /* + * Found an alias. + */ + cp += dlen; + if (aliasPtr >= &host_aliases[MAXALIASES-1]) { + continue; + } + *aliasPtr++ = (char *)bp; + s = strlen((char *)bp) + 1; + host_aliases_len[numAliases] = s; + numAliases++; + bp += s; + buflen -= s; + continue; + } else if (type == T_PTR) { + /* + * Found a "pointer" to the real name. + */ + n = dn_expand(answer.qb2, eom, cp, (char *)bp, buflen); + if (n < 0) { + cp += n; + continue; + } + cp += n; + s = strlen((char *)bp) + 1; + hostPtr->name = Calloc(1, s); + memcpy(hostPtr->name, bp, s); + haveAnswer = TRUE; + break; + } else if (type != T_A && type != T_AAAA) { + cp += dlen; + continue; + } + if (type == T_A && dlen != INADDRSZ) + return (ERROR); + if (type == T_AAAA && dlen != 16) + return (ERROR); + if (haveAnswer) { + /* + * If we've already got 1 address, we aren't interested + * in addresses with a different class. + */ + if (class != origClass) { + cp += dlen; + continue; + } + } else { + /* + * First address: record its class so we only save + * additonal ones with the same attributes. + */ + origClass = class; + if (hostPtr->name == NULL) { + s = strlen((char *)bp) + 1; + hostPtr->name = Calloc(1, s); + memcpy(hostPtr->name, bp, s); + } + } + bp += (((u_int32_t)bp) % sizeof(align)); + + if (bp + dlen >= &hostbuf[sizeof(hostbuf)]) { + if (res.options & RES_DEBUG) { + printf("Size (%d) too big\n", dlen); + } + break; + } + if (numAddresses >= MAXADDRS) { + printf("MAXADDRS exceeded: skipping address\n"); + cp += dlen; + continue; + } + memcpy(*addrPtr++ = (char *)bp, cp, dlen); + *lenPtr++ = dlen; + *typePtr++ = (class == C_IN) ? + ((type == T_A) ? AF_INET : AF_INET6) : + AF_UNSPEC; + bp += dlen; + cp += dlen; + numAddresses++; + haveAnswer = TRUE; + } + } + } + + if ((queryType == T_A || queryType == T_AAAA || queryType == T_PTR) && + haveAnswer) { + + /* + * Go through the alias and address lists and return them + * in the hostPtr variable. + */ + + oldAliases = 0; + if (merge && hostPtr->aliases != NULL) { + while (hostPtr->aliases[oldAliases] != NULL) + oldAliases++; + } + if (numAliases > 0) { + newAliases = + (char **) Calloc(1 + numAliases + oldAliases, sizeof(char *)); + if (merge && hostPtr->aliases != NULL) { + memcpy(newAliases, hostPtr->aliases, + oldAliases * sizeof(char *)); + free(hostPtr->aliases); + } + hostPtr->aliases = newAliases; + k = oldAliases; + for (i = 0; i < numAliases; i++) { + for (l = 0; l < k; l++) + if (!strcasecmp(hostPtr->aliases[l], host_aliases[i])) + break; + if (l < k) + continue; + hostPtr->aliases[k] = Calloc(1, host_aliases_len[i]); + memcpy(hostPtr->aliases[k], host_aliases[i], + host_aliases_len[i]); + k++; + } + hostPtr->aliases[k] = NULL; + } + oldAddresses = 0; + if (merge && hostPtr->addrList != NULL) { + while (hostPtr->addrList[oldAddresses] != NULL) + oldAddresses++; + } + if (numAddresses > 0) { + newAddresses = + (AddrInfo **)Calloc(1+numAddresses, sizeof(AddrInfo *)); + if (merge && hostPtr->addrList != NULL) { + memcpy(newAddresses, hostPtr->addrList, + oldAddresses * sizeof(char *)); + free(hostPtr->addrList); + } + hostPtr->addrList = newAddresses; + k = oldAddresses; + for (i = 0; i < numAddresses; i++) { + for (l = 0; l < k; l++) + if (hostPtr->addrList[l]->addrType == addr_type[i] && + hostPtr->addrList[l]->addrLen == addr_len[i] && + !memcmp(hostPtr->addrList[l]->addr, addr_list[i], + addr_len[i])) + break; + if (l < k) + continue; + hostPtr->addrList[k] = (AddrInfo*)Calloc(1, sizeof(AddrInfo)); + hostPtr->addrList[k]->addr = Calloc(1, addr_len[i]); + hostPtr->addrList[k]->addrType = addr_type[i]; + hostPtr->addrList[k]->addrLen = addr_len[i]; + memcpy(hostPtr->addrList[k]->addr, addr_list[i], addr_len[i]); + k++; + } + hostPtr->addrList[k] = NULL; + } +#ifdef verbose + if (headerPtr->aa || nscount == 0) { + hostPtr->servers = NULL; + return (SUCCESS); + } +#else + hostPtr->servers = NULL; + return (SUCCESS); +#endif + } + + /* + * At this point, for the T_A query type, only empty answers remain. + * For other query types, additional information might be found + * in the additional resource records part. + */ + + if (!headerPtr->aa && (queryType != T_A) && (queryType != T_AAAA) && + (nscount > 0 || arcount > 0)) { + if (printedAnswers) { + putchar('\n'); + } + printf("Authoritative answers can be found from:\n"); + } + + cp = res_skip((u_char *)&answer, 2, eom); + + numServers = 0; + if (queryType != T_A && queryType != T_AAAA) { + /* + * If we don't need to save the record, just print it. + */ + while (--nscount >= 0 && cp < eom) { + if ((cp = Print_rr(cp, (u_char *) &answer, + eom, stdout)) == NULL) { + return(ERROR); + } + } + } else { + while (--nscount >= 0 && cp < eom) { + /* + * Go through the NS records and retrieve the names of hosts + * that serve the requested domain. + */ + + n = dn_expand(answer.qb2, eom, cp, (char *)bp, buflen); + if (n < 0) { + return(ERROR); + } + cp += n; + s = strlen((char *)bp) + 1; + dnamePtr = Calloc(1, s); /* domain name */ + memcpy(dnamePtr, bp, s); + + if (cp + 3 * INT16SZ + INT32SZ > eom) + return (ERROR); + type = GetShort(cp); + class = GetShort(cp); + cp += INT32SZ; /* skip TTL */ + dlen = GetShort(cp); + if (cp + dlen > eom) + return (ERROR); + + if (type != T_NS) { + cp += dlen; + } else { + Boolean found; + + n = dn_expand(answer.qb2, eom, cp, (char *)bp, buflen); + if (n < 0) { + return(ERROR); + } + cp += n; + s = strlen((char *)bp) + 1; + namePtr = Calloc(1, s); /* server host name */ + memcpy(namePtr, bp, s); + + /* + * Store the information keyed by the server host name. + */ + found = FALSE; + for (j = 0; j < numServers; j++) { + if (strcasecmp(namePtr, server[j].name) == 0) { + found = TRUE; + free(namePtr); + break; + } + } + if (found) { + server[j].numDomains++; + if (server[j].numDomains <= MAXDOMAINS) { + server[j].domain[server[j].numDomains-1] = dnamePtr; + } + } else { + if (numServers >= MAXSERVERS) { + break; + } + server[numServers].name = namePtr; + server[numServers].domain[0] = dnamePtr; + server[numServers].numDomains = 1; + server[numServers].numAddresses = 0; + numServers++; + } + } + } + } + + /* + * Additional resource records contain addresses of servers. + */ + cp = res_skip((u_char*)&answer, 3, eom); + + if (queryType != T_A && queryType != T_AAAA) { + /* + * If we don't need to save the record, just print it. + */ + while (--arcount >= 0 && cp < eom) { + if ((cp = Print_rr(cp, (u_char *) &answer, + eom, stdout)) == NULL) { + return(ERROR); + } + } + } else { + while (--arcount >= 0 && cp < eom) { + n = dn_expand(answer.qb2, eom, cp, (char *)bp, buflen); + if (n < 0) { + break; + } + cp += n; + if (cp + 3 * INT16SZ + INT32SZ > eom) + return (ERROR); + type = GetShort(cp); + class = GetShort(cp); + cp += INT32SZ; /* skip TTL */ + dlen = GetShort(cp); + if (cp + dlen > eom) + return (ERROR); + + if (type != T_A && type != T_AAAA) { + cp += dlen; + continue; + } else { + if (type == T_A && dlen != INADDRSZ) + return (ERROR); + if (type == T_AAAA && dlen != 16) + return (ERROR); + for (j = 0; j < numServers; j++) { + if (strcasecmp((char *)bp, server[j].name) == 0) { + server[j].numAddresses++; + if (server[j].numAddresses <= MAXADDRS) { + server[j].address[server[j].numAddresses-1] = + Calloc(1,dlen); + memcpy(server[j].address[server[j].numAddresses-1], + cp, dlen); + server[j].len[server[j].numAddresses-1] = dlen; + server[j].type[server[j].numAddresses-1] = + (type == T_A) ? AF_INET : AF_INET6; + break; + } + } + } + cp += dlen; + } + } + } + + /* + * If we are returning name server info, transfer it to the hostPtr. + */ + oldServers = 0; + if (merge && hostPtr->servers != NULL) { + while (hostPtr->servers[oldServers] != NULL) + oldServers++; + } + if (numServers > 0) { + newServers = (ServerInfo **) Calloc(numServers+oldServers+1, + sizeof(ServerInfo *)); + if (merge && hostPtr->servers != NULL) { + memcpy(newServers, hostPtr->servers, + oldServers * sizeof(ServerInfo *)); + free(hostPtr->servers); + } + hostPtr->servers = newServers; + k = oldServers; + for (i = 0; i < numServers; i++) { + for (l = 0; l < k; l++) + if (!strcasecmp(hostPtr->servers[l]->name, server[i].name)) + break; + if (l < k) { + free(server[i].name); + for (j = 0; j < server[i].numDomains; j++) + free(server[i].domain[j]); + } else { + hostPtr->servers[l] = (ServerInfo *) + Calloc(1, sizeof(ServerInfo)); + hostPtr->servers[l]->name = server[i].name; + k++; + + hostPtr->servers[l]->domains = (char **) + Calloc(server[i].numDomains+1,sizeof(char *)); + for (j = 0; j < server[i].numDomains; j++) { + hostPtr->servers[l]->domains[j] = server[i].domain[j]; + } + hostPtr->servers[l]->domains[j] = NULL; + } + + + oldAddresses = 0; + if (merge && hostPtr->servers[l]->addrList != NULL) + while (hostPtr->servers[l]->addrList[oldAddresses] != NULL) + oldAddresses++; + newAddresses = (AddrInfo **) + Calloc(server[i].numAddresses+oldAddresses+1, + sizeof(AddrInfo *)); + if (merge && hostPtr->servers[l]->addrList != NULL) { + memcpy(newAddresses, hostPtr->servers[l]->addrList, + sizeof(AddrInfo *) * oldAddresses); + free(hostPtr->servers[l]->addrList); + } + hostPtr->servers[l]->addrList = newAddresses; + m = oldAddresses; + for (j = 0; j < server[l].numAddresses; j++) { + for (n = 0; n < m; n++) + if (hostPtr->servers[l]->addrList[n]->addrType == + server[i].type[j] && + hostPtr->servers[l]->addrList[n]->addrLen == + server[i].len[j] && + !memcmp(hostPtr->servers[l]->addrList[n]->addr, + server[i].address[j], server[i].len[j])) + break; + if (n < m) { + free(server[i].address[j]); + continue; + } + hostPtr->servers[l]->addrList[m] = + (AddrInfo*)Calloc(1, sizeof(AddrInfo)); + hostPtr->servers[l]->addrList[m]->addr = + server[i].address[j]; + hostPtr->servers[l]->addrList[m]->addrType = + server[i].type[j]; + hostPtr->servers[l]->addrList[m]->addrLen = + server[i].len[j]; + m++; + } + hostPtr->servers[l]->addrList[m] = NULL; + } + hostPtr->servers[k] = NULL; + } + + switch (queryType) { + case T_AAAA: + case T_A: + return NONAUTH; + case T_PTR: + if (iquery) + return NO_INFO; + /* fall through */ + default: + return SUCCESS; + } +} + +/* +******************************************************************************* +* +* GetHostInfo -- +* +* Retrieves host name, address and alias information +* for a domain. +* +* Algorithm from res_nsearch(). +* +* Results: +* ERROR - res_nmkquery failed. +* + return values from GetAnswer() +* +******************************************************************************* +*/ + +int +GetHostInfoByName(nsAddrPtr, queryClass, queryType, name, hostPtr, isServer, + merge) + union res_sockaddr_union *nsAddrPtr; + int queryClass; + int queryType; + const char *name; + HostInfo *hostPtr; + Boolean isServer; + Boolean merge; +{ + int n; + register int result; + register char **domain; + const char *cp; + Boolean got_nodata = FALSE; + union res_sockaddr_union ina; + Boolean tried_as_is = FALSE; + char tmp[NS_MAXDNAME]; + + /* Catch explicit addresses */ + if ((queryType == T_A) && IsAddr(name, &ina)) { + hostPtr->name = Calloc(strlen(name)+3, 1); + (void)sprintf(hostPtr->name,"[%s]",name); + switch (ina.sin.sin_family) { + case AF_INET: + hostPtr->aliases = NULL; + hostPtr->servers = NULL; + hostPtr->addrList = (AddrInfo **)Calloc(2, sizeof(AddrInfo *)); + hostPtr->addrList[0] = (AddrInfo *)Calloc(1, sizeof(AddrInfo)); + hostPtr->addrList[0]->addr = Calloc(INT32SZ, sizeof(char)); + memcpy(hostPtr->addrList[0]->addr, &ina.sin.sin_addr, INADDRSZ); + hostPtr->addrList[0]->addrType = AF_INET; + hostPtr->addrList[0]->addrLen = INADDRSZ; + hostPtr->addrList[1] = NULL; + break; + case AF_INET6: + hostPtr->aliases = NULL; + hostPtr->servers = NULL; + hostPtr->addrList = (AddrInfo **)Calloc(2, sizeof(AddrInfo *)); + hostPtr->addrList[0] = (AddrInfo *)Calloc(1, sizeof(AddrInfo)); + hostPtr->addrList[0]->addr = Calloc(1, 16); + memcpy(hostPtr->addrList[0]->addr, &ina.sin6.sin6_addr, 16); + hostPtr->addrList[0]->addrType = AF_INET6; + hostPtr->addrList[0]->addrLen = 16; + hostPtr->addrList[1] = NULL; + break; + } + return(SUCCESS); + } + + result = NXDOMAIN; + for (cp = name, n = 0; *cp; cp++) + if (*cp == '.') + n++; + if (n == 0 && (cp = res_hostalias(&res, name, tmp, sizeof tmp))) { + printf("Aliased to \"%s\"\n\n", cp); + return (GetHostDomain(nsAddrPtr, queryClass, queryType, + cp, (char *)NULL, hostPtr, isServer, merge)); + } + + /* + * If there are dots in the name already, let's just give it a try + * 'as is'. The threshold can be set with the "ndots" option. + */ + if (n >= (int)res.ndots) { + result = GetHostDomain(nsAddrPtr, queryClass, queryType, + name, (char *)NULL, hostPtr, isServer, + merge); + if (result == SUCCESS) + return (result); + if (result == NO_INFO) + got_nodata++; + tried_as_is++; + } + + /* + * We do at least one level of search if + * - there is no dot and RES_DEFNAME is set, or + * - there is at least one dot, there is no trailing dot, + * and RES_DNSRCH is set. + */ + if ((n == 0 && (res.options & RES_DEFNAMES) != 0) || + (n != 0 && *--cp != '.' && (res.options & RES_DNSRCH) != 0)) + for (domain = res.dnsrch; *domain != NULL; domain++) { + result = GetHostDomain(nsAddrPtr, queryClass, queryType, + name, *domain, hostPtr, isServer, + merge); + /* + * If no server present, give up. + * If name isn't found in this domain, + * keep trying higher domains in the search list + * (if that's enabled). + * On a NO_INFO error, keep trying, otherwise + * a wildcard entry of another type could keep us + * from finding this entry higher in the domain. + * If we get some other error (negative answer or + * server failure), then stop searching up, + * but try the input name below in case it's fully-qualified. + */ + if (result == SUCCESS || result == NO_RESPONSE) + return result; + if (result == NO_INFO) + got_nodata++; + if ((result != NXDOMAIN && result != NO_INFO) || + (res.options & RES_DNSRCH) == 0) + break; + } + /* if we have not already tried the name "as is", do that now. + * note that we do this regardless of how many dots were in the + * name or whether it ends with a dot. + */ + if (!tried_as_is && + (result = GetHostDomain(nsAddrPtr, queryClass, queryType, + name, (char *)NULL, hostPtr, isServer, merge) + ) == SUCCESS) + return (result); + if (got_nodata) + result = NO_INFO; + return (result); +} + +/* + * Perform a query on the concatenation of name and domain, + * removing a trailing dot from name if domain is NULL. + */ +int +GetHostDomain(nsAddrPtr, queryClass, queryType, name, domain, hostPtr, + isServer, merge) + union res_sockaddr_union *nsAddrPtr; + int queryClass; + int queryType; + const char *name; + char *domain; + HostInfo *hostPtr; + Boolean isServer; + Boolean merge; +{ + querybuf buf; + char nbuf[2*MAXDNAME+2]; + const char *longname = nbuf; + int n; + + if (domain == NULL) { + /* + * Check for trailing '.'; + * copy without '.' if present. + */ + n = strlen(name) - 1; + if (name[n] == '.' && n < (int)sizeof(nbuf) - 1) { + memcpy(nbuf, name, n); + nbuf[n] = '\0'; + } else + longname = name; + } else { + (void)sprintf(nbuf, "%.*s.%.*s", + MAXDNAME, name, MAXDNAME, domain); + longname = nbuf; + } + n = res_nmkquery(&res, QUERY, longname, queryClass, queryType, + NULL, 0, 0, buf.qb2, sizeof(buf)); + if (n < 0) { + if (res.options & RES_DEBUG) { + printf("Res_nmkquery failed\n"); + } + return (ERROR); + } + + n = GetAnswer(nsAddrPtr, queryType, (char *)&buf, n, 0, hostPtr, + isServer, merge); + + /* + * GetAnswer didn't find a name, so set it to the specified one. + */ + if (n == NONAUTH) { + if (hostPtr->name == NULL) { + size_t len = strlen(longname) + 1; + + hostPtr->name = Calloc(len, sizeof(char)); + memcpy(hostPtr->name, longname, len); + } + } + return(n); +} + + +/* +******************************************************************************* +* +* GetHostInfoByAddr -- +* +* Performs a PTR lookup in in-addr.arpa to find the host name +* that corresponds to the given address. +* +* Results: +* ERROR - res_nmkquery failed. +* + return values from GetAnswer() +* +******************************************************************************* +*/ + +int +GetHostInfoByAddr(union res_sockaddr_union *nsAddrPtr, + union res_sockaddr_union *address, + HostInfo * hostPtr) +{ + int n; + querybuf buf; + char qbuf[MAXDNAME]; + char qbuf2[MAXDNAME]; + char *p = NULL; + int ismapped = 0; + + switch (address->sin.sin_family) { + case AF_INET: + p = (char *) &address->sin.sin_addr.s_addr; + mapped: + (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", + ((unsigned)p[3 + (ismapped ? 12 : 0)] & 0xff), + ((unsigned)p[2 + (ismapped ? 12 : 0)] & 0xff), + ((unsigned)p[1 + (ismapped ? 12 : 0)] & 0xff), + ((unsigned)p[0 + (ismapped ? 12 : 0)] & 0xff)); + break; + case AF_INET6: + p = (char *)address->sin6.sin6_addr.s6_addr; + if (IN6_IS_ADDR_V4MAPPED(&address->sin6.sin6_addr) || + IN6_IS_ADDR_V4COMPAT(&address->sin6.sin6_addr)) { + ismapped = 1; + goto mapped; + } + (void)sprintf(qbuf, + "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." + "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." + "ip6.arpa", + p[15] & 0xf, (p[15] >> 4) & 0xf, + p[14] & 0xf, (p[14] >> 4) & 0xf, + p[13] & 0xf, (p[13] >> 4) & 0xf, + p[12] & 0xf, (p[12] >> 4) & 0xf, + p[11] & 0xf, (p[11] >> 4) & 0xf, + p[10] & 0xf, (p[10] >> 4) & 0xf, + p[9] & 0xf, (p[9] >> 4) & 0xf, + p[8] & 0xf, (p[8] >> 4) & 0xf, + p[7] & 0xf, (p[7] >> 4) & 0xf, + p[6] & 0xf, (p[4] >> 4) & 0xf, + p[5] & 0xf, (p[5] >> 4) & 0xf, + p[4] & 0xf, (p[4] >> 4) & 0xf, + p[3] & 0xf, (p[3] >> 4) & 0xf, + p[2] & 0xf, (p[2] >> 4) & 0xf, + p[1] & 0xf, (p[1] >> 4) & 0xf, + p[0] & 0xf, (p[0] >> 4) & 0xf); + (void)sprintf(qbuf2, + "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." + "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." + "ip6.int", + p[15] & 0xf, (p[15] >> 4) & 0xf, + p[14] & 0xf, (p[14] >> 4) & 0xf, + p[13] & 0xf, (p[13] >> 4) & 0xf, + p[12] & 0xf, (p[12] >> 4) & 0xf, + p[11] & 0xf, (p[11] >> 4) & 0xf, + p[10] & 0xf, (p[10] >> 4) & 0xf, + p[9] & 0xf, (p[9] >> 4) & 0xf, + p[8] & 0xf, (p[8] >> 4) & 0xf, + p[7] & 0xf, (p[7] >> 4) & 0xf, + p[6] & 0xf, (p[4] >> 4) & 0xf, + p[5] & 0xf, (p[5] >> 4) & 0xf, + p[4] & 0xf, (p[4] >> 4) & 0xf, + p[3] & 0xf, (p[3] >> 4) & 0xf, + p[2] & 0xf, (p[2] >> 4) & 0xf, + p[1] & 0xf, (p[1] >> 4) & 0xf, + p[0] & 0xf, (p[0] >> 4) & 0xf); + break; + } + n = res_nmkquery(&res, QUERY, qbuf, C_IN, T_PTR, NULL, 0, NULL, + buf.qb2, sizeof buf); + if (n < 0) { + if (res.options & RES_DEBUG) { + printf("res_nmkquery() failed\n"); + } + return (ERROR); + } + n = GetAnswer(nsAddrPtr, T_PTR, (char *) &buf, n, 1, hostPtr, 1, 0); + if (n == SUCCESS) { + switch (address->sin.sin_family) { + case AF_INET: + hostPtr->addrList = (AddrInfo **)Calloc(2, sizeof(AddrInfo *)); + hostPtr->addrList[0] = (AddrInfo *)Calloc(1, sizeof(AddrInfo)); + hostPtr->addrList[0]->addr = Calloc(INT32SZ, sizeof(char)); + memcpy(hostPtr->addrList[0]->addr, p, INADDRSZ); + hostPtr->addrList[0]->addrType = AF_INET; + hostPtr->addrList[0]->addrLen = 4; + hostPtr->addrList[1] = NULL; + break; + case AF_INET6: + hostPtr->addrList = (AddrInfo **)Calloc(2, sizeof(AddrInfo *)); + hostPtr->addrList[0] = (AddrInfo *)Calloc(1, sizeof(AddrInfo)); + hostPtr->addrList[0]->addr = Calloc(16, sizeof(char)); + memcpy(hostPtr->addrList[0]->addr, p, 16); + hostPtr->addrList[0]->addrType = AF_INET6; + hostPtr->addrList[0]->addrLen = 16; + hostPtr->addrList[1] = NULL; + break; + } + } + if (n == SUCCESS || ismapped || address->sin.sin_family != AF_INET6) + return n; + n = res_nmkquery(&res, QUERY, qbuf2, C_IN, T_PTR, NULL, 0, NULL, + buf.qb2, sizeof buf); + if (n < 0) { + if (res.options & RES_DEBUG) { + printf("res_nmkquery() failed\n"); + } + return (ERROR); + } + n = GetAnswer(nsAddrPtr, T_PTR, (char *) &buf, n, 1, hostPtr, 1, 0); + if (n == SUCCESS) { + hostPtr->addrList = (AddrInfo **)Calloc(2, sizeof(AddrInfo *)); + hostPtr->addrList[0] = (AddrInfo *)Calloc(1, sizeof(AddrInfo *)); + hostPtr->addrList[0]->addr = Calloc(16, sizeof(char)); + memcpy(hostPtr->addrList[0]->addr, p, 16); + hostPtr->addrList[0]->addrType = AF_INET6; + hostPtr->addrList[0]->addrLen = 16; + hostPtr->addrList[1] = NULL; + } + return n; +} + +/* +******************************************************************************* +* +* FreeHostInfoPtr -- +* +* Deallocates all the calloc'd areas for a HostInfo variable. +* +******************************************************************************* +*/ + +void +FreeHostInfoPtr(hostPtr) + register HostInfo *hostPtr; +{ + int i, j; + + if (hostPtr->name != NULL) { + free(hostPtr->name); + hostPtr->name = NULL; + } + + if (hostPtr->aliases != NULL) { + i = 0; + while (hostPtr->aliases[i] != NULL) { + free(hostPtr->aliases[i]); + i++; + } + free((char *)hostPtr->aliases); + hostPtr->aliases = NULL; + } + + if (hostPtr->addrList != NULL) { + i = 0; + while (hostPtr->addrList[i] != NULL) { + free(hostPtr->addrList[i]->addr); + free(hostPtr->addrList[i]); + i++; + } + free((char *)hostPtr->addrList); + hostPtr->addrList = NULL; + } + + if (hostPtr->servers != NULL) { + i = 0; + while (hostPtr->servers[i] != NULL) { + + if (hostPtr->servers[i]->name != NULL) { + free(hostPtr->servers[i]->name); + } + + if (hostPtr->servers[i]->domains != NULL) { + j = 0; + while (hostPtr->servers[i]->domains[j] != NULL) { + free(hostPtr->servers[i]->domains[j]); + j++; + } + free((char *)hostPtr->servers[i]->domains); + } + + if (hostPtr->servers[i]->addrList != NULL) { + j = 0; + while (hostPtr->servers[i]->addrList[j] != NULL) { + free(hostPtr->servers[i]->addrList[j]->addr); + free(hostPtr->servers[i]->addrList[j]); + j++; + } + free((char *)hostPtr->servers[i]->addrList); + } + free((char *)hostPtr->servers[i]); + i++; + } + free((char *)hostPtr->servers); + hostPtr->servers = NULL; + } +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/nslookup/getinfo.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/nslookup/main.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/nslookup/main.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/nslookup/main.c (revision 109985) @@ -0,0 +1,1331 @@ +/* + * Copyright (c) 1985, 1989 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1985,1989 Regents of the University of California.\n\ + All rights reserved.\n\ + @(#) Portions Copyright (c) 1996-1999 Internet Software Consortium.\n"; +#endif /* not lint */ + +#ifndef lint +static const char sccsid[] = "@(#)main.c 5.42 (Berkeley) 3/3/91"; +static const char rcsid[] = "$Id: main.c,v 8.24 2002/05/26 03:12:20 marka Exp $"; +#endif /* not lint */ + +/* + ****************************************************************************** + * + * main.c -- + * + * Main routine and some action routines for the name server + * lookup program. + * + * Andrew Cherenson + * U.C. Berkeley Computer Science Div. + * CS298-26, Fall 1985 + * + ****************************************************************************** + */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +#include + +#include "res.h" +#include "pathnames.h" + +int yylex(void); + +/* + * Name of a top-level name server. Can be changed with + * the "set root" command. + */ + +#ifndef ROOT_SERVER +#define ROOT_SERVER "f.root-servers.net." +#endif +char rootServerName[NAME_LEN] = ROOT_SERVER; + +/* + * Declare a resolver context. + */ + +struct __res_state res; + + +/* + * Info about the most recently queried host. + */ + +HostInfo curHostInfo; +int curHostValid = FALSE; + + +/* + * Info about the default name server. + */ + +HostInfo *defaultPtr = NULL; +char defaultServer[NAME_LEN]; +union res_sockaddr_union defaultAddr; + + +/* + * Initial name server query type is Address. + */ + +int queryType = T_A; +int queryClass = C_IN; + +/* + * Stuff for Interrupt (control-C) signal handler. + */ + +extern SIG_FN IntrHandler(int); +FILE *filePtr; +jmp_buf env; + + +/* + * Browser command for help. + */ +const char *pager; + +static void CvtAddrToPtr(char *name); +static void ReadRC(void); + +/* + * Forward declarations. + */ +static void LocalServer(HostInfo *defaultPtr); +static void res_re_init(void); +static void res_dnsrch(char *cp); +static void Usage(void); +static void ShowOptions(void); + +static void +UnionFromAddr(union res_sockaddr_union *u, int family, void *addr) { + memset(u, 0, sizeof *u); + switch (family) { + case AF_INET: + u->sin.sin_family = AF_INET; + u->sin.sin_port = htons(nsport); + memcpy(&u->sin.sin_addr, addr, 4); +#ifdef HAVE_SA_LEN + u->sin.sin_len = sizeof(u->sin); +#endif + break; + case AF_INET6: + u->sin6.sin6_family = AF_INET6; + u->sin6.sin6_port = htons(nsport); + memcpy(&u->sin6.sin6_addr, addr, 16); +#ifdef HAVE_SA_LEN + u->sin6.sin6_len = sizeof(u->sin6); +#endif + break; + default: + abort(); + } +} + +/* + ****************************************************************************** + * + * main -- + * + * Initializes the resolver library and determines the address + * of the initial name server. The yylex routine is used to + * read and perform commands. + * + ****************************************************************************** + */ + +int +main(int argc, char **argv) { + char *wantedHost = NULL; + Boolean useLocalServer; + int result; + int i; + + /* + * Initialize the resolver library routines. + */ + + if (res_ninit(&res) == -1) { + fprintf(stderr,"*** Can't initialize resolver.\n"); + exit(1); + } + + /* + * Allocate space for the default server's host info and + * find the server's address and name. If the resolver library + * already has some addresses for a potential name server, + * then use them. Otherwise, see if the current host has a server. + * Command line arguments may override the choice of initial server. + */ + + defaultPtr = (HostInfo *) Calloc(1, sizeof(HostInfo)); + + /* + * Parse the arguments: + * no args = go into interactive mode, use default host as server + * 1 arg = use as host name to be looked up, default host will be server + * non-interactive mode + * 2 args = 1st arg: + * if it is '-', then + * ignore but go into interactive mode + * else + * use as host name to be looked up, + * go into non-interactive mode + * 2nd arg: name or inet address of server + * + * "Set" options are specified with a leading - and must come before + * any arguments. For example, to find the well-known services for + * a host, type "nslookup -query=wks host" + */ + + ReadRC(); /* look for options file */ + + ++argv; --argc; /* skip prog name */ + + while (argc && *argv[0] == '-' && argv[0][1]) { + (void) SetOption (&(argv[0][1])); + ++argv; --argc; + } + if (argc > 2) { + Usage(); + } + if (argc && *argv[0] != '-') { + wantedHost = *argv; /* name of host to be looked up */ + } + + useLocalServer = FALSE; + if (argc == 2) { + int nscount = 0; + union res_sockaddr_union u[MAXNS]; + struct addrinfo *answer = NULL; + struct addrinfo *cur = NULL; + struct addrinfo hint; + + /* + * Use an explicit name server. If the hostname lookup fails, + * default to the server(s) in resolv.conf. + */ + + memset(u, 0, sizeof(u)); + memset(&hint, 0, sizeof(hint)); + hint.ai_socktype = SOCK_DGRAM; + if (!getaddrinfo(*++argv, NULL, &hint, &answer)) { + for (cur = answer; cur != NULL; cur = cur->ai_next) { + if (nscount == MAXNS) + break; + switch (cur->ai_addr->sa_family) { + case AF_INET6: + u[nscount].sin6 = *(struct sockaddr_in6*)cur->ai_addr; + u[nscount++].sin6.sin6_port = htons(nsport); + break; + case AF_INET: + u[nscount].sin = *(struct sockaddr_in*)cur->ai_addr; + u[nscount++].sin.sin_port = htons(nsport); + break; + } + } + if (nscount != 0) + res_setservers(&res, u, nscount); + freeaddrinfo(answer);; + } + } + + + if (res.nscount == 0 || useLocalServer) { + LocalServer(defaultPtr); + } else { + int nscount = 0; + union res_sockaddr_union u[MAXNS]; + + nscount = res_getservers(&res, u, MAXNS); + for (i = 0; i < nscount; i++) { + if (u[i].sin.sin_family == AF_INET && + u[i].sin.sin_addr.s_addr == INADDR_ANY) { + LocalServer(defaultPtr); + break; + } else { + result = GetHostInfoByAddr(&u[i], &u[i], defaultPtr); + if (result != SUCCESS) { + char t[80]; + switch (u[i].sin.sin_family) { + case AF_INET: + inet_ntop(AF_INET, &u[i].sin.sin_addr, t, sizeof(t)); + break; + case AF_INET6: + inet_ntop(AF_INET6, &u[i].sin6.sin6_addr, t, sizeof(t)); + break; + default: + strcpy(t, ""); + break; + } + fprintf(stderr, + "*** Can't find server name for address %s: %s\n", + t, DecodeError(result)); + } else { + defaultAddr = u[i]; + break; + } + } + } + + /* + * If we have exhausted the list, tell the user about the + * command line argument to specify an address. + */ + + if (i == res.nscount) { + fprintf(stderr, "*** Default servers are not available\n"); + exit(1); + } + + } + strcpy(defaultServer, defaultPtr->name); + + +#ifdef DEBUG +#ifdef DEBUG2 + res.options |= RES_DEBUG2; +#endif + res.options |= RES_DEBUG; + res.retry = 2; +#endif /* DEBUG */ + + /* + * If we're in non-interactive mode, look up the wanted host and quit. + * Otherwise, print the initial server's name and continue with + * the initialization. + */ + + if (wantedHost != (char *) NULL) { + LookupHost(wantedHost, 0); + } else { + PrintHostInfo(stdout, "Default Server:", defaultPtr); + + pager = getenv("PAGER"); + if (pager == NULL) { + pager = _PATH_PAGERCMD; + } + + /* + * Setup the environment to allow the interrupt handler to return here. + */ + + (void) setjmp(env); + + /* + * Return here after a longjmp. + */ + + signal(SIGINT, IntrHandler); + signal(SIGPIPE, SIG_IGN); + + /* + * Read and evaluate commands. The commands are described in commands.l + * Yylex returns 0 when ^D or 'exit' is typed. + */ + + printf("> "); + fflush(stdout); + while(yylex()) { + printf("> "); + fflush(stdout); + } + } + exit(0); +} + + +static void +LocalServer(defaultPtr) + HostInfo *defaultPtr; +{ + char hostName[NAME_LEN]; + + (void) gethostname(hostName, sizeof(hostName)); + + memset(&defaultAddr, 0, sizeof(defaultAddr)); + defaultAddr.sin.sin_addr.s_addr = htonl(INADDR_ANY); + defaultAddr.sin.sin_family = AF_INET; + defaultAddr.sin.sin_port = htons(nsport); +#ifdef HAVE_SA_LEN + defaultAddr.sin.sin_len = sizeof(defaultAddr.sin); +#endif + (void) GetHostInfoByName(&defaultAddr, C_IN, T_A, + "0.0.0.0", defaultPtr, 1, 0); + free(defaultPtr->name); + defaultPtr->name = Calloc(1, sizeof(hostName)+1); + strcpy(defaultPtr->name, hostName); +} + + +/* + ****************************************************************************** + * + * Usage -- + * + * Lists the proper methods to run the program and exits. + * + ****************************************************************************** + */ + +static void +Usage(void) { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, +" nslookup [-opt ...] # interactive mode using default server\n"); + fprintf(stderr, +" nslookup [-opt ...] - server # interactive mode using 'server'\n"); + fprintf(stderr, +" nslookup [-opt ...] host # just look up 'host' using default server\n"); + fprintf(stderr, +" nslookup [-opt ...] host server # just look up 'host' using 'server'\n"); + exit(1); +} + +/* + ****************************************************************************** + * + * IsAddr -- + * + * Returns TRUE if the string looks like an Internet address. + * A string with a trailing dot is not an address, even if it looks + * like one. + * + ****************************************************************************** + */ + +Boolean +IsAddr(host, addrPtr) + const char *host; + union res_sockaddr_union *addrPtr; + /* If return TRUE, contains IP address */ +{ + if (inet_pton(AF_INET6, host, &addrPtr->sin6.sin6_addr) == 1) { + addrPtr->sin6.sin6_family = AF_INET6; + addrPtr->sin6.sin6_port = htons(nsport); +#ifdef HAVE_SA_LEN + addrPtr->sin6.sin6_len = sizeof(addrPtr->sin6); +#endif + } else if (inet_pton(AF_INET, host, &addrPtr->sin.sin_addr) == 1) { + addrPtr->sin.sin_family = AF_INET; + addrPtr->sin.sin_port = htons(nsport); +#ifdef HAVE_SA_LEN + addrPtr->sin.sin_len = sizeof(addrPtr->sin); +#endif + } else + return FALSE; + return TRUE; +} + + +/* + ****************************************************************************** + * + * SetDefaultServer -- + * + * Changes the default name server to the one specified by + * the first argument. The command "server name" uses the current + * default server to lookup the info for "name". The command + * "lserver name" uses the original server to lookup "name". + * + * Side effects: + * This routine will cause a core dump if the allocation requests fail. + * + * Results: + * SUCCESS The default server was changed successfully. + * NONAUTH The server was changed but addresses of + * other servers who know about the requested server + * were returned. + * Errors No info about the new server was found or + * requests to the current server timed-out. + * + ****************************************************************************** + */ + +int +SetDefaultServer(string, local) + char *string; + Boolean local; +{ + register HostInfo *newDefPtr; + union res_sockaddr_union servAddr; + union res_sockaddr_union addr; + char newServer[NAME_LEN]; + int result; + int tresult; + int i; + int j; + + /* + * Parse the command line. It maybe of the form "server name", + * "lserver name" or just "name". + */ + + if (local) { + i = matchString (" lserver ", string); + if (i > 0) { + j = pickString(string + i, newServer, sizeof newServer); + if (j == 0) { /* value was too big for newServer variable */ + fprintf(stderr, + "SetDefaultServer: invalid name: %s\n", + string + i); + return(ERROR); + } + } + } else { + i = matchString(" server ", string); + if (i > 0) { + j = pickString(string + i, newServer, sizeof newServer); + if (j == 0) { /* value was too big for newServer variable */ + fprintf(stderr, + "SetDefaultServer: invalid name: %s\n", + string + i); + return(ERROR); + } + } + } + + if (i == 0) { + i = pickString(string, newServer, sizeof newServer); + if (i == 0) { /* value was too big for newServer variable */ + fprintf(stderr,"SetDefaultServer: invalid name: %s\n", string); + return(ERROR); + } + } + + /* + * Allocate space for a HostInfo variable for the new server. Don't + * overwrite the old HostInfo struct because info about the new server + * might not be found and we need to have valid default server info. + */ + + newDefPtr = (HostInfo *) Calloc(1, sizeof(HostInfo)); + + + /* + * A 'local' lookup uses the original server that the program was + * initialized with. + * + * Check to see if we have the address of the server or the + * address of a server who knows about this domain. + * XXX For now, just use the first address in the list. + */ + + if (local) { + servAddr = defaultAddr; + } else if (defaultPtr->addrList != NULL) { + UnionFromAddr(&servAddr, defaultPtr->addrList[0]->addrType, + defaultPtr->addrList[0]->addr); + } else { + UnionFromAddr(&servAddr, defaultPtr->addrList[0]->addrType, + defaultPtr->servers[0]->addrList[0]->addr); + } + + result = ERROR; + if (IsAddr(newServer, &addr)) { + result = GetHostInfoByAddr(&servAddr, &addr, newDefPtr); + /* If we can't get the name, fall through... */ + } + if (result != SUCCESS && result != NONAUTH) { + result = GetHostInfoByName(&servAddr, C_IN, T_A, + newServer, newDefPtr, 1, 0); + if (result == SUCCESS || result == NONAUTH || result == NO_INFO) + tresult = GetHostInfoByName(&servAddr, C_IN, T_AAAA, + newServer, newDefPtr, 1, 1); + if (result == NO_INFO) + result = tresult; + } + + /* If we ask for an A record and get none back, but get an NS + record for the NS server, this is the NONAUTH case. + We must check whether we got an IP address for the NS + server or not. */ + if ((result == SUCCESS || result == NONAUTH) && + ((newDefPtr->addrList && newDefPtr->addrList[0] != 0) || + (newDefPtr->servers && newDefPtr->servers[0] && + newDefPtr->servers[0]->addrList[0] != 0))) { + /* + * Found info about the new server. Free the resources for + * the old server. + */ + + FreeHostInfoPtr(defaultPtr); + free((char *)defaultPtr); + defaultPtr = newDefPtr; + strcpy(defaultServer, defaultPtr->name); + PrintHostInfo(stdout, "Default Server:", defaultPtr); + return(SUCCESS); + } else { + fprintf(stderr, "*** Can't find address for server %s: %s\n", + newServer, DecodeError(result)); + free((char *)newDefPtr); + + return(result); + } +} + +/* + ****************************************************************************** + * + * DoLoookup -- + * + * Common subroutine for LookupHost and LookupHostWithServer. + * + * Results: + * SUCCESS - the lookup was successful. + * Misc. Errors - an error message is printed if the lookup failed. + * + ****************************************************************************** + */ + +static int +DoLookup(host, servPtr, serverName) + char *host; + HostInfo *servPtr; + char *serverName; +{ + int result; + union res_sockaddr_union servAddr; + union res_sockaddr_union addr; + + /* Skip escape character */ + if (host[0] == '\\') + host++; + + /* + * If the user gives us an address for an address query, + * silently treat it as a PTR query. If the query type is already + * PTR, then convert the address into the in-addr.arpa format. + * + * Use the address of the server if it exists, otherwise use the + * address of a server who knows about this domain. + * XXX For now, just use the first address in the list. + */ + + if (servPtr->addrList != NULL) { + UnionFromAddr(&servAddr, servPtr->addrList[0]->addrType, + servPtr->addrList[0]->addr); + } else { + UnionFromAddr(&servAddr, servPtr->servers[0]->addrList[0]->addrType, + servPtr->servers[0]->addrList[0]->addr); + } + + /* + * RFC1123 says we "SHOULD check the string syntactically for a + * dotted-decimal number before looking it up [...]" (p. 13). + */ + if ((queryType == T_A || queryType == T_AAAA) && IsAddr(host, &addr)) { + result = GetHostInfoByAddr(&servAddr, &addr, &curHostInfo); + } else { + if (queryType == T_PTR) { + CvtAddrToPtr(host); + } + result = GetHostInfoByName(&servAddr, queryClass, queryType, host, + &curHostInfo, 0, 0); + } + + switch (result) { + case SUCCESS: + /* + * If the query was for an address, then the &curHostInfo + * variable can be used by Finger. + * There's no need to print anything for other query types + * because the info has already been printed. + */ + if (queryType == T_A || queryType == T_AAAA) { + curHostValid = TRUE; + PrintHostInfo(filePtr, "Name:", &curHostInfo); + } + break; + + /* + * No Authoritative answer was available but we got names + * of servers who know about the host. + */ + case NONAUTH: + PrintHostInfo(filePtr, "Name:", &curHostInfo); + break; + + case NO_INFO: + fprintf(stderr, "*** No %s (%s) records available for %s\n", + DecodeType(queryType), p_type(queryType), host); + break; + + case TIME_OUT: + fprintf(stderr, "*** Request to %s timed-out\n", serverName); + break; + + default: + fprintf(stderr, "*** %s can't find %s: %s\n", serverName, host, + DecodeError(result)); + } + return result; +} + +/* + ****************************************************************************** + * + * LookupHost -- + * + * Asks the default name server for information about the + * specified host or domain. The information is printed + * if the lookup was successful. + * + * Results: + * ERROR - the output file could not be opened. + * + results of DoLookup + * + ****************************************************************************** + */ + +int +LookupHost(string, putToFile) + char *string; + Boolean putToFile; +{ + char host[NAME_LEN]; + char file[PATH_MAX]; + int result; + int i; + + /* + * Invalidate the current host information to prevent Finger + * from using bogus info. + */ + + curHostValid = FALSE; + + /* + * Parse the command string into the host and + * optional output file name. + * + */ + + i = pickString(string, host, sizeof host); + if (i == 0) { /* string was too long for host variable */ + fprintf(stderr, "*** invalid name: %s\n", string); + return(ERROR); + } + + if (!putToFile) { + filePtr = stdout; + } else { + filePtr = OpenFile(string, file, sizeof file); + if (filePtr == NULL) { + fprintf(stderr, "*** Can't open %s for writing\n", file); + return(ERROR); + } + fprintf(filePtr,"> %s\n", string); + } + + PrintHostInfo(filePtr, "Server:", defaultPtr); + + result = DoLookup(host, defaultPtr, defaultServer); + + if (putToFile) { + fclose(filePtr); + filePtr = NULL; + } + return(result); +} + +/* + ****************************************************************************** + * + * LookupHostWithServer -- + * + * Asks the name server specified in the second argument for + * information about the host or domain specified in the first + * argument. The information is printed if the lookup was successful. + * + * Address info about the requested name server is obtained + * from the default name server. This routine will return an + * error if the default server doesn't have info about the + * requested server. Thus an error return status might not + * mean the requested name server doesn't have info about the + * requested host. + * + * Comments from LookupHost apply here, too. + * + * Results: + * ERROR - the output file could not be opened. + * + results of DoLookup + * + ****************************************************************************** + */ + +int +LookupHostWithServer(char *string, Boolean putToFile) { + char file[PATH_MAX]; + char host[NAME_LEN]; + char server[NAME_LEN]; + int result; + static HostInfo serverInfo; + int i; + int j; + union res_sockaddr_union u; + + curHostValid = FALSE; + + i = pickString(string, host, sizeof host); + if (i == 0) { /* value was too big for host variable */ + fprintf(stderr, "*** invalid name: %s\n", string); + return(ERROR); + } + + j = pickString(string + i, server, sizeof server); + if (j == 0) { /* value was too big for server variable */ + fprintf(stderr, "*** invalid server name: %s\n", string + i); + return(ERROR); + } + + if (!putToFile) { + filePtr = stdout; + } else { + filePtr = OpenFile(string, file, sizeof file); + if (filePtr == NULL) { + fprintf(stderr, "*** Can't open %s for writing\n", file); + return(ERROR); + } + fprintf(filePtr,"> %s\n", string); + } + + if (defaultPtr->addrList != NULL) + UnionFromAddr(&u, defaultPtr->addrList[0]->addrType, + defaultPtr->addrList[0]->addr); + else + UnionFromAddr(&u, defaultPtr->servers[0]->addrList[0]->addrType, + defaultPtr->servers[0]->addrList[0]->addr); + result = GetHostInfoByName(&u, C_IN, T_A, server, &serverInfo, 1, 0); + if (result == NO_INFO) + result = GetHostInfoByName(&u, C_IN, T_AAAA, server, + &serverInfo, 1, 1); + + if (result != SUCCESS) { + fprintf(stderr,"*** Can't find address for server %s: %s\n", server, + DecodeError(result)); + } else { + PrintHostInfo(filePtr, "Server:", &serverInfo); + + result = DoLookup(host, &serverInfo, server); + } + if (putToFile) { + fclose(filePtr); + filePtr = NULL; + } + return(result); +} + +/* + ****************************************************************************** + * + * SetOption -- + * + * This routine is used to change the state information + * that affect the lookups. The command format is + * set keyword[=value] + * Most keywords can be abbreviated. Parsing is very simplistic-- + * A value must not be separated from its keyword by white space. + * + * Valid keywords: Meaning: + * all lists current values of options. + * ALL lists current values of options, including + * hidden options. + * [no]d2 turn on/off extra debugging mode. + * [no]debug turn on/off debugging mode. + * [no]defname use/don't use default domain name. + * [no]search use/don't use domain search list. + * domain=NAME set default domain name to NAME. + * [no]ignore ignore/don't ignore trunc. errors. + * query=value set default query type to value, + * value is one of the query types in RFC883 + * without the leading T_. (e.g., A, HINFO) + * [no]recurse use/don't use recursive lookup. + * retry=# set number of retries to #. + * root=NAME change root server to NAME. + * time=# set timeout length to #. + * [no]vc use/don't use virtual circuit. + * port TCP/UDP port to server. + * + * Deprecated: + * [no]primary use/don't use primary server. + * + * Results: + * SUCCESS the command was parsed correctly. + * ERROR the command was not parsed correctly. + * + ****************************************************************************** + */ + +int +SetOption(option) + register char *option; +{ + char type[NAME_LEN]; + char *ptr; + int tmp; + int i; + + while (isspace(*option)) + ++option; + if (strncmp (option, "set ", 4) == 0) + option += 4; + while (isspace(*option)) + ++option; + + if (*option == 0) { + fprintf(stderr, "*** Invalid set command\n"); + return(ERROR); + } else { + if (strncmp(option, "all", 3) == 0) { + ShowOptions(); + } else if (strncmp(option, "ALL", 3) == 0) { + ShowOptions(); + } else if (strncmp(option, "d2", 2) == 0) { /* d2 (more debug) */ + res.options |= (RES_DEBUG | RES_DEBUG2); + } else if (strncmp(option, "nod2", 4) == 0) { + res.options &= ~RES_DEBUG2; + printf("d2 mode disabled; still in debug mode\n"); + } else if (strncmp(option, "def", 3) == 0) { /* defname */ + res.options |= RES_DEFNAMES; + } else if (strncmp(option, "nodef", 5) == 0) { + res.options &= ~RES_DEFNAMES; + } else if (strncmp(option, "do", 2) == 0) { /* domain */ + ptr = strchr(option, '='); + if (ptr != NULL) { + i = pickString(++ptr, res.defdname, sizeof res.defdname); + if (i == 0) { /* name too long or nothing there */ + fprintf(stderr, "** invalid 'domain' value: %s\n", + ptr) ; + return(ERROR); + } + + res_re_init(); + } + } else if (strncmp(option, "deb", 1) == 0) { /* debug */ + res.options |= RES_DEBUG; + } else if (strncmp(option, "nodeb", 5) == 0) { + res.options &= ~(RES_DEBUG | RES_DEBUG2); + } else if (strncmp(option, "ig", 2) == 0) { /* ignore */ + res.options |= RES_IGNTC; + } else if (strncmp(option, "noig", 4) == 0) { + res.options &= ~RES_IGNTC; + } else if (strncmp(option, "po", 2) == 0) { /* port */ + ptr = strchr(option, '='); + if (ptr != NULL) { + sscanf(++ptr, "%hu", &nsport); + } +#ifdef deprecated + } else if (strncmp(option, "pri", 3) == 0) { /* primary */ + res.options |= RES_PRIMARY; + } else if (strncmp(option, "nopri", 5) == 0) { + res.options &= ~RES_PRIMARY; +#endif + } else if (strncmp(option, "q", 1) == 0 || /* querytype */ + strncmp(option, "ty", 2) == 0) { /* type */ + ptr = strchr(option, '='); + if (ptr != NULL) { + i = pickString(++ptr, type, sizeof type); + if (i == 0) { /* value too big or nothing there */ + fprintf(stderr, "*** invalid type value: %s\n", + ptr) ; + return(ERROR); + } + + i = StringToType(type, queryType, stderr); + if (ns_t_xfr_p(i)) { + fprintf(stderr, "*** qtype may not be a zone transfer\n"); + return(ERROR); + } + + queryType = i; + } + } else if (strncmp(option, "cl", 2) == 0) { /* query class */ + ptr = strchr(option, '='); + if (ptr != NULL) { + i = pickString(++ptr, type, sizeof type); + if (i == 0) { /* value too big or nothing there */ + fprintf(stderr, "*** invalid class : %s\n", + ptr) ; + return(ERROR); + } + + queryClass = StringToClass(type, queryClass, stderr); + } + } else if (strncmp(option, "rec", 3) == 0) { /* recurse */ + res.options |= RES_RECURSE; + } else if (strncmp(option, "norec", 5) == 0) { + res.options &= ~RES_RECURSE; + } else if (strncmp(option, "ret", 3) == 0) { /* retry */ + ptr = strchr(option, '='); + if (ptr != NULL) { + sscanf(++ptr, "%d", &tmp); + if (tmp >= 0) { + res.retry = tmp; + } + } + } else if (strncmp(option, "ro", 2) == 0) { /* root */ + ptr = strchr(option, '='); + if (ptr != NULL) { + i = pickString(++ptr, rootServerName, sizeof rootServerName); + if (i == 0) { /* value too big or nothing there */ + fprintf(stderr, "*** invalid root server name : %s\n", + ptr) ; + return(ERROR) ; + } + } + } else if (strncmp(option, "sea", 3) == 0) { /* search list */ + res.options |= RES_DNSRCH; + } else if (strncmp(option, "nosea", 5) == 0) { + res.options &= ~RES_DNSRCH; + } else if (strncmp(option, "srchl", 5) == 0) { /* domain search list */ + ptr = strchr(option, '='); + if (ptr != NULL) { + res_dnsrch(++ptr); + } + } else if (strncmp(option, "ti", 2) == 0) { /* timeout */ + ptr = strchr(option, '='); + if (ptr != NULL) { + sscanf(++ptr, "%d", &tmp); + if (tmp >= 0) { + res.retrans = tmp; + } + } + } else if (strncmp(option, "v", 1) == 0) { /* vc */ + res.options |= RES_USEVC; + } else if (strncmp(option, "nov", 3) == 0) { + res.options &= ~RES_USEVC; + } else { + fprintf(stderr, "*** Invalid option: %s\n", option); + return(ERROR); + } + } + return(SUCCESS); +} + +/* + * Fake a reinitialization when the domain is changed. + */ +static void +res_re_init(void) { + register char *cp, **pp; + int n; + + /* find components of local domain that might be searched */ + pp = res.dnsrch; + *pp++ = res.defdname; + for (cp = res.defdname, n = 0; *cp; cp++) + if (*cp == '.') + n++; + cp = res.defdname; + for (; n >= LOCALDOMAINPARTS && pp < res.dnsrch + MAXDFLSRCH; n--) { + cp = strchr(cp, '.'); + *pp++ = ++cp; + } + *pp = 0; + res.options |= RES_INIT; +} + +#define SRCHLIST_SEP '/' + +static void +res_dnsrch(char *cp) { + char **pp; + int n; + + (void)strncpy(res.defdname, cp, sizeof(res.defdname) - 1); + res.defdname[sizeof(res.defdname) - 1] = '\0'; + if ((cp = strchr(res.defdname, '\n')) != NULL) + *cp = '\0'; + /* + * Set search list to be blank-separated strings + * on rest of line. + */ + cp = res.defdname; + pp = res.dnsrch; + *pp++ = cp; + for (n = 0; *cp && pp < res.dnsrch + MAXDNSRCH; cp++) { + if (*cp == SRCHLIST_SEP) { + *cp = '\0'; + n = 1; + } else if (n) { + *pp++ = cp; + n = 0; + } + } + if ((cp = strchr(pp[-1], SRCHLIST_SEP)) != NULL) { + *cp = '\0'; + } + *pp = NULL; +} + + +/* + ****************************************************************************** + * + * ShowOptions -- + * + * Prints out the state information used by the resolver + * library and other options set by the user. + * + ****************************************************************************** + */ + +static void +ShowOptions(void) +{ + register char **cp; + + PrintHostInfo(stdout, "Default Server:", defaultPtr); + if (curHostValid) { + PrintHostInfo(stdout, "Host:", &curHostInfo); + } + + printf("Set options:\n"); + printf(" %sdebug \t", (res.options & RES_DEBUG) ? "" : "no"); + printf(" %sdefname\t", (res.options & RES_DEFNAMES) ? "" : "no"); + printf(" %ssearch\t", (res.options & RES_DNSRCH) ? "" : "no"); + printf(" %srecurse\n", (res.options & RES_RECURSE) ? "" : "no"); + + printf(" %sd2\t\t", (res.options & RES_DEBUG2) ? "" : "no"); + printf(" %svc\t\t", (res.options & RES_USEVC) ? "" : "no"); + printf(" %signoretc\t", (res.options & RES_IGNTC) ? "" : "no"); + printf(" port=%u\n", nsport); + + printf(" querytype=%s\t", p_type(queryType)); + printf(" class=%s\t", p_class(queryClass)); + printf(" timeout=%d\t", res.retrans); + printf(" retry=%d\n", res.retry); + printf(" root=%s\n", rootServerName); + printf(" domain=%s\n", res.defdname); + + cp = res.dnsrch; + if (cp != NULL) { + printf(" srchlist=%s", *cp); + for (cp++; *cp; cp++) { + printf("%c%s", SRCHLIST_SEP, *cp); + } + putchar('\n'); + } + putchar('\n'); +} +#undef SRCHLIST_SEP + +/* + ****************************************************************************** + * + * PrintHelp -- + * + * Displays the help file. + * + ****************************************************************************** + */ + +void +PrintHelp(void) +{ + char cmd[PATH_MAX]; + + sprintf(cmd, "%s %s", pager, _PATH_HELPFILE); + system(cmd); +} + +/* + ****************************************************************************** + * + * CvtAddrToPtr -- + * + * Convert a dotted-decimal Internet address into the standard + * PTR format (reversed address with .in-arpa. suffix). + * + * Assumes the argument buffer is large enougth to hold the result. + * + ****************************************************************************** + */ + +static void +CvtAddrToPtr(name) + char *name; +{ + const char *p; + int ip[4]; + union res_sockaddr_union addr; + + if (IsAddr(name, &addr)) { + switch (addr.sin.sin_family) { + case AF_INET: + p = inet_ntoa(addr.sin.sin_addr); + if (sscanf(p, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3]) == 4) + sprintf(name, "%d.%d.%d.%d.in-addr.arpa.", + ip[3], ip[2], ip[1], ip[0]); + break; + case AF_INET6: + sprintf(name, + "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." + "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." + "ip6.arpa", + addr.sin6.sin6_addr.s6_addr[15] & 0xf, + (addr.sin6.sin6_addr.s6_addr[15] >> 4) & 0xf, + addr.sin6.sin6_addr.s6_addr[14] & 0xf, + (addr.sin6.sin6_addr.s6_addr[14] >> 4) & 0xf, + addr.sin6.sin6_addr.s6_addr[13] & 0xf, + (addr.sin6.sin6_addr.s6_addr[13] >> 4) & 0xf, + addr.sin6.sin6_addr.s6_addr[12] & 0xf, + (addr.sin6.sin6_addr.s6_addr[12] >> 4) & 0xf, + addr.sin6.sin6_addr.s6_addr[11] & 0xf, + (addr.sin6.sin6_addr.s6_addr[11] >> 4) & 0xf, + addr.sin6.sin6_addr.s6_addr[10] & 0xf, + (addr.sin6.sin6_addr.s6_addr[10] >> 4) & 0xf, + addr.sin6.sin6_addr.s6_addr[9] & 0xf, + (addr.sin6.sin6_addr.s6_addr[9] >> 4) & 0xf, + addr.sin6.sin6_addr.s6_addr[8] & 0xf, + (addr.sin6.sin6_addr.s6_addr[8] >> 4) & 0xf, + addr.sin6.sin6_addr.s6_addr[7] & 0xf, + (addr.sin6.sin6_addr.s6_addr[7] >> 4) & 0xf, + addr.sin6.sin6_addr.s6_addr[6] & 0xf, + (addr.sin6.sin6_addr.s6_addr[6] >> 4) & 0xf, + addr.sin6.sin6_addr.s6_addr[5] & 0xf, + (addr.sin6.sin6_addr.s6_addr[5] >> 4) & 0xf, + addr.sin6.sin6_addr.s6_addr[4] & 0xf, + (addr.sin6.sin6_addr.s6_addr[4] >> 4) & 0xf, + addr.sin6.sin6_addr.s6_addr[3] & 0xf, + (addr.sin6.sin6_addr.s6_addr[3] >> 4) & 0xf, + addr.sin6.sin6_addr.s6_addr[2] & 0xf, + (addr.sin6.sin6_addr.s6_addr[2] >> 4) & 0xf, + addr.sin6.sin6_addr.s6_addr[1] & 0xf, + (addr.sin6.sin6_addr.s6_addr[1] >> 4) & 0xf, + addr.sin6.sin6_addr.s6_addr[0] & 0xf, + (addr.sin6.sin6_addr.s6_addr[0] >> 4) & 0xf); + break; + } + } +} + +/* + ****************************************************************************** + * + * ReadRC -- + * + * Use the contents of ~/.nslookuprc as options. + * + ****************************************************************************** + */ + +static void +ReadRC(void) +{ + register FILE *fp; + register char *cp; + char buf[PATH_MAX]; + + if ((cp = getenv("HOME")) != NULL && + (strlen(cp) + strlen(_PATH_NSLOOKUPRC)) < sizeof(buf)) { + + (void) strcpy(buf, cp); + (void) strcat(buf, _PATH_NSLOOKUPRC); + + if ((fp = fopen(buf, "r")) != NULL) { + while (fgets(buf, sizeof(buf), fp) != NULL) { + if ((cp = strchr(buf, '\n')) != NULL) { + *cp = '\0'; + } + (void) SetOption(buf); + } + (void) fclose(fp); + } + } +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/nslookup/main.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/nslookup/send.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/nslookup/send.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/nslookup/send.c (revision 109985) @@ -0,0 +1,404 @@ +/* + * Copyright (c) 1985, 1989 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +#ifndef lint +static const char sccsid[] = "@(#)send.c 5.18 (Berkeley) 3/2/91"; +static const char rcsid[] = "$Id: send.c,v 8.14 2002/05/10 04:35:09 marka Exp $"; +#endif /* not lint */ + +/* + ****************************************************************************** + * + * send.c -- + * + * Routine to send request packets to a name server. + * + * Based on "@(#)res_send.c 6.25 (Berkeley) 6/1/90". + * + ****************************************************************************** + */ + + +/* + * Send query to name server and wait for reply. + */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "port_after.h" + +#include "res.h" + +static int s = -1; /* socket used for communications */ + +unsigned short nsport = NAMESERVER_PORT; + + + +/* + ****************************************************************************** + * + * SendRequest -- + * + * Sends a request packet to a name server whose address + * is specified by the first argument and returns with + * the answer packet. + * + * Results: + * SUCCESS - the request was sent and an answer + * was received. + * TIME_OUT - the virtual circuit connection timed-out + * or a reply to a datagram wasn't received. + * + * + ****************************************************************************** + */ + +int +SendRequest(union res_sockaddr_union *nsAddrPtr, const u_char *buf, + int buflen, u_char *answer, u_int anslen, int *trueLenPtr) +{ + int n, try, v_circuit, resplen; + ISC_SOCKLEN_T salen; + int gotsomewhere = 0, connected = 0; + int connreset = 0; + u_short id, len; + u_char *cp; + fd_set dsmask; + struct timeval timeout; + const HEADER *hp = (const HEADER *) buf; + HEADER *anhp = (HEADER *) answer; + struct iovec iov[2]; + int terrno = ETIMEDOUT; + char junk[512]; + struct sockaddr_storage sa; + int family = nsAddrPtr->sin.sin_family; + int clen = (family == AF_INET) ? sizeof(struct sockaddr_in) : + sizeof(struct sockaddr_in6); + + if (res.options & RES_DEBUG2) { + printf("------------\nSendRequest(), len %d\n", buflen); + Print_query(buf, buf + buflen, 1); + } + v_circuit = (res.options & RES_USEVC) || buflen > PACKETSZ; + id = hp->id; + /* + * Send request, RETRY times, or until successful + */ + for (try = 0; try < res.retry; try++) { + usevc: + if (v_circuit) { + int truncated = 0; + + /* + * Use virtual circuit; + * at most one attempt per server. + */ + try = res.retry; + if (s < 0) { + s = socket(family, SOCK_STREAM, 0); + if (s < 0) { + terrno = errno; + if (res.options & RES_DEBUG) + perror("socket (vc) failed"); + continue; + } + if (connect(s, (struct sockaddr *)nsAddrPtr, + clen) < 0) { + terrno = errno; + if (res.options & RES_DEBUG) + perror("connect failed"); + (void) close(s); + s = -1; + continue; + } + } + /* + * Send length & message + */ + __putshort(buflen, (u_char *)&len); + iov[0].iov_base = (caddr_t)&len; + iov[0].iov_len = INT16SZ; + DE_CONST(buf, iov[1].iov_base); + iov[1].iov_len = buflen; + if (writev(s, iov, 2) != INT16SZ + buflen) { + terrno = errno; + if (res.options & RES_DEBUG) + perror("write failed"); + (void) close(s); + s = -1; + continue; + } + /* + * Receive length & response + */ + cp = answer; + len = INT16SZ; + while ((n = read(s, (char *)cp, (int)len)) > 0) { + cp += n; + if ((len -= n) <= 0) + break; + } + if (n <= 0) { + terrno = errno; + if (res.options & RES_DEBUG) + perror("read failed"); + (void) close(s); + s = -1; + /* + * A long running process might get its TCP + * connection reset if the remote server was + * restarted. Requery the server instead of + * trying a new one. When there is only one + * server, this means that a query might work + * instead of failing. We only allow one reset + * per query to prevent looping. + */ + if (terrno == ECONNRESET && !connreset) { + connreset = 1; + } + continue; + } + cp = answer; + if ((resplen = ns_get16((u_char*)cp)) > (int)anslen) { + if (res.options & RES_DEBUG) + fprintf(stderr, "response truncated\n"); + len = anslen; + truncated = 1; + } else + len = resplen; + while (len != 0 && + (n = read(s, (char *)cp, (int)len)) > 0) { + cp += n; + len -= n; + } + if (n <= 0) { + terrno = errno; + if (res.options & RES_DEBUG) + perror("read failed"); + (void) close(s); + s = -1; + continue; + } + if (truncated) { + /* + * Flush rest of answer + * so connection stays in synch. + */ + anhp->tc = 1; + len = resplen - anslen; + while (len != 0) { + n = (len > sizeof(junk) ? + sizeof(junk) : len); + if ((n = read(s, junk, n)) > 0) + len -= n; + else + break; + } + } + } else { + /* + * Use datagrams. + */ + if (s < 0) { + s = socket(family, SOCK_DGRAM, 0); + if (s < 0) { + terrno = errno; + if (res.options & RES_DEBUG) + perror("socket (dg) failed"); + continue; + } + } +#if BSD >= 43 + if (connected == 0) { + if (connect(s, (struct sockaddr *)nsAddrPtr, + clen) < 0) { + if (res.options & RES_DEBUG) + perror("connect"); + continue; + } + connected = 1; + } + if (send(s, buf, buflen, 0) != buflen) { + if (res.options & RES_DEBUG) + perror("send"); + continue; + } +#else /* BSD */ + if (sendto(s, (const char *)buf, buflen, 0, + (struct sockaddr *) nsAddrPtr, + clen) != buflen) { + if (res.options & RES_DEBUG) + perror("sendto"); + continue; + } +#endif + + /* + * Wait for reply + */ + timeout.tv_sec = (res.retrans << try); + if (timeout.tv_sec <= 0) + timeout.tv_sec = 1; + timeout.tv_usec = 0; + wait: + FD_ZERO(&dsmask); + FD_SET(s, &dsmask); + n = select(s+1, &dsmask, (fd_set *)NULL, + (fd_set *)NULL, &timeout); + if (n < 0) { + if (res.options & RES_DEBUG) + perror("select"); + continue; + } + if (n == 0) { + /* + * timeout + */ + if (res.options & RES_DEBUG) + printf("timeout\n"); +#if BSD >= 43 + gotsomewhere = 1; +#endif + continue; + } + + salen = sizeof sa; + resplen = recvfrom(s, (char *)answer, anslen, 0, + (struct sockaddr *)&sa, &salen); + if (resplen <= 0) { + if (res.options & RES_DEBUG) + perror("recvfrom"); + continue; + } + gotsomewhere = 1; + if (id != anhp->id) { + /* + * response from old query, ignore it + */ + if (res.options & RES_DEBUG2) { + printf("------------\nOld answer:\n"); + Print_query(answer, answer+resplen, 1); + } + goto wait; + } + if (!(res.options & RES_IGNTC) && anhp->tc) { + /* + * get rest of answer; + * use TCP with same server. + */ + if (res.options & RES_DEBUG) + printf("truncated answer\n"); + (void) close(s); + s = -1; + v_circuit = 1; + goto usevc; + } + } + if (res.options & RES_DEBUG) { + if (res.options & RES_DEBUG2) + printf("------------\nGot answer (%d bytes):\n", + resplen); + else + printf("------------\nGot answer:\n"); + Print_query(answer, answer+resplen, 1); + } + (void) close(s); + s = -1; + *trueLenPtr = resplen; + return (SUCCESS); + } + if (s >= 0) { + (void) close(s); + s = -1; + } + if (v_circuit == 0) + if (gotsomewhere == 0) + return NO_RESPONSE; /* no nameservers found */ + else + return TIME_OUT; /* no answer obtained */ + else + if (errno == ECONNREFUSED) + return NO_RESPONSE; + else + return ERROR; +} + +/* + * This routine is for closing the socket if a virtual circuit is used and + * the program wants to close it. + * + * Called from the interrupt handler. + */ +void +SendRequest_close(void) { + if (s != -1) { + (void) close(s); + s = -1; + } +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/nslookup/send.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/nslookup/list.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/nslookup/list.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/nslookup/list.c (revision 109985) @@ -0,0 +1,705 @@ +/* + * Copyright (c) 1985, 1989 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +#ifndef lint +static const char sccsid[] = "@(#)list.c 5.23 (Berkeley) 3/21/91"; +static const char rcsid[] = "$Id: list.c,v 8.27 2002/04/09 05:55:17 marka Exp $"; +#endif /* not lint */ + +/* + ******************************************************************************* + * + * list.c -- + * + * Routines to obtain info from name and finger servers. + * + * Adapted from 4.3BSD BIND ns_init.c and from finger.c. + * + ******************************************************************************* + */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +#include "res.h" + +extern char *pager; + +typedef union { + HEADER qb1; + u_char qb2[PACKETSZ]; +} querybuf; + +extern HostInfo *defaultPtr; +extern HostInfo curHostInfo; +extern int curHostValid; +extern int queryType; +extern int queryClass; + +static int sockFD = -1; +int ListSubr(); + +/* + * During a listing to a file, hash marks are printed + * every HASH_SIZE records. + */ + +#define HASH_SIZE 50 + + +/* + ******************************************************************************* + * + * ListHosts -- + * ListHostsByType -- + * + * Requests the name server to do a zone transfer so we + * find out what hosts it knows about. + * + * For ListHosts, there are five types of output: + * - Internet addresses (default) + * - cpu type and operating system (-h option) + * - canonical and alias names (-a option) + * - well-known service names (-s option) + * - ALL records (-d option) + * ListHostsByType prints records of the default type or of a speicific + * type. + * + * To see all types of information sorted by name, do the following: + * ls -d domain.edu > file + * + * Results: + * SUCCESS the listing was successful. + * ERROR the server could not be contacted because + * a socket could not be obtained or an error + * occured while receiving, or the output file + * could not be opened. + * + ******************************************************************************* + */ + +void +ListHostsByType(char *string, int putToFile) { + char *namePtr, name[NAME_LEN], option[NAME_LEN]; + int i, j, qtype, result; + + /* + * Parse the command line. It maybe of the form "ls -t domain" + * or "ls -t type domain". + */ + + /* simulate sscanf(string, " ls -t %s %s", option, name) */ + i = matchString(" ls -t ", string); + if (i > 0) { + j = pickString(string + i, option, sizeof option); + if (j > 0) { + j = pickString(string + i + j, name, sizeof name); + if (j > 0) + i = 2; + else + i = 1; + } else { + i = 0; + } + } + + if (putToFile && i == 2 && name[0] == '>') + i--; + if (i == 2) { + qtype = StringToType(option, -1, stderr); + if (qtype == -1) + return; + namePtr = name; + } else if (i == 1) { + namePtr = option; + qtype = queryType; + } else { + fprintf(stderr, "*** ls: invalid request %s\n", string); + return; + } + result = ListSubr(qtype, namePtr, putToFile ? string : NULL); + if (result != SUCCESS) + fprintf(stderr, "*** Can't list domain %s: %s\n", + namePtr, DecodeError(result)); +} + +void +ListHosts(char *string, int putToFile) { + char *namePtr, name[NAME_LEN], option[NAME_LEN]; + int i, j, qtype, result; + + /* + * Parse the command line. It maybe of the form "ls domain", + * "ls -X domain". + */ + + /* simulate i = sscanf(string, " ls %s %s", option, name) */ + i = matchString(" ls ", string); + if (i > 0) { + j = pickString(string + i, option, sizeof option); + if (j > 0) { + j = pickString(string + i + j, name, sizeof name); + if (j > 0) + i = 2; + else + i = 1; + } else { + i = 0; + } + } + + if (putToFile && i == 2 && name[0] == '>') + i--; + if (i == 2) { + if (strcmp("-a", option) == 0) + qtype = T_CNAME; + else if (strcmp("-h", option) == 0) + qtype = T_HINFO; + else if (strcmp("-m", option) == 0) + qtype = T_MX; + else if (strcmp("-p", option) == 0) + qtype = T_PX; + else if (strcmp("-s", option) == 0) + qtype = T_WKS; + else if (strcmp("-d", option) == 0) + qtype = T_ANY; + else if (strcmp("-n", option) == 0) + qtype = T_NAPTR; + else + qtype = T_A; + namePtr = name; + } else if (i == 1) { + namePtr = option; + qtype = T_A; + } else { + fprintf(stderr, "*** ls: invalid request %s\n",string); + return; + } + result = ListSubr(qtype, namePtr, putToFile ? string : NULL); + if (result != SUCCESS) + fprintf(stderr, "*** Can't list domain %s: %s\n", + namePtr, DecodeError(result)); +} + +int +ListSubr(int qtype, char *domain, char *cmd) { + static u_char *answer = NULL; + static int answerLen = 0; + + ns_msg handle; + querybuf buf; + struct sockaddr_storage sa; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + HEADER *headerPtr; + int msglen, amtToRead, numRead, soacnt; + u_int len; + int numAnswers = 0; + int numRecords = 0; + u_char tmp[INT16SZ], *cp; + char soaname[2][NAME_LEN], file[PATH_MAX]; + enum { NO_ERRORS, ERR_READING_LEN, ERR_READING_MSG, ERR_PRINTING } + error = NO_ERRORS; + struct iovec iov[2]; + AddrInfo *AddrPtr; + int salen = 0; + + /* + * Create a query packet for the requested domain name. + */ + msglen = res_nmkquery(&res, QUERY, domain, queryClass, T_AXFR, + NULL, 0, 0, buf.qb2, sizeof buf); + if (msglen < 0) { + if (_res.options & RES_DEBUG) + fprintf(stderr, "*** ls: res_nmkquery failed\n"); + return (ERROR); + } + + /* + * Check to see if we have the address of the server or the + * address of a server who knows about this domain. + * + * For now, just use the first address in the list. XXX. + */ + + if (defaultPtr->addrList != NULL) + AddrPtr = defaultPtr->addrList[0]; + else + AddrPtr = defaultPtr->servers[0]->addrList[0]; + + memset(&sa, 0, sizeof sa); + switch (AddrPtr->addrType) { + case AF_INET: + sin = (struct sockaddr_in *)&sa; + sin->sin_family = AddrPtr->addrType; + sin->sin_port = htons(nsport); + memcpy(&sin->sin_addr, AddrPtr->addr, AddrPtr->addrLen); +#ifdef HAVE_SA_LEN + sin->sin_len = sizeof(*sin); +#endif + salen = sizeof(struct sockaddr_in); + break; + + case AF_INET6: + sin6 = (struct sockaddr_in6 *)&sa; + sin6->sin6_family = AddrPtr->addrType; + sin6->sin6_port = htons(nsport); + memcpy(&sin6->sin6_addr, AddrPtr->addr, AddrPtr->addrLen); +#ifdef HAVE_SA_LEN + sin6->sin6_len = sizeof(*sin6); +#endif + salen = sizeof(struct sockaddr_in6); + break; + } + + /* + * Set up a virtual circuit to the server. + */ + sockFD = socket(AddrPtr->addrType, SOCK_STREAM, 0); + if (sockFD < 0) { + perror("ls: socket"); + return (ERROR); + } + if (connect(sockFD, (struct sockaddr *)&sa, salen) < 0) { + int e; + + if (errno == ECONNREFUSED) + e = NO_RESPONSE; + else { + perror("ls: connect"); + e = ERROR; + } + (void) close(sockFD); + sockFD = -1; + return (e); + } + + /* + * Send length & message for zone transfer + */ + ns_put16(msglen, tmp); + iov[0].iov_base = (char *)tmp; + iov[0].iov_len = INT16SZ; + iov[1].iov_base = (char *)buf.qb2; + iov[1].iov_len = msglen; + if (writev(sockFD, iov, 2) != INT16SZ + msglen) { + perror("ls: write"); + (void) close(sockFD); + sockFD = -1; + return(ERROR); + } + + fprintf(stdout,"[%s]\n", (defaultPtr->addrList != NULL) + ? defaultPtr->name : defaultPtr->servers[0]->name); + + if (cmd == NULL) { + filePtr = stdout; + } else { + filePtr = OpenFile(cmd, file, sizeof file); + if (filePtr == NULL) { + fprintf(stderr, "*** Can't open %s for writing\n", + file); + (void) close(sockFD); + sockFD = -1; + return (ERROR); + } + fprintf(filePtr, "> %s\n", cmd); + fprintf(filePtr, "[%s]\n", (defaultPtr->addrList != NULL) + ? defaultPtr->name : defaultPtr->servers[0]->name); + } + + soacnt = 0; + while (soacnt < 2) { + /* + * Read the length of the response. + */ + + cp = tmp; amtToRead = INT16SZ; + while (amtToRead > 0 && + (numRead = read(sockFD, cp, amtToRead)) > 0) { + cp += numRead; + amtToRead -= numRead; + } + if (numRead <= 0) { + error = ERR_READING_LEN; + break; + } + + len = ns_get16(tmp); + if (len == 0) + break; /* nothing left to read */ + + /* + * If the server sent too much data to fit the existing + * buffer, allocate a new one. + */ + if (len > (u_int)answerLen) { + if (answerLen != 0) + free(answer); + answerLen = len; + answer = (u_char *)Malloc(answerLen); + } + + /* + * Read the response. + */ + amtToRead = len; cp = answer; + while (amtToRead > 0 && + (numRead = read(sockFD, cp, amtToRead)) > 0) { + cp += numRead; + amtToRead -= numRead; + } + if (numRead <= 0) { + error = ERR_READING_MSG; + break; + } + + if (ns_initparse(answer, cp - answer, &handle) < 0) { + perror("ns_initparse"); + error = ERR_PRINTING; + break; + } + if (ns_msg_getflag(handle, ns_f_rcode) != ns_r_noerror || + ns_msg_count(handle, ns_s_an) == 0) { + /* Signalled protocol error, or empty message. */ + error = ERR_PRINTING; + break; + } + + for (;;) { + static char origin[NS_MAXDNAME], name_ctx[NS_MAXDNAME]; + const char *name; + char buf[2048]; /* XXX need to malloc/realloc. */ + ns_rr rr; + + if (ns_parserr(&handle, ns_s_an, -1, &rr)) { + if (errno != ENODEV) { + perror("ns_parserr"); + error = ERR_PRINTING; + } + break; + } + name = ns_rr_name(rr); + if (origin[0] == '\0' && name[0] != '\0') { + if (strcmp(name, ".") != 0) + strcpy(origin, name); + fprintf(filePtr, "$ORIGIN %s.\n", origin); + if (strcmp(name, ".") == 0) + strcpy(origin, name); + strcpy(name_ctx, "@"); + } + if (qtype == T_ANY || (int)ns_rr_type(rr) == qtype) { + if (ns_sprintrr(&handle, &rr, name_ctx, origin, + buf, sizeof buf) < 0) { + perror("ns_sprintrr"); + error = ERR_PRINTING; + break; + } + strcpy(name_ctx, name); + numRecords++; + fputs(buf, filePtr); + fputc('\n', filePtr); + } + if (ns_rr_type(rr) == T_SOA) { + strcpy(soaname[soacnt], name); + if (soacnt == 0) + soacnt = 1; + else if (ns_samename(soaname[0], + soaname[1]) == 1) { + soacnt = 2; + /* This means we're finished. + * But we've to reset origin and + * name_ctx now ! */ + origin[0] = name_ctx[0] ='\0'; + } + } + } + if (error != NO_ERRORS) + break; + numAnswers++; + if (cmd != NULL && ((numAnswers % HASH_SIZE) == 0)) { + fprintf(stdout, "#"); + fflush(stdout); + } + } + + if (cmd != NULL) + fprintf(stdout, "%sReceived %d answer%s (%d record%s).\n", + (numAnswers >= HASH_SIZE) ? "\n" : "", + numAnswers, (numAnswers != 1) ? "s" : "", + numRecords, (numRecords != 1) ? "s" : ""); + + (void) close(sockFD); + sockFD = -1; + if (cmd != NULL && filePtr != NULL) { + fclose(filePtr); + filePtr = NULL; + } + + switch (error) { + case NO_ERRORS: + return (SUCCESS); + + case ERR_READING_LEN: + return (ERROR); + + case ERR_PRINTING: + return (ERROR); + + case ERR_READING_MSG: + headerPtr = (HEADER *) answer; + fprintf(stderr,"*** ls: error receiving zone transfer:\n"); + fprintf(stderr, + " result: %s, answers = %d, authority = %d, additional = %d\n", + p_rcode(headerPtr->rcode), + ntohs(headerPtr->ancount), ntohs(headerPtr->nscount), + ntohs(headerPtr->arcount)); + return (ERROR); + default: + return (ERROR); + } +} + +/* + ******************************************************************************* + * + * Finger -- + * + * Connects with the finger server for the current host + * to request info on the specified person (long form) + * who is on the system (short form). + * + * Results: + * SUCCESS the finger server was contacted. + * ERROR the server could not be contacted because + * a socket could not be obtained or connected + * to or the service could not be found. + * + ******************************************************************************* + */ + +int +Finger(string, putToFile) + char *string; + int putToFile; +{ + struct servent *sp; + struct sockaddr_storage sa; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + FILE *f; + int c; + int lastc; + char name[NAME_LEN]; + char file[PATH_MAX]; + int i; + int salen = 0; + + /* + * We need a valid current host info to get an inet address. + */ + if (!curHostValid) { + fprintf(stderr, "Finger: no current host defined.\n"); + return (ERROR); + } + + /* simulate: sscanf("finger %s") ; */ + + i = matchString(" finger ", string); + if (i > 0) { + i = pickString(string + i, name, sizeof name); + if (i > 0) { + i = 1 ; + } + /* note that if the argument to the finger command is + bigger than sizeof name it will be treated as if there + was no argument. */ + } + + if (i == 1) { + if (putToFile && (name[0] == '>')) { + name[0] = '\0'; + } + } else { + name[0] = '\0'; + } + + sp = getservbyname("finger", "tcp"); + if (sp == 0) { + fprintf(stderr, "Finger: unknown service\n"); + return (ERROR); + } + + memset(&sa, 0, sizeof sa); + switch (curHostInfo.addrList[0]->addrType) { + case AF_INET: + sin = (struct sockaddr_in *)&sa; + sin->sin_family = curHostInfo.addrList[0]->addrType; + sin->sin_port = sp->s_port; + memcpy(&sin->sin_addr, curHostInfo.addrList[0]->addr, + curHostInfo.addrList[0]->addrLen); +#ifdef HAVE_SA_LEN + sin->sin_len = sizeof(*sin); +#endif + salen = sizeof(struct sockaddr_in); + break; + + case AF_INET6: + sin6 = (struct sockaddr_in6 *)&sa; + sin6->sin6_family = curHostInfo.addrList[0]->addrType; + sin6->sin6_port = sp->s_port; + memcpy(&sin6->sin6_addr, curHostInfo.addrList[0]->addr, + curHostInfo.addrList[0]->addrLen); +#ifdef HAVE_SA_LEN + sin6->sin6_len = sizeof(*sin6); +#endif + salen = sizeof(struct sockaddr_in6); + break; + } + + /* + * Set up a virtual circuit to the host. + */ + + sockFD = socket(curHostInfo.addrList[0]->addrType, SOCK_STREAM, 0); + if (sockFD < 0) { + fflush(stdout); + perror("finger: socket"); + return (ERROR); + } + + if (connect(sockFD, (struct sockaddr *)&sa, salen) < 0) { + fflush(stdout); + perror("finger: connect"); + close(sockFD); + sockFD = -1; + return (ERROR); + } + + if (!putToFile) { + filePtr = stdout; + } else { + filePtr = OpenFile(string, file, sizeof file); + if (filePtr == NULL) { + fprintf(stderr, "*** Can't open %s for writing\n", file); + close(sockFD); + sockFD = -1; + return(ERROR); + } + fprintf(filePtr,"> %s\n", string); + } + fprintf(filePtr, "[%s]\n", curHostInfo.name); + + if (name[0] != '\0') { + write(sockFD, "/W ", 3); + } + write(sockFD, name, strlen(name)); + write(sockFD, "\r\n", 2); + f = fdopen(sockFD, "r"); + lastc = '\n'; + while ((c = getc(f)) != EOF) { + switch (c) { + case 0210: + case 0211: + case 0212: + case 0214: + c -= 0200; + break; + case 0215: + c = '\n'; + break; + } + putc(lastc = c, filePtr); + } + if (lastc != '\n') { + putc('\n', filePtr); + } + putc('\n', filePtr); + + close(sockFD); + sockFD = -1; + + if (putToFile) { + fclose(filePtr); + filePtr = NULL; + } + return (SUCCESS); +} + +void +ListHost_close(void) { + if (sockFD != -1) { + (void) close(sockFD); + sockFD = -1; + } +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/nslookup/list.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/nslookup/res.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/nslookup/res.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/nslookup/res.h (revision 109985) @@ -0,0 +1,227 @@ +/* + * ++Copyright++ 1985, 1989 + * - + * Copyright (c) 1985, 1989 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + * - + * 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 + * SOFTWARE. + * - + * --Copyright-- + */ + +/* + * @(#)res.h 5.10 (Berkeley) 6/1/90 + * $Id: res.h,v 8.10 2002/04/09 05:55:22 marka Exp $ + */ + +/* + ******************************************************************************* + * + * res.h -- + * + * Definitions used by modules of the name server lookup program. + * + * Copyright (c) 1985 + * Andrew Cherenson + * U.C. Berkeley + * CS298-26 Fall 1985 + * + ******************************************************************************* + */ + +#define TRUE 1 +#define FALSE 0 +typedef int Boolean; + +#define MAXALIASES 35 +#define MAXADDRS 35 +#define MAXDOMAINS 35 +#define MAXSERVERS 10 + +/* + * Define return statuses in addtion to the ones defined in namserv.h + * let SUCCESS be a synonym for NOERROR + * + * TIME_OUT - a socket connection timed out. + * NO_INFO - the server didn't find any info about the host. + * ERROR - one of the following types of errors: + * dn_expand, res_mkquery failed + * bad command line, socket operation failed, etc. + * NONAUTH - the server didn't have the desired info but + * returned the name(s) of some servers who should. + * NO_RESPONSE - the server didn't respond. + * + */ + +#ifdef ERROR +#undef ERROR +#endif + +#define SUCCESS 0 +#define TIME_OUT -1 +#define NO_INFO -2 +#define ERROR -3 +#define NONAUTH -4 +#define NO_RESPONSE -5 + +/* + * Define additional options for the resolver state structure. + * + * RES_DEBUG2 more verbose debug level + */ + +#define RES_DEBUG2 0x80000000 + +/* + * Maximum length of server, host and file names. + */ + +#define NAME_LEN 256 + + +/* + * Modified struct hostent from + * + * "Structures returned by network data base library. All addresses + * are supplied in host order, and returned in network order (suitable + * for use in system calls)." + */ + +typedef struct { + int addrType; + int addrLen; + char *addr; +} AddrInfo; + +typedef struct { + char *name; /* official name of host */ + char **domains; /* domains it serves */ + AddrInfo **addrList; /* list of addresses from name server */ +} ServerInfo; + +typedef struct { + char *name; /* official name of host */ + char **aliases; /* alias list */ + AddrInfo **addrList; /* list of addresses from name server */ + ServerInfo **servers; +} HostInfo; + + +/* + * FilePtr is used for directing listings to a file. + * It is global so the Control-C handler can close it. + */ + +extern FILE *filePtr; + +/* + * TCP/UDP port of server. + */ +extern unsigned short nsport; + +/* + * Our resolver context. + */ +extern struct __res_state res; + +/* + * External routines: + */ + +/* XXX need prototypes */ +void Print_query(const u_char *msg, const u_char *eom, int printHeader); +void Fprint_query(const u_char *msg, const u_char *eom, int printHeader, + FILE *file); +const u_char *Print_cdname(const u_char *cp, const u_char *msg, + const u_char *eom, FILE *file); +const u_char *Print_cdname2(const u_char *cp, const u_char *msg, + const u_char *eom, FILE *file); +const u_char *Print_rr(const u_char *ocp, const u_char *msg, + const u_char *eom, FILE *file); +extern const char *DecodeType(); /* descriptive version of p_type */ +extern const char *DecodeError(); +extern char *Calloc(); +extern char *Malloc(); +extern void NsError(); +extern void PrintServer(); +extern void PrintHostInfo(); +extern void FreeHostInfoPtr(); +extern FILE *OpenFile(); +extern int pickString(const char *, char *, size_t); +extern int GetHostInfoByName(union res_sockaddr_union *, int, int, + const char *, HostInfo *, Boolean, Boolean); +extern int GetHostDomain(union res_sockaddr_union *, int, int, + const char *, char *, HostInfo *, Boolean, Boolean); +extern int matchString(const char *, const char *); +extern int StringToType(char *, int, FILE *); +extern int StringToClass(char *, int, FILE *); +extern int SendRequest(union res_sockaddr_union *, const u_char *, int, + u_char *, u_int, int *); +extern void SendRequest_close(void); +extern int SetDefaultServer(char *, Boolean); +extern int Finger(char *, int); +void ListHostsByType(char *, int); +void ListHosts(char *, int); +void ListHost_close(void); +int SetOption(char *); +int LookupHost(char *, Boolean); +int LookupHostWithServer(char *, Boolean); +const char * DecodeType(int); +const char * DecodeError(int); +FILE * OpenFile(char *, char *, size_t); +void PrintHostInfo(FILE *, const char *, HostInfo *); +char * Calloc(int, int); +char * Malloc(int); +SIG_FN IntrHandler(int); +int ListSubr(int, char *, char *); +void FreeHostInfoPtr(HostInfo *); +unsigned char * res_skip(unsigned char *, int, unsigned char *); +extern Boolean IsAddr(const char *, union res_sockaddr_union *); +void PrintHelp(void); +int GetHostInfoByAddr(union res_sockaddr_union *, union res_sockaddr_union *, + HostInfo *); + Property changes on: vendor/bind/8.3.4/contrib/bind/bin/nslookup/res.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/nslookup/subr.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/nslookup/subr.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/nslookup/subr.c (revision 109985) @@ -0,0 +1,603 @@ +/* + * Copyright (c) 1985, 1989 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +#ifndef lint +static const char sccsid[] = "@(#)subr.c 5.24 (Berkeley) 3/2/91"; +static const char rcsid[] = "$Id: subr.c,v 8.16 2002/04/09 05:55:24 marka Exp $"; +#endif /* not lint */ + +/* + ******************************************************************************* + * + * subr.c -- + * + * Miscellaneous subroutines for the name server + * lookup program. + * + * Copyright (c) 1985 + * Andrew Cherenson + * U.C. Berkeley + * CS298-26 Fall 1985 + * + ******************************************************************************* + */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +#include "resolv.h" +#include "res.h" + +/* + ******************************************************************************* + * + * IntrHandler -- + * + * This routine is called whenever a control-C is typed. + * It performs three main functions: + * - closes an open socket connection, + * - closes an open output file (used by LookupHost, et al.), + * - jumps back to the main read-eval loop. + * + * If a user types a ^C in the middle of a routine that uses a socket, + * the routine would not be able to close the socket. To prevent an + * overflow of the process's open file table, the socket and output + * file descriptors are closed by the interrupt handler. + * + * Side effects: + * Open file descriptors are closed. + * If filePtr is valid, it is closed. + * Flow of control returns to the main() routine. + * + ******************************************************************************* + */ + +SIG_FN +IntrHandler(int sig) +{ + extern jmp_buf env; +#if defined(BSD) && BSD >= 199006 && !defined(RISCOS_BSD) && !defined(__osf__) + extern FILE *yyin; /* scanner input file */ + extern void yyrestart(); /* routine to restart scanner after interrupt */ +#endif + extern void ListHost_close(void); + + UNUSED(sig); + + SendRequest_close(); + ListHost_close(); + if (filePtr != NULL && filePtr != stdout) { + fclose(filePtr); + filePtr = NULL; + } + printf("\n"); +#if defined(BSD) && BSD >= 199006 && !defined(RISCOS_BSD) && !defined(__osf__) + yyrestart(yyin); +#endif + longjmp(env, 1); +} + + +/* + ******************************************************************************* + * + * Malloc -- + * Calloc -- + * + * Calls the malloc library routine with SIGINT blocked to prevent + * corruption of malloc's data structures. We need to do this because + * a control-C doesn't kill the program -- it causes a return to the + * main command loop. + * + * NOTE: This method doesn't prevent the pointer returned by malloc + * from getting lost, so it is possible to get "core leaks". + * + * If malloc fails, the program exits. + * + * Results: + * (address) - address of new buffer. + * + ******************************************************************************* + */ + +char * +Malloc(size) + int size; +{ + char *ptr; + +#ifdef SYSV +#if defined(SVR3) || defined(SVR4) + sighold(SIGINT); + ptr = malloc((unsigned) size); + sigrelse(SIGINT); +#else + { SIG_FN (*old)(); + old = signal(SIGINT, SIG_IGN); + ptr = malloc((unsigned) size); + signal(SIGINT, old); + } +#endif +#else +#ifdef POSIX_SIGNALS + { sigset_t sset; + sigemptyset(&sset); + sigaddset(&sset,SIGINT); + sigprocmask(SIG_BLOCK,&sset,NULL); + ptr = malloc((unsigned) size); + sigprocmask(SIG_UNBLOCK,&sset,NULL); + } +#else + { int saveMask; + saveMask = sigblock(sigmask(SIGINT)); + ptr = malloc((unsigned) size); + (void) sigsetmask(saveMask); + } +#endif +#endif + if (ptr == NULL) { + fflush(stdout); + fprintf(stderr, "*** Can't allocate memory\n"); + fflush(stderr); + abort(); + /*NOTREACHED*/ + } + return (ptr); +} + +char * +Calloc(num, size) + register int num, size; +{ + char *ptr = Malloc(num*size); + memset(ptr, 0, num*size); + return(ptr); +} + + +/* + ******************************************************************************* + * + * PrintHostInfo -- + * + * Prints out the HostInfo structure for a host. + * + ******************************************************************************* + */ + +void +PrintHostInfo(file, title, hp) + FILE *file; + const char *title; + register HostInfo *hp; +{ + register AddrInfo **ap; + register char **cp; + register ServerInfo **sp; + char comma; + int i; + char buf[80]; + + fprintf(file, "%-7s %s", title, hp->name); + + if (hp->addrList != NULL) { + if (hp->addrList[1] != NULL) { + fprintf(file, "\nAddresses:"); + } else { + fprintf(file, "\nAddress:"); + } + comma = ' '; + i = 0; + for (ap = hp->addrList; ap && *ap; ap++) { + i++; + if (i > 4) { + fprintf(file, "\n\t"); + comma = ' '; + i = 0; + } + if (inet_ntop((*ap)->addrType, (*ap)->addr, + buf, sizeof(buf)) != NULL) { + fprintf(file,"%c %s", comma, buf); + } else + fprintf(file,"%c ", comma); + comma = ','; + } + } + + if (hp->aliases != NULL) { + fprintf(file, "\nAliases:"); + comma = ' '; + i = 10; + for (cp = hp->aliases; cp && *cp && **cp; cp++) { + i += strlen(*cp) + 2; + if (i > 75) { + fprintf(file, "\n\t"); + comma = ' '; + i = 10; + } + fprintf(file, "%c %s", comma, *cp); + comma = ','; + } + } + + if (hp->servers != NULL) { + fprintf(file, "\nServed by:\n"); + for (sp = hp->servers; *sp != NULL ; sp++) { + + fprintf(file, "- %s\n\t", (*sp)->name); + + comma = ' '; + i = 0; + for (ap = (*sp)->addrList; ap && *ap; ap++) { + i++; + if (i > 4) { + fprintf(file, "\n\t"); + comma = ' '; + i = 0; + } + if (inet_ntop((*ap)->addrType, (*ap)->addr, + buf, sizeof(buf)) != NULL) + fprintf(file,"%c %s", comma, buf); + else + fprintf(file,"%c ", comma); + comma = ','; + } + fprintf(file, "\n\t"); + + comma = ' '; + i = 10; + for (cp = (*sp)->domains; cp && *cp && **cp; cp++) { + i += strlen(*cp) + 2; + if (i > 75) { + fprintf(file, "\n\t"); + comma = ' '; + i = 10; + } + fprintf(file, "%c %s", comma, *cp); + comma = ','; + } + fprintf(file, "\n"); + } + } + + fprintf(file, "\n\n"); +} + +/* + ******************************************************************************* + * + * OpenFile -- + * + * Parses a command string for a file name and opens + * the file. The file name is copued to the argument FILE. The + * parameter SIZE parameter includes space for a null byte. + * + * Results: + * file pointer - the open was successful. + * NULL - there was an error opening the file or + * the input string was invalid. + * + ******************************************************************************* + */ + +FILE * +OpenFile(string, file, size) + char *string; + char *file; + size_t size; +{ + char *redirect; + FILE *tmpPtr; + int i; + + /* + * Open an output file if we see '>' or >>'. + * Check for overwrite (">") or concatenation (">>"). + */ + + redirect = strchr(string, '>'); + if (redirect == NULL) { + return(NULL); + } + + tmpPtr = NULL; + if (redirect[1] == '>') { + i = pickString(redirect + 2, file, size); + if (i > 0) { + tmpPtr = fopen(file, "a+"); + } + } else { + i = pickString(redirect + 1, file, size); + if (i > 0) { + tmpPtr = fopen(file, "w"); + } + } + + if (tmpPtr != NULL) { + redirect[0] = '\0'; + } + + return(tmpPtr); +} + +/* + ******************************************************************************* + * + * DecodeError -- + * + * Converts an error code into a character string. + * + ******************************************************************************* + */ + +const struct res_sym error_syms[] = { + { NOERROR, "Success", NULL }, + { FORMERR, "Format error", NULL }, + { SERVFAIL, "Server failed", NULL }, + { NXDOMAIN, "Non-existent host/domain", NULL }, + { NOTIMP, "Not implemented", NULL }, + { REFUSED, "Query refused", NULL }, +#ifdef NOCHANGE + { NOCHANGE, "No change", NULL }, +#endif + { TIME_OUT, "Timed out", NULL }, + { NO_INFO, "No information", NULL }, + { ERROR, "Unspecified error", NULL }, + { NONAUTH, "Non-authoritative answer", NULL }, + { NO_RESPONSE, "No response from server", NULL }, + { 0, NULL, NULL } +}; + +const char * +DecodeError(result) + int result; +{ + const char *string; + int success; + + string = sym_ntos(error_syms, result, &success); + if (success) + return string; + return ("BAD ERROR VALUE"); +} + + +int +StringToClass(class, dflt, errorfile) + char *class; + int dflt; + FILE *errorfile; +{ + int result, success; + + result = sym_ston(__p_class_syms, class, &success); + if (success) + return result; + + if (errorfile) + fprintf(errorfile, "unknown query class: %s\n", class); + return(dflt); +} + + +/* + ******************************************************************************* + * + * StringToType -- + * + * Converts a string form of a query type name to its + * corresponding integer value. + * + ******************************************************************************* + */ + +int +StringToType(type, dflt, errorfile) + char *type; + int dflt; + FILE *errorfile; +{ + int result, success; + + result = sym_ston(__p_type_syms, type, &success); + if (success) + return (result); + + if (errorfile) + fprintf(errorfile, "unknown query type: %s\n", type); + return (dflt); +} + +/* + ******************************************************************************* + * + * DecodeType -- + * + * Converts a query type to a descriptive name. + * (A more verbose form of p_type.) + * + * + ******************************************************************************* + */ + +const char * +DecodeType(type) + int type; +{ + + return (sym_ntop(__p_type_syms, type, (int *)0)); +} + + + + +/* + * Skip over leading white space in SRC and then copy the next sequence of + * non-whitespace characters into DEST. No more than (DEST_SIZE - 1) + * characters are copied. DEST is always null-terminated. Returns 0 if no + * characters could be copied into DEST. Returns the number of characters + * in SRC that were processed (i.e. the count of characters in the leading + * white space and the first non-whitespace sequence). + * + * int i; + * char *p = " foo bar ", *q; + * char buf[100]; + * + * q = p + pickString(p, buf, sizeof buff); + * assert (strcmp (q, " bar ") == 0) ; + * + */ + +int +pickString(const char *src, char *dest, size_t dest_size) { + const char *start; + const char *end ; + size_t sublen ; + + if (dest_size == 0 || dest == NULL || src == NULL) + return 0; + + for (start = src ; isspace(*start) ; start++) + /* nada */ ; + + for (end = start ; *end != '\0' && !isspace(*end) ; end++) + /* nada */ ; + + sublen = end - start ; + + if (sublen == 0 || sublen > (dest_size - 1)) + return 0; + + strncpy (dest, start, sublen); + + dest[sublen] = '\0' ; + + return (end - src); +} + + + + +/* + * match the string FORMAT against the string SRC. Leading whitespace in + * FORMAT will match any amount of (including no) leading whitespace in + * SRC. Any amount of whitespace inside FORMAT matches any non-zero amount + * of whitespace in SRC. Value returned is 0 if match didn't occur, or the + * amount of characters in SRC that did match + * + * int i ; + * + * i = matchString(" a b c", "a b c") ; + * assert (i == 5) ; + * i = matchString("a b c", " a b c"); + * assert (i == 0) ; becasue no leading white space in format + * i = matchString(" a b c", " a b c"); + * assert(i == 12); + * i = matchString("aa bb ", "aa bb ddd sd"); + * assert(i == 16); + */ +int +matchString (const char *format, const char *src) { + const char *f = format; + const char *s = src; + + if (f == NULL || s == NULL) + goto notfound; + + if (isspace(*f)) { + while (isspace(*f)) + f++ ; + while (isspace(*s)) + s++ ; + } + + while (1) { + if (isspace(*f)) { + if (!isspace(*s)) + goto notfound; + while(isspace(*s)) + s++; + /* any amount of whitespace in the format string + will match any amount of space in the source + string. */ + while (isspace(*f)) + f++; + } else if (*f == '\0') { + return (s - src); + } else if (*f != *s) { + goto notfound; + } else { + s++ ; + f++ ; + } + } + notfound: + return 0 ; +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/nslookup/subr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/nslookup/debug.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/nslookup/debug.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/nslookup/debug.c (revision 109985) @@ -0,0 +1,656 @@ +/* + * Copyright (c) 1985, 1989 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +#ifndef lint +static const char sccsid[] = "@(#)debug.c 5.26 (Berkeley) 3/21/91"; +static const char rcsid[] = "$Id: debug.c,v 8.19 2001/09/25 04:50:26 marka Exp $"; +#endif /* not lint */ + +/* + ******************************************************************************* + * + * debug.c -- + * + * Routines to print out packets received from a name server query. + * + * Modified version of 4.3BSD BIND res_debug.c 5.30 6/27/90 + * + ******************************************************************************* + */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#include "res.h" + +/* + * Imported from res_debug.c + */ +#ifndef HAVE_DECL_RES_OPCODES +extern char *_res_opcodes[]; +#endif + +/* + * Used to highlight the start of a record when printing it. + */ +#define INDENT " -> " + +/* + * Print the contents of a query. + * This is intended to be primarily a debugging routine. + */ + +void +Print_query(const u_char *msg, const u_char *eom, int printHeader) { + Fprint_query(msg, eom, printHeader, stdout); +} + +void +Fprint_query(const u_char *msg, const u_char *eom, int printHeader, FILE *file) +{ + const u_char *cp; + const HEADER *hp; + int n; + u_int class, type = 0; + + /* + * Print header fields. + */ + hp = (const HEADER *)msg; + cp = msg + HFIXEDSZ; + if (printHeader || (res.options & RES_DEBUG2)) { + fprintf(file," HEADER:\n"); + fprintf(file,"\topcode = %s", _res_opcodes[hp->opcode]); + fprintf(file,", id = %d", ntohs(hp->id)); + fprintf(file,", rcode = %s\n", p_rcode(hp->rcode)); + fprintf(file,"\theader flags: "); + if (hp->qr) { + fprintf(file," response"); + } else { + fprintf(file," query"); + } + if (hp->aa) + fprintf(file,", auth. answer"); + if (hp->tc) + fprintf(file,", truncation"); + if (hp->rd) + fprintf(file,", want recursion"); + if (hp->ra) + fprintf(file,", recursion avail."); + if (hp->unused) + fprintf(file,", UNUSED-QUERY_BIT"); + if (hp->ad) + fprintf(file,", authentic data"); + if (hp->cd) + fprintf(file,", checking disabled"); + fprintf(file,"\n\tquestions = %d", ntohs(hp->qdcount)); + fprintf(file,", answers = %d", ntohs(hp->ancount)); + fprintf(file,", authority records = %d", ntohs(hp->nscount)); + fprintf(file,", additional = %d\n\n", ntohs(hp->arcount)); + } + + /* + * Print question records. + */ + n = ntohs(hp->qdcount); + if (n > 0) { + fprintf(file," QUESTIONS:\n"); + while (--n >= 0) { + fprintf(file,"\t"); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) + return; + type = ns_get16((const u_char*)cp); + cp += INT16SZ; + class = ns_get16((const u_char*)cp); + cp += INT16SZ; + fprintf(file,", type = %s", p_type(type)); + fprintf(file,", class = %s\n", p_class(class)); + } + } + /* + * Print authoritative answer records + */ + n = ntohs(hp->ancount); + if (n > 0) { + fprintf(file," ANSWERS:\n"); + if (type == ns_t_a && n > MAXADDRS) { + printf("Limiting response to MAX Addrs = %d \n", + MAXADDRS); + n = MAXADDRS; + } + while (--n >= 0) { + fprintf(file, INDENT); + cp = Print_rr(cp, msg, eom, file); + if (cp == NULL) + return; + } + } + /* + * print name server records + */ + n = ntohs(hp->nscount); + if (n > 0) { + fprintf(file," AUTHORITY RECORDS:\n"); + while (--n >= 0) { + fprintf(file, INDENT); + cp = Print_rr(cp, msg, eom, file); + if (cp == NULL) + return; + } + } + /* + * print additional records + */ + n = ntohs(hp->arcount); + if (n > 0) { + fprintf(file," ADDITIONAL RECORDS:\n"); + while (--n >= 0) { + fprintf(file, INDENT); + cp = Print_rr(cp, msg, eom, file); + if (cp == NULL) + return; + } + } + fprintf(file,"\n------------\n"); +} + +static const u_char * +Print_cdname_sub(const u_char *cp, const u_char *msg, const u_char *eom, + FILE *file, int format) +{ + char name[MAXDNAME]; + int n; + + n = dn_expand(msg, eom, cp, name, sizeof name); + if (n < 0) + return (NULL); + if (name[0] == '\0') + strcpy(name, "(root)"); + if (format) + fprintf(file, "%-30s", name); + else + fputs(name, file); + return (cp + n); +} + +const u_char * +Print_cdname(const u_char *cp, const u_char *msg, const u_char *eom, + FILE *file) +{ + return (Print_cdname_sub(cp, msg, eom, file, 0)); +} + +const u_char * +Print_cdname2(const u_char *cp, const u_char *msg, const u_char *eom, + FILE *file) +{ + return (Print_cdname_sub(cp, msg, eom, file, 1)); +} + +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eom) { \ + fprintf(file, "(form error.)\n"); \ + return (NULL); \ + } \ + } while (0) + +/* + * Print resource record fields in human readable form (not master file form). + */ +const u_char * +Print_rr(const u_char *ocp, const u_char *msg, const u_char *eom, FILE *file) { + u_int type, class; + int dlen, n, c, debug; + u_long rrttl, ttl; + struct in_addr inaddr; + const u_char *cp, *cp1, *cp2; + + if ((cp = Print_cdname(ocp, msg, eom, file)) == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + + BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); + NS_GET16(type, cp); + NS_GET16(class, cp); + NS_GET32(rrttl, cp); + NS_GET16(dlen, cp); + BOUNDS_CHECK(cp, dlen); + + debug = res.options & (RES_DEBUG|RES_DEBUG2); + if (debug) { + if (res.options & RES_DEBUG2) + fprintf(file,"\n\ttype = %s, class = %s, dlen = %d", + p_type(type), p_class(class), dlen); + if (type == T_SOA) + fprintf(file,"\n\tttl = %lu (%s)", + rrttl, p_time(rrttl)); + putc('\n', file); + } + + cp1 = cp; + + /* + * Print type specific data, if appropriate + */ + switch (type) { + case T_A: + BOUNDS_CHECK(cp, INADDRSZ); + memcpy(&inaddr, cp, INADDRSZ); + fprintf(file,"\tinternet address = %s\n", inet_ntoa(inaddr)); + cp += dlen; + break; + + case T_CNAME: + fprintf(file,"\tcanonical name = "); + goto doname; + + case T_MG: + fprintf(file,"\tmail group member = "); + goto doname; + + case T_MB: + fprintf(file,"\tmail box = "); + goto doname; + + case T_MR: + fprintf(file,"\tmailbox rename = "); + goto doname; + + case T_MX: + BOUNDS_CHECK(cp, INT16SZ); + fprintf(file,"\tpreference = %u",ns_get16((const u_char*)cp)); + cp += INT16SZ; + fprintf(file,", mail exchanger = "); + goto doname; + + case T_NAPTR: + BOUNDS_CHECK(cp, 2 * INT16SZ); + fprintf(file, "\torder = %u",ns_get16((const u_char*)cp)); + cp += INT16SZ; + fprintf(file,", preference = %u\n", ns_get16((const u_char*)cp)); + cp += INT16SZ; + /* Flags */ + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); + fprintf(file,"\tflags = \"%.*s\"\n", (int)n, cp); + cp += n; + /* Service */ + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); + fprintf(file,"\tservices = \"%.*s\"\n", (int)n, cp); + cp += n; + /* Regexp */ + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); + fprintf(file,"\trule = \"%.*s\"\n", (int)n, cp); + cp += n; + /* Replacement */ + fprintf(file,"\treplacement = "); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(replacement truncated?)\n"); + return (NULL); /* compression error */ + } + (void) putc('\n', file); + break; + + case T_SRV: + BOUNDS_CHECK(cp, 3 * INT16SZ); + fprintf(file, "\tpriority = %u",ns_get16((const u_char*)cp)); + cp += INT16SZ; + fprintf(file,", weight = %u", ns_get16((const u_char*)cp)); + cp += INT16SZ; + fprintf(file,", port= %u\n", ns_get16((const u_char*)cp)); + cp += INT16SZ; + + fprintf(file,"\thost = "); + goto doname; + + case T_PX: + BOUNDS_CHECK(cp, INT16SZ); + fprintf(file,"\tpreference = %u",ns_get16((const u_char*)cp)); + cp += INT16SZ; + fprintf(file,", RFC 822 = "); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + fprintf(file,"\nX.400 = "); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + (void) putc('\n', file); + break; + + case T_RT: + BOUNDS_CHECK(cp, INT16SZ); + fprintf(file,"\tpreference = %u",ns_get16((const u_char*)cp)); + cp += INT16SZ; + fprintf(file,", router = "); + goto doname; + + case T_AFSDB: + BOUNDS_CHECK(cp, INT16SZ); + fprintf(file,"\tsubtype = %d",ns_get16((const u_char*)cp)); + cp += INT16SZ; + fprintf(file,", DCE/AFS server = "); + goto doname; + + case T_NS: + fprintf(file,"\tnameserver = "); + goto doname; + + case T_PTR: + fprintf(file,"\tname = "); + doname: + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + (void) putc('\n', file); + break; + + case T_HINFO: + cp2 = cp + dlen; + BOUNDS_CHECK(cp, 1); + if ((n = *cp++) != 0) { + BOUNDS_CHECK(cp, n); + fprintf(file,"\tCPU = %.*s", n, cp); + cp += n; + } + if ((cp < cp2) && ((n = *cp++) != 0)) { + BOUNDS_CHECK(cp, n); + fprintf(file,"\tOS = %.*s\n", n, cp); + cp += n; + } else fprintf(file, "\n*** Warning *** OS-type missing\n"); + break; + + case T_ISDN: + cp2 = cp + dlen; + BOUNDS_CHECK(cp, 1); + n = *cp++; + if (n != 0) { + BOUNDS_CHECK(cp, n); + fprintf(file,"\tISDN = \"%.*s", n, cp); + cp += n; + } + if ((cp < cp2) && (n = *cp++)) { + BOUNDS_CHECK(cp, n); + fprintf(file,"-%.*s\"\n", n, cp); + cp += n; + } else fprintf(file,"\"\n"); + break; + + case T_SOA: + if (!debug) + putc('\n', file); + fprintf(file,"\torigin = "); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + fprintf(file,"\n\tmail addr = "); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + BOUNDS_CHECK(cp, 5 * INT32SZ); + fprintf(file,"\n\tserial = %lu", ns_get32((const u_char*)cp)); + cp += INT32SZ; + ttl = ns_get32((const u_char*)cp); + fprintf(file,"\n\trefresh = %lu (%s)", ttl, p_time(ttl)); + cp += INT32SZ; + ttl = ns_get32((const u_char*)cp); + fprintf(file,"\n\tretry = %lu (%s)", ttl, p_time(ttl)); + cp += INT32SZ; + ttl = ns_get32((const u_char*)cp); + fprintf(file,"\n\texpire = %lu (%s)", ttl, p_time(ttl)); + cp += INT32SZ; + ttl = ns_get32((const u_char*)cp); + fprintf(file, + "\n\tminimum ttl = %lu (%s)\n", ttl, p_time(ttl)); + cp += INT32SZ; + break; + + case T_MINFO: + if (!debug) + putc('\n', file); + fprintf(file,"\trequests = "); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + fprintf(file,"\n\terrors = "); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + (void) putc('\n', file); + break; + + case T_RP: + if (!debug) + putc('\n', file); + fprintf(file,"\tmailbox = "); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + fprintf(file,"\n\ttext = "); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + (void) putc('\n', file); + break; + + case T_TXT: + (void) fputs("\ttext = ", file); + cp2 = cp1 + dlen; + while (cp < cp2) { + (void) putc('"', file); + n = (unsigned char) *cp++; + if (n != 0) { + for (c = n; c > 0 && cp < cp2; c--) { + if ((*cp == '\n') || (*cp == '"') || (*cp == '\\')) + (void) putc('\\', file); + (void) putc(*cp++, file); + } + } + (void) putc('"', file); + if (cp < cp2) + (void) putc(' ', file); + } + (void) putc('\n', file); + break; + + case T_X25: + (void) fputs("\tX25 = \"", file); + cp2 = cp1 + dlen; + while (cp < cp2) { + n = (unsigned char) *cp++; + if (n != 0) { + for (c = n; c > 0 && cp < cp2; c--) + if (*cp == '\n') { + (void) putc('\\', file); + (void) putc(*cp++, file); + } else + (void) putc(*cp++, file); + } + } + (void) fputs("\"\n", file); + break; + + case T_NSAP: + fprintf(file, "\tnsap = %s\n", inet_nsap_ntoa(dlen, cp, NULL)); + cp += dlen; + break; + + case T_AAAA: { + char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; + + BOUNDS_CHECK(cp, IN6ADDRSZ); + fprintf(file, "\tIPv6 address = %s\n", + inet_ntop(AF_INET6, cp, t, sizeof t)); + cp += IN6ADDRSZ; + break; + } + + case T_WKS: { + struct protoent *protoPtr; + + BOUNDS_CHECK(cp, INADDRSZ + 1); + if (!debug) + (void) putc('\n', file); + memcpy(&inaddr, cp, INADDRSZ); + cp += INADDRSZ; + if ((protoPtr = getprotobynumber(*cp)) != NULL) { + fprintf(file,"\tinet address = %s, protocol = %s\n\t", + inet_ntoa(inaddr), protoPtr->p_name); + } else { + fprintf(file,"\tinet address = %s, protocol = %d\n\t", + inet_ntoa(inaddr), *cp); + } + cp++; + n = 0; + while (cp < cp1 + dlen) { + c = *cp++; + do { + struct servent *s; + + if (c & 0200) { + s = getservbyport((int)htons(n), + protoPtr ? protoPtr->p_name : NULL); + if (s != NULL) { + fprintf(file," %s", s->s_name); + } else { + fprintf(file," #%d", n); + } + } + c <<= 1; + } while (++n & 07); + } + putc('\n',file); + break; + } + + case T_NULL: + fprintf(file, "\tNULL (dlen %d)\n", dlen); + cp += dlen; + break; + + case T_NXT: + case T_SIG: + case T_KEY: + default: { + char buf[2048]; /* XXX need to malloc/realloc. */ + char rrname[NS_MAXDNAME]; + + cp2 = p_fqnname(ocp, msg, NS_MAXCDNAME, rrname, sizeof rrname); + if (cp2 == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + + if (ns_sprintrrf(msg, eom - msg, rrname, (ns_class)class, + (ns_type)type, rrttl, cp1, dlen, NULL, NULL, + buf, sizeof buf) < 0) { + perror("ns_sprintrrf"); + } else { + fprintf(file, + "\trecord type %s, interpreted as:\n%s\n", + p_type(type), buf); + } + cp += dlen; + } + } + if (res.options & RES_DEBUG && type != T_SOA) { + fprintf(file,"\tttl = %lu (%s)\n", rrttl, p_time(rrttl)); + } + if (cp != cp1 + dlen) { + fprintf(file, + "\n*** Error: record size incorrect (%d != %d)\n\n", + cp - cp1, dlen); + cp = NULL; + } + return (cp); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/nslookup/debug.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/nslookup/skip.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/nslookup/skip.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/nslookup/skip.c (revision 109985) @@ -0,0 +1,219 @@ +/* + * Copyright (c) 1985, 1989 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +#ifndef lint +static const char sccsid[] = "@(#)skip.c 5.12 (Berkeley) 3/21/91"; +static const char rcsid[] = "$Id: skip.c,v 8.7 2001/06/20 12:30:35 marka Exp $"; +#endif /* not lint */ + +/* + ******************************************************************************* + * + * skip.c -- + * + * Routines to skip over portions of a query buffer. + * + * Note: this file has been submitted for inclusion in + * BIND resolver library. When this has been done, this file + * is no longer necessary (assuming there haven't been any + * changes). + * + * Adapted from 4.3BSD BIND res_debug.c + * + ******************************************************************************* + */ + +#include "port_before.h" + +#include + +#include +#include + +#include +#include + +#include "port_after.h" +#include "res.h" + +static unsigned char *res_skip_rr(unsigned char *cp, unsigned char *eom); + + +/* + ******************************************************************************* + * + * res_skip -- + * + * Skip the contents of a query. + * + * Interpretation of numFieldsToSkip argument: + * res_skip returns pointer to: + * 1 -> start of question records. + * 2 -> start of authoritative answer records. + * 3 -> start of additional records. + * 4 -> first byte after end of additional records. + * + * Results: + * (address) - success operation. + * NULL - a resource record had an incorrect format. + * + ******************************************************************************* + */ + +unsigned char * +res_skip(msg, numFieldsToSkip, eom) + unsigned char *msg; + int numFieldsToSkip; + unsigned char *eom; +{ + register unsigned char *cp; + register HEADER *hp; + register int tmp; + register int n; + + /* + * Skip the header fields. + */ + hp = (HEADER *)msg; + cp = msg + HFIXEDSZ; + + /* + * skip question records. + */ + n = ntohs(hp->qdcount); + if (n > 0) { + while (--n >= 0 && cp < eom) { + tmp = dn_skipname(cp, eom); + if (tmp == -1) return(NULL); + cp += tmp; + cp += INT16SZ; /* type */ + cp += INT16SZ; /* class */ + } + } + if (--numFieldsToSkip <= 0) return(cp); + + /* + * skip authoritative answer records + */ + n = ntohs(hp->ancount); + if (n > 0) { + while (--n >= 0 && cp < eom) { + cp = res_skip_rr(cp, eom); + if (cp == NULL) return(NULL); + } + } + if (--numFieldsToSkip == 0) return(cp); + + /* + * skip name server records + */ + n = ntohs(hp->nscount); + if (n > 0) { + while (--n >= 0 && cp < eom) { + cp = res_skip_rr(cp, eom); + if (cp == NULL) return(NULL); + } + } + if (--numFieldsToSkip == 0) return(cp); + + /* + * skip additional records + */ + n = ntohs(hp->arcount); + if (n > 0) { + while (--n >= 0 && cp < eom) { + cp = res_skip_rr(cp, eom); + if (cp == NULL) return(NULL); + } + } + + return(cp); +} + + +/* + ******************************************************************************* + * + * res_skip_rr -- + * + * Skip over resource record fields. + * + * Results: + * (address) - success operation. + * NULL - a resource record had an incorrect format. + ******************************************************************************* + */ + +static unsigned char * +res_skip_rr(cp, eom) + unsigned char *cp; + unsigned char *eom; +{ + int tmp; + int dlen; + + if ((tmp = dn_skipname(cp, eom)) == -1) + return (NULL); /* compression error */ + cp += tmp; + if ((cp + RRFIXEDSZ) > eom) + return (NULL); + cp += INT16SZ; /* type */ + cp += INT16SZ; /* class */ + cp += INT32SZ; /* ttl */ + dlen = ns_get16(cp); + cp += INT16SZ; /* dlen */ + cp += dlen; + if (cp > eom) + return (NULL); + return (cp); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/nslookup/skip.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/nslookup/pathnames.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/nslookup/pathnames.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/nslookup/pathnames.h (revision 109985) @@ -0,0 +1,73 @@ +/* + * ++Copyright++ 1990 + * - + * Copyright (c) 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 + * are met: + * 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 + * SUCH DAMAGE. + * - + * 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 + * SOFTWARE. + * - + * --Copyright-- + */ + +/* + * @(#)pathnames.h 5.1 (Berkeley) 5/28/90 + * $Id: pathnames.h,v 8.2 2000/11/08 06:47:32 marka Exp $ + */ + +#define _PATH_NSLOOKUPRC "/.nslookuprc" +#ifndef _PATH_PAGERCMD +#define _PATH_PAGERCMD "more" +#endif + +#ifndef _PATH_HELPFILE +#if defined(BSD) && BSD >= 198810 +#define _PATH_HELPFILE "/usr/share/misc/nslookup.help" +#else +#define _PATH_HELPFILE "/usr/lib/nslookup.help" +#endif +#endif + Property changes on: vendor/bind/8.3.4/contrib/bind/bin/nslookup/pathnames.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/nslookup/nslookup.help =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/nslookup/nslookup.help (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/nslookup/nslookup.help (revision 109985) @@ -0,0 +1,33 @@ +$Id: nslookup.help,v 8.5 2000/03/30 23:25:35 vixie Exp $ + +Commands: (identifiers are shown in uppercase, [] means optional) +NAME - print info about the host/domain NAME using default server +NAME1 NAME2 - as above, but use NAME2 as server +help or ? - print info on common commands; see nslookup(1) for details +set OPTION - set an option + all - print options, current server and host + [no]debug - print debugging information + [no]d2 - print exhaustive debugging information + [no]defname - append domain name to each query + [no]recurse - ask for recursive answer to query + [no]vc - always use a virtual circuit + domain=NAME - set default domain name to NAME + srchlist=N1[/N2/.../N6] - set domain to N1 and search list to N1,N2, etc. + root=NAME - set root server to NAME + retry=X - set number of retries to X + timeout=X - set initial time-out interval to X seconds + querytype=X - set query type, e.g., A,ANY,CNAME,HINFO,MX,PX,NS,PTR,SOA,TXT,WKS,SRV,NAPTR + port=X - set port number to send query on + type=X - synonym for querytype + class=X - set query class to one of IN (Internet), CHAOS, HESIOD or ANY +server NAME - set default server to NAME, using current default server +lserver NAME - set default server to NAME, using initial server +finger [USER] - finger the optional USER at the current default host +root - set current default server to the root +ls [opt] DOMAIN [> FILE] - list addresses in DOMAIN (optional: output to FILE) + -a - list canonical names and aliases + -h - list HINFO (CPU type and operating system) + -s - list well-known services + -d - list all records + -t TYPE - list records of the given type (e.g., A,CNAME,MX, etc.) +exit - exit the program, ^D also exits Property changes on: vendor/bind/8.3.4/contrib/bind/bin/nslookup/nslookup.help ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/addr/addr.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/addr/addr.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/addr/addr.c (revision 109985) @@ -0,0 +1,168 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: addr.c,v 8.9 2002/05/21 02:26:21 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "port_after.h" + +static const char *prog = "addr"; + +#define BIGGEST_ADDRESS IN6ADDRSZ + +static void +usage() { + fprintf(stderr, + "usage: %s [-4] [-6] [-n hexstring] [-p address]\n", + prog); + exit(1); +} + +/* Warning: this scribbles on `dst' even if it's going to return `0'. */ +static int +hexstring(const char *src, u_char *dst, int len) { + static const char xdigits[] = "0123456789abcdef"; + u_char *ptr = dst, *end = dst + len; + u_int val; + int ch, digits; + + val = 0; + digits = 0; + memset(dst, 0, len); + while ((ch = *src++) != '\0') { + if (ch == '0' && (*src == 'x' || *src == 'X')) { + src++; + continue; + } + if (isascii(ch) && (isspace(ch) || ispunct(ch))) { + if (digits > 0) { + if (ptr == end) + return (0); + *ptr++ = (u_char) (val & 0xff); + val = 0; + digits = 0; + } + digits = 0; + continue; + } + if (!isascii(ch) || !isxdigit(ch)) + return (0); + if (isupper(ch)) + ch = tolower(ch); + /* Clock it in using little endian arithmetic. */ + val <<= 4; + val |= (strchr(xdigits, ch) - xdigits); + if (++digits == 2) { + if (ptr == end) + return (0); + *ptr++ = (u_char) (val & 0xff); + digits = 0; + val = 0; + } + } + if (digits > 0) { + if (ptr == end) + return (0); + *ptr++ = (u_char) (val & 0xff); + } + return ((ptr - dst) == len); +} + +static void +display(const char *input, int af, const u_char *addr, int len) { + static int before = 0; + char p[sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255"]; + int i; + + if (before) + putchar('\n'); + else + before++; + + printf("Input: \"%s\"\n", input); + printf("Network: [af%d len%d]", af, len); + for (i = 0; i < len; i++) + printf(" %02x", addr[i]); + putchar('\n'); + printf("Presentation: \"%s\"\n", inet_ntop(af, addr, p, sizeof p)); +} + +int +main(argc, argv) + int argc; + char *argv[]; +{ + u_char addr[BIGGEST_ADDRESS]; + int optchr, af, len, some; + + prog = argv[0]; + af = AF_INET; + len = INADDRSZ; + some = 0; + while ((optchr = getopt(argc, argv, "46n:p:")) != -1) { + switch (optchr) { + case '4': + af = AF_INET; + len = INADDRSZ; + break; + case '6': + af = AF_INET6; + len = IN6ADDRSZ; + break; + case 'n': + if (!hexstring(optarg, addr, len)) { + fprintf(stderr, "bad hex string: \"%s\"\n", + optarg); + usage(); + /* NOTREACHED */ + } + display(optarg, af, addr, len); + some++; + break; + case 'p': + if (inet_pton(af, optarg, addr) <= 0) { + fprintf(stderr, "bad address: \"%s\"\n", + optarg); + usage(); + /* NOTREACHED */ + } + display(optarg, af, addr, len); + some++; + break; + default: + usage(); + /* NOTREACHED */ + } + } + if (!some) + usage(); + exit(0); + /* NOTREACHED */ +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/addr/addr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/addr/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/addr/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/addr/Makefile (revision 109985) @@ -0,0 +1,85 @@ +## Copyright (c) 1996,1999 by Internet Software Consortium +## +## 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. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM 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 +## SOFTWARE. + +# $Id: Makefile,v 8.27 2000/12/23 08:02:49 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g -Wall + +#(net2 and its descendents) +SYSTYPE = freebsd +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +EXE= +LEX = lex -I +SYSLIBS = -ll -lutil +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +STRIP=-s +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin + +LDFLAGS= +CFLAGS= ${CDEBUG} +CPPFLAGS= -I${PORTINCL} -I${INCL} + +PROG= addr +SRCS= ${PROG}.c +OBJS= ${PROG}.${O} + +all: ${PROG}${EXE} + +${PROG}${EXE}: ${OBJS} ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} ${BOUNDS} -o ${PROG}${EXE} ${OBJS} \ + ${LIBBIND} ${SYSLIBS} + +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c + +distclean: clean + +clean: FRC + rm -f ${PROG}${EXE} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + +depend: ${SRCS} + mkdep ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${SRCS} + +${DESTDIR}${DESTBIN}: + mkdir -p ${DESTDIR}${DESTBIN} + +install: ${DESTDIR}${DESTBIN} ${PROG}${EXE} + ${INSTALL} ${STRIP} -c ${INSTALL_EXEC} -m 755 ${PROG}${EXE} ${DESTDIR}${DESTBIN}/${PROG}${EXE} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +tags: FRC + ctags *.[ch] + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Property changes on: vendor/bind/8.3.4/contrib/bind/bin/addr/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/dig/dig.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/dig/dig.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/dig/dig.c (revision 109985) @@ -0,0 +1,1806 @@ +#ifndef lint +static const char rcsid[] = "$Id: dig.c,v 8.57 2002/06/18 02:26:49 marka Exp $"; +#endif + +/* + * Copyright (c) 1989 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/*********************** Notes for the BIND 4.9 release (Paul Vixie, DEC) + * dig 2.0 was written by copying sections of libresolv.a and nslookup + * and modifying them to be more useful for a general lookup utility. + * as of BIND 4.9, the changes needed to support dig have mostly been + * incorporated into libresolv.a and nslookup; dig now links against + * some of nslookup's .o files rather than #including them or maintaining + * local copies of them. + * + * while merging dig back into the BIND release, i made a number of + * structural changes. for one thing, i put all of dig's private + * library routines into this file rather than maintaining them in + * separate, #included, files. i don't like to #include ".c" files. + * i removed all calls to "bcopy", replacing them with structure + * assignments. i removed all "extern"'s of standard functions, + * replacing them with #include's of standard header files. this + * version of dig is probably as portable as the rest of BIND. + * + * i had to remove the query-time and packet-count statistics since + * the current libresolv.a is a lot harder to modify to maintain these + * than the 4.8 one (used in the original dig) was. for consolation, + * i added a "usage" message with extensive help text. + * + * to save my (limited, albeit) sanity, i ran "indent" over the source. + * i also added the standard berkeley/DEC copyrights, since this file now + * contains a fair amount of non-USC code. note that the berkeley and + * DEC copyrights do not prohibit redistribution, with or without fee; + * we add them only to protect ourselves (you have to claim copyright + * in order to disclaim liability and warranty). + * + * Paul Vixie, Palo Alto, CA, April 1993 + **************************************************************************** + + ****************************************************************** + * DiG -- Domain Information Groper * + * * + * dig.c - Version 2.1 (7/12/94) ("BIND takeover") * + * * + * Developed by: Steve Hotz & Paul Mockapetris * + * USC Information Sciences Institute (USC-ISI) * + * Marina del Rey, California * + * 1989 * + * * + * dig.c - * + * Version 2.0 (9/1/90) * + * o renamed difftime() difftv() to avoid * + * clash with ANSI C * + * o fixed incorrect # args to strcmp,gettimeofday * + * o incorrect length specified to strncmp * + * o fixed broken -sticky -envsa -envset functions * + * o print options/flags redefined & modified * + * * + * Version 2.0.beta (5/9/90) * + * o output format - helpful to `doc` * + * o minor cleanup * + * o release to beta testers * + * * + * Version 1.1.beta (10/26/89) * + * o hanging zone transer (when REFUSED) fixed * + * o trailing dot added to domain names in RDATA * + * o ISI internal * + * * + * Version 1.0.tmp (8/27/89) * + * o Error in prnttime() fixed * + * o no longer dumps core on large pkts * + * o zone transfer (axfr) added * + * o -x added for inverse queries * + * (i.e. "dig -x 128.9.0.32") * + * o give address of default server * + * o accept broadcast to server @255.255.255.255 * + * * + * Version 1.0 (3/27/89) * + * o original release * + * * + * DiG is Public Domain, and may be used for any purpose as * + * long as this notice is not removed. * + ******************************************************************/ + +/* Import. */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +#include + +#include "../nslookup/res.h" + +/* Global. */ + +#define VERSION 83 +#define VSTRING "8.3" + +#define PRF_DEF (RES_PRF_STATS | RES_PRF_CMD | RES_PRF_QUES | \ + RES_PRF_ANS | RES_PRF_AUTH | RES_PRF_ADD | \ + RES_PRF_HEAD1 | RES_PRF_HEAD2 | RES_PRF_TTLID | \ + RES_PRF_HEADX | RES_PRF_REPLY | RES_PRF_TRUNC) +#define PRF_MIN (RES_PRF_QUES | RES_PRF_ANS | RES_PRF_HEAD1 | \ + RES_PRF_HEADX | RES_PRF_REPLY | RES_PRF_TRUNC) +#define PRF_ZONE (RES_PRF_STATS | RES_PRF_CMD | RES_PRF_QUES | \ + RES_PRF_ANS | RES_PRF_AUTH | RES_PRF_ADD | \ + RES_PRF_TTLID | RES_PRF_REPLY | RES_PRF_TRUNC) + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif + +#define SAVEENV "DiG.env" +#define DIG_MAXARGS 30 + +static int eecode = 0; +static FILE * qfp; +static char *defsrv, *srvmsg; +static char defbuf[40] = "default -- "; +static char srvbuf[1024]; +static char myhostname[MAXHOSTNAMELEN]; +static struct sockaddr_in myaddress; +static struct sockaddr_in6 myaddress6; +static u_int32_t ixfr_serial; + +/* stuff for nslookup modules */ +struct __res_state res; +FILE *filePtr; +jmp_buf env; +HostInfo *defaultPtr = NULL; +HostInfo curHostInfo, defaultRec; +int curHostValid = FALSE; +int queryType, queryClass; +extern int StringToClass(), StringToType(); /* subr.c */ +#if defined(BSD) && BSD >= 199006 && !defined(RISCOS_BSD) +FILE *yyin = NULL; +void yyrestart(FILE *f) { UNUSED(f); } +#endif +char *pager = NULL; +/* end of nslookup stuff */ + +/* Forward. */ + +static void Usage(void); +static int setopt(const char *); +static void res_re_init(void); +static int xstrtonum(char *); +static int printZone(ns_type, const char *, + const struct sockaddr_in *, ns_tsig_key *); +static int print_axfr(FILE *output, const u_char *msg, + size_t msglen); +static struct timeval difftv(struct timeval, struct timeval); +static void prnttime(struct timeval); +static void stackarg(char *, char **); +static void reverse6(char *, struct in6_addr *); + +/* Public. */ + +int +main(int argc, char **argv) { + short port = htons(NAMESERVER_PORT); + short lport; + /* Wierd stuff for SPARC alignment, hurts nothing else. */ + union { + HEADER header_; + u_char packet_[PACKETSZ]; + } packet_; +#define header (packet_.header_) +#define packet (packet_.packet_) + u_char answer[64*1024]; + int n; + char doping[90]; + char pingstr[50]; + char *afile; + char *addrc, *addrend, *addrbegin; + + time_t exectime; + struct timeval tv1, tv2, start_time, end_time, query_time; + + char *srv; + int anyflag = 0; + int sticky = 0; + int tmp; + int qtypeSet; + int addrflag = 0; + ns_type xfr = ns_t_invalid; + int bytes_out, bytes_in; + + char cmd[512]; + char domain[MAXDNAME]; + char msg[120], **vtmp; + char *args[DIG_MAXARGS]; + char **ax; + int once = 1, dofile = 0; /* batch -vs- interactive control */ + char fileq[384]; + int fp; + int wait=0, delay; + int envset=0, envsave=0; + struct __res_state res_x, res_t; + int r; + struct in6_addr in6; + + ns_tsig_key key; + char *keyfile = NULL, *keyname = NULL; + + res_ninit(&res); + res.pfcode = PRF_DEF; + qtypeSet = 0; + memset(domain, 0, sizeof domain); + gethostname(myhostname, (sizeof myhostname)); +#ifdef HAVE_SA_LEN + myaddress.sin_len = sizeof(struct sockaddr_in); +#endif + myaddress.sin_family = AF_INET; + myaddress.sin_addr.s_addr = INADDR_ANY; + myaddress.sin_port = 0; /*INPORT_ANY*/; + +#ifdef HAVE_SA_LEN + myaddress6.sin6_len = sizeof(struct sockaddr_in6); +#endif + myaddress6.sin6_family = AF_INET6; + myaddress6.sin6_addr = in6addr_any; + myaddress6.sin6_port = 0; /*INPORT_ANY*/; + + defsrv = strcat(defbuf, inet_ntoa(res.nsaddr.sin_addr)); + res_x = res; + +/* + * If LOCALDEF in environment, should point to file + * containing local favourite defaults. Also look for file + * DiG.env (i.e. SAVEENV) in local directory. + */ + + if ((((afile = (char *) getenv("LOCALDEF")) != (char *) NULL) && + ((fp = open(afile, O_RDONLY)) > 0)) || + ((fp = open(SAVEENV, O_RDONLY)) > 0)) { + read(fp, (char *)&res_x, (sizeof res_x)); + close(fp); + res = res_x; + } +/* + * Check for batch-mode DiG; also pre-scan for 'help'. + */ + vtmp = argv; + ax = args; + while (*vtmp != NULL) { + if (strcmp(*vtmp, "-h") == 0 || + strcmp(*vtmp, "-help") == 0 || + strcmp(*vtmp, "-usage") == 0 || + strcmp(*vtmp, "help") == 0) { + Usage(); + exit(0); + } + + if (strcmp(*vtmp, "-f") == 0) { + dofile++; once=0; + if ((qfp = fopen(*++vtmp, "r")) == NULL) { + fflush(stdout); + perror("file open"); + fflush(stderr); + exit(10); + } + } else { + if (ax - args == DIG_MAXARGS) { + fprintf(stderr, "dig: too many arguments\n"); + exit(10); + } + *ax++ = *vtmp; + } + vtmp++; + } + + res.id = 1; + gettimeofday(&tv1, NULL); + +/* + * Main section: once if cmd-line query + * while !EOF if batch mode + */ + *fileq = '\0'; + while ((dofile && fgets(fileq, sizeof fileq, qfp) != NULL) || + (!dofile && once--)) + { + if (*fileq == '\n' || *fileq == '#' || *fileq==';') { + printf("%s", fileq); /* echo but otherwise ignore */ + continue; /* blank lines and comments */ + } + +/* + * "Sticky" requests that before current parsing args + * return to current "working" environment (X******). + */ + if (sticky) { + printf(";; (using sticky settings)\n"); + res = res_x; + } + +/* + * Concat cmd-line and file args. + */ + stackarg(fileq, ax); + + /* defaults */ + queryType = ns_t_ns; + queryClass = ns_c_in; + xfr = ns_t_invalid; + *pingstr = 0; + srv = NULL; + + sprintf(cmd, "\n; <<>> DiG %s <<>> ", VSTRING); + argv = args; + argc = ax - args; +/* + * More cmd-line options than anyone should ever have to + * deal with .... + */ + while (*(++argv) != NULL && **argv != '\0') { + strcat(cmd, *argv); + strcat(cmd, " "); + if (**argv == '@') { + srv = (*argv+1); + continue; + } + if (**argv == '%') + continue; + if (**argv == '+') { + setopt(*argv+1); + continue; + } + if (**argv == '=') { + ixfr_serial = strtoul(*argv+1, NULL, 0); + continue; + } + if (strncmp(*argv, "-nost", 5) == 0) { + sticky = 0; + continue; + } else if (strncmp(*argv, "-st", 3) == 0) { + sticky++; + continue; + } else if (strncmp(*argv, "-envsa", 6) == 0) { + envsave++; + continue; + } else if (strncmp(*argv, "-envse", 6) == 0) { + envset++; + continue; + } + + if (**argv == '-') { + switch (argv[0][1]) { + case 'T': + if (*++argv == NULL) + printf("; no arg for -T?\n"); + else + wait = atoi(*argv); + break; + case 'c': + if(*++argv == NULL) + printf("; no arg for -c?\n"); + else if ((tmp = atoi(*argv)) + || *argv[0] == '0') { + queryClass = tmp; + } else if ((tmp = StringToClass(*argv, + 0, NULL) + ) != 0) { + queryClass = tmp; + } else { + printf( + "; invalid class specified\n" + ); + } + break; + case 't': + if (*++argv == NULL) + printf("; no arg for -t?\n"); + else if ((tmp = atoi(*argv)) + || *argv[0]=='0') { + if (ns_t_xfr_p(tmp)) { + xfr = tmp; + } else { + queryType = tmp; + qtypeSet++; + } + } else if ((tmp = StringToType(*argv, + 0, NULL) + ) != 0) { + if (ns_t_xfr_p(tmp)) { + xfr = tmp; + } else { + queryType = tmp; + qtypeSet++; + } + } else { + printf( + "; invalid type specified\n" + ); + } + break; + case 'x': + if (!qtypeSet) { + queryType = T_ANY; + qtypeSet++; + } + if ((addrc = *++argv) == NULL) { + printf("; no arg for -x?\n"); + break; + } + r = inet_pton(AF_INET6, addrc, &in6); + if (r > 0) { + reverse6(domain, &in6); + break; + } + addrend = addrc + strlen(addrc); + if (*addrend == '.') + *addrend = '\0'; + *domain = '\0'; + while ((addrbegin = strrchr(addrc,'.'))) { + strcat(domain, addrbegin+1); + strcat(domain, "."); + *addrbegin = '\0'; + } + strcat(domain, addrc); + strcat(domain, ".in-addr.arpa."); + break; + case 'p': + if (argv[0][2] != '\0') + port = htons(atoi(argv[0]+2)); + else if (*++argv == NULL) + printf("; no arg for -p?\n"); + else + port = htons(atoi(*argv)); + break; + case 'P': + if (argv[0][2] != '\0') + strcpy(pingstr, argv[0]+2); + else + strcpy(pingstr, "ping -s"); + break; + case 'n': + if (argv[0][2] != '\0') + res.ndots = atoi(argv[0]+2); + else if (*++argv == NULL) + printf("; no arg for -n?\n"); + else + res.ndots = atoi(*argv); + break; + case 'b': { + char *a, *p; + + if (argv[0][2] != '\0') + a = argv[0]+2; + else if (*++argv == NULL) { + printf("; no arg for -b?\n"); + break; + } else + a = *argv; + if ((p = strchr(a, ':')) != NULL) { + *p++ = '\0'; + lport = htons(atoi(p)); + } else + lport = htons(0); + if (inet_pton(AF_INET6, a, + &myaddress6.sin6_addr) == 1) { + myaddress6.sin6_port = lport; + } else if (!inet_aton(a, + &myaddress.sin_addr)) { + fprintf(stderr, + ";; bad -b addr\n"); + exit(1); + } else + myaddress.sin_port = lport; + } + break; + case 'k': + /* -k keydir:keyname */ + + if (argv[0][2] != '\0') + keyfile = argv[0]+2; + else if (*++argv == NULL) { + printf("; no arg for -k?\n"); + break; + } else + keyfile = *argv; + + keyname = strchr(keyfile, ':'); + if (keyname == NULL) { + fprintf(stderr, + "key option argument should be keydir:keyname\n"); + exit(1); + } + *keyname++='\0'; + break; + } /* switch - */ + continue; + } /* if '-' */ + + if ((tmp = StringToType(*argv, -1, NULL)) != -1) { + if ((T_ANY == tmp) && anyflag++) { + queryClass = C_ANY; + continue; + } + if (ns_t_xfr_p(tmp) && + (tmp == ns_t_axfr || + (res.options & RES_USEVC) != 0) + ) { + res.pfcode = PRF_ZONE; + xfr = (ns_type)tmp; + } else { + queryType = tmp; + qtypeSet++; + } + } else if ((tmp = StringToClass(*argv, -1, NULL)) + != -1) { + queryClass = tmp; + } else { + memset(domain, 0, sizeof domain); + sprintf(domain,"%s",*argv); + } + } /* while argv remains */ + + /* process key options */ + if (keyfile) { +#ifdef PARSE_KEYFILE + int i, n1; + char buf[BUFSIZ], *p; + FILE *fp = NULL; + int file_major, file_minor, alg; + + fp = fopen(keyfile, "r"); + if (fp == NULL) { + perror(keyfile); + exit(1); + } + /* Now read the header info from the file. */ + i = fread(buf, 1, BUFSIZ, fp); + if (i < 5) { + fclose(fp); + exit(1); + } + fclose(fp); + + p = buf; + + n=strlen(p); /* get length of strings */ + n1=strlen("Private-key-format: v"); + if (n1 > n || + strncmp(buf, "Private-key-format: v", n1)) { + fprintf(stderr, "Invalid key file format\n"); + exit(1); /* not a match */ + } + p+=n1; /* advance pointer */ + sscanf((char *)p, "%d.%d", &file_major, &file_minor); + /* should do some error checking with these someday */ + while (*p++!='\n'); /* skip to end of line */ + + n=strlen(p); /* get length of strings */ + n1=strlen("Algorithm: "); + if (n1 > n || strncmp(p, "Algorithm: ", n1)) { + fprintf(stderr, "Invalid key file format\n"); + exit(1); /* not a match */ + } + p+=n1; /* advance pointer */ + if (sscanf((char *)p, "%d", &alg)!=1) { + fprintf(stderr, "Invalid key file format\n"); + exit(1); + } + while (*p++!='\n'); /* skip to end of line */ + + n=strlen(p); /* get length of strings */ + n1=strlen("Key: "); + if (n1 > n || strncmp(p, "Key: ", n1)) { + fprintf(stderr, "Invalid key file format\n"); + exit(1); /* not a match */ + } + p+=n1; /* advance pointer */ + pp=p; + while (*pp++!='\n'); /* skip to end of line, + * terminate it */ + *--pp='\0'; + + key.data=malloc(1024*sizeof(char)); + key.len=b64_pton(p, key.data, 1024); + + strcpy(key.name, keyname); + strcpy(key.alg, "HMAC-MD5.SIG-ALG.REG.INT"); +#else + /* use the dst* routines to parse the key files + * + * This requires that both the .key and the .private + * files exist in your cwd, so the keyfile parmeter + * here is assumed to be a path in which the + * K*.{key,private} files exist. + */ + DST_KEY *dst_key; + char cwd[PATH_MAX+1]; + + if (getcwd(cwd, PATH_MAX)==NULL) { + perror("unable to get current directory"); + exit(1); + } + if (chdir(keyfile)<0) { + fprintf(stderr, + "unable to chdir to %s: %s\n", keyfile, + strerror(errno)); + exit(1); + } + + dst_init(); + dst_key = dst_read_key(keyname, + 0 /* not used for priv keys */, + KEY_HMAC_MD5, DST_PRIVATE); + if (!dst_key) { + fprintf(stderr, + "dst_read_key: error reading key\n"); + exit(1); + } + key.data=malloc(1024*sizeof(char)); + dst_key_to_buffer(dst_key, key.data, 1024); + key.len=dst_key->dk_key_size; + + strcpy(key.name, keyname); + strcpy(key.alg, "HMAC-MD5.SIG-ALG.REG.INT"); + + if (chdir(cwd)<0) { + fprintf(stderr, "unable to chdir to %s: %s\n", + cwd, strerror(errno)); + exit(1); + } +#endif + } + + if (res.pfcode & 0x80000) + printf("; pfcode: %08lx, options: %08lx\n", + res.pfcode, res.options); + +/* + * Current env. (after this parse) is to become the + * new "working" environmnet. Used in conj. with sticky. + */ + if (envset) { + res_x = res; + envset = 0; + } + +/* + * Current env. (after this parse) is to become the + * new default saved environmnet. Save in user specified + * file if exists else is SAVEENV (== "DiG.env"). + */ + if (envsave) { + afile = (char *) getenv("LOCALDEF"); + if ((afile && + ((fp = open(afile, + O_WRONLY|O_CREAT|O_TRUNC, + S_IREAD|S_IWRITE)) > 0)) + || + ((fp = open(SAVEENV, + O_WRONLY|O_CREAT|O_TRUNC, + S_IREAD|S_IWRITE)) > 0)) { + write(fp, (char *)&res, (sizeof res)); + close(fp); + } + envsave = 0; + } + + if (res.pfcode & RES_PRF_CMD) + printf("%s\n", cmd); + + addrflag = anyflag = 0; + +/* + * Find address of server to query. If not dot-notation, then + * try to resolve domain-name (if so, save and turn off print + * options, this domain-query is not the one we want. Restore + * user options when done. + * Things get a bit wierd since we need to use resolver to be + * able to "put the resolver to work". + */ + + srvbuf[0] = 0; + srvmsg = defsrv; + if (srv != NULL) { + int nscount = 0; + union res_sockaddr_union u[MAXNS]; + struct addrinfo *answer = NULL; + struct addrinfo *cur = NULL; + struct addrinfo hint; + + memset(u, 0, sizeof(u)); + res_t = res; + res_ninit(&res); + res.pfcode = 0; + res.options = RES_DEFAULT; + memset(&hint, 0, sizeof(hint)); + hint.ai_socktype = SOCK_DGRAM; + if (!getaddrinfo(srv, NULL, &hint, &answer)) { + res = res_t; + cur = answer; + for (cur = answer; + cur != NULL; + cur = cur->ai_next) { + if (nscount == MAXNS) + break; + switch (cur->ai_addr->sa_family) { + case AF_INET6: + u[nscount].sin6 = + *(struct sockaddr_in6*)cur->ai_addr; + u[nscount++].sin6.sin6_port = + port; + break; + case AF_INET: + u[nscount].sin = + *(struct sockaddr_in*)cur->ai_addr; + u[nscount++].sin6.sin6_port = + port; + break; + } + } + if (nscount != 0) { + char buf[80]; + res_setservers(&res, u, nscount); + srvmsg = strcat(srvbuf, srv); + strcat(srvbuf, " "); + buf[0] = '\0'; + switch (u[0].sin.sin_family) { + case AF_INET: + inet_ntop(AF_INET, + &u[0].sin.sin_addr, + buf, sizeof(buf)); + break; + case AF_INET6: + inet_ntop(AF_INET6, + &u[0].sin6.sin6_addr, + buf, sizeof(buf)); + break; + } + strcat(srvbuf, buf); + } + freeaddrinfo(answer); + } else { + res = res_t; + fflush(stdout); + fprintf(stderr, + "; Bad server: %s -- using default server and timer opts\n", + srv); + fflush(stderr); + srvmsg = defsrv; + srv = NULL; + } + printf("; (%d server%s found)\n", + res.nscount, (res.nscount==1)?"":"s"); + res.id += res.retry; + } + + if (ns_t_xfr_p(xfr)) { + int i; + int nscount; + union res_sockaddr_union u[MAXNS]; + nscount = res_getservers(&res, u, MAXNS); + for (i = 0; i < res.nscount; i++) { + int x; + + if (keyfile) + x = printZone(xfr, domain, + &u[i].sin, + &key); + else + x = printZone(xfr, domain, + &u[i].sin, + NULL); + if (res.pfcode & RES_PRF_STATS) { + char buf[80]; + exectime = time(NULL); + buf[0] = '\0'; + switch (u[i].sin.sin_family) { + case AF_INET: + inet_ntop(AF_INET, + &u[i].sin.sin_addr, + buf, sizeof(buf)); + break; + case AF_INET6: + inet_ntop(AF_INET6, + &u[i].sin6.sin6_addr, + buf, sizeof(buf)); + break; + } + printf(";; FROM: %s to SERVER: %s\n", + myhostname, + buf); + printf(";; WHEN: %s", ctime(&exectime)); + } + if (!x) + break; /* success */ + } + fflush(stdout); + continue; + } + + if (*domain && !qtypeSet) { + queryType = T_A; + qtypeSet++; + } + + bytes_out = n = res_nmkquery(&res, QUERY, domain, + queryClass, queryType, + NULL, 0, NULL, + packet, sizeof packet); + if (n < 0) { + fflush(stderr); + printf(";; res_nmkquery: buffer too small\n\n"); + fflush(stdout); + continue; + } + if (queryType == T_IXFR) { + HEADER *hp = (HEADER *) packet; + u_char *cpp = packet + bytes_out; + + hp->nscount = htons(1+ntohs(hp->nscount)); + n = dn_comp(domain, cpp, + (sizeof packet) - (cpp - packet), + NULL, NULL); + cpp += n; + PUTSHORT(T_SOA, cpp); /* type */ + PUTSHORT(C_IN, cpp); /* class */ + PUTLONG(0, cpp); /* ttl */ + PUTSHORT(22, cpp); /* dlen */ + *cpp++ = 0; /* mname */ + *cpp++ = 0; /* rname */ + PUTLONG(ixfr_serial, cpp); + PUTLONG(0xDEAD, cpp); /* Refresh */ + PUTLONG(0xBEEF, cpp); /* Retry */ + PUTLONG(0xABCD, cpp); /* Expire */ + PUTLONG(0x1776, cpp); /* Min TTL */ + bytes_out = n = cpp - packet; + }; + +#if defined(RES_USE_EDNS0) && defined(RES_USE_DNSSEC) + if (n > 0 && + (res.options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0) + bytes_out = n = res_nopt(&res, n, packet, + sizeof(packet), 4096); +#endif + + eecode = 0; + if (res.pfcode & RES_PRF_HEAD1) + fp_resstat(&res, stdout); + (void) gettimeofday(&start_time, NULL); + if (keyfile) + n = res_nsendsigned(&res, packet, n, &key, answer, sizeof answer); + else + n = res_nsend(&res, packet, n, answer, sizeof answer); + if ((bytes_in = n) < 0) { + fflush(stdout); + n = 0 - n; + msg[0]=0; + if (keyfile) + strcat(msg,";; res_nsendsigned to server "); + else + strcat(msg,";; res_nsend to server "); + strcat(msg,srvmsg); + perror(msg); + fflush(stderr); + + if (!dofile) { + if (eecode) + exit(eecode); + else + exit(9); + } + } + (void) gettimeofday(&end_time, NULL); + + if (res.pfcode & RES_PRF_STATS) { + query_time = difftv(start_time, end_time); + printf(";; Total query time: "); + prnttime(query_time); + putchar('\n'); + exectime = time(NULL); + printf(";; FROM: %s to SERVER: %s\n", + myhostname, srvmsg); + printf(";; WHEN: %s", ctime(&exectime)); + printf(";; MSG SIZE sent: %d rcvd: %d\n", + bytes_out, bytes_in); + } + + fflush(stdout); +/* + * Argh ... not particularly elegant. Should put in *real* ping code. + * Would necessitate root priviledges for icmp port though! + */ + if (*pingstr) { + sprintf(doping,"%s %s 56 3 | tail -3",pingstr, + (srv==NULL)?(defsrv+10):srv); + system(doping); + } + putchar('\n'); + +/* + * Fairly crude method and low overhead method of keeping two + * batches started at different sites somewhat synchronized. + */ + gettimeofday(&tv2, NULL); + delay = (int)(tv2.tv_sec - tv1.tv_sec); + if (delay < wait) { + sleep(wait - delay); + } + tv1 = tv2; + } + return (eecode); +} + +/* Private. */ + +static void +Usage() { + fputs("\ +usage: dig [@server] [domain] [q-type] [q-class] {q-opt} {d-opt} [%comment]\n\ +where: server,\n\ + domain are names in the Domain Name System\n\ + q-class is one of (in,any,...) [default: in]\n\ + q-type is one of (a,any,mx,ns,soa,hinfo,axfr,txt,...) [default: a]\n\ +", stderr); + fputs("\ + q-opt is one of:\n\ + -x dot-notation-address (shortcut to in-addr.arpa lookups)\n\ + -f file (batch mode input file name)\n\ + -T time (batch mode time delay, per query)\n\ + -p port (nameserver is on this port) [53]\n\ + -b addr[:port] (bind to this tcp address) [*]\n\ + -P[ping-string] (see man page)\n\ + -t query-type (synonym for q-type)\n\ + -c query-class (synonym for q-class)\n\ + -k keydir:keyname (sign the query with this TSIG key)\n\ + -envsav,-envset (see man page)\n\ + -[no]stick (see man page)\n\ +", stderr); + fputs("\ + d-opt is of the form ``+keyword=value'' where keyword is one of:\n\ + [no]debug [no]d2 [no]recurse retry=# time=# [no]ko [no]vc\n\ + [no]defname [no]search domain=NAME [no]ignore [no]primary\n\ + [no]aaonly [no]cmd [no]stats [no]Header [no]header [no]trunc\n\ + [no]ttlid [no]cl [no]qr [no]reply [no]ques [no]answer\n\ + [no]author [no]addit [no]dnssec pfdef pfmin\n\ + pfset=# pfand=# pfor=#\n\ +", stderr); + fputs("\ +notes: defname and search don't work; use fully-qualified names.\n\ + this is DiG version " VSTRING "\n\ + $Id: dig.c,v 8.57 2002/06/18 02:26:49 marka Exp $\n\ +", stderr); +} + +static int +setopt(const char *string) { + char option[NAME_LEN], *ptr; + int i; + + i = pickString(string, option, sizeof option); + if (i == 0) { + fprintf(stderr, ";*** Invalid option: %s\n", string); + + /* this is ugly, but fixing the caller to behave + properly with an error return value would require a major + cleanup. */ + exit(9); + } + + if (strncmp(option, "aa", 2) == 0) { /* aaonly */ + res.options |= RES_AAONLY; + } else if (strncmp(option, "noaa", 4) == 0) { + res.options &= ~RES_AAONLY; + } else if (strncmp(option, "deb", 3) == 0) { /* debug */ + res.options |= RES_DEBUG; + } else if (strncmp(option, "nodeb", 5) == 0) { + res.options &= ~(RES_DEBUG | RES_DEBUG2); + } else if (strncmp(option, "ko", 2) == 0) { /* keepopen */ + res.options |= (RES_STAYOPEN | RES_USEVC); + } else if (strncmp(option, "noko", 4) == 0) { + res.options &= ~RES_STAYOPEN; + } else if (strncmp(option, "d2", 2) == 0) { /* d2 (more debug) */ + res.options |= (RES_DEBUG | RES_DEBUG2); + } else if (strncmp(option, "nod2", 4) == 0) { + res.options &= ~RES_DEBUG2; + } else if (strncmp(option, "def", 3) == 0) { /* defname */ + res.options |= RES_DEFNAMES; + } else if (strncmp(option, "nodef", 5) == 0) { + res.options &= ~RES_DEFNAMES; + } else if (strncmp(option, "dn", 2) == 0) { /* dnssec */ + res.options |= RES_USE_DNSSEC; + } else if (strncmp(option, "nodn", 4) == 0) { + res.options &= ~RES_USE_DNSSEC; + } else if (strncmp(option, "sea", 3) == 0) { /* search list */ + res.options |= RES_DNSRCH; + } else if (strncmp(option, "nosea", 5) == 0) { + res.options &= ~RES_DNSRCH; + } else if (strncmp(option, "do", 2) == 0) { /* domain */ + ptr = strchr(option, '='); + if (ptr != NULL) { + i = pickString(++ptr, res.defdname, sizeof res.defdname); + if (i == 0) { /* value's too long or non-existant. This actually + shouldn't happen due to pickString() + above */ + fprintf(stderr, "*** Invalid domain: %s\n", ptr) ; + exit(9); /* see comment at previous call to exit()*/ + } + } + } else if (strncmp(option, "ti", 2) == 0) { /* timeout */ + ptr = strchr(option, '='); + if (ptr != NULL) + sscanf(++ptr, "%d", &res.retrans); + } else if (strncmp(option, "ret", 3) == 0) { /* retry */ + ptr = strchr(option, '='); + if (ptr != NULL) + sscanf(++ptr, "%d", &res.retry); + } else if (strncmp(option, "i", 1) == 0) { /* ignore */ + res.options |= RES_IGNTC; + } else if (strncmp(option, "noi", 3) == 0) { + res.options &= ~RES_IGNTC; + } else if (strncmp(option, "pr", 2) == 0) { /* primary */ + res.options |= RES_PRIMARY; + } else if (strncmp(option, "nop", 3) == 0) { + res.options &= ~RES_PRIMARY; + } else if (strncmp(option, "rec", 3) == 0) { /* recurse */ + res.options |= RES_RECURSE; + } else if (strncmp(option, "norec", 5) == 0) { + res.options &= ~RES_RECURSE; + } else if (strncmp(option, "v", 1) == 0) { /* vc */ + res.options |= RES_USEVC; + } else if (strncmp(option, "nov", 3) == 0) { + res.options &= ~RES_USEVC; + } else if (strncmp(option, "pfset", 5) == 0) { + ptr = strchr(option, '='); + if (ptr != NULL) + res.pfcode = xstrtonum(++ptr); + } else if (strncmp(option, "pfand", 5) == 0) { + ptr = strchr(option, '='); + if (ptr != NULL) + res.pfcode = res.pfcode & xstrtonum(++ptr); + } else if (strncmp(option, "pfor", 4) == 0) { + ptr = strchr(option, '='); + if (ptr != NULL) + res.pfcode |= xstrtonum(++ptr); + } else if (strncmp(option, "pfmin", 5) == 0) { + res.pfcode = PRF_MIN; + } else if (strncmp(option, "pfdef", 5) == 0) { + res.pfcode = PRF_DEF; + } else if (strncmp(option, "an", 2) == 0) { /* answer section */ + res.pfcode |= RES_PRF_ANS; + } else if (strncmp(option, "noan", 4) == 0) { + res.pfcode &= ~RES_PRF_ANS; + } else if (strncmp(option, "qu", 2) == 0) { /* question section */ + res.pfcode |= RES_PRF_QUES; + } else if (strncmp(option, "noqu", 4) == 0) { + res.pfcode &= ~RES_PRF_QUES; + } else if (strncmp(option, "au", 2) == 0) { /* authority section */ + res.pfcode |= RES_PRF_AUTH; + } else if (strncmp(option, "noau", 4) == 0) { + res.pfcode &= ~RES_PRF_AUTH; + } else if (strncmp(option, "ad", 2) == 0) { /* addition section */ + res.pfcode |= RES_PRF_ADD; + } else if (strncmp(option, "noad", 4) == 0) { + res.pfcode &= ~RES_PRF_ADD; + } else if (strncmp(option, "tt", 2) == 0) { /* TTL & ID */ + res.pfcode |= RES_PRF_TTLID; + } else if (strncmp(option, "nott", 4) == 0) { + res.pfcode &= ~RES_PRF_TTLID; + } else if (strncmp(option, "tr", 2) == 0) { /* TTL & ID */ + res.pfcode |= RES_PRF_TRUNC; + } else if (strncmp(option, "notr", 4) == 0) { + res.pfcode &= ~RES_PRF_TRUNC; + } else if (strncmp(option, "he", 2) == 0) { /* head flags stats */ + res.pfcode |= RES_PRF_HEAD2; + } else if (strncmp(option, "nohe", 4) == 0) { + res.pfcode &= ~RES_PRF_HEAD2; + } else if (strncmp(option, "H", 1) == 0) { /* header all */ + res.pfcode |= RES_PRF_HEADX; + } else if (strncmp(option, "noH", 3) == 0) { + res.pfcode &= ~(RES_PRF_HEADX); + } else if (strncmp(option, "qr", 2) == 0) { /* query */ + res.pfcode |= RES_PRF_QUERY; + } else if (strncmp(option, "noqr", 4) == 0) { + res.pfcode &= ~RES_PRF_QUERY; + } else if (strncmp(option, "rep", 3) == 0) { /* reply */ + res.pfcode |= RES_PRF_REPLY; + } else if (strncmp(option, "norep", 5) == 0) { + res.pfcode &= ~RES_PRF_REPLY; + } else if (strncmp(option, "cm", 2) == 0) { /* command line */ + res.pfcode |= RES_PRF_CMD; + } else if (strncmp(option, "nocm", 4) == 0) { + res.pfcode &= ~RES_PRF_CMD; + } else if (strncmp(option, "cl", 2) == 0) { /* class mnemonic */ + res.pfcode |= RES_PRF_CLASS; + } else if (strncmp(option, "nocl", 4) == 0) { + res.pfcode &= ~RES_PRF_CLASS; + } else if (strncmp(option, "st", 2) == 0) { /* stats*/ + res.pfcode |= RES_PRF_STATS; + } else if (strncmp(option, "nost", 4) == 0) { + res.pfcode &= ~RES_PRF_STATS; + } else { + fprintf(stderr, "; *** Invalid option: %s\n", option); + return (ERROR); + } + res_re_init(); + return (SUCCESS); +} + +/* + * Force a reinitialization when the domain is changed. + */ +static void +res_re_init() { + static char localdomain[] = "LOCALDOMAIN"; + u_long pfcode = res.pfcode, options = res.options; + unsigned ndots = res.ndots; + int retrans = res.retrans, retry = res.retry; + char *buf; + + /* + * This is ugly but putenv() is more portable than setenv(). + */ + buf = malloc((sizeof localdomain) + strlen(res.defdname) +10/*fuzz*/); + sprintf(buf, "%s=%s", localdomain, res.defdname); + putenv(buf); /* keeps the argument, so we won't free it */ + res_ninit(&res); + res.pfcode = pfcode; + res.options = options; + res.ndots = ndots; + res.retrans = retrans; + res.retry = retry; +} + +/* + * convert char string (decimal, octal, or hex) to integer + */ +static int +xstrtonum(char *p) { + int v = 0; + int i; + int b = 10; + int flag = 0; + while (*p != 0) { + if (!flag++) + if (*p == '0') { + b = 8; p++; + continue; + } + if (isupper(*p)) + *p = tolower(*p); + if (*p == 'x') { + b = 16; p++; + continue; + } + if (isdigit(*p)) { + i = *p - '0'; + } else if (isxdigit(*p)) { + i = *p - 'a' + 10; + } else { + fprintf(stderr, + "; *** Bad char in numeric string..ignored\n"); + i = -1; + } + if (i >= b) { + fprintf(stderr, + "; *** Bad char in numeric string..ignored\n"); + i = -1; + } + if (i >= 0) + v = v * b + i; + p++; + } + return (v); +} + +typedef union { + HEADER qb1; + u_char qb2[PACKETSZ]; +} querybuf; + +static int +printZone(ns_type xfr, const char *zone, const struct sockaddr_in *sin, + ns_tsig_key *key) +{ + static u_char *answer = NULL; + static int answerLen = 0; + + querybuf buf; + int msglen, amtToRead, numRead, result, sockFD, len; + int count, type, class, rlen, done, n; + int numAnswers, numRecords, soacnt; + u_char *cp, tmp[NS_INT16SZ]; + char dname[2][NS_MAXDNAME]; + enum { NO_ERRORS, ERR_READING_LEN, ERR_READING_MSG, ERR_PRINTING } + error; + pid_t zpid = -1; + u_char *newmsg; + int newmsglen; + ns_tcp_tsig_state tsig_state; + int tsig_ret, tsig_required, tsig_present; + + switch (xfr) { + case ns_t_axfr: + case ns_t_zxfr: + break; + default: + fprintf(stderr, ";; %s - transfer type not supported\n", + p_type(xfr)); + return (ERROR); + } + + /* + * Create a query packet for the requested zone name. + */ + msglen = res_nmkquery(&res, ns_o_query, zone, + queryClass, ns_t_axfr, NULL, + 0, 0, buf.qb2, sizeof buf); + if (msglen < 0) { + if (res.options & RES_DEBUG) + fprintf(stderr, ";; res_nmkquery failed\n"); + return (ERROR); + } + + /* + * Sign the message if a key was sent + */ + if (key == NULL) { + newmsg = (u_char *)&buf; + newmsglen = msglen; + } else { + DST_KEY *dstkey; + int bufsize, siglen; + u_char sig[64]; + int ret; + + /* ns_sign() also calls dst_init(), but there is no harm + * doing it twice + */ + dst_init(); + + bufsize = msglen + 1024; + newmsg = (u_char *) malloc(bufsize); + if (newmsg == NULL) { + errno = ENOMEM; + return (-1); + } + memcpy(newmsg, (u_char *)&buf, msglen); + newmsglen = msglen; + + if (strcmp(key->alg, NS_TSIG_ALG_HMAC_MD5) != 0) + dstkey = NULL; + else + dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5, + NS_KEY_TYPE_AUTH_ONLY, + NS_KEY_PROT_ANY, + key->data, key->len); + if (dstkey == NULL) { + errno = EINVAL; + if (key) + free(newmsg); + return (-1); + } + + siglen = sizeof(sig); +/* newmsglen++; */ + ret = ns_sign(newmsg, &newmsglen, bufsize, NOERROR, dstkey, NULL, 0, + sig, &siglen, 0); + if (ret < 0) { + if (key) + free (newmsg); + if (ret == NS_TSIG_ERROR_NO_SPACE) + errno = EMSGSIZE; + else if (ret == -1) + errno = EINVAL; + return (ret); + } + ns_verify_tcp_init(dstkey, sig, siglen, &tsig_state); + } + + /* + * Set up a virtual circuit to the server. + */ + if ((sockFD = socket(sin->sin_family, SOCK_STREAM, 0)) < 0) { + int e = errno; + + perror(";; socket"); + return (e); + } + + switch (sin->sin_family) { + case AF_INET: + if (bind(sockFD, (struct sockaddr *)&myaddress, + sizeof myaddress) < 0){ + int e = errno; + + fprintf(stderr, ";; bind(%s:%u): %s\n", + inet_ntoa(myaddress.sin_addr), + ntohs(myaddress.sin_port), + strerror(e)); + (void) close(sockFD); + sockFD = -1; + return (e); + } + if (connect(sockFD, (const struct sockaddr *)sin, + sizeof *sin) < 0) { + int e = errno; + + perror(";; connect"); + (void) close(sockFD); + sockFD = -1; + return (e); + } + break; + case AF_INET6: + if (bind(sockFD, (struct sockaddr *)&myaddress6, + sizeof myaddress6) < 0){ + int e = errno; + char buf[80]; + + fprintf(stderr, ";; bind(%s:%u): %s\n", + inet_ntop(AF_INET6, &myaddress6.sin6_addr, + buf, sizeof(buf)), + ntohs(myaddress6.sin6_port), + strerror(e)); + (void) close(sockFD); + sockFD = -1; + return (e); + } + if (connect(sockFD, (const struct sockaddr *)sin, + sizeof(struct sockaddr_in6)) < 0) { + int e = errno; + + perror(";; connect"); + (void) close(sockFD); + sockFD = -1; + return (e); + } + break; + } + + /* + * Send length & message for zone transfer + */ + + ns_put16(newmsglen, tmp); + if (write(sockFD, (char *)tmp, NS_INT16SZ) != NS_INT16SZ || + write(sockFD, (char *)newmsg, newmsglen) != newmsglen) { + int e = errno; + if (key) + free (newmsg); + perror(";; write"); + (void) close(sockFD); + sockFD = -1; + return (e); + } else if (key) + free (newmsg); + + /* + * If we're compressing, push a gzip into the pipeline. + */ + if (xfr == ns_t_zxfr) { + enum { rd = 0, wr = 1 }; + int z[2]; + + if (pipe(z) < 0) { + int e = errno; + + perror(";; pipe"); + (void) close(sockFD); + sockFD = -1; + return (e); + } + zpid = vfork(); + if (zpid < 0) { + int e = errno; + + perror(";; fork"); + (void) close(sockFD); + sockFD = -1; + return (e); + } else if (zpid == 0) { + /* Child. */ + (void) close(z[rd]); + (void) dup2(sockFD, STDIN_FILENO); + (void) close(sockFD); + (void) dup2(z[wr], STDOUT_FILENO); + (void) close(z[wr]); + execlp("gzip", "gzip", "-d", "-v", NULL); + perror(";; child: execlp(gunzip)"); + _exit(1); + } + /* Parent. */ + (void) close(z[wr]); + (void) dup2(z[rd], sockFD); + (void) close(z[rd]); + } + result = 0; + numAnswers = 0; + numRecords = 0; + soacnt = 0; + error = NO_ERRORS; + + dname[0][0] = '\0'; + for (done = 0; !done; (void)NULL) { + /* + * Read the length of the response. + */ + + cp = tmp; + amtToRead = INT16SZ; + while (amtToRead > 0 && + (numRead = read(sockFD, cp, amtToRead)) > 0) { + cp += numRead; + amtToRead -= numRead; + } + if (numRead <= 0) { + error = ERR_READING_LEN; + break; + } + + len = ns_get16(tmp); + if (len == 0) + break; /* nothing left to read */ + + /* + * The server sent too much data to fit the existing buffer -- + * allocate a new one. + */ + if (len > answerLen) { + if (answerLen != 0) + free(answer); + answerLen = len; + answer = (u_char *)Malloc(answerLen); + } + + /* + * Read the response. + */ + + amtToRead = len; + cp = answer; + while (amtToRead > 0 && + (numRead = read(sockFD, cp, amtToRead)) > 0) { + cp += numRead; + amtToRead -= numRead; + } + if (numRead <= 0) { + error = ERR_READING_MSG; + break; + } + + result = print_axfr(stdout, answer, len); + if (result != 0) { + error = ERR_PRINTING; + break; + } + numRecords += htons(((HEADER *)answer)->ancount); + numAnswers++; + + /* Header. */ + cp = answer + HFIXEDSZ; + /* Question. */ + for (count = ntohs(((HEADER *)answer)->qdcount); + count > 0; + count--) { + n = dn_skipname(cp, answer + len); + if (n < 0) { + error = ERR_PRINTING; + done++; + break; + } + cp += n + QFIXEDSZ; + if (cp > answer + len) { + error = ERR_PRINTING; + done++; + break; + } + } + /* Answer. */ + for (count = ntohs(((HEADER *)answer)->ancount); + count > 0 && !done; + count--) { + n = dn_expand(answer, answer + len, cp, + dname[soacnt], sizeof dname[0]); + if (n < 0) { + error = ERR_PRINTING; + done++; + break; + } + cp += n; + if (cp + 3 * INT16SZ + INT32SZ > answer + len) { + error = ERR_PRINTING; + done++; + break; + } + GETSHORT(type, cp); + GETSHORT(class, cp); + cp += INT32SZ; /* ttl */ + GETSHORT(rlen, cp); + cp += rlen; + if (cp > answer + len) { + error = ERR_PRINTING; + done++; + break; + } + if (type == T_SOA && soacnt++ && + ns_samename(dname[0], dname[1]) == 1) { + done++; + break; + } + } + + /* + * Verify the TSIG + */ + + if (key) { + if (ns_find_tsig(answer, answer + len) != NULL) + tsig_present = 1; + else + tsig_present = 0; + if (numAnswers == 1 || soacnt > 1) + tsig_required = 1; + else + tsig_required = 0; + tsig_ret = ns_verify_tcp(answer, &len, &tsig_state, + tsig_required); + if (tsig_ret == 0) { + if (tsig_present) + printf("; TSIG ok\n"); + } + else + printf("; TSIG invalid\n"); + } + + } + + printf(";; Received %d answer%s (%d record%s).\n", + numAnswers, (numAnswers != 1) ? "s" : "", + numRecords, (numRecords != 1) ? "s" : ""); + + (void) close(sockFD); + sockFD = -1; + + /* + * If we were uncompressing, reap the uncompressor. + */ + if (xfr == ns_t_zxfr) { + pid_t pid; + int status; + + pid = wait(&status); + if (pid < 0) { + int e = errno; + + perror(";; wait"); + return (e); + } + if (pid != zpid) { + fprintf(stderr, ";; wrong pid (%lu != %lu)\n", + (u_long)pid, (u_long)zpid); + return (ERROR); + } + printf(";; pid %lu: exit %d, signal %d, core %c\n", + (u_long)pid, WEXITSTATUS(status), + WIFSIGNALED(status) ? WTERMSIG(status) : 0, + WCOREDUMP(status) ? 't' : 'f'); + } + + switch (error) { + case NO_ERRORS: + return (0); + + case ERR_READING_LEN: + return (EMSGSIZE); + + case ERR_PRINTING: + return (result); + + case ERR_READING_MSG: + return (EMSGSIZE); + + default: + return (EFAULT); + } +} + +static int +print_axfr(FILE *file, const u_char *msg, size_t msglen) { + ns_msg handle; + + if (ns_initparse(msg, msglen, &handle) < 0) { + fprintf(file, ";; ns_initparse: %s\n", strerror(errno)); + return (ns_r_formerr); + } + if (ns_msg_getflag(handle, ns_f_rcode) != ns_r_noerror) + return (ns_msg_getflag(handle, ns_f_rcode)); + + /* + * We are looking for info from answer resource records. + * If there aren't any, return with an error. We assume + * there aren't any question records. + */ + if (ns_msg_count(handle, ns_s_an) == 0) + return (NO_INFO); + +#ifdef PROTOCOLDEBUG + printf(";;; (message of %d octets has %d answers)\n", + msglen, ns_msg_count(handle, ns_s_an)); +#endif + for (;;) { + static char origin[NS_MAXDNAME], name_ctx[NS_MAXDNAME]; + const char *name; + char buf[2048]; /* XXX need to malloc/realloc. */ + ns_rr rr; + + if (ns_parserr(&handle, ns_s_an, -1, &rr)) { + if (errno != ENODEV) { + fprintf(file, ";; ns_parserr: %s\n", + strerror(errno)); + return (FORMERR); + } + break; + } + name = ns_rr_name(rr); + if (origin[0] == '\0' && name[0] != '\0') { + if (strcmp(name, ".") != 0) + strcpy(origin, name); + fprintf(file, "$ORIGIN %s.\n", origin); + if (strcmp(name, ".") == 0) + strcpy(origin, name); + if (res.pfcode & RES_PRF_TRUNC) + strcpy(name_ctx, "@"); + } + if (ns_sprintrr(&handle, &rr, + (res.pfcode & RES_PRF_TRUNC) ? name_ctx : NULL, + (res.pfcode & RES_PRF_TRUNC) ? origin : NULL, + buf, sizeof buf) < 0) { + fprintf(file, ";; ns_sprintrr: %s\n", strerror(errno)); + return (FORMERR); + } + strcpy(name_ctx, name); + fputs(buf, file); + fputc('\n', file); + } + return (SUCCESS); +} + +static struct timeval +difftv(struct timeval a, struct timeval b) { + static struct timeval diff; + + diff.tv_sec = b.tv_sec - a.tv_sec; + if ((diff.tv_usec = b.tv_usec - a.tv_usec) < 0) { + diff.tv_sec--; + diff.tv_usec += 1000000; + } + return (diff); +} + +static void +prnttime(struct timeval t) { + printf("%lu msec", (u_long)(t.tv_sec * 1000 + (t.tv_usec / 1000))); +} + +/* + * Take arguments appearing in simple string (from file or command line) + * place in char**. + */ +static void +stackarg(char *l, char **y) { + int done = 0; + + while (!done) { + switch (*l) { + case '\t': + case ' ': + l++; + break; + case '\0': + case '\n': + done++; + *y = NULL; + break; + default: + *y++ = l; + while (!isspace(*l)) + l++; + if (*l == '\n') + done++; + *l++ = '\0'; + *y = NULL; + } + } +} + +static void +reverse6(char *domain, struct in6_addr *in6) { + sprintf(domain, "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa", + in6->s6_addr[15] & 0x0f, (in6->s6_addr[15] >> 4) & 0x0f, + in6->s6_addr[14] & 0x0f, (in6->s6_addr[14] >> 4) & 0x0f, + in6->s6_addr[13] & 0x0f, (in6->s6_addr[13] >> 4) & 0x0f, + in6->s6_addr[12] & 0x0f, (in6->s6_addr[12] >> 4) & 0x0f, + in6->s6_addr[11] & 0x0f, (in6->s6_addr[11] >> 4) & 0x0f, + in6->s6_addr[10] & 0x0f, (in6->s6_addr[10] >> 4) & 0x0f, + in6->s6_addr[9] & 0x0f, (in6->s6_addr[9] >> 4) & 0x0f, + in6->s6_addr[8] & 0x0f, (in6->s6_addr[8] >> 4) & 0x0f, + in6->s6_addr[7] & 0x0f, (in6->s6_addr[7] >> 4) & 0x0f, + in6->s6_addr[6] & 0x0f, (in6->s6_addr[6] >> 4) & 0x0f, + in6->s6_addr[5] & 0x0f, (in6->s6_addr[5] >> 4) & 0x0f, + in6->s6_addr[4] & 0x0f, (in6->s6_addr[4] >> 4) & 0x0f, + in6->s6_addr[6] & 0x0f, (in6->s6_addr[3] >> 4) & 0x0f, + in6->s6_addr[2] & 0x0f, (in6->s6_addr[2] >> 4) & 0x0f, + in6->s6_addr[1] & 0x0f, (in6->s6_addr[1] >> 4) & 0x0f, + in6->s6_addr[0] & 0x0f, (in6->s6_addr[0] >> 4) & 0x0f); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/dig/dig.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/dig/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/dig/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/dig/Makefile (revision 109985) @@ -0,0 +1,89 @@ +## Copyright (c) 1996,1999 by Internet Software Consortium +## +## 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. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM 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 +## SOFTWARE. + +# $Id: Makefile,v 8.27 2000/12/23 08:02:50 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g -Wall + +#(net2 and its descendents) +SYSTYPE = freebsd +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +EXE= +LEX = lex -I +SYSLIBS = -ll -lutil +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +STRIP=-s +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin + +LDFLAGS= +CFLAGS= ${CDEBUG} +CPPFLAGS= -I${PORTINCL} -I${INCL} + +NSLOOKUP_OBJS= \ + ../nslookup/subr.${O} ../nslookup/send.${O} \ + ../nslookup/list.${O} ../nslookup/debug.${O} + +PROG= dig +SRCS= ${PROG}.c +OBJS= ${PROG}.${O} + +all: ${PROG}${EXE} + +${PROG}${EXE}: ${OBJS} ${NSLOOKUP_OBJS} ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} ${BOUNDS} -o ${PROG}${EXE} ${OBJS} \ + ${NSLOOKUP_OBJS} ${LIBBIND} ${SYSLIBS} + +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c + +distclean: clean + +clean: FRC + rm -f ${PROG}${EXE} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + +depend: ${SRCS} + mkdep ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${SRCS} + +${DESTDIR}${DESTBIN}: + mkdir -p ${DESTDIR}${DESTBIN} + +install: ${DESTDIR}${DESTBIN} ${PROG}${EXE} + ${INSTALL} ${STRIP} -c ${INSTALL_EXEC} -m 755 ${PROG}${EXE} ${DESTDIR}${DESTBIN}/${PROG}${EXE} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +tags: FRC + ctags *.[ch] + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Property changes on: vendor/bind/8.3.4/contrib/bind/bin/dig/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/host/host.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/host/host.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/host/host.c (revision 109985) @@ -0,0 +1,2140 @@ +#ifndef lint +static const char rcsid[] = "$Id: host.c,v 8.53 2002/06/18 02:34:02 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1986 Regents of the University of California.\n\ + Portions Copyright (c) 1993 Digital Equipment Corporation.\n\ + Portions Copyright (c) 1996-1999 Internet Software Consortium.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +/* + * Actually, this program is from Rutgers University, however it is + * based on nslookup and other pieces of named tools, so it needs + * the above copyright notices. + */ + +/* Import. */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#include + +/* Global. */ + +#ifndef PATH_SEP +#define PATH_SEP '/' +#endif +#define SIG_RDATA_BY_NAME 18 +#define NS_HEADERDATA_SIZE 10 /* type + class + ttl + rdlen */ + +#define NUMNS 8 +#define NUMNSADDR 16 +#define NUMMX 50 +#define NUMRR 127 /* max rr's per node to verify signatures for */ + +#define SUCCESS 0 +#define TIME_OUT -1 +#define NO_INFO -2 +#ifdef ERROR +#undef ERROR +#endif +#define ERROR -3 +#define NONAUTH -4 + +#define MY_PACKETSZ 64*1024 /* need this to hold tcp answers */ + +typedef union { + HEADER qb1; + u_char qb2[MY_PACKETSZ]; +} querybuf; + +#define SD_RR 1 +#define SD_SIG 2 +#define SD_BADSIG 4 + +typedef struct { + u_char data[MY_PACKETSZ]; + size_t len; +} rrstruct; + +static char chase_domain[NS_MAXDNAME]; +static int chase_class; +static int chase_type; +static char chase_sigorigttl[NS_INT32SZ]; +static rrstruct chase_rr[NUMRR]; +static int chase_rr_num; +static char chase_lastgoodkey[NS_MAXDNAME]; +static char chase_signer[NS_MAXDNAME]; +static u_char chase_sigrdata[MY_PACKETSZ]; +static size_t chase_sigrdata_len; +static u_char chase_signature[MY_PACKETSZ]; +static size_t chase_signature_len; +static int chase_step; +static int sigchase; + +static char cnamebuf[NS_MAXDNAME]; +static u_char hostbuf[NS_MAXDNAME]; + +static int sockFD; +static FILE *filePtr; + +static struct __res_state res; +static char *cname = NULL; +static const char *progname = "amnesia"; +static int getclass = ns_c_in, verbose = 0, list = 0; +static int server_specified = 0; +static int gettype = 0; +static int querytype = 0; +static char getdomain[NS_MAXDNAME]; + +/* Forward. */ + +static int parsetype(const char *s); +static int parseclass(const char *s); +static void hperror(int errnum); +static int addrinfo(struct sockaddr_storage *addr); +static int gethostinfo(char *name); +static int getdomaininfo(const char *name, const char *domain); +static int getinfo(const char *name, const char *domain, + int type); +static int printinfo(const querybuf *answer, const u_char *eom, + int filter, int isls, int isinaddr); +static const u_char * pr_rr(const u_char *cp, const u_char *msg, FILE *file, + int filter); +static const char * pr_type(int type); +static const char * pr_class(int class); +static const u_char * pr_cdname(const u_char *cp, const u_char *msg, + char *name, int namelen); +static int ListHosts(char *namePtr, int queryType); +static const char * DecodeError(int result); + +static void +usage(const char *msg) { + fprintf(stderr, "%s: usage error (%s)\n", progname, msg); + fprintf(stderr, "\ +Usage: %s [-adlrwv] [-t querytype] [-c class] host [server]\n\ +\t-a is equivalent to '-v -t *'\n\ +\t-c class to look for non-Internet data\n\ +\t-d to turn on debugging output\n\ +\t-l to turn on 'list mode'\n\ +\t-r to disable recursive processing\n\ +\t-s recursively chase signature found in answers\n\ +\t-t querytype to look for a specific type of information\n\ +\t-v for verbose output\n\ +\t-w to wait forever until reply\n\ +", progname); + exit(1); +} + +/* Public. */ + +int +main(int argc, char **argv) { + struct sockaddr_storage addr; + struct hostent *hp; + char *s; + int waitmode = 0; + int ncnames, ch; + int nkeychains; + struct addrinfo *answer = NULL; + struct addrinfo *cur = NULL; + struct addrinfo hint; + int ip = 0; + + dst_init(); + + if ((progname = strrchr(argv[0], PATH_SEP)) == NULL) + progname = argv[0]; + else + progname++; + res_ninit(&res); + res.retrans = 5; + while ((ch = getopt(argc, argv, "ac:dlrst:vw")) != -1) { + switch (ch) { + case 'a': + verbose = 1; + querytype = ns_t_any; + break; + case 'c': + getclass = parseclass(optarg); + break; + case 'd': + res.options |= RES_DEBUG; + break; + case 'l': + list = 1; + break; + case 'r': + res.options &= ~RES_RECURSE; + break; + case 's': + sigchase = 1; + break; + case 't': + querytype = parsetype(optarg); + break; + case 'v': + verbose = 1; + break; + case 'w': + res.retry = 1; + res.retrans = 15; + waitmode = 1; + break; + default: + usage("unrecogized switch"); + /*NOTREACHED*/ + } + } + if ((querytype == 0) && (sigchase)) { + if (verbose) + printf ("Forcing `-t a' for signature trace.\n"); + querytype = ns_t_a; + } + argc -= optind; + argv += optind; + if (argc < 1) + usage("missing host argument"); + strncpy(getdomain, *argv++, NS_MAXDNAME); + getdomain[NS_MAXDNAME-1] = 0; + argc--; + if (argc > 1) + usage("extra undefined arguments"); + if (argc == 1) { + union res_sockaddr_union u[MAXNS]; + int nscount; + + s = *argv++; + argc--; + server_specified++; + memset(&hint, 0, sizeof(hint)); + hint.ai_flags = AI_CANONNAME; + hint.ai_family = PF_UNSPEC; + hint.ai_socktype = SOCK_DGRAM; + + if (!getaddrinfo(s, NULL, &hint, &answer)) { + nscount = 0; + if (answer->ai_canonname != NULL) { + printf("Using domain server:\n"); + printf("Name: %s\n", answer->ai_canonname); + printf("Addresses:"); + } else + printf("Using domain server"); + + for (cur = answer; cur != NULL; cur = cur->ai_next) { + char buf[80]; + struct sockaddr_in6 *sin6; + struct sockaddr_in *sin; + + switch (cur->ai_addr->sa_family) { + case AF_INET6: + sin6 = + (struct sockaddr_in6 *)cur->ai_addr; + inet_ntop(cur->ai_addr->sa_family, + &sin6->sin6_addr, + buf, sizeof(buf)); + printf(" %s", buf); + if (nscount >= MAXNS) + break; + u[nscount].sin6 = *sin6; + u[nscount++].sin6.sin6_port = + htons(NAMESERVER_PORT); + break; + case AF_INET: + sin = + (struct sockaddr_in*)cur->ai_addr; + inet_ntop(cur->ai_addr->sa_family, + &sin->sin_addr, + buf, sizeof(buf)); + printf(" %s", buf); + if (nscount >= MAXNS) + break; + u[nscount].sin = *sin; + u[nscount++].sin6.sin6_port = + htons(NAMESERVER_PORT); + break; + } + } + if (nscount != 0) { + res_setservers(&res, u, nscount); + } + if (answer->ai_canonname != NULL) + printf("\n\n"); + else + printf(":\n\n"); + freeaddrinfo(answer); + } else { + fprintf(stderr, "Error in looking up server name:\n"); + exit(1); + } + res.retry = 2; + } + memset(&hint, 0, sizeof(hint)); + hint.ai_flags = AI_NUMERICHOST; + hint.ai_socktype = SOCK_DGRAM; + if(!getaddrinfo(getdomain, NULL, &hint, &answer)) { + memset(&addr, 0, sizeof(addr)); + switch (answer->ai_family) { + case AF_INET: + memcpy(&addr, answer->ai_addr, + sizeof(struct sockaddr_in)); + ip = 1; + break; + case AF_INET6: + memcpy(&addr, answer->ai_addr, + sizeof(struct sockaddr_in6)); + ip = 1; + break; + } + freeaddrinfo(answer); + } + hp = NULL; + res.res_h_errno = TRY_AGAIN; +/* + * We handle default domains ourselves, thank you. + */ + res.options &= ~RES_DEFNAMES; + + if (list) + exit(ListHosts(getdomain, querytype ? querytype : ns_t_a)); + ncnames = 5; nkeychains = 18; + while (hp == NULL && res.res_h_errno == TRY_AGAIN) { + if (!ip) { + cname = NULL; + hp = (struct hostent *)gethostinfo(getdomain); + getdomain[0] = 0; /* clear this query */ + if (sigchase && (chase_step & SD_RR)) { + if (nkeychains-- == 0) { + printf("Too many sig/key chains. Loop?\n"); + exit(1); + } + if (chase_step & SD_SIG) { + /* start new query, for KEY */ + strcpy (getdomain, chase_signer); + strcat (getdomain, "."); + querytype = ns_t_key; + } else if (!(chase_step & SD_BADSIG)) { + /* start new query, for SIG */ + strcpy (getdomain, chase_domain); + strcat (getdomain, "."); + querytype = ns_t_sig; + } else if (hp && !(chase_step & SD_SIG) && + (chase_step & SD_BADSIG)) { + printf ("%s for %s not found, last verified key %s\n", + chase_step & SD_SIG ? "Key" : "Signature", + chase_step & SD_SIG ? chase_signer : chase_domain, + chase_lastgoodkey[0] ? chase_lastgoodkey : "None"); + } + } + if (!getdomain[0] && cname) { + if (ncnames-- == 0) { + printf("Too many cnames. Loop?\n"); + exit(1); + } + strcpy(getdomain, cname); + strcat(getdomain, "."); + } + if (getdomain[0]) { + if (chase_step & SD_SIG) { + printf ("Locating key for %s\n", getdomain); + } else if (chase_step & SD_SIG) { + printf ("Locating signature for %s record(s) on %s\n", + sym_ntos(__p_type_syms, chase_type, NULL), + getdomain); + } + hp = NULL; + res.res_h_errno = TRY_AGAIN; + continue; + } + } else { + if (addrinfo(&addr) == 0) + hp = NULL; + else + hp = (struct hostent *)1; /* XXX */ + } + if (!waitmode) + break; + } + + if (hp == NULL) { + hperror(res.res_h_errno); + exit(1); + } + + exit(0); +} + +/* Private. */ + +static int +parsetype(const char *s) { + int type, success; + + type = sym_ston(__p_type_syms, s, &success); + if (success) + return (type); + if (strcmp(s, "*") == 0) + return (ns_t_any); + if (atoi(s)) + return (atoi(s)); + fprintf(stderr, "Invalid query type: %s\n", s); + exit(2); + /*NOTREACHED*/ +} + +static int +parseclass(const char *s) { + int class, success; + + class = sym_ston(__p_class_syms, s, &success); + if (success) + return (class); + if (atoi(s)) + return (atoi(s)); + fprintf(stderr, "Invalid query class: %s\n", s); + exit(2); + /*NOTREACHED*/ +} + +static void +hperror(int errnum) { + switch(errnum) { + case HOST_NOT_FOUND: + fprintf(stderr, "Host not found.\n"); + break; + case TRY_AGAIN: + fprintf(stderr, "Host not found, try again.\n"); + break; + case NO_RECOVERY: + fprintf(stderr, "No recovery, Host not found.\n"); + break; + case NO_ADDRESS: + fprintf(stderr, + "There is an entry for this host, but it doesn't have " + ); + switch (gettype) { + case ns_t_a: + fprintf(stderr, "an Internet address.\n"); + break; + case ns_t_ns: + fprintf(stderr, "a Name Server.\n"); + break; + case ns_t_md: + fprintf(stderr, "a Mail Destination.\n"); + break; + case ns_t_mf: + fprintf(stderr, "a Mail Forwarder.\n"); + break; + case ns_t_cname: + fprintf(stderr, "a Canonical Name.\n"); + break; + case ns_t_soa: + fprintf(stderr, "a Start of Authority record.\n"); + break; + case ns_t_mb: + fprintf(stderr, "a Mailbox Domain Name.\n"); + break; + case ns_t_mg: + fprintf(stderr, "a Mail Group Member.\n"); + break; + case ns_t_mr: + fprintf(stderr, "a Mail Rename Name.\n"); + break; + case ns_t_null: + fprintf(stderr, "a Null Resource record.\n"); + break; + case ns_t_wks: + fprintf(stderr, "any Well Known Service information.\n"); + break; + case ns_t_ptr: + fprintf(stderr, "a Pointer record.\n"); + break; + case ns_t_hinfo: + fprintf(stderr, "any Host Information.\n"); + break; + case ns_t_minfo: + fprintf(stderr, "any Mailbox Information.\n"); + break; + case ns_t_mx: + fprintf(stderr, "a Mail Exchanger record.\n"); + break; + case ns_t_txt: + fprintf(stderr, "a Text record.\n"); + break; + case ns_t_rp: + fprintf(stderr, "a Responsible Person.\n"); + break; + case ns_t_srv: + fprintf(stderr, "a Server Selector.\n"); + break; + case ns_t_naptr: + fprintf(stderr, "a URN Naming Authority.\n"); + break; + default: + fprintf(stderr, "the information you requested.\n"); + break; + } + break; + } +} + +static int +addrinfo(struct sockaddr_storage *addr) { + char name[NS_MAXDNAME]; + unsigned char *p; + struct in6_addr *addr6; + + switch(addr->ss_family) { + case AF_INET: + p = (unsigned char*)&((struct sockaddr_in *)addr)->sin_addr; + mapped: + sprintf(name, "%u.%u.%u.%u.IN-ADDR.ARPA.", + p[3], p[2], p[1], p[0]); + break; + case AF_INET6: + addr6 = &((struct sockaddr_in6 *)addr)->sin6_addr; + p = (unsigned char *)addr6; + if (IN6_IS_ADDR_V4MAPPED(addr6) || + IN6_IS_ADDR_V4COMPAT(addr6)) { + p += 12; + goto mapped; + } + sprintf(name, + "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." + "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." + "IP6.ARPA", + p[15] & 0xf, (p[15] >> 4) & 0xf, + p[14] & 0xf, (p[14] >> 4) & 0xf, + p[13] & 0xf, (p[13] >> 4) & 0xf, + p[12] & 0xf, (p[12] >> 4) & 0xf, + p[11] & 0xf, (p[11] >> 4) & 0xf, + p[10] & 0xf, (p[10] >> 4) & 0xf, + p[9] & 0xf, (p[9] >> 4) & 0xf, + p[8] & 0xf, (p[8] >> 4) & 0xf, + p[7] & 0xf, (p[7] >> 4) & 0xf, + p[6] & 0xf, (p[6] >> 4) & 0xf, + p[5] & 0xf, (p[5] >> 4) & 0xf, + p[4] & 0xf, (p[4] >> 4) & 0xf, + p[3] & 0xf, (p[3] >> 4) & 0xf, + p[2] & 0xf, (p[2] >> 4) & 0xf, + p[1] & 0xf, (p[1] >> 4) & 0xf, + p[0] & 0xf, (p[0] >> 4) & 0xf); + break; + default: + abort(); + } + return (getinfo(name, NULL, ns_t_ptr)); +} + +static int +gethostinfo(char *name) { + char *cp, **domain; + char tmp[NS_MAXDNAME]; + const char *tp; + int hp; + int asis = 0; + u_int n; + + if (strcmp(name, ".") == 0) + return (getdomaininfo(name, NULL)); + for (cp = name, n = 0; *cp; cp++) + if (*cp == '.') + n++; + if (n && cp[-1] == '.') { + if (cp[-1] == '.') + cp[-1] = 0; + hp = getdomaininfo(name, (char *)NULL); + if (cp[-1] == 0) + cp[-1] = '.'; + return (hp); + } + if (n == 0 && (tp = res_hostalias(&res, name, tmp, sizeof tmp))) { + if (verbose) + printf("Aliased to \"%s\"\n", tp); + res.options |= RES_DEFNAMES; + return (getdomaininfo(tp, (char *)NULL)); + } + if (n >= res.ndots) { + asis = 1; + if (verbose) + printf("Trying null domain\n"); + hp = getdomaininfo(name, (char*)NULL); + if (hp) + return (hp); + } + for (domain = res.dnsrch; *domain; domain++) { + if (verbose) + printf("Trying domain \"%s\"\n", *domain); + hp = getdomaininfo(name, *domain); + if (hp) + return (hp); + } + if (res.res_h_errno != HOST_NOT_FOUND || (res.options & RES_DNSRCH) == 0) + return (0); + if (!asis) + return (0); + if (verbose) + printf("Trying null domain\n"); + return (getdomaininfo(name, (char *)NULL)); +} + +static int +getdomaininfo(const char *name, const char *domain) { + int val1, val2, val3; + + if (querytype) + return (getinfo(name, domain, gettype=querytype)); + else { + val1 = getinfo(name, domain, gettype=ns_t_a); + if (cname || verbose) + return (val1); + val2 = getinfo(name, domain, gettype=ns_t_aaaa); + val3 = getinfo(name, domain, gettype=ns_t_mx); + return (val1 || val2 || val3); + } +} + +static int +getinfo(const char *name, const char *domain, int type) { + u_char *eom; + querybuf buf, answer; + int n; + char host[NS_MAXDNAME]; + + if (domain == NULL || + (domain[0] == '.' && domain[1] == '\0')) + sprintf(host, "%.*s", NS_MAXDNAME, name); + else + sprintf(host, "%.*s.%.*s", + NS_MAXDNAME, name, NS_MAXDNAME, domain); + + n = res_nmkquery(&res, QUERY, host, getclass, type, NULL, 0, NULL, + buf.qb2, sizeof buf); + if (n < 0) { + if (res.options & RES_DEBUG) + printf("res_nmkquery failed\n"); + res.res_h_errno = NO_RECOVERY; + return (0); + } + n = res_nsend(&res, buf.qb2, n, answer.qb2, sizeof answer); + if (n < 0) { + if (res.options & RES_DEBUG) + printf("res_nsend failed\n"); + res.res_h_errno = TRY_AGAIN; + return (0); + } + eom = answer.qb2 + n; + return (printinfo(&answer, eom, ns_t_any, 0, (type == ns_t_ptr))); +} + +static int +printinfo(const querybuf *answer, const u_char *eom, int filter, int isls, + int isinaddr) +{ + int n, nmx, ancount, nscount, arcount, qdcount, buflen, savesigchase; + const u_char *bp, *cp; + const HEADER *hp; + + /* + * Find first satisfactory answer. + */ + hp = (const HEADER *) answer; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + nscount = ntohs(hp->nscount); + arcount = ntohs(hp->arcount); + if (res.options & RES_DEBUG || (verbose && isls == 0)) + printf("rcode = %d (%s), ancount=%d\n", + hp->rcode, DecodeError(hp->rcode), ancount); + if (hp->rcode != NOERROR || (ancount+nscount+arcount) == 0) { + switch (hp->rcode) { + case NXDOMAIN: + res.res_h_errno = HOST_NOT_FOUND; + return (0); + case SERVFAIL: + res.res_h_errno = TRY_AGAIN; + return (0); + case NOERROR: + res.res_h_errno = NO_DATA; + return (0); + case FORMERR: + case NOTIMP: + case REFUSED: + res.res_h_errno = NO_RECOVERY; + return (0); + } + return (0); + } + bp = hostbuf; + nmx = 0; + buflen = sizeof(hostbuf); + cp = answer->qb2 + HFIXEDSZ; + if (qdcount > 0) { + while (qdcount-- > 0) { + n = dn_skipname(cp, eom); + if (n < 0) { + printf("Form error.\n"); + return (0); + } + cp += n + QFIXEDSZ; + if (cp > eom) { + printf("Form error.\n"); + return (0); + } + } + } + if (ancount) { + if (!hp->aa) + if (verbose && isls == 0) + printf( + "The following answer is not authoritative:\n" + ); + if (!hp->ad) + if (verbose && isls == 0) + printf("The following answer is not verified as authentic by the server:\n"); + while (--ancount >= 0 && cp && cp < eom) { + cp = pr_rr(cp, answer->qb2, stdout, filter); + /* + * When we ask for address and there is a CNAME, it + * seems to return both the CNAME and the address. + * Since we trace down the CNAME chain ourselves, we + * don't really want to print the address at this + * point. + */ + if (cname && (!verbose) && (!isinaddr)) + return (1); + } + } + if (!verbose) + return (1); + + /* don't chase signatures for non-answer stuff */ + + savesigchase = sigchase; + sigchase = 0; + + if (nscount) { + printf("For authoritative answers, see:\n"); + while (--nscount >= 0 && cp && cp < eom) + cp = pr_rr(cp, answer->qb2, stdout, filter); + } + if (arcount) { + printf("Additional information:\n"); + while (--arcount >= 0 && cp && cp < eom) + cp = pr_rr(cp, answer->qb2, stdout, filter); + } + + /* restore sigchase value */ + + sigchase = savesigchase; + + return (1); +} + +static void print_hex_field (u_int8_t field[], int length, int width, + const char *pref) +{ + /* Prints an arbitrary bit field, from one address for some number of + bytes. Output is formatted via the width, and includes the raw + hex value and (if printable) the printed value underneath. "pref" + is a string used to start each line, e.g., " " to indent. + + This is very useful in gdb to see what's in a memory field. + */ + int i, start, stop; + + start=0; + do + { + stop=(start+width)= 0) + cname = cnamebuf; + case ns_t_mb: + case ns_t_mg: + case ns_t_mr: + case ns_t_ns: + case ns_t_ptr: + { + const u_char *startrdata = cp; + u_char cdname[NS_MAXCDNAME]; + + cp = pr_cdname(cp, msg, name, sizeof name); + if (doprint) + fprintf(file, "%c%s", punc, name); + + /* Extract DNSSEC canonical RR. */ + + n = ns_name_unpack(msg, msg+MY_PACKETSZ, startrdata, + cdname, sizeof cdname); + if (n >= 0) + n = ns_name_ntol(cdname, cdname, sizeof cdname); + if (n >= 0) { + /* Copy header. */ + memcpy(canonrr, cp1 - NS_HEADERDATA_SIZE, NS_HEADERDATA_SIZE); + /* Overwrite length field. */ + ns_put16(n, canonrr + NS_HEADERDATA_SIZE - NS_INT16SZ); + /* Copy unpacked name. */ + memcpy(canonrr + NS_HEADERDATA_SIZE, cdname, n); + canonrr_len = NS_HEADERDATA_SIZE + n; + } + break; + } + + case ns_t_hinfo: + case ns_t_isdn: + { + const u_char *cp2 = cp + dlen; + n = *cp++; + if (n != 0) { + if (doprint) + fprintf(file,"%c%.*s", punc, n, cp); + cp += n; + } + if ((cp < cp2) && (n = *cp++)) { + if (doprint) + fprintf(file,"%c%.*s", punc, n, cp); + cp += n; + } else if (type == ns_t_hinfo) + if (doprint) + fprintf(file, + "\n; *** Warning *** OS-type missing" + ); + } + break; + + case ns_t_soa: + { + const u_char *startname = cp; + u_char cdname[NS_MAXCDNAME]; + + cp = pr_cdname(cp, msg, name, sizeof name); + if (doprint) + fprintf(file, "\t%s", name); + + n = ns_name_unpack(msg, msg + 512, startname, + cdname, sizeof cdname); + if (n >= 0) + n = ns_name_ntol(cdname, cdname, sizeof cdname); + if (n >= 0) { + /* Copy header. */ + memcpy(canonrr, cp1 - NS_HEADERDATA_SIZE, NS_HEADERDATA_SIZE); + /* Copy expanded name. */ + memcpy(canonrr + NS_HEADERDATA_SIZE, cdname, n); + canonrr_len = NS_HEADERDATA_SIZE + n; + } + + startname = cp; + cp = pr_cdname(cp, msg, name, sizeof name); + if (doprint) + fprintf(file, " %s", name); + + n = ns_name_unpack(msg, msg + 512, startname, + cdname, sizeof cdname); + if (n >= 0) + n = ns_name_ntol(cdname, cdname, sizeof cdname); + if (n >= 0) { + /* Copy expanded name. */ + memcpy(canonrr + canonrr_len, cdname, n); + canonrr_len += n; + /* Copy rest of SOA. */ + memcpy(canonrr + canonrr_len, cp, 5 * INT32SZ); + canonrr_len += 5 * INT32SZ; + /* Overwrite length field. */ + ns_put16(canonrr_len - NS_HEADERDATA_SIZE, + canonrr + NS_HEADERDATA_SIZE - NS_INT16SZ); + } + + if (doprint) + fprintf(file, "(\n\t\t\t%lu\t;serial (version)", + ns_get32(cp)); + cp += INT32SZ; + if (doprint) + fprintf(file, "\n\t\t\t%lu\t;refresh period", + ns_get32(cp)); + cp += INT32SZ; + if (doprint) + fprintf(file, + "\n\t\t\t%lu\t;retry refresh this often", + ns_get32(cp)); + cp += INT32SZ; + if (doprint) + fprintf(file, "\n\t\t\t%lu\t;expiration period", + ns_get32(cp)); + cp += INT32SZ; + if (doprint) + fprintf(file, "\n\t\t\t%lu\t;minimum TTL\n\t\t\t)", + ns_get32(cp)); + cp += INT32SZ; + break; + } + case ns_t_mx: + case ns_t_afsdb: + case ns_t_rt: + { + const u_char *startrdata = cp; + u_char cdname[NS_MAXCDNAME]; + + if (doprint) { + if (type == ns_t_mx && !verbose) + fprintf(file," (pri=%d) by ", ns_get16(cp)); + else if (verbose) + fprintf(file,"\t%d ", ns_get16(cp)); + else + fprintf(file," "); + } + cp += sizeof(u_short); + cp = pr_cdname(cp, msg, name, sizeof(name)); + if (doprint) + fprintf(file, "%s", name); + + n = ns_name_unpack(msg, msg+512, startrdata + sizeof(u_short), + cdname, sizeof cdname); + if (n >= 0) + n = ns_name_ntol(cdname, cdname, sizeof cdname); + if (n >= 0) { + /* Copy header. */ + memcpy(canonrr, cp1 - NS_HEADERDATA_SIZE, + NS_HEADERDATA_SIZE); + /* Overwrite length field. */ + ns_put16(sizeof(u_short) + n, + canonrr + NS_HEADERDATA_SIZE - NS_INT16SZ); + /* Copy u_short. */ + memcpy(canonrr + NS_HEADERDATA_SIZE, startrdata, + sizeof(u_short)); + /* Copy expanded name. */ + memcpy(canonrr + NS_HEADERDATA_SIZE + sizeof(u_short), + cdname, n); + canonrr_len = NS_HEADERDATA_SIZE + sizeof(u_short) + n; + } + break; + } + + case ns_t_srv: + if (doprint) + fprintf(file," %d", ns_get16(cp)); + cp += sizeof(u_short); + if (doprint) + fprintf(file," %d", ns_get16(cp)); + cp += sizeof(u_short); + if (doprint) + fprintf(file," %d", ns_get16(cp)); + cp += sizeof(u_short); + cp = pr_cdname(cp, msg, name, sizeof(name)); + if (doprint) + fprintf(file, " %s", name); + break; + + case ns_t_naptr: + /* order */ + if (doprint) + fprintf(file, " %d", ns_get16(cp)); + cp += sizeof(u_short); + /* preference */ + if (doprint) + fprintf(file, " %d", ns_get16(cp)); + cp += NS_INT16SZ; + /* Flags */ + n = *cp++; + if (doprint) { + if (n) + fprintf(file, "%c%.*s", punc, n, cp); + else + fprintf(file, "%c\"\"",punc); + } + cp += n; + /* Service */ + n = *cp++; + if (doprint) { + if (n) + fprintf(file, "%c%.*s", punc, n, cp); + else + fprintf(file,"%c\"\"",punc); + } + cp += n; + /* Regexp */ + n = *cp++; + if (doprint) { + if (n) + fprintf(file, "%c%.*s", punc, n, cp); + else + fprintf(file, "%c\"\"",punc); + } + cp += n; + /* replacement */ + cp = pr_cdname(cp, msg, name, sizeof(name)); + if (doprint) + fprintf(file, "%s", name); + break; + + case ns_t_minfo: + case ns_t_rp: + cp = pr_cdname(cp, msg, name, sizeof name); + if (doprint) { + if (type == ns_t_rp) { + char *p; + + p = strchr(name, '.'); + if (p != NULL) + *p = '@'; + } + fprintf(file, "%c%s", punc, name); + } + cp = pr_cdname(cp, msg, name, sizeof(name)); + if (doprint) + fprintf(file, " %s", name); + break; + + case ns_t_x25: + n = *cp++; + if (n != 0) { + if (doprint) + fprintf(file, "%c%.*s", punc, n, cp); + cp += n; + } + break; + + case ns_t_txt: + { + int n, j; + const u_char *end = cp + dlen; + + while (cp < end) { + if (doprint) + (void) fputs(" \"", file); + n = *cp++; + if (n != 0) + for (j = n; j > 0 && cp < end ; j --) { + if (doprint) { + if (*cp == '\n' || + *cp == '"' || + *cp == '\\') + putc('\\', + file); + putc(*cp, file); + } + cp++; + } + if (doprint) + putc('"', file); + } + } + break; + + case ns_t_wks: + if (dlen < INT32SZ + 1) + break; + memcpy(&inaddr, cp, INADDRSZ); + cp += INT32SZ; + proto = *cp++; + protop = getprotobynumber(proto); + if (doprint) { + if (protop) + fprintf(file, "%c%s %s", punc, + inet_ntoa(inaddr), protop->p_name); + else + fprintf(file, "%c%s %d", punc, + inet_ntoa(inaddr), proto); + } + n = 0; + while (cp < cp1 + dlen) { + c = *cp++; + do { + if (c & 0200) { + servp = NULL; + if (protop) + servp = getservbyport(htons(n), + protop-> + p_name); + if (doprint) { + if (servp) + fprintf(file, " %s", + servp->s_name); + else + fprintf(file, " %d", + n); + } + } + c <<= 1; + } while (++n & 07); + } + break; + case ns_t_nxt: + { + const u_char *startrdata = cp; + u_char cdname[NS_MAXCDNAME]; + size_t bitmaplen; + + cp = pr_cdname(cp, msg, name, sizeof name); + if (doprint) + fprintf(file, "%c%s", punc, name); + bitmaplen = dlen - (cp - startrdata); + + /* extract dnssec canonical rr */ + + n = ns_name_unpack(msg, msg+MY_PACKETSZ, startrdata, + cdname, sizeof cdname); + if (n >= 0) + n = ns_name_ntol(cdname, cdname, sizeof cdname); + if (n >= 0) { + /* Copy header. */ + memcpy(canonrr, cp1 - NS_HEADERDATA_SIZE, + NS_HEADERDATA_SIZE); + /* Overwrite length field. */ + ns_put16(n + bitmaplen, + canonrr + NS_HEADERDATA_SIZE - NS_INT16SZ); + /* Copy expanded name. */ + memcpy(canonrr + NS_HEADERDATA_SIZE, cdname, n); + /* Copy type bit map. */ + memcpy(canonrr + NS_HEADERDATA_SIZE + n, cp, + bitmaplen); + canonrr_len = NS_HEADERDATA_SIZE + n + bitmaplen; + } + cp += bitmaplen; + break; + } + case ns_t_sig: + { + int tc; + const u_char *origttl; + + /* type covered */ + tc = ns_get16(cp); + if (doprint && verbose) + fprintf(file, "%c%s", punc, sym_ntos(__p_type_syms, tc, NULL)); + cp += sizeof(u_short); + /* algorithm */ + if (doprint && verbose) + fprintf(file, " %d", *cp); + cp++; + /* labels */ + if (doprint && verbose) + fprintf(file, " %d", *cp); + cp++; + /* original ttl */ + origttl = cp; + if (doprint && verbose) + fprintf(file, " %ld", ns_get32(cp)); + cp += INT32SZ; + /* signature expiration */ + if (doprint && verbose) + fprintf(file, " %ld", ns_get32(cp)); + cp += INT32SZ; + /* time signed */ + if (doprint && verbose) + fprintf(file, " %ld", ns_get32(cp)); + cp += INT32SZ; + /* key footprint */ + if (doprint && verbose) + fprintf(file, " %d", ns_get16(cp)); + cp += sizeof(u_short); + /* signer's name */ + cp = pr_cdname(cp, msg, name, sizeof(name)); + if (doprint && verbose) + fprintf(file, " %s", name); + else if (doprint && !verbose) + fprintf (file, " %s for type %s", name, + sym_ntos(__p_type_syms, tc, NULL)); + /* signature */ + { + char str[MY_PACKETSZ]; + size_t len = cp1-cp+dlen; + + b64_ntop (cp, len, str, MY_PACKETSZ-1); + + if (sigchase && !(chase_step & SD_SIG) && + strcmp (chase_domain, thisdomain) == 0 && + chase_class == class && chase_type == tc) + { + u_char cdname[NS_MAXCDNAME]; + + if (doprint && !verbose) + fprintf(file, " (chasing key)"); + + strcpy(chase_signer, name); + + memcpy(&chase_sigorigttl[0], origttl, + NS_INT32SZ); + + n = ns_name_ntol(cp1 + SIG_RDATA_BY_NAME, + cdname, sizeof cdname); + if (n >= 0) { + memcpy(chase_sigrdata, cp1, + SIG_RDATA_BY_NAME); + memcpy(chase_sigrdata + SIG_RDATA_BY_NAME, + cdname, n); + chase_sigrdata_len = SIG_RDATA_BY_NAME + n; + memcpy(chase_signature, cp, len); + chase_signature_len = len; + + chase_step |= SD_SIG; + } + } else if (sigchase) { + chase_step |= SD_BADSIG; + } + + cp += len; + if (doprint && verbose) + fprintf (file, " %s", str); + } + break; + } + case ns_t_key: + /* flags */ + if (doprint && verbose) + fprintf(file, "%c%d", punc, ns_get16(cp)); + cp += sizeof(u_short); + /* protocol */ + if (doprint && verbose) + fprintf(file, " %d", *cp); + cp++; + /* algorithm */ + n = *cp; + if (doprint && verbose) + fprintf(file, " %d", *cp); + cp++; + switch (n) { + case 1: /* MD5/RSA */ + { + char str[MY_PACKETSZ]; + size_t len = cp1-cp+dlen; + + b64_ntop (cp, len, str, MY_PACKETSZ-1); + cp += len; + + if (doprint && verbose) + fprintf (file, " %s", str); + break; + } + + default: + fprintf (stderr, "Unknown algorithm %d\n", n); + cp = cp1 + dlen; + break; + } + + if (sigchase && (chase_step & (SD_SIG|SD_RR)) && + strcmp (getdomain, name) == 0 && + getclass == class && gettype == type) + { + DST_KEY *dstkey; + int rc, len, i, j; + + /* convert dnskey to dstkey */ + + dstkey = dst_dnskey_to_key (name, cp1, dlen); + + /* fix ttl in rr */ + + for (i = 0; i < NUMRR && chase_rr[i].len; i++) + { + len = dn_skipname(chase_rr[i].data, + chase_rr[i].data + + chase_rr[i].len); + if (len>=0) + memcpy(chase_rr[i].data + len + NS_INT16SZ + + NS_INT16SZ, + &chase_sigorigttl, INT32SZ); + } + + /* sort rr's (qsort() is too slow) */ + + for (i = 0; i < NUMRR && chase_rr[i].len; i++) + for (j = i + 1; j < NUMRR && chase_rr[j].len; + j++) + if (memcmp(chase_rr[i].data, + chase_rr[j].data, + MY_PACKETSZ) < 0) + memswap(&chase_rr[i], + &chase_rr[j], + sizeof(rrstruct)); + /* append rr's to sigrdata */ + + for (i = 0; i < NUMRR && chase_rr[i].len; i++) + { + memcpy (chase_sigrdata + chase_sigrdata_len, + chase_rr[i].data, chase_rr[i].len); + chase_sigrdata_len += chase_rr[i].len; + } + + /* print rr-data and signature */ + + if (verbose) { + fprintf(file, "\n"); + print_hex_field(chase_sigrdata, + chase_sigrdata_len, + 21,"DATA: "); + print_hex_field(chase_signature, + chase_signature_len, + 21,"SIG: "); + } + + /* do the works */ + + if (dstkey) + rc = dst_verify_data(SIG_MODE_ALL, dstkey, NULL, + chase_sigrdata, + chase_sigrdata_len, + chase_signature, + chase_signature_len); + else + rc = 1; + + dst_free_key(dstkey); + + if (verbose) + { + fprintf(file, "\nVerification %s", rc == 0 ? + "was SUCCESSFULL" : + "FAILED"); + } + else + { + fprintf (file, + " that %s verify our %s " + "record(s) on %s", + rc == 0 ? "successfully" : + "DOES NOT", + sym_ntos(__p_type_syms, chase_type, + NULL), + chase_domain); + } + + if (rc == 0) + { + strcpy (chase_lastgoodkey, name); + } + else + { + /* don't trace further after a failure */ + sigchase = 0; + } + + chase_step = 0; + chase_signature_len = 0; + chase_sigrdata_len = 0; + memset(chase_sigorigttl, 0, NS_INT32SZ); + memset(chase_rr, 0, sizeof(chase_rr)); + chase_rr_num = 0; + } + break; + + default: + if (doprint) + fprintf(file, "%c???", punc); + cp += dlen; + break; + } + if (cp != cp1 + dlen) + fprintf(file, "packet size error (%p != %p)\n", + cp, cp1 + dlen); + + if (sigchase && !(chase_step & SD_SIG) && + strcmp (getdomain, thisdomain) == 0 && getclass == class && + gettype == type && type != ns_t_sig) + { + u_char cdname[NS_MAXCDNAME]; + + if (doprint && !verbose) + fprintf(file, " (chasing signature)"); + + /* unpack rr */ + + n = ns_name_unpack(msg, msg + MY_PACKETSZ, savecp, + cdname, sizeof cdname); + if (n >= 0) + n = ns_name_ntol(cdname, cdname, sizeof cdname); + if (n >= 0) { + memcpy(chase_rr[chase_rr_num].data, cdname, n); + memcpy(chase_rr[chase_rr_num].data + n, + canonrr_len ? canonrr : cp1 - NS_HEADERDATA_SIZE, + canonrr_len ? canonrr_len : dlen + NS_HEADERDATA_SIZE); + chase_rr[chase_rr_num].len = + n + (canonrr_len != 0 ? canonrr_len : + dlen + NS_HEADERDATA_SIZE); + + strcpy(chase_domain, getdomain); + chase_class = class; + chase_type = type; + chase_step |= SD_RR; + chase_rr_num++; + } + } + + if (doprint) + fprintf(file, "\n"); + + return (cp); +} + +/* + * Return a string for the type. A few get special treatment when + * not in verbose mode, to make the program more chatty and easier to + * understand. + */ +static const char * +pr_type(int type) { + if (!verbose) switch (type) { + case ns_t_a: + case ns_t_aaaa: + return ("has address"); + case ns_t_cname: + return ("is a nickname for"); + case ns_t_mx: + return ("mail is handled"); + case ns_t_txt: + return ("descriptive text"); + case ns_t_sig: + return ("has a signature signed by"); + case ns_t_key: + return ("has a key"); + case ns_t_nxt: + return ("next valid name"); + case ns_t_afsdb: + return ("DCE or AFS service from"); + } + if (verbose) + return (sym_ntos(__p_type_syms, type, NULL)); + else + return (sym_ntop(__p_type_syms, type, NULL)); +} + +/* + * Return a mnemonic for class + */ +static const char * +pr_class(int class) { + static char spacestr[20]; + + if (!verbose) switch (class) { + case ns_c_in: /* internet class */ + return (""); + case ns_c_hs: /* hesiod class */ + return (""); + } + + spacestr[0] = ' '; + strcpy(&spacestr[1], p_class(class)); + return (spacestr); +} + +static const u_char * +pr_cdname(const u_char *cp, const u_char *msg, char *name, int namelen) { + int n = dn_expand(msg, msg + MY_PACKETSZ, cp, name, namelen - 2); + + if (n < 0) + return (NULL); + if (name[0] == '\0') { + name[0] = '.'; + name[1] = '\0'; + } + return (cp + n); +} + +static void +add(union res_sockaddr_union *u, int type, void *p) { + memset(u, 0, sizeof(*u)); + switch (type) { + case ns_t_a: + memcpy(&u->sin.sin_addr, p, NS_INADDRSZ); + u->sin.sin_family = AF_INET; + u->sin.sin_port = htons(NAMESERVER_PORT); +#ifdef HAVE_SA_LEN + u->sin.sin_len = sizeof(u->sin); +#endif + break; + + case ns_t_aaaa: + memcpy(&u->sin6.sin6_addr, p, 16); + u->sin6.sin6_family = AF_INET6; + u->sin6.sin6_port = htons(NAMESERVER_PORT); +#ifdef HAVE_SA_LEN + u->sin6.sin6_len = sizeof(u->sin6); +#endif + break; + } +} + +static int +salen(union res_sockaddr_union *u) { + switch (u->sin.sin_family) { + case AF_INET6: return (sizeof(u->sin6)); + case AF_INET: return (sizeof(u->sin)); + } + return (0); +} + +static int +ListHosts(char *namePtr, int queryType) { + querybuf buf, answer; + struct sockaddr_in sin; + const HEADER *headerPtr; + enum { NO_ERRORS, ERR_READING_LEN, ERR_READING_MSG, ERR_PRINTING } + error = NO_ERRORS; + + int msglen, amtToRead, numRead, i, len, dlen, type, nscount, n; + int numAnswers = 0, soacnt = 0, result = 0; + u_char tmp[NS_INT16SZ]; + char name[NS_MAXDNAME], dname[2][NS_MAXDNAME], domain[NS_MAXDNAME]; + u_char *cp, *nmp, *eom; + + /* Names and addresses of name servers to try. */ + char nsname[NUMNS][NS_MAXDNAME]; + int nshaveaddr[NUMNS]; + union res_sockaddr_union nsipaddr[NUMNSADDR]; + int numns, numnsaddr, thisns; + int qdcount, ancount; + + /* + * Normalize to not have trailing dot. We do string compares below + * of info from name server, and it won't have trailing dots. + */ + i = strlen(namePtr); + if (namePtr[i-1] == '.') + namePtr[i-1] = 0; + + if (server_specified) + numnsaddr = res_getservers(&res, nsipaddr, NUMNSADDR); + else { + /* + * First we have to find out where to look. This needs a NS + * query, possibly followed by looking up addresses for some + * of the names. + */ + msglen = res_nmkquery(&res, ns_o_query, namePtr, + ns_c_in, ns_t_ns, + NULL, 0, NULL, + buf.qb2, sizeof buf); + if (msglen < 0) { + printf("res_nmkquery failed\n"); + return (ERROR); + } + + msglen = res_nsend(&res, buf.qb2, msglen, + answer.qb2, sizeof answer); + if (msglen < 0) { + printf("Cannot find nameserver -- try again later\n"); + return (ERROR); + } + if (res.options & RES_DEBUG || verbose) + printf("rcode = %d (%s), ancount=%d\n", + answer.qb1.rcode, DecodeError(answer.qb1.rcode), + ntohs(answer.qb1.ancount)); + + /* + * Analyze response to our NS lookup. + */ + + nscount = ntohs(answer.qb1.ancount) + + ntohs(answer.qb1.nscount) + + ntohs(answer.qb1.arcount); + + if (answer.qb1.rcode != NOERROR || nscount == 0) { + switch (answer.qb1.rcode) { + case NXDOMAIN: + /* Check if it's an authoritive answer */ + if (answer.qb1.aa) + printf("No such domain\n"); + else + printf("Unable to get information about domain -- try again later.\n"); + break; + case SERVFAIL: + printf("Unable to get information about that domain -- try again later.\n"); + break; + case NOERROR: + printf("That domain exists, but seems to be a leaf node.\n"); + break; + case FORMERR: + case NOTIMP: + case REFUSED: + printf("Unrecoverable error looking up domain name.\n"); + break; + } + return (0); + } + + cp = answer.qb2 + HFIXEDSZ; + eom = answer.qb2 + msglen; + qdcount = ntohs(answer.qb1.qdcount); + while (qdcount-- > 0) { + n = dn_skipname(cp, eom); + if (n < 0) { + printf("Form error.\n"); + return (ERROR); + } + cp += n + QFIXEDSZ; + if (cp > eom) { + printf("Form error.\n"); + return (ERROR); + } + } + + numns = 0; + numnsaddr = 0; + + /* + * Look at response from NS lookup for NS and A records. + */ + + for ((void)NULL; nscount; nscount--) { + cp += dn_expand(answer.qb2, answer.qb2 + msglen, cp, + domain, sizeof(domain)); + if (cp + 3 * INT16SZ + INT32SZ > eom) { + printf("Form error.\n"); + return (ERROR); + } + type = ns_get16(cp); + cp += INT16SZ + INT16SZ + INT32SZ; + dlen = ns_get16(cp); + cp += INT16SZ; + if (cp + dlen > eom) { + printf("Form error.\n"); + return (ERROR); + } + if (type == ns_t_ns) { + if (dn_expand(answer.qb2, eom, + cp, name, sizeof(name)) >= 0) { + if (numns < NUMNS && + ns_samename((char *)domain, + namePtr) == 1) { + for (i = 0; i < numns; i++) + if (ns_samename( + nsname[i], + (char *)name + ) == 1) + /* duplicate */ + break; + if (i >= numns) { + strncpy(nsname[numns], + (char *)name, + sizeof(name)); + nshaveaddr[numns] = 0; + numns++; + } + } + } + } else if ((type == ns_t_a || type == ns_t_aaaa) && + numnsaddr < NUMNSADDR) { + for (i = 0; i < numns; i++) { + if (ns_samename(nsname[i], + (char *)domain) + != 1) + continue; + nshaveaddr[i]++; + add(&nsipaddr[numnsaddr++], type, cp); + break; + } + } + cp += dlen; + } + + /* + * Usually we'll get addresses for all the servers in the + * additional info section. But in case we don't, look up + * their addresses. + */ + + for (i = 0; i < numns; i++) { + struct addrinfo *answer = NULL; + struct addrinfo *cur = NULL; + struct addrinfo hint; + + memset(&hint, 0, sizeof(hint)); + hint.ai_family = PF_UNSPEC; + hint.ai_socktype = SOCK_STREAM; + + if (nshaveaddr[i] == 0 && + !getaddrinfo(nsname[i], NULL, &hint, &answer)) { + int numaddrs = 0; + for (cur = answer; + cur != NULL; + cur = cur->ai_next) { + union res_sockaddr_union *u; + + if (numnsaddr >= NUMNSADDR) + break; + + u = &nsipaddr[numnsaddr]; + switch (cur->ai_addr->sa_family) { + case AF_INET6: + u->sin6 = + *(struct sockaddr_in6 *)cur->ai_addr; + u->sin6.sin6_port = + htons(NAMESERVER_PORT); + numnsaddr++; + numaddrs++; + break; + case AF_INET: + u->sin = + *(struct sockaddr_in*)cur->ai_addr; + u->sin6.sin6_port = + htons(NAMESERVER_PORT); + numnsaddr++; + numaddrs++; + break; + } + } + if (res.options & RES_DEBUG || verbose) + printf( + "Found %d addresses for %s by extra query\n", + numaddrs, nsname[i]); + freeaddrinfo(answer); + } else if (res.options & RES_DEBUG || verbose) + printf("Found %d addresses for %s\n", + nshaveaddr[i], nsname[i]); + } + } + /* + * Now nsipaddr has numnsaddr addresses for name servers that + * serve the requested domain. Now try to find one that will + * accept a zone transfer. + */ + thisns = 0; + + again: + numAnswers = 0; + soacnt = 0; + + /* + * Create a query packet for the requested domain name. + */ + msglen = res_nmkquery(&res, QUERY, namePtr, getclass, ns_t_axfr, NULL, + 0, NULL, buf.qb2, sizeof buf); + if (msglen < 0) { + if (res.options & RES_DEBUG) + fprintf(stderr, "ListHosts: Res_mkquery failed\n"); + return (ERROR); + } + + memset(&sin, 0, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(NAMESERVER_PORT); + + /* + * Set up a virtual circuit to the server. + */ + + for ((void)NULL; thisns < numnsaddr; thisns++) { + if ((sockFD = socket(nsipaddr[thisns].sin.sin_family, + SOCK_STREAM, 0)) < 0) { + if (errno == EPROTONOSUPPORT) + continue; + perror("ListHosts"); + return (ERROR); + } + if (res.options & RES_DEBUG || verbose) { + char buf[80]; + switch (nsipaddr[thisns].sin.sin_family) { + case AF_INET: + inet_ntop(nsipaddr[thisns].sin.sin_family, + &nsipaddr[thisns].sin.sin_addr, + buf, sizeof(buf)); + break; + case AF_INET6: + inet_ntop(nsipaddr[thisns].sin6.sin6_family, + &nsipaddr[thisns].sin6.sin6_addr, + buf, sizeof(buf)); + break; + } + printf("Trying %s\n", buf); + } + if (connect(sockFD, (struct sockaddr *)&nsipaddr[thisns], + salen(&nsipaddr[thisns])) >= 0) + break; + if (verbose) + perror("Connection failed, trying next server"); + close(sockFD); + sockFD = -1; + } + if (thisns >= numnsaddr) { + printf("No server for that domain responded\n"); + if (!verbose) + perror("Error from the last server was"); + return (ERROR); + } + + /* + * Send length & message for zone transfer + */ + + ns_put16(msglen, tmp); + if (write(sockFD, (char *)tmp, INT16SZ) != INT16SZ || + write(sockFD, (char *)buf.qb2, msglen) != msglen) { + perror("ListHosts"); + (void) close(sockFD); + sockFD = -1; + return (ERROR); + } + + filePtr = stdout; + + for (;;) { + /* + * Read the length of the response. + */ + cp = buf.qb2; + amtToRead = INT16SZ; + while (amtToRead > 0 && + (numRead = read(sockFD, cp, amtToRead)) > 0) { + cp += numRead; + amtToRead -= numRead; + } + if (numRead <= 0) { + error = ERR_READING_LEN; + break; + } + + if ((len = ns_get16(buf.qb2)) == 0) + break; /* Protocol violation. */ + + /* + * Read the response. + */ + + amtToRead = len; + cp = buf.qb2; + while (amtToRead > 0 && + (numRead = read(sockFD, cp, amtToRead)) > 0) { + cp += numRead; + amtToRead -= numRead; + } + if (numRead <= 0) { + error = ERR_READING_MSG; + break; + } + + i = buf.qb1.rcode; + if (i != NOERROR || ntohs(buf.qb1.ancount) == 0) { + if (thisns + 1 < numnsaddr && + (i == SERVFAIL || i == NOTIMP || i == REFUSED)) { + if (res.options & RES_DEBUG || verbose) + printf( + "Server failed, trying next server: %s\n", + i != NOERROR + ? DecodeError(i) + : "Premature end of data"); + (void) close(sockFD); + sockFD = -1; + thisns++; + goto again; + } + printf("Server failed: %s\n", i != NOERROR + ? DecodeError(i) : "Premature end of data"); + break; + } + + result = printinfo(&buf, cp, queryType, 1, 0); + if (! result) { + error = ERR_PRINTING; + break; + } + numAnswers++; + cp = buf.qb2 + HFIXEDSZ; + qdcount = ntohs(buf.qb1.qdcount); + while (qdcount-- > 0) { + n = dn_skipname(cp, buf.qb2 + len); + if (n <= 0) { + error = ERR_PRINTING; + break; + } + if (cp + n + QFIXEDSZ > buf.qb2 + len) { + error = ERR_PRINTING; + break; + } + cp += n + QFIXEDSZ; + } + ancount = ntohs(buf.qb1.ancount); + while (ancount-- > 0) { + nmp = cp; + n = dn_skipname(cp, buf.qb2 + len); + if (n <= 0) { + error = ERR_PRINTING; + break; + } + cp += n; + if (cp + INT16SZ > buf.qb2 + len) { + error = ERR_PRINTING; + break; + } + type = ns_get16(cp); + cp += INT16SZ; + if (type == ns_t_soa) { + (void) dn_expand(buf.qb2, buf.qb2 + len, nmp, + dname[soacnt], sizeof dname[0]); + if (soacnt) { + if (ns_samename(dname[0], dname[1]) == 1) + goto done; + } else + soacnt++; + } + if (cp + INT16SZ*2 + INT32SZ > buf.qb2 + len) { + error = ERR_PRINTING; + break; + } + cp += INT32SZ + INT16SZ; + dlen = ns_get16(cp); + cp += INT16SZ; + if (cp + dlen > buf.qb2 + len) { + error = ERR_PRINTING; + break; + } + cp += dlen; + } + if (error != NO_ERRORS) + break; + } + done: + + (void) close(sockFD); + sockFD = -1; + + switch (error) { + case NO_ERRORS: + return (SUCCESS); + + case ERR_READING_LEN: + return (ERROR); + + case ERR_PRINTING: + fprintf(stderr,"*** Error during listing of %s: %s\n", + namePtr, DecodeError(result)); + return (result); + + case ERR_READING_MSG: + headerPtr = (HEADER *) &buf; + fprintf(stderr,"ListHosts: error receiving zone transfer:\n"); + fprintf(stderr, + " result: %s, answers = %d, authority = %d, additional = %d\n", + p_rcode(headerPtr->rcode), + ntohs(headerPtr->ancount), ntohs(headerPtr->nscount), + ntohs(headerPtr->arcount)); + return (ERROR); + default: + return (ERROR); + } +} + +static const char * +DecodeError(int result) { + switch(result) { + case NOERROR: return ("Success"); + case FORMERR: return ("Format error"); + case SERVFAIL: return ("Server failed"); + case NXDOMAIN: return ("Non-existent domain"); + case NOTIMP: return ("Not implemented"); + case REFUSED: return ("Query refused"); + case NO_INFO: return ("No information"); + case ERROR: return ("Unspecified error"); + case TIME_OUT: return ("Timed out"); + case NONAUTH: return ("Non-authoritative answer"); + default: return ("BAD ERROR VALUE"); + } + /* NOTREACHED */ +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/host/host.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/host/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/host/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/host/Makefile (revision 109985) @@ -0,0 +1,85 @@ +## Copyright (c) 1996,1999 by Internet Software Consortium +## +## 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. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM 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 +## SOFTWARE. + +# $Id: Makefile,v 8.26 2000/12/23 08:02:51 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g -Wall + +#(net2 and its descendents) +SYSTYPE = freebsd +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +EXE= +LEX = lex -I +SYSLIBS = -ll -lutil +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +STRIP=-s +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin + +LDFLAGS= +CFLAGS= ${CDEBUG} +CPPFLAGS= -I${PORTINCL} -I${INCL} + +PROG= host +SRCS= ${PROG}.c +OBJS= ${PROG}.${O} + +all: ${PROG}${EXE} + +${PROG}${EXE}: ${OBJS} ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} ${BOUNDS} -o ${PROG}${EXE} ${OBJS} \ + ${LIBBIND} ${SYSLIBS} + +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c + +distclean: clean + +clean: FRC + rm -f ${PROG}${EXE} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + +depend: ${SRCS} + mkdep ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${SRCS} + +${DESTDIR}${DESTBIN}: + mkdir -p ${DESTDIR}${DESTBIN} + +install: ${DESTDIR}${DESTBIN} ${PROG}${EXE} + ${INSTALL} ${STRIP} -c ${INSTALL_EXEC} -m 755 ${PROG}${EXE} ${DESTDIR}${DESTBIN}/${PROG}${EXE} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +tags: FRC + ctags *.[ch] + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Property changes on: vendor/bind/8.3.4/contrib/bind/bin/host/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named-xfer/named-xfer.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named-xfer/named-xfer.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named-xfer/named-xfer.c (revision 109985) @@ -0,0 +1,3252 @@ +/* + * The original version of named-xfer by Kevin Dunlap. + * Completed and integrated with named by David Waitzman + * (dwaitzman@bbn.com) 3/14/88. + * Modified by M. Karels and O. Kure 10-88. + * Modified extensively since then by just about everybody. + */ + +/* + * Copyright (c) 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1998 by MetaInfo, Incorporated. + * + * 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 MetaInfo Incorporated 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 METAINFO INCORPORATED DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL METAINFO INCORPRATED + * 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 SOFTWARE. + */ +#if !defined(lint) && !defined(SABER) +char copyright[] = +"@(#) Copyright (c) 1988, 1990 The Regents of the University of California.\n\ + portions Copyright (c) 1993 Digital Equipment Corporation\n\ + portions Copyright (c) 1998 MetaInfo, Inc.\n\ + portions Copyright (c) 1995, 1996 Internet Software Consorium\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#if !defined(lint) && !defined(SABER) +static const char sccsid[] = "@(#)named-xfer.c 4.18 (Berkeley) 3/7/91"; +static const char rcsid[] = "$Id: named-xfer.c,v 8.121 2002/06/26 03:27:22 marka Exp $"; +#endif /* not lint */ + +#include "port_before.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + + +#ifndef PATH_SEP +#define PATH_SEP '/' +#endif + +#define MAIN_PROGRAM +#include "../named/named.h" +#undef MAIN_PROGRAM + +#define MAX_XFER_RESTARTS 2 + +#define ENABLE_IXFR 1 + +# ifdef SHORT_FNAMES +extern long pathconf __P((const char *path, int name)); /* XXX */ +# endif + + +static struct zoneinfo zone; /* zone information */ + +static char *ddtfilename = NULL, + *ddtfile = NULL; + +static char *tmpname = NULL, + *tmpiname = NULL, /* temporary file name for ixfr transaction file */ + *domain; /* domain being xfered */ + +static int quiet = 0, + read_interrupted = 0, + curclass, + domain_len; /* strlen(domain) */ + +static FILE *fp = NULL, + *dbfp = NULL, + *ixfp = NULL; + +static char *ProgName; + +static void usage(const char *); +static int tsig_init(const char *); +static int getzone(struct zoneinfo *, u_int32_t, int), + print_output(struct zoneinfo *, u_int32_t, + u_char *, int, u_char *, int), + netread(int, char *, int, int), + writemsg(int, const u_char *, int); +static int ixfr_log(const u_char *msg, int len, int *delete, + FILE *file, struct sockaddr_in *sin, + u_int32_t *serial_no, int *); +static SIG_FN read_alarm(void); +static SIG_FN term_handler(void); +static const char *soa_zinfo(struct zoneinfo *, u_char *, u_char*), + *tsig_rcode(int); + +struct zoneinfo zp_start, zp_finish; + +static int restarts = 0; +static int check_serial = 0; +static int xfr_qtype = T_AXFR; + +FILE *ddt = NULL; +int servermethode[NSMAX]; +char *soa_buf; + +typedef struct _tsig_node { + struct in_addr addr; + DST_KEY *dst_key; + LINK(struct _tsig_node) link; +} tsig_node; + +LIST(tsig_node) tsig_list; + +/* + * Debugging printf. + */ +void +dprintf(int level, const char *format, ...) { + va_list ap; + + va_start(ap, format); + if (ddt != NULL && debug >= level) + (void) vfprintf(ddt, format, ap); + va_end(ap); +} + +static int +init_xfer_logging() { + log_channel chan; + + if (log_new_context(ns_log_max_category, NULL, &log_ctx) < 0) { + perror("log_new_context"); + return (0); + } + log_option(log_ctx, LOG_OPTION_DEBUG, debug); + log_option(log_ctx, LOG_OPTION_LEVEL, debug); + + log_ctx_valid = 1; + + chan = log_new_syslog_channel(0, 0, ISC_FACILITY); + if (chan == NULL) + return (0); + if (log_add_channel(log_ctx, ns_log_default, chan) < 0) { + perror("log_add_channel syslog"); + return (0); + } + + if (debug) { + unsigned int flags = LOG_USE_CONTEXT_LEVEL|LOG_REQUIRE_DEBUG; + + chan = log_new_file_channel(flags, 0, NULL, ddt, 0, ULONG_MAX); + if (chan == NULL) + return (0); + if (log_add_channel(log_ctx, ns_log_default, chan) < 0) { + perror("log_add_channel debug"); + return (0); + } + } + + return (1); +} + +static void +cleanup_for_exit(void) { +#ifdef DEBUG + if (!debug) +#endif + { + (void) unlink(tmpname); + if (tmpiname != NULL) + (void) unlink(tmpiname); + } + if(tmpiname) + free(tmpiname); + tmpiname = NULL; + if (ddtfilename != NULL) { + free(ddtfilename); + if (ddtfilename == ddtfile) + ddtfile = NULL; + ddtfilename = NULL; + } + if(tmpname) + free(tmpname); + tmpname = NULL; + if(ddtfile) + free(ddtfile); + ddtfile = NULL; +} + + +int +main(int argc, char *argv[]) { + struct zoneinfo *zp; + struct hostent *hp; + struct in_addr axfr_src; + char *dbfile = NULL, *tracefile = NULL, *tm = NULL, *tsigfile = NULL; + char *ixfrfile = NULL; + int dbfd, ddtd, result, c, ixfd = -1; + u_int32_t serial_no = 0; + u_int port = htons(NAMESERVER_PORT); + struct stat statbuf; + int stub_only = 0; + int class = C_IN; + int n; + +#ifdef _AUX_SOURCE + set42sig(); +#endif + memset(&axfr_src, 0, sizeof axfr_src); + ProgName = strrchr(argv[0], PATH_SEP); + if (ProgName != NULL) + ProgName++; + else + ProgName = argv[0]; + + (void) umask(022); + + ddtfilename = (char *)malloc(strlen(_PATH_TMPXFER) + 1); + strcpy(ddtfilename, _PATH_TMPXFER); + ddtfile = ddtfilename; + +#ifdef RENICE + nice(-40); /* this is the recommended procedure to */ + nice(20); /* reset the priority of the current process */ + nice(0); /* to "normal" (== 0) - see nice(3) */ +#endif + + n = LOG_PID; +#ifdef LOG_PERROR + n |= LOG_PERROR; +#endif +#if defined(LOG_CONS) && defined(USE_LOG_CONS) + n |= LOG_CONS; +#endif +#ifdef SYSLOG_42BSD + openlog(ProgName, n); +#else + openlog(ProgName, n, ISC_FACILITY); +#endif + while ((c = getopt(argc, argv, "C:d:l:s:t:z:f:i:p:P:qx:ST:Z")) != -1) + switch (c) { + case 'C': + class = get_class(optarg); + break; + case 'd': +#ifdef DEBUG + debug = atoi(optarg); +#endif + break; + case 'l': + ddtfile = (char *)malloc(strlen(optarg) + + sizeof(".XXXXXX") + 1); + if (!ddtfile) + panic("malloc(ddtfile)", NULL); +#ifdef SHORT_FNAMES + filenamecpy(ddtfile, optarg); +#else + (void) strcpy(ddtfile, optarg); +#endif /* SHORT_FNAMES */ + (void) strcat(ddtfile, ".XXXXXX"); + break; + case 's': + serial_no = strtoul(optarg, (char **)NULL, 10); + check_serial++; + break; + case 't': + tracefile = optarg; + break; + case 'z': /* zone == domain */ + domain = optarg; + domain_len = strlen(domain); + while ((domain_len > 0) && + (domain[domain_len-1] == '.')) + domain[--domain_len] = '\0'; + break; + case 'f': + dbfile = optarg; + tmpname = (char *)malloc((unsigned)strlen(optarg) + + sizeof(".XXXXXX") + 1); + if (!tmpname) + panic("malloc(tmpname)", NULL); +#ifdef SHORT_FNAMES + filenamecpy(tmpname, optarg); +#else + (void) strcpy(tmpname, optarg); +#endif /* SHORT_FNAMES */ + break; + case 'i': +#if ENABLE_IXFR + ixfrfile = optarg; + tmpiname = (char *) malloc(strlen(optarg) + + sizeof(".XXXXXX") + 1); + if (!tmpiname) + panic("malloc(tmpiname)", NULL); +#ifdef SHORT_FNAMES + filenamecpy(tmpiname, optarg); +#else + (void) strcpy(tmpiname, optarg); +#endif /* SHORT_FNAMES */ +#endif /* ENABLE_IXFR */ + break; + case 'p': + port = htons((u_int16_t)atoi(optarg)); + break; + case 'P': + port = (u_int16_t)atoi(optarg); + break; + case 'S': + stub_only = 1; + break; + case 'q': + quiet++; + break; + case 'x': + if (!inet_aton(optarg, &axfr_src)) + panic("bad -x addr: %s", optarg); + break; + case 'T': + tsigfile = optarg; + break; + case 'Z': + xfr_qtype = ns_t_zxfr; + break; + case '?': + default: + usage("unrecognized argument"); + /* NOTREACHED */ + } + if (!domain || ((!dbfile) && (!ixfrfile)) || optind >= argc) { + if (!domain) + usage("no domain"); + if (!dbfile) + usage("no dbfile"); + if (optind >= argc) + usage("not enough arguments"); + /* NOTREACHED */ + } + if (stat(dbfile, &statbuf) != -1 && + !S_ISREG(statbuf.st_mode) && + !S_ISFIFO(statbuf.st_mode)) + usage("dbfile must be a regular file or FIFO"); + if (ixfrfile && (stat(ixfrfile, &statbuf) != -1 && + !S_ISREG(statbuf.st_mode) && + !S_ISFIFO(statbuf.st_mode))) + usage("ixfrfile must be a regular file or FIFO"); + if (tsigfile && stat(tsigfile, &statbuf) != -1 && + !S_ISREG(statbuf.st_mode) && + !S_ISFIFO(statbuf.st_mode)) + usage("tsigfile must be a regular file or FIFO"); + if (tracefile && (fp = fopen(tracefile, "w")) == NULL) + perror(tracefile); + (void) strcat(tmpname, ".XXXXXX"); + /* tmpname is now something like "/etc/named/named.bu.db.XXXXXX" */ + if ((dbfd = mkstemp(tmpname)) == -1) { + perror(tmpname); + if (!quiet) + syslog(LOG_ERR, "can't make tmpfile (%s): %s\n", + tmpname, strerror(errno)); + exit(XFER_FAIL); + } +#ifdef HAVE_FCHMOD /* XXX */ + if (fchmod(dbfd, 0644) == -1) +#else + if (chmod(tmpname, 0644) == -1) +#endif + { + perror(tmpname); + if (!quiet) + syslog(LOG_ERR, "can't [f]chmod tmpfile (%s): %s\n", + tmpname, strerror(errno)); + close(dbfd); + unlink(tmpname); + exit(XFER_FAIL); + } + if ((dbfp = fdopen(dbfd, "r+")) == NULL) { + perror(tmpname); + if (!quiet) + syslog(LOG_ERR, "can't fdopen tmpfile (%s)", tmpname); + close(dbfd); + unlink(tmpname); + exit(XFER_FAIL); + } + if (ixfrfile) { + (void) strcat(tmpiname, ".XXXXXX"); + if ((ixfd = mkstemp(tmpiname)) == -1) { + perror(tmpiname); + if (!quiet) + syslog(LOG_ERR, + "can't make tmpifile (%s): %s\n", + tmpiname, strerror(errno)); + (void) fclose(dbfp); + (void) close(dbfd); + exit(XFER_FAIL); + } +#ifdef HAVE_FCHMOD /* XXX */ + if (fchmod(ixfd, 0644) == -1) +#else + if (chmod(tmpiname, 0644) == -1) +#endif + { + perror(tmpiname); + if (!quiet) + syslog(LOG_ERR, + "can't [f]chmod tmpifile (%s): %s\n", + tmpiname, strerror(errno)); + (void) fclose(dbfp); + (void) close(dbfd); + (void) close(ixfd); + exit(XFER_FAIL); + } + close(ixfd); + } +#ifdef DEBUG + if (debug) { + /* ddtfile is now something like "/usr/tmp/xfer.ddt.XXXXXX" */ + if ((ddtd = mkstemp(ddtfile)) == -1) { + perror(ddtfile); + debug = 0; + } +#ifdef HAVE_FCHMOD + else if (fchmod(ddtd, 0644) == -1) +#else + else if (chmod(ddtfile, 0644) == -1) +#endif + { + perror(ddtfile); + close(ddtd); + unlink(ddtfile); + debug = 0; + } else if ((ddt = fdopen(ddtd, "w")) == NULL) { + perror(ddtfile); + close(ddtd); + unlink(ddtfile); + debug = 0; + } else + setvbuf(ddt, NULL, _IOLBF, 0); + } +#endif + if (!init_xfer_logging()) { + cleanup_for_exit(); + perror("init_xfer_logging"); + } + + /* + * Ignore many types of signals that named (assumed to be our parent) + * considers important- if not, the user controlling named with + * signals usually kills us. + */ + (void) signal(SIGHUP, SIG_IGN); +#ifdef SIGSYS + (void) signal(SIGSYS, SIG_IGN); +#endif +#ifdef DEBUG + if (debug == 0) +#endif + { + (void) signal(SIGINT, SIG_IGN); + (void) signal(SIGQUIT, SIG_IGN); + } + (void) signal(SIGILL, SIG_IGN); + +#if defined(SIGUSR1) && defined(SIGUSR2) + (void) signal(SIGUSR1, SIG_IGN); + (void) signal(SIGUSR2, SIG_IGN); +#else /* SIGUSR1&&SIGUSR2 */ + (void) signal(SIGEMT, SIG_IGN); + (void) signal(SIGFPE, SIG_IGN); +#endif /* SIGUSR1&&SIGUSR2 */ + + if (dbfile) + dprintf(1, "domain `%s'; file `%s'; serial %u\n", + domain, dbfile, serial_no); + + if (ixfrfile) + dprintf(1, "domain `%s'; ixfrfile `%s'; serial %u\n", + domain, ixfrfile, serial_no); + + if (tsigfile) + dprintf(1, "tsigfile `%s'\n", tsigfile); + + buildservicelist(); + buildprotolist(); + + if (tsig_init(tsigfile) == -1) { + cleanup_for_exit(); + return (XFER_FAIL); + } + + /* init zone data */ + + zp = &zone; + if (stub_only) + zp->z_type = Z_STUB; + else + zp->z_type = Z_SECONDARY; + zp->z_class = class; + zp->z_origin = domain; + zp->z_source = dbfile; + zp->z_axfr_src = axfr_src; + zp->z_addrcnt = 0; + dprintf(1, "zone found (%d): \"%s\", source = %s\n", + zp->z_type, + (zp->z_origin[0] == '\0') ? "." : zp->z_origin, + zp->z_source); + + for (; optind != argc; optind++) { + int tmpsupportixfr; + + tm = argv[optind]; + tmpsupportixfr = ISNOTIXFR; + if ((optind+1) != argc) { + if (strcasecmp("ixfr", argv[optind+1]) == 0) { +#if ENABLE_IXFR + tmpsupportixfr = ISIXFR; + servermethode[zp->z_addrcnt] = tmpsupportixfr; +#endif + optind++; + } else if (strcasecmp("axfr", argv[optind+1]) == 0) { + tmpsupportixfr = ISNOTIXFR; + optind++; + } + } + if (!inet_aton(tm, &zp->z_addr[zp->z_addrcnt])) { + if (strcmp("-ixfr",tm)==0) { +#if ENABLE_IXFR + tmpsupportixfr = ISIXFR; + servermethode[zp->z_addrcnt-1] = tmpsupportixfr; +#endif + continue; + } else + if (strcmp("-axfr",tm)==0) { + tmpsupportixfr = ISNOTIXFR; + continue; + } + hp = gethostbyname(tm); + if (hp == NULL) { + syslog(LOG_NOTICE, + "uninterpretable server (%s) for %s\n", + tm, zp->z_origin); + continue; + } + memcpy(&zp->z_addr[zp->z_addrcnt], + hp->h_addr, + INADDRSZ); + dprintf(1, "Arg: \"%s\" %s\n", tm,((tmpsupportixfr) ? "IXFR":"AXFR")); + } + if (++zp->z_addrcnt >= NSMAX) { + zp->z_addrcnt = NSMAX; + dprintf(1, "NSMAX reached\n"); + break; + } + } + dprintf(1, "addrcnt = %d\n", zp->z_addrcnt); + + res_ninit(&res); + res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE); + result = getzone(zp, serial_no, port); + (void) fclose(dbfp); + (void) close(dbfd); + + if (ixfp) + (void) my_fclose(ixfp); + else + close(ixfd); + + switch (result) { + + case XFER_SUCCESSAXFR: /* ok exit */ + if (tmpiname != NULL) + unlink(tmpiname); + if (ixfrfile) { + /* + * An IXFR was requested but we performed an + * AXFR. Rename the temporary file to the IXFR + * name, named will rename it again to the dbname. + */ + if (isc_movefile(tmpname, ixfrfile) == -1) { + perror("isc_movefile"); +#ifdef DEBUG + if (debug) + (void) unlink(ddtfile); +#endif + if (!quiet) + syslog(LOG_ERR, + "rename %s to %s: %s", + tmpname, ixfrfile, strerror(errno)); + cleanup_for_exit(); + exit(XFER_FAIL); + }; + exit(XFER_SUCCESSAXFRIXFRFILE); + } + if (isc_movefile(tmpname, dbfile) == -1) { + perror("isc_movefile"); + if (!quiet) + syslog(LOG_ERR, "isc_movefile %s to %s: %m", + tmpname, dbfile); + cleanup_for_exit(); + exit(XFER_FAIL); + } + exit(XFER_SUCCESSAXFR); + + case XFER_SUCCESSIXFR: + unlink(tmpname); + if (isc_movefile(tmpiname, ixfrfile) == -1) { + perror("isc_movefile"); + if (!quiet) + syslog(LOG_ERR, "isc_movefile %s to %s: %m", + tmpiname, ixfrfile); + cleanup_for_exit(); + exit(XFER_FAIL); + } + cleanup_for_exit(); + exit(XFER_SUCCESSIXFR); + + case XFER_UPTODATE: /* the zone was already uptodate */ + (void) unlink(tmpname); + if (tmpiname != NULL) + (void) unlink(tmpiname); + cleanup_for_exit(); + exit(XFER_UPTODATE); + + default: + result = XFER_FAIL; + /* fall through */ + case XFER_REFUSED: + case XFER_TIMEOUT: + case XFER_FAIL: + (void) unlink(tmpname); + cleanup_for_exit(); + exit(result); /* error or timeout */ + } + /*NOTREACHED*/ + return (0); /* Make gcc happy. */ +} + +static const char *UsageText[] = { + "\t-z zone_to_transfer\n", + "\t-f db_file\n", + "\t[-i ixfr_file]\n", + "\t[-s serial_no]\n", + "\t[-d debug_level]\n", + "\t[-l debug_log_file]\n", + "\t[-t trace_file]\n", + "\t[-p port]\n", + "\t[-S] [-Z]\n", + "\t[-C class]\n", + "\t[-x axfr-src]\n", + "\t[-T tsig_info_file]\n", + "\tservers [-ixfr|-axfr]...\n", + NULL +}; + +static void +usage(const char *msg) { + const char **line; + + fprintf(stderr, "Usage error: %s\n", msg); + fprintf(stderr, "Usage: %s\n", ProgName); + for (line = UsageText; *line; line++) + fputs(*line, stderr); + exit(XFER_FAIL); +} + +static int +tsig_init(const char *file) { + char buf[1024]; + FILE *fp; + char *s; + + if (file == NULL) + return (0); + fp = fopen(file, "r"); + if (fp == NULL) + return (-1); + dst_init(); + INIT_LIST(tsig_list); + while (1) { + tsig_node *n = malloc(sizeof(tsig_node)); + int alg, secret_len; + char *cp; + u_char secret[128]; + char *name; + + if (n == NULL) + return (-1); + + s = fgets(buf, sizeof(buf), fp); + if (s == NULL) + break; + buf[strlen(buf)-1] = 0; + inet_aton(buf, &n->addr); + + fgets(buf, sizeof(buf), fp); + buf[strlen(buf)-1] = 0; + name = strdup(buf); + + if (name == NULL) + return (-1); + + fscanf(fp, "%d", &alg); + fgets(buf, sizeof(buf), fp); + + fgets(buf, sizeof(buf), fp); + buf[strlen(buf)-1] = 0; + cp = buf; + while (isspace(*cp)) + cp++; + + secret_len = b64_pton(cp, secret, sizeof(secret)); + n->dst_key = dst_buffer_to_key(name, alg, 0, 0, + secret, secret_len); + + free(name); + INIT_LINK(n, link); + APPEND(tsig_list, n, link); + } + fclose(fp); + unlink(file); + return (0); +} + +#define DEF_DNAME '\001' /* '\0' means the root domain */ +/* XXX: The following variables should probably all be "static" */ +u_int32_t minimum_ttl = 0; +int soa_cnt = 0, scdsoa = 0, methode = ISNOTIXFR; +int delete_soa = 1; +int ixfr_single_answer_mode = 0; +u_int32_t final_serial = 0; +int ixfr_soa = 0; +int ns_cnt = 0; +int query_type = 0; +int prev_comment = 0; /* was previous record a comment? */ +char zone_top[MAXDNAME]; /* the top of the zone */ +char prev_origin[MAXDNAME]; /* from most recent $ORIGIN line */ +char prev_dname[MAXDNAME] = { DEF_DNAME }; /* from previous record */ +char prev_ns_dname[MAXDNAME] = { DEF_DNAME }; /* from most recent NS record */ + +/* + * TSIG state + */ +static int tsig_signed; +static ns_tcp_tsig_state tsig_state; + +static int +make_query(int fd, struct zoneinfo *zp, int type, u_int32_t serial_no, + DST_KEY *tsig_key, u_char *buf, u_int bufsize) +{ + HEADER *hp; + u_char *cp; + int n, ret; + time_t timesigned = 0; + + n = res_nmkquery(&res, QUERY, zp->z_origin, curclass, + type, NULL, 0, NULL, buf, bufsize); + if (n < 0) { + if (!quiet) + syslog(LOG_INFO, "zone %s: res_nmkquery %s failed", + p_type(query_type), zp->z_origin); + return (n); + } + + if (type == T_IXFR) { + hp = (HEADER *) buf; + cp = buf; + dprintf(1, "len = %d\n", n); + hp->nscount = htons(1+ntohs(hp->nscount)); + cp += n; + n = dn_comp(zp->z_origin, cp, bufsize - (cp - buf), NULL, NULL); + if (n < 0) + return (n); + cp += n; + if (cp + 3 * INT16SZ + 6 * INT32SZ + 2 > buf + bufsize) + return (-1); + PUTSHORT(T_SOA, cp); /* type */ + PUTSHORT(C_IN, cp); /* class */ + PUTLONG(0, cp); /* ttl */ + PUTSHORT(22, cp); /* dlen */ + *cp++ = 0; /* mname */ + *cp++ = 0; /* rname */ + PUTLONG(serial_no, cp); + PUTLONG(0xDEAD, cp); /* Refresh */ + PUTLONG(0xBEEF, cp); /* Retry */ + PUTLONG(0xABCD, cp); /* Expire */ + PUTLONG(0x1776, cp); /* Min TTL */ + n = cp - buf; + dprintf(1, "len = %d\n", cp-buf); + } + + tsig_signed = 0; + if (tsig_key != NULL) { + int siglen; + u_char sig[64]; + + siglen = sizeof(sig); + ret = ns_sign(buf, &n, bufsize, NOERROR, tsig_key, + NULL, 0, sig, &siglen, timesigned); + if (ret == 0) { + tsig_signed = 1; + ns_verify_tcp_init(tsig_key, sig, siglen, &tsig_state); + } + } + + if (debug) + res_pquery(&res, buf, n, ddt); + + if (writemsg(fd, buf, n) < 0) { + syslog(LOG_INFO, "writemsg: %m"); + return (-1); + } + + return (n); +} + +static u_int +readandverify(int fd, u_char **bufp, u_int *bufsizep, + struct sockaddr_in *sin, char *z_origin, int sig_req) +{ + u_char *buf = *bufp; + u_char *newbuf; + u_int bufsize = *bufsizep; + u_int len; + + if (netread(fd, (char *)buf, INT16SZ, XFER_TIMER) < 0) + return (0); + + if ((len = ns_get16(buf)) == 0) + return (0); + + if (len > bufsize) { + newbuf = realloc(buf, len); + if (newbuf == NULL) { + syslog(LOG_INFO, "realloc(%u) failed\n", len); + return (0); + } + *bufp = buf = newbuf; + *bufsizep = bufsize = len; + } + + if (netread(fd, (char *)buf, len, XFER_TIMER) < 0) + return (0); + +#ifdef DEBUG + if (debug >= 3) { + (void)fprintf(ddt,"len = %d\n", len); + res_pquery(&res, buf, len, ddt); + } + if (fp) + res_pquery(&res, buf, len, fp); +#endif + + if (tsig_signed) { + int ret; + + ret = ns_verify_tcp(buf, (int *)&len, &tsig_state, sig_req); + if (ret != 0) { + syslog(LOG_NOTICE, "%s [%s] %s %s: %s (%d)\n", + "TSIG verification from server", + inet_ntoa(sin->sin_addr), "zone", z_origin, + tsig_rcode(ret), ret); + return (0); + } + } + + return (len); +} + +static void +print_comment(int s, struct sockaddr_in *sin, int check_serial, + u_int32_t serial_no, DST_KEY *tsig_key) +{ + struct sockaddr_in local; + ISC_SOCKLEN_T locallen; + const char *l, *nl; + + gettime(&tt); + locallen = sizeof local; + if (getsockname(s, (struct sockaddr *)&local, &locallen) < 0) + memset(&local, 0, sizeof local); + + for (l = Version; l; l = nl) { + size_t len; + if ((nl = strchr(l, '\n')) != NULL) { + len = nl - l; + nl = nl + 1; + } else { + len = strlen(l); + nl = NULL; + } + while (isspace((unsigned char) *l)) + l++; + if (*l) + fprintf(dbfp, "; BIND version %.*s\n", (int)len, l); + } + + fprintf(dbfp, check_serial ? + "; zone '%s' last serial %u\n" : + "; zone '%s' first transfer\n", + domain, serial_no); + fprintf(dbfp, "; from %s:%d", + inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); + fprintf(dbfp, " (local %s) using %s at %s", + inet_ntoa(local.sin_addr), (methode == ISIXFR) ? "IXFR":"AXFR", + ctimel(tt.tv_sec)); + if (tsig_signed != 0) + fprintf(dbfp, "; TSIG verified: key %s.\n", + tsig_key->dk_key_name); + else + fprintf(dbfp, "; NOT TSIG verified\n"); +} + +static int +getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { + HEADER *hp; + u_int len; + int s, n, l, error = 0; + int was_ixfr = 0; + u_int cnt; + u_char *cp, *nmp, *eom, *tmp ; + u_char *buf = NULL; + u_char *bp; + u_int bufsize = 0; + u_char *buf2 = NULL; + u_int buf2size = 0; + char name2[MAXDNAME]; + struct sockaddr_in sin; +#ifdef POSIX_SIGNALS + struct sigaction sv, osv; +#else + struct sigvec sv, osv; +#endif + int qdcount, ancount, aucount, arcount, class = 0, type = 0; + const char *badsoa_msg = "Nil"; + struct sockaddr_in my_addr; + char my_addr_text[30]; + ISC_SOCKLEN_T alen; + int tsig_req; + DST_KEY *tsig_key; + int ixfr_first = 1; + int loop_cnt = 0; + u_int32_t query_serial = serial_no; + int first_soa_printed; + struct in_addr z_axfr_src; + int refused = 0; + +#ifdef DEBUG + if (debug) { + (void)fprintf(ddt,"getzone() %s ", zp->z_origin); + switch (zp->z_type) { + case Z_STUB: + fprintf(ddt, "stub\n"); + break; + case Z_SECONDARY: + fprintf(ddt, "slave\n"); + break; + default: + fprintf(ddt, "unknown type\n"); + } + } +#endif +#ifdef POSIX_SIGNALS + memset(&sv, 0, sizeof sv); + sv.sa_handler = (SIG_FN (*)()) read_alarm; + /* SA_ONSTACK isn't recommended for strict POSIX code */ + /* is it absolutely necessary? */ + /* sv.sa_flags = SA_ONSTACK; */ + sigfillset(&sv.sa_mask); + (void) sigaction(SIGALRM, &sv, &osv); + memset(&sv, 0, sizeof sv); + sv.sa_handler = (SIG_FN (*)()) term_handler; + sigfillset(&sv.sa_mask); + (void) sigaction(SIGTERM, &sv, &osv); +#else + memset(&sv, 0, sizeof sv); + sv.sv_handler = read_alarm; + sv.sv_mask = ~0; + (void) sigvec(SIGALRM, &sv, &osv); + memset(&sv, 0, sizeof sv); + sv.sv_handler = term_handler; + sv.sv_mask = ~0; + (void) sigvec(SIGTERM, &sv, &osv); +#endif + + strcpy(zone_top, zp->z_origin); + if ((l = strlen(zone_top)) != 0 && zone_top[l - 1] == '.') + zone_top[l - 1] = '\0'; + strcpy(prev_origin, zone_top); + + for (cnt = 0; cnt < zp->z_addrcnt; cnt++) { + methode = servermethode[cnt]; + sin.sin_addr = zp->z_addr[cnt]; + dprintf(3, "address [%s] %s\n", + inet_ntoa(sin.sin_addr), + (methode == ISIXFR) ? "IXFR":"AXFR"); + } + + for (cnt = 0; cnt < zp->z_addrcnt; cnt++) { + methode = ISNOTIXFR; + curclass = zp->z_class; + /* + * If we have been given a serial number and a ixfr log + * file name then set methode. + */ + if (check_serial && tmpiname != NULL) + methode = servermethode[cnt]; + error = 0; + tsig_signed = 0; + z_axfr_src = zp->z_axfr_src; + if (buf == NULL) { + if ((buf = (u_char *)malloc(2 * PACKETSZ)) == NULL) { + syslog(LOG_INFO, "malloc(%u) failed", + 2 * PACKETSZ); + error++; + break; + } + bufsize = 2 * PACKETSZ; + } + tsig_key = tsig_key_from_addr(sin.sin_addr); + + try_again: + first_soa_printed = 0; + if ((s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) { + syslog(LOG_INFO, "socket: %m"); + error++; + break; + } + if (z_axfr_src.s_addr != 0) { + memset(&sin, 0, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_port = 0; /* "ANY" */ + sin.sin_addr = z_axfr_src; + dprintf(2, "binding to address [%s]\n", + inet_ntoa(sin.sin_addr)); + if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) + syslog(LOG_INFO, "warning: bind(%s) failed", + inet_ntoa(zp->z_axfr_src)); + } + memset(&sin, 0, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_port = port; + sin.sin_addr = zp->z_addr[cnt]; + dprintf(2, "connecting to server #%d [%s].%d\n", + cnt + 1, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); + if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + if (z_axfr_src.s_addr != 0) { + dprintf(2, "connect failed, trying w/o -x"); + z_axfr_src.s_addr = 0; + (void) my_close(s); + goto try_again; + } + if (!quiet) + syslog(LOG_INFO, + "connect(%s) for zone %s failed: %s", + inet_ntoa(sin.sin_addr), zp->z_origin, + strerror(errno)); + error++; + (void) my_close(s); + continue; + } + + query_type = (methode == ISIXFR && was_ixfr == 0) ? + T_IXFR : T_SOA; + + n = make_query(s, zp, query_type, serial_no, tsig_key, + buf, bufsize); + + if (n < 0) { + (void) my_close(s); +#ifdef POSIX_SIGNALS + (void) sigaction(SIGALRM, &osv, + (struct sigaction *)0); +#else + (void) sigvec(SIGALRM, &osv, + (struct sigvec *)0); +#endif + return (XFER_FAIL); + } + + /* + * Get out your butterfly net and catch the answer. + */ + len = readandverify(s, &buf, &bufsize, &sin, zp->z_origin, 1); + if (len == 0) { + my_close(s); + error++; + continue; + } + + if (query_type == T_IXFR && ixfp == NULL) { + delete_soa = 1; + ixfr_soa = 0; + if ((ixfp = fopen(tmpiname, "w+")) == NULL) { + perror(tmpiname); + if (!quiet) + syslog(LOG_ERR, + "can't fopen ixfr log (%s)", + tmpname); + exit(XFER_FAIL); + } + } + + hp = (HEADER *) buf; + qdcount = ntohs(hp->qdcount); + ancount = ntohs(hp->ancount); + aucount = ntohs(hp->nscount); + arcount = ntohs(hp->arcount); + /* + * close socket if any of these apply: + * 1) rcode != NOERROR + * 2) not an authority response + * 3) not an answer to our question + * 4) both the number of answers and authority count < 1) + */ + if (hp->rcode != NOERROR || + (query_type == T_SOA && (!hp->aa || qdcount != 1)) || + (ancount < 1 && aucount < 1)) { +#ifndef SYSLOG_42BSD + syslog(LOG_NOTICE, + "[%s] %s for %s, %s query got rcode %d, aa %d, ancount %d, aucount %d", + inet_ntoa(sin.sin_addr), + (hp->aa + ? (qdcount==1 ?"no SOA found" :"bad response") + : "not authoritative"), + zp->z_origin[0] != '\0' ? zp->z_origin : ".", + p_type(query_type), + hp->rcode, hp->aa, ancount, aucount); +#endif + error++; + (void) my_close(s); + continue; + } + zp_start = *zp; + if ((int)len < HFIXEDSZ + QFIXEDSZ) { + badsoa_msg = "too short"; + badsoa: + syslog(LOG_INFO, + "malformed %s from [%s], zone %s: %s", + p_type(query_type), inet_ntoa(sin.sin_addr), + zp->z_origin, badsoa_msg); + error++; + (void) my_close(s); + continue; + } + /* + * Step through response. + */ + tmp = buf + HFIXEDSZ; + eom = buf + len; + /* Query Section. */ + if (qdcount > 1) { + badsoa_msg = "question error"; + goto badsoa; + } + if (qdcount < 1) + goto no_question; + n = dn_expand(buf, eom, tmp, name2, sizeof name2); + if (n < 0) { + badsoa_msg = "qname error"; + goto badsoa; + } + tmp += n; + if (tmp + 2 * INT16SZ > eom) { + badsoa_msg = "query error"; + goto badsoa; + } + NS_GET16(type, tmp); + NS_GET16(class, tmp); + if (class != curclass || + ((type != T_SOA) && (type != T_IXFR) && (type != T_AXFR)) || + ns_samename(zp->z_origin, name2) != 1) + { + syslog(LOG_INFO, + "wrong query in resp from [%s], zone %s: [%s %s %s]\n", + inet_ntoa(sin.sin_addr), zp->z_origin, + name2, p_class(class), p_type(type)); + error++; + (void) my_close(s); + continue; + } + no_question: + /* ... Answer Section. + * We may have to loop a little, to bypass SIG SOA's in + * the response. + */ + loop_cnt = 0; + bp = NULL; + do { + u_char *cp4, *ocp = tmp; + u_short type, class, dlen, olen = len; + u_int32_t ttl; + + n = dn_expand(buf, eom, tmp, name2, sizeof name2); + if (n < 0) { + badsoa_msg = "aname error"; + goto badsoa; + } + tmp += n; + + if (loop_cnt == 0) + bp = tmp; + + /* Are type, class, and ttl OK? */ + cp4 = tmp; /* Leave tmp pointing to type field */ + if (eom - cp4 < 3 * INT16SZ + INT32SZ) { + badsoa_msg = "zinfo too short"; + goto badsoa; + } + NS_GET16(type, cp4); + NS_GET16(class, cp4); + NS_GET32(ttl, cp4); + NS_GET16(dlen, cp4); + if (cp4 + dlen > eom) { + badsoa_msg = "zinfo dlen too big"; + goto badsoa; + } + if (type == T_SOA) { + if (was_ixfr) { + methode = ISNOTIXFR; + break; + } + if ((methode == ISIXFR) && (loop_cnt == 0)) { + soa_cnt++; + badsoa_msg = soa_zinfo(&zp_finish, tmp, + eom); + if (badsoa_msg) + goto badsoa; + if (ixfp && ixfr_log(buf, len, + &delete_soa, + ixfp, &sin, + &serial_no, + &ixfr_first) < 0) { + error++; + break; + } + } else { + if (methode == ISIXFR) { + check_serial = 0; + soa_cnt++; + break; + } + break; + } + } + if ((loop_cnt >= 1) && (soa_cnt < 2)) { + dprintf(1, + "server %s %d rejected IXFR and responded with AXFR\n", + inet_ntoa(sin.sin_addr), soa_cnt); + methode = ISNOTIXFR; + check_serial = 0; + was_ixfr++; + tmp = bp; + break; + } + /* Skip to next record, if any. */ + dprintf(1, "skipping %s %s RR in response\n", + name2, p_type(type)); + tmp = cp4 + dlen; + loop_cnt++; + if (loop_cnt == 1) { + + badsoa_msg = soa_zinfo(&zp_start, bp, eom); + if (badsoa_msg) + goto badsoa; + if (check_serial && + !SEQ_GT(zp_start.z_serial, query_serial)) { + (void) my_close(s); + dprintf(1, + "zone up-to-date, serial %u\n", + zp_start.z_serial); + if (ixfp) { + (void) fclose(ixfp); + (void) unlink (tmpiname); + ixfp = NULL; + } + return (XFER_UPTODATE); + } + } + if (ancount == 1 && loop_cnt == 1) { + if (buf2 == NULL) { + if ((buf2 = (u_char *)malloc(2 * PACKETSZ)) == NULL) { + syslog(LOG_INFO, + "malloc(%u) failed", + 2 * PACKETSZ); + error++; + break; + } + buf2size = 2 * PACKETSZ; + } + len = readandverify(s, &buf2, &buf2size, &sin, + zp->z_origin, 0); + if (len == 0) { + error++; + tmp = bp; + check_serial = 0; + break; + } + + hp = (HEADER *) buf2; + qdcount = ntohs(hp->qdcount); + ancount = ntohs(hp->ancount); + aucount = ntohs(hp->nscount); + arcount = ntohs(hp->arcount); + + tmp = buf2 + HFIXEDSZ; + eom = buf2 + len; + /* Query Section. */ + if (qdcount > 1) { + badsoa_msg = "question error"; + goto badsoa; + } else if (qdcount == 1) { + n = dn_skipname(tmp, eom); + if (n < 0) { + badsoa_msg = "qname error"; + goto badsoa; + } + tmp += n; + if (tmp + 2 * INT16SZ > eom) { + badsoa_msg = "query error"; + goto badsoa; + } + tmp += 2 * INT16SZ; + } + /* answer section */ + if (ancount < 1) { + badsoa_msg = "empty answer"; + goto badsoa; + } + n = dn_expand(buf2, eom, tmp, name2, + sizeof name2); + if (n < 0) { + badsoa_msg = "qname error"; + goto badsoa; + } + tmp += n; + bp = tmp; + if (tmp + 2 * INT16SZ > eom) { + badsoa_msg = "query error"; + goto badsoa; + } + NS_GET16(type, tmp); + NS_GET16(class, tmp); + if (class != curclass || + ns_samename(zp->z_origin, name2) != 1) + { + syslog(LOG_INFO, + "wrong query in resp from [%s], zone %s: [%s %s %s]\n", + inet_ntoa(sin.sin_addr), zp->z_origin, + name2, p_class(class), p_type(type)); + error++; + tmp = bp; + check_serial = 0; + break; + } + if (type == T_SOA) { + ixfr_single_answer_mode = 1; + if (ixfp && + ixfr_log(buf2, len, &delete_soa, ixfp, + &sin, &serial_no, + &ixfr_first) < 0) { + error++; + break; + } + free(buf); + buf = buf2; + bufsize = buf2size; + buf2 = NULL; + break; + } else { + methode = ISNOTIXFR; + was_ixfr++; + check_serial = 0; + cp = buf + HFIXEDSZ; + n = print_output(zp, serial_no, buf, olen, ocp, 3); + first_soa_printed = 1; + free(buf); + buf = buf2; + buf2 = NULL; + bufsize = buf2size; + break; + } + } + if (loop_cnt > 1) { + tmp = bp; + check_serial = 0; + break; + } + } while (1); + + if (error != 0) { + (void) my_close(s); + continue; + } + + if (ns_samename(zp->z_origin, name2) != 1) { + syslog(LOG_INFO, + "wrong answer in resp from [%s], zone %s: [%s %s %s]\n", + inet_ntoa(sin.sin_addr), zp->z_origin, + name2, p_class(class), p_type(type)); + error++; + (void) my_close(s); + continue; + } + if (loop_cnt < 1) { + badsoa_msg = soa_zinfo(&zp_start, tmp, eom); + if (badsoa_msg) + goto badsoa; + } + if (methode == ISNOTIXFR) { + if (SEQ_GT(zp_start.z_serial, serial_no) || + !check_serial) { + if (soa_cnt) { + if (!first_soa_printed) + soa_cnt = 0; + goto axfr_response; + } + dprintf(1, "need update, serial %u\n", + zp_start.z_serial); + soa_cnt = 0; + hp = (HEADER *) buf; + ns_cnt = 0; + print_comment(s, &sin, check_serial, + serial_no, tsig_key); + + for (;;) { + if ((soa_cnt == 0) || (zp->z_type == Z_STUB)) { + if (zp->z_type == Z_STUB) { + if (soa_cnt == 1 && + ns_cnt == 0) + query_type = T_NS; + else + query_type = T_SOA; + } else if (methode == ISIXFR) + query_type = T_IXFR; + else + query_type = xfr_qtype; + n = make_query(s, zp, query_type, + serial_no, tsig_key, + buf, bufsize); + syslog(LOG_INFO, + "send %s query %d to %s", + p_type(query_type), + cnt, inet_ntoa(sin.sin_addr)); + dprintf(1, + "send %s query to %s\n", + p_type(query_type), + inet_ntoa(sin.sin_addr)); + dprintf(1,"bufsize = %d\n", bufsize); + if (n < 0) { + if (!quiet) { + if (zp->z_type == Z_STUB) + syslog(LOG_INFO, + "zone %s: res_nmkquery %s failed", + p_type(query_type), + zp->z_origin); + else + syslog(LOG_INFO, + "zone %s: res_nmkquery %s failed", + zp->z_origin, + p_type(query_type)); + } + (void) my_close(s); +#ifdef POSIX_SIGNALS + sigaction(SIGALRM, &osv, + (struct sigaction *)0); +#else + sigvec(SIGALRM, &osv, + (struct sigvec *)0); +#endif + return (XFER_FAIL); + } + } +/*XXX ZXFR*/ +receive: + /* + * Receive length & response + */ + tsig_req = (soa_cnt == 0); + len = readandverify(s, &buf, &bufsize, &sin, + zp->z_origin, tsig_req); + if (len == 0) { + error++; + break; + } + hp = (HEADER *)buf; + eom = buf + len; + if (len < HFIXEDSZ) { + badrec: + error++; + alen = sizeof my_addr; + if (getsockname(s, (struct sockaddr *) + &my_addr, &alen) < 0) + sprintf(my_addr_text, + "[errno %d]", errno); + else + sprintf(my_addr_text, + "[%s].%u", + inet_ntoa(my_addr. + sin_addr), + ntohs(my_addr.sin_port) + ); + if ((len >= HFIXEDSZ) && + (hp->rcode == REFUSED)) { + syslog(LOG_INFO, + "[%s] transfer refused from [%s], zone %s\n", + my_addr_text, + inet_ntoa(sin.sin_addr), + zp->z_origin); + refused = 1; + } else { + syslog(LOG_INFO, + "[%s] record too short from [%s], zone %s\n", + my_addr_text, + inet_ntoa(sin.sin_addr), + zp->z_origin); + } + break; + } +axfr_response: + if (query_type == T_IXFR) + if (hp->rcode != NOERROR) { + dprintf(1, + "server %s did not support IXFR\n", + inet_ntoa(sin.sin_addr)); + methode = ISNOTIXFR; + continue; + }; + cp = buf + HFIXEDSZ; + if (ntohs(hp->qdcount) == 1) { + if ((query_type == T_IXFR) && + (methode == ISIXFR)) { + dprintf(1, + "server %s rejected IXFR and responded with AXFR\n", + inet_ntoa(sin.sin_addr)); + methode = ISNOTIXFR; + } + n = dn_skipname(cp, eom); + if ((n == -1) || + ((n + QFIXEDSZ) >= (eom - cp))) + goto badrec; + cp += n + QFIXEDSZ; + } + nmp = cp; + if ((n = dn_skipname(cp, eom)) == -1) + goto badrec; + tmp = cp + n; + if (zp->z_type == Z_STUB) { + ancount = ntohs(hp->ancount); + n = 0; + for (cnt = 0; + cnt < (u_int)ancount; + cnt++) { + n = print_output(zp, + serial_no, + buf, len, cp, + 0); + if (n < 0) + break; + cp += n; + } + /* + * If we've processed the answer + * section and didn't get any useful + * answers, bail out. + */ + if (query_type == T_SOA && + soa_cnt == 0) { + syslog(LOG_ERR, + "stubs: no SOA in answer"); + error++; + break; + } + if (query_type == T_NS && + ns_cnt == 0) { + syslog(LOG_ERR, + "stubs: no NS in answer"); + error++; + break; + } + if (n >= 0 && hp->nscount) { + ancount = ntohs(hp->nscount); + for (cnt = 0; + cnt < (u_int)ancount; + cnt++) { + n = print_output(zp, + serial_no, + buf, + len, + cp, + 0); + if (n < 0) + break; + cp += n; + } + } + ancount = ntohs(hp->arcount); + for (cnt = 0; + n > 0 && cnt < (u_int)ancount; + cnt++) { + n = print_output(zp, serial_no, + buf, len, cp, + 0); + cp += n; + } + if (n < 0) { + syslog(LOG_INFO, + "print_output: unparseable answer (%d), zone %s", + hp->rcode, + zp->z_origin); + error++; + break; + } + if (cp != eom) { + syslog(LOG_INFO, + "print_output: short answer (%d, %d), zone %s", + cp - buf, eom - buf, + zp->z_origin); + error++; + break; + } + } else { + ancount = ntohs(hp->ancount); + if (query_type == T_IXFR && + methode == ISIXFR && + ixfr_log(buf, len, &delete_soa, + ixfp, &sin, &serial_no, + &ixfr_first) < 0 ){ + error++; + break; + } + for (n = cnt = 0; + cnt < (u_int)ancount; + cnt++) { + n = print_output(zp, serial_no, + buf, len, cp, + 0); + if (n < 0) + break; + cp += n; + } + if (n < 0) { + syslog(LOG_INFO, + "print_output: unparseable answer (%d), zone %s", + hp->rcode, + zp->z_origin); + error++; + break; + } + if (cp != eom) { + syslog(LOG_INFO, + "print_output: short answer (%d, %d), zone %s", + cp - buf, eom - buf, + zp->z_origin); + error++; + break; + } + } + if ((soa_cnt >= 2) && (methode == ISNOTIXFR)) + break; + if ((soa_cnt == -1) && (methode == ISIXFR)) + break; + } + (void) my_close(s); + if (error == 0) { +#ifdef POSIX_SIGNALS + (void) sigaction(SIGALRM, &osv, + (struct sigaction *)0); +#else + (void) sigvec(SIGALRM, &osv, + (struct sigvec *)0); +#endif + if (ixfp) { + (void) fclose(ixfp); + ixfp = NULL; + } + return (XFER_SUCCESSAXFR); + } + if (ixfp) { + (void) fclose(ixfp); + ixfp = NULL; + } + dprintf(2, "error receiving zone transfer\n"); + } else if (zp_start.z_serial == serial_no) { + (void) my_close(s); + dprintf(1, "zone up-to-date, serial %u\n", + zp_start.z_serial); + if (ixfp) { + (void) fclose(ixfp); + (void) unlink (tmpiname); + ixfp = NULL; + } + return (XFER_UPTODATE); + } else { + (void) my_close(s); + if (!quiet) + syslog(LOG_NOTICE, + "serial from [%s], zone %s: %u lower than current: %u\n", + inet_ntoa(sin.sin_addr), zp->z_origin, + zp_start.z_serial, serial_no); + return (XFER_FAIL); + } + } else { + if (zp_finish.z_serial == query_serial) { + (void) my_close(s); + dprintf(1, "zone up-to-date, serial %u\n", + zp_start.z_serial); + if (ixfp) { + (void) fclose(ixfp); + (void) unlink (tmpiname); + ixfp = NULL; + } + return (XFER_UPTODATE); + } + if (SEQ_GT(query_serial, zp_finish.z_serial)) { + if (!quiet) + syslog(LOG_NOTICE, + "serial from [%s], zone %s: %u lower than current: %u\n", + inet_ntoa(sin.sin_addr), zp->z_origin, + zp_finish.z_serial, query_serial); + dprintf(1, + "serial from [%s], zone %s: %u lower than current: %u\n", + inet_ntoa(sin.sin_addr), zp->z_origin, + zp_finish.z_serial, query_serial); + if (ixfp) { + (void) fclose(ixfp); + (void) unlink (tmpiname); + ixfp = NULL; + } + if (was_ixfr == 0) { + was_ixfr++; + n = make_query(s, zp, T_AXFR, + serial_no, tsig_key, + buf, bufsize); + if (n < 0) { + (void) my_close(s); +#ifdef POSIX_SIGNALS + (void) sigaction(SIGALRM, &osv, + (struct sigaction *)0); +#else + (void) sigvec(SIGALRM, &osv, + (struct sigvec *)0); +#endif + return (XFER_FAIL); + } + methode = ISNOTIXFR; + check_serial = 0; + soa_cnt = 0; + was_ixfr = 0; + goto receive; + } + (void) my_close(s); + return (XFER_FAIL); + } + if (soa_cnt > 2) { + methode = ISNOTIXFR; + check_serial = 0; + soa_cnt = 0; + goto axfr_response; + } + dprintf(1, "We have an IXFR\n"); + loop_cnt = 0; + while (SEQ_GT(zp_finish.z_serial, serial_no)) { + /* + * Receive length & response + */ + tsig_req = (soa_cnt == 0); + len = readandverify(s, &buf, &bufsize, &sin, + zp->z_origin, 1); + if (len == 0) { + error++; + break; + } + hp = (HEADER *)buf; + eom = buf + len; + if (len < HFIXEDSZ) { + error++; + alen = sizeof my_addr; + if (getsockname(s, (struct sockaddr *) + &my_addr, &alen) < 0) + sprintf(my_addr_text, "[errno %d]", errno); + else + sprintf(my_addr_text, "[%s].%u", + inet_ntoa(my_addr. sin_addr), + ntohs(my_addr.sin_port)); + if ((hp->rcode == REFUSED) && + (len >= HFIXEDSZ)) { + syslog(LOG_INFO, + "[%s] transfer refused from [%s], zone %s\n", + my_addr_text, + inet_ntoa(sin.sin_addr), + zp->z_origin); + refused = 1; + } else { + syslog(LOG_INFO, + "[%s] record too short from [%s], zone %s\n", + my_addr_text, + inet_ntoa(sin.sin_addr), + zp->z_origin); + } + break; + } + if (ixfp && + ixfr_log(buf, len, &delete_soa, ixfp, + &sin, &serial_no, &ixfr_first) < 0) + { + error++; + break; + } + } + (void) my_close(s); + if (!error) { + fprintf(ixfp, "update:\t{add} "); + if (soa_buf) + fputs(soa_buf, ixfp); + fprintf(ixfp, "[END_DELTA]\n"); + return (XFER_SUCCESSIXFR); + } + } + } +#ifdef POSIX_SIGNALS + (void) sigaction(SIGALRM, &osv, (struct sigaction *)0); +#else + (void) sigvec(SIGALRM, &osv, (struct sigvec *)0); +#endif + if (ixfp) { + (void) my_fclose(ixfp); + (void) unlink (tmpiname); + ixfp = NULL; + } + if (!error) + return (XFER_TIMEOUT); + if (refused) + return (XFER_REFUSED); + return (XFER_FAIL); +} + +static SIG_FN +term_handler() { + cleanup_for_exit(); + _exit(XFER_FAIL); /* not safe to call exit() from a signal handler */ +} + +/* + * Set flag saying to read was interrupted + * used for a read timer + */ +static SIG_FN +read_alarm() { + read_interrupted = 1; +} + +static int +netread(int fd, char *buf, int len, int timeout) { + static const char setitimerStr[] = "setitimer: %m"; + struct itimerval ival, zeroival; + struct sockaddr_in sa; + int n; + ISC_SOCKLEN_T salen; +#if defined(NETREAD_BROKEN) + int retries = 0; +#endif + + memset(&zeroival, 0, sizeof zeroival); + ival = zeroival; + ival.it_value.tv_sec = timeout; + while (len > 0) { +#ifndef _WIN32 + if (setitimer(ITIMER_REAL, &ival, NULL) < 0) { + syslog(LOG_INFO, setitimerStr); + return (-1); + } +#endif + errno = 0; + salen = sizeof sa; + n = recvfrom(fd, buf, len, 0, (struct sockaddr *)&sa, &salen); + if (n == 0 && errno == 0) { +#if defined(NETREAD_BROKEN) + if (++retries < 42) /* doug adams */ + continue; +#endif + syslog(LOG_INFO, "premature EOF, fetching \"%s\"", + domain); + return (-1); + } + if (n < 0) { + if (errno == 0) { +#if defined(NETREAD_BROKEN) + if (++retries < 42) /* doug adams */ + continue; +#endif + syslog(LOG_INFO, + "recv(len=%d): n=%d && !errno", + len, n); + return (-1); + } + if (errno == EINTR) { + if (!read_interrupted) { + /* It wasn't a timeout; ignore it. */ + continue; + } + errno = ETIMEDOUT; + } + syslog(LOG_INFO, "recv(len=%d): %m", len); + return (-1); + } + buf += n; + len -= n; +#if defined(NETREAD_BROKEN) + /* Reset the retry counter if we are successfully reading. */ + if(n > 0) + retries = 0; +#endif + } +#ifndef _WIN32 + if (setitimer(ITIMER_REAL, &zeroival, NULL) < 0) { + syslog(LOG_INFO, setitimerStr); + return (-1); + } +#endif + return (0); +} + +/* + * Write a counted buffer to a file descriptor preceded by a length word. + */ +static int +writemsg(int rfd, const u_char *msg, int msglen) { + struct iovec iov[2]; + u_char len[INT16SZ]; + int ret; + + __putshort(msglen, len); + iov[0].iov_base = (char *)len; + iov[0].iov_len = INT16SZ; + DE_CONST(msg, iov[1].iov_base); + iov[1].iov_len = msglen; + ret = writev(rfd, iov, 2); + if (ret != INT16SZ + msglen) { + syslog(LOG_DEBUG, "writemsg(%d,%p,%d) failed: %s", + rfd, msg, msglen, strerror(errno)); + return (-1); + } + return (ret); +} + +static const char * +soa_zinfo(struct zoneinfo *zp, u_char *cp, u_char *eom) { + int n, type, class; + u_int32_t ttl; + u_int16_t dlen; + u_char *rdatap; + + /* Are type, class, and ttl OK? */ + if (eom - cp < 3 * INT16SZ + INT32SZ) + return ("zinfo too short"); + NS_GET16(type, cp); + NS_GET16(class, cp); + NS_GET32(ttl, cp); + NS_GET16(dlen, cp); + rdatap = cp; + if (type != T_SOA || class != curclass) + return ("zinfo wrong typ/cla/ttl"); + /* Skip master name and contact name, we can't validate them. */ + if ((n = dn_skipname(cp, eom)) == -1) + return ("zinfo mname"); + cp += n; + if ((n = dn_skipname(cp, eom)) == -1) + return ("zinfo hname"); + cp += n; + /* Grab the data fields. */ + if (eom - cp < 5 * INT32SZ) + return ("zinfo dlen"); + NS_GET32(zp->z_serial, cp); + NS_GET32(zp->z_refresh, cp); + NS_GET32(zp->z_retry, cp); + NS_GET32(zp->z_expire, cp); + NS_GET32(zp->z_minimum, cp); + if (cp != rdatap + dlen) + return ("bad soa dlen"); + return (NULL); +} + +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eom) { \ + hp->rcode = FORMERR; \ + return (-1); \ + } \ + } while (0) + +/* + * Parse the message, determine if it should be printed, and if so, print it + * in .db file form. Does minimal error checking on the message content. + * + * XXX why aren't we using ns_sprintrr() ? + */ +static int +print_output(struct zoneinfo *zp, u_int32_t serial_no, u_char *msg, + int msglen, u_char *rrp, int xfr_detect) { + u_char *cp; + HEADER *hp = (HEADER *) msg; + u_int32_t ttl, tmpnum; + int i, j, longname, result, n1, n; + u_int class, type, dlen; + char data[MAXDATA]; + u_char *cp1, *cp2, *temp_ptr, *eom, *rr_type_ptr; + u_char *cdata, *rdatap; + char *origin, dname[MAXDNAME]; + const char *proto; + const char *ignore = ""; + const char *badsoa_msg; + int escaped = 0; + + eom = msg + msglen; + cp = rrp; + n = dn_expand(msg, msg + msglen, cp, dname, sizeof dname); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); + rr_type_ptr = cp; + NS_GET16(type, cp); + NS_GET16(class, cp); + NS_GET32(ttl, cp); + /* + * Following the Clarification draft's direction, we treat TTLs with + * the MSB set as if they were 0. + */ + if (ttl > MAXIMUM_TTL) { + syslog(LOG_INFO, "%s: TTL > %u, converted to 0", dname, + MAXIMUM_TTL); + ttl = 0; + } + NS_GET16(dlen, cp); + BOUNDS_CHECK(cp, dlen); + rdatap = cp; + + origin = dname; + while (*origin) { + if (!escaped && *origin == '.') { + origin++; /* skip over '.' */ + break; + } + escaped = (*origin++ == '\\') && !escaped; + } + dprintf(3, "print_output: dname %s type %d class %d ttl %u\n", + dname, type, class, ttl); + /* + * Convert the resource record data into the internal database format. + * CP points to the raw resource record. + * After this switch: + * CP has been updated to point past the RR. + * CP1 points to the internal database version. + * N is the length of the internal database version. + */ + switch (type) { + case T_A: + case T_WKS: + case T_HINFO: + case T_TXT: + case T_X25: + case T_ISDN: + case T_LOC: + case T_NSAP: + case T_AAAA: + case T_KEY: + case ns_t_cert: + cp1 = cp; + n = dlen; + cp += n; + break; + + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_NS: + case T_PTR: + n = dn_expand(msg, msg + msglen, cp, data, sizeof data); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + cp1 = (u_char *)data; + n = strlen(data) + 1; + break; + + case T_MINFO: + case T_SOA: + case T_RP: + n = dn_expand(msg, msg + msglen, cp, data, sizeof data); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + n = strlen(data) + 1; + cp1 = (u_char *)data + n; + n1 = sizeof data - n; + if (type == T_SOA) + n1 -= 5 * INT32SZ; + n = dn_expand(msg, msg + msglen, cp, (char *)cp1, n1); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + cp1 += strlen((char *) cp1) + 1; + if (type == T_SOA) { + BOUNDS_CHECK(cp, 5 * INT32SZ); + temp_ptr = cp + 4 * INT32SZ; + NS_GET32(minimum_ttl, temp_ptr); + /* + * Following the Clarification draft's direction, + * we treat TTLs with the MSB set as if they were 0. + */ + if (minimum_ttl > MAXIMUM_TTL) { + syslog(LOG_INFO, + "%s: SOA minimum TTL > %u, converted to 0", + dname, MAXIMUM_TTL); + minimum_ttl = 0; + } + n = 5 * INT32SZ; + memcpy(cp1, cp, n); + cp += n; + cp1 += n; + } + n = cp1 - (u_char *)data; + cp1 = (u_char *)data; + break; + + case T_NAPTR: + /* Grab weight and port. */ + BOUNDS_CHECK(cp, INT16SZ*2); + memcpy(data, cp, INT16SZ*2); + cp1 = (u_char *)data + INT16SZ*2; + cp += INT16SZ*2; + + /* Flags */ + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); + *cp1++ = n; + memcpy(cp1, cp, n); + cp += n; cp1 += n; + + /* Service */ + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); + *cp1++ = n; + memcpy(cp1, cp, n); + cp += n; cp1 += n; + + /* Regexp */ + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); + *cp1++ = n; + memcpy(cp1, cp, n); + cp += n; cp1 += n; + + /* Replacement */ + n = dn_expand(msg, msg + msglen, cp, (char *)cp1, + sizeof data - ((char *)cp1 - data)); + if (n < 0) + return (-1); + cp += n; + + /* compute end of data */ + cp1 += strlen((char *)cp1) + 1; + /* compute size of data */ + n = cp1 - (u_char *)data; + cp1 = (u_char *)data; + break; + + case T_MX: + case T_AFSDB: + case T_RT: + case T_SRV: + /* grab preference */ + BOUNDS_CHECK(cp, INT16SZ); + memcpy(data, cp, INT16SZ); + cp1 = (u_char *)data + INT16SZ; + cp += INT16SZ; + + if (type == T_SRV) { + BOUNDS_CHECK(cp, INT16SZ*2); + memcpy(cp1, cp, INT16SZ*2); + cp1 += INT16SZ*2; + cp += INT16SZ*2; + } + + /* get name */ + n = dn_expand(msg, msg + msglen, cp, + (char *)cp1, + sizeof data - (cp1 - (u_char *)data)); + if (n < 0) + return (-1); + cp += n; + + /* compute end of data */ + cp1 += strlen((char *) cp1) + 1; + /* compute size of data */ + n = cp1 - (u_char *)data; + cp1 = (u_char *)data; + break; + + case T_PX: + /* grab preference */ + BOUNDS_CHECK(cp, INT16SZ); + memcpy(data, cp, INT16SZ); + cp1 = (u_char *)data + INT16SZ; + cp += INT16SZ; + + /* get MAP822 name */ + n = dn_expand(msg, msg + msglen, cp, + (char *)cp1, sizeof data - INT16SZ); + if (n < 0) + return (-1); + cp += n; + cp1 += (n = (strlen((char *) cp1) + 1)); + n1 = sizeof data - n; + + /* get MAPX400 name */ + n = dn_expand(msg, msg + msglen, cp, (char *)cp1, n1); + if (n < 0) + return (-1); + cp += n; + cp1 += strlen((char *) cp1) + 1; + n = cp1 - (u_char *)data; + cp1 = (u_char *)data; + break; + + case T_SIG: + /* CP is the raw resource record as it arrived. + * CP1, after this switch, points to the internal database version. */ + cp1 = (u_char *)data; + + /* first just copy over the type_covered, algorithm, */ + /* labels, orig ttl, two timestamps, and the footprint */ + BOUNDS_CHECK(cp, NS_SIG_SIGNER); + memcpy(cp1, cp, NS_SIG_SIGNER); + cp += NS_SIG_SIGNER; + cp1 += NS_SIG_SIGNER; + + /* then the signer's name */ + n = dn_expand(msg, msg + msglen, cp, + (char *)cp1, (sizeof data) - 18); + if (n < 0) + return (-1); + cp += n; + cp1 += strlen((char*)cp1)+1; + + /* finally, we copy over the variable-length signature. + Its size is the total data length, minus what we copied. */ + n = dlen - (NS_SIG_SIGNER + n); + if (n > ((int)(sizeof data) - (int)(cp1 - (u_char *)data))) { + hp->rcode = FORMERR; + return (-1); /* out of room! */ + } + memcpy(cp1, cp, n); + cp += n; + cp1 += n; + + /* compute size of data */ + n = cp1 - (u_char *)data; + cp1 = (u_char *)data; + break; + + case T_NXT: + n = dn_expand(msg, msg + msglen, cp, + (char *)data, sizeof data); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + cp1 = (u_char *)data + strlen(data) + 1; + n = dlen - n; + if (n > ((int)(sizeof data) - (int)(cp1 - (u_char *)data))) { + hp->rcode = FORMERR; + return (-1); /* out of room! */ + } + if (n > 0) { /* Actually, n should never be less than 4 */ + memcpy(cp1, cp, n); + cp += n; + } else { + hp->rcode = FORMERR; + return (-1); + } + n += cp1 - (u_char *)data; + cp1 = (u_char *)data; + break; + + default: + cp1 = cp; + n = dlen; + cp += n; + break; + } + + if (n > MAXDATA) { + dprintf(1, "update type %d: %d bytes is too much data\n", + type, n); + hp->rcode = FORMERR; + return (-1); + } + if (cp != rdatap + dlen) { + dprintf(1, + "encoded rdata length is %u, but actual length was %u\n", + dlen, (u_int)(cp - rdatap)); + hp->rcode = FORMERR; + return (-1); + } + + cdata = cp1; + result = cp - rrp; + + /* + * Special handling for SOA records. + */ + + if (type == T_SOA) { + if (ns_samename(dname, zp->z_origin) != 1) { + syslog(LOG_INFO, + "wrong zone name in XFR (wanted \"%s\", got \"%s\")", + zp->z_origin, dname); + hp->rcode = FORMERR; + return (-1); + } + if (soa_cnt == 0) { + badsoa_msg = soa_zinfo(&zp_start, rr_type_ptr, eom); + if (badsoa_msg) { + syslog(LOG_INFO, + "malformed SOA for zone %s: %s", + zp->z_origin, badsoa_msg); + hp->rcode = FORMERR; + return (-1); + } + if (SEQ_GT(zp_start.z_serial, serial_no) || + !check_serial) { + soa_cnt++; + } else { + syslog(LOG_INFO, + "serial went backwards after transfer started"); + return (-1); + } + } else if (soa_cnt == 1) { + badsoa_msg = soa_zinfo(&zp_finish, rr_type_ptr, eom); + if (badsoa_msg) { + syslog(LOG_INFO, + "malformed SOA for zone %s: %s", + zp->z_origin, badsoa_msg); + hp->rcode = FORMERR; + return (-1); + } + if (zp_start.z_serial == zp_finish.z_serial) { + methode = ISNOTIXFR; + if (xfr_detect == 3) + soa_cnt = 0; + } else if (zp_finish.z_serial != serial_no) { + syslog(LOG_INFO, + "Unexpected serial number for zone %s: %u", + zp->z_origin, zp_finish.z_serial); + } + soa_cnt++; + if (methode == ISIXFR) + return (result); + } else { + badsoa_msg = soa_zinfo(&zp_finish, rr_type_ptr, eom); + if (badsoa_msg) { + syslog(LOG_INFO, + "malformed SOA for zone %s: %s", + zp->z_origin, badsoa_msg); + hp->rcode = FORMERR; + return (-1); + } + if (methode == ISIXFR) { + if (zp_start.z_serial == zp_finish.z_serial) { + if (scdsoa) { + soa_cnt = -1; + return (result); + } else { + scdsoa = 1; + soa_cnt++; + }; + } else + soa_cnt++; + } else { + dprintf(2, "SOA, serial %u\n", + zp_finish.z_serial); + if (zp_start.z_serial != zp_finish.z_serial) { + dprintf(1, "serial changed, restart\n"); + restarts++; + if (restarts > MAX_XFER_RESTARTS) { + syslog(LOG_INFO, + "too many transfer restarts for zone %s", + zp->z_origin); + hp->rcode = FORMERR; + return (-1); + } + soa_cnt = 0; + ns_cnt = 0; + minimum_ttl = 0; + strcpy(prev_origin, zp->z_origin); + prev_dname[0] = DEF_DNAME; + /* + * Flush buffer, truncate file + * and seek to beginning to restart. + */ + fflush(dbfp); + if (ftruncate(fileno(dbfp), 0) != 0) { + if (!quiet) + syslog(LOG_INFO, + "ftruncate %s: %m\n", + tmpname); + return (-1); + } + fseek(dbfp, 0L, 0); + return (result); + } + soa_cnt++; + return (result); + } + } + if (soa_cnt == 2) + return (result); + + } + + if (zp->z_type == Z_STUB) { + if (query_type == T_NS && type == T_NS) + ns_cnt++; + /* + * If we're processing a response to an SOA query, we don't + * want to print anything from the response except for the SOA. + * We do want to check everything in the packet, which is + * why we do this check now instead of earlier. + */ + if (query_type == T_SOA && type != T_SOA) + return (result); + } + + if ((!soa_cnt || soa_cnt > 2) && methode == ISNOTIXFR) { + const char *gripe; + + if (!soa_cnt) + gripe = "got RR before first SOA"; + else + gripe = "got RR after second SOA"; + syslog(LOG_INFO, "%s in zone %s", gripe, zp->z_origin); + hp->rcode = FORMERR; + return (-1); + } + + /* + * If they are trying to tell us info about something that is + * not in the zone that we are transfering, then ignore it! + * They don't have the authority to tell us this info. + * + * We have to do a bit of checking here - the name that we are + * checking is is fully qualified & may be in a subdomain of the + * zone in question. We also need to ignore any final dots. + * + * If a domain has both NS records and non-NS records, (for + * example, NS and MX records), then we should ignore the non-NS + * records (except that we should not ignore glue A records). + * XXX: It is difficult to do this properly, so we just compare + * the current dname with that in the most recent NS record. + * This defends against the most common error case, + * where the remote server sends MX records soon after the + * NS records for a particular domain. If sent earlier, we lose. XXX + */ + if (!ns_samedomain(dname, domain)) { + (void) fprintf(dbfp, "; Ignoring info about %s, not in zone %s.\n", + dname, domain); + ignore = "; "; + } else if (type != T_NS && type != T_A && + ns_samename(zone_top, dname) != 1 && + ns_samename(prev_ns_dname, dname) == 1) + { + (void) fprintf(dbfp, "; Ignoring extra info about %s, invalid after NS delegation.\n", + dname); + ignore = "; "; + } else if (class != (unsigned)zp->z_class) { + (void) fprintf(dbfp, "; Ignoring info about %s, not class %s\n", + dname, p_class(zp->z_class)); + ignore = "; "; + } + + /* + * If the current record is not being ignored, but the + * previous record was ignored, then we invalidate information + * that might have been altered by ignored records. + * (This means that we sometimes output unnecessary $ORIGIN + * lines, but that is harmless.) + * + * Also update prev_comment now. + */ + if (prev_comment && ignore[0] == '\0') { + prev_dname[0] = DEF_DNAME; + prev_origin[0] = DEF_DNAME; + } + prev_comment = (ignore[0] != '\0'); + + /* + * set prev_ns_dname if necessary + */ + if (type == T_NS) { + (void) strcpy(prev_ns_dname, dname); + } + + /* + * If the origin has changed, print the new origin + */ + if (ns_samename(prev_origin, origin) != 1) { + (void) strcpy(prev_origin, origin); + (void) fprintf(dbfp, "%s$ORIGIN %s.\n", ignore, origin); + } + + longname = 0; + + if (ns_samename(prev_dname, dname) != 1) { + /* + * set the prev_dname to be the current dname, then cut off all + * characters of dname after (and including) the first '.' + */ + char *cutp; + + (void) strcpy(prev_dname, dname); + escaped = 0; + cutp = dname; + while (*cutp) { + if (!escaped && *cutp == '.') + break; + escaped = (*cutp++ == '\\') && !escaped; + } + *cutp = '\0'; + + if (dname[0] == 0) { + if (origin[0] == 0) + (void) fprintf(dbfp, "%s.\t", ignore); + else + (void) fprintf(dbfp, "%s.%s.\t", + ignore, origin); /* ??? */ + } else { + const char *backslash; + backslash = (*dname == '@' || *dname == '$') ? + "\\" : ""; + (void) fprintf(dbfp, "%s%s%s\t", ignore, + backslash, dname); + } + if (strlen(dname) > (size_t)8) + longname = 1; + } else { + (void) fprintf(dbfp, "%s\t", ignore); + } + + (void) fprintf(dbfp, "%d\t", (int) ttl); + + (void) fprintf(dbfp, "%s\t%s\t", p_class(class), p_type(type)); + cp = cdata; + + /* + * Print type specific data + */ + switch (type) { + + case T_A: + switch (class) { + case C_IN: + case C_HS: + fputs(inet_ntoa(ina_get(cp)), dbfp); + break; + } + (void) fprintf(dbfp, "\n"); + break; + + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_PTR: + if (cp[0] == '\0') + (void) fprintf(dbfp, ".\n"); + else + (void) fprintf(dbfp, "%s.\n", cp); + break; + + case T_NS: + cp = cdata; + if (cp[0] == '\0') + (void) fprintf(dbfp, ".\t"); + else + (void) fprintf(dbfp, "%s.", cp); + (void) fprintf(dbfp, "\n"); + break; + + case T_HINFO: + case T_ISDN: + cp2 = cp + n; + for (i = 0; i < 2; i++) { + if (i != 0) + (void) putc(' ', dbfp); + n = *cp++; + cp1 = cp + n; + if (cp1 > cp2) + cp1 = cp2; + (void) putc('"', dbfp); + j = 0; + while (cp < cp1) { + if (*cp == '\0') { + cp = cp1; + break; + } + if (strchr("\n\"\\", *cp)) + (void) putc('\\', dbfp); + (void) putc(*cp++, dbfp); + j++; + } + if (j == 0 && (type != T_ISDN || i == 0)) + (void) putc('?', dbfp); + (void) putc('"', dbfp); + } + (void) putc('\n', dbfp); + break; + + case T_SOA: + (void) fprintf(dbfp, "%s.", cp); + cp += strlen((char *) cp) + 1; + (void) fprintf(dbfp, " %s. (\n", cp); + cp += strlen((char *) cp) + 1; + NS_GET32(tmpnum, cp); + (void) fprintf(dbfp, "%s\t\t%u", ignore, tmpnum); + NS_GET32(tmpnum, cp); + (void) fprintf(dbfp, " %u", tmpnum); + NS_GET32(tmpnum, cp); + (void) fprintf(dbfp, " %u", tmpnum); + NS_GET32(tmpnum, cp); + (void) fprintf(dbfp, " %u", tmpnum); + NS_GET32(tmpnum, cp); + (void) fprintf(dbfp, " %u )\n", tmpnum); + break; + + case T_MX: + case T_AFSDB: + case T_RT: + NS_GET16(tmpnum, cp); + (void) fprintf(dbfp, "%u", tmpnum); + (void) fprintf(dbfp, " %s.\n", cp); + break; + + case T_PX: + NS_GET16(tmpnum, cp); + (void) fprintf(dbfp, "%u", tmpnum); + (void) fprintf(dbfp, " %s.", cp); + cp += strlen((char *) cp) + 1; + (void) fprintf(dbfp, " %s.\n", cp); + break; + + case T_TXT: + case T_X25: + cp1 = cp + n; + while (cp < cp1) { + (void) putc('"', dbfp); + if ((i = *cp++) != 0) { + for (j = i; j > 0 && cp < cp1; j--) { + if (strchr("\n\"\\", *cp)) + (void) putc('\\', dbfp); + (void) putc(*cp++, dbfp); + } + } + (void) putc('"', dbfp); + if (cp < cp1) + (void) putc(' ', dbfp); + } + (void) putc('\n', dbfp); + break; + + case T_NSAP: + fprintf(dbfp, "%s\n", inet_nsap_ntoa(n, cp, NULL)); + break; + + case T_AAAA: { + char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; + + fprintf(dbfp, "%s\n", inet_ntop(AF_INET6, cp, t, sizeof t)); + break; + } + + case T_LOC: { + char t[255]; + + (void) fprintf(dbfp, "%s\n", loc_ntoa(cp, t)); + break; + } + + case T_NAPTR: { + u_int32_t order, preference; + + /* Order */ + NS_GET16(order, cp); + fprintf(dbfp, "%u", order); + + /* Preference */ + NS_GET16(preference, cp); + fprintf(dbfp, " %u", preference); + + /* Flags */ + n = *cp++; + fprintf(dbfp, " \"%.*s\"", (int)n, cp); + cp += n; + + /* Service */ + n = *cp++; + fprintf(dbfp, " \"%.*s\"", (int)n, cp); + cp += n; + + /* Regexp */ + n = *cp++; + fprintf(dbfp, " \"%.*s\"", (int)n, cp); + cp += n; + + /* Replacement */ + fprintf(dbfp, " %s.\n", cp); + + break; + } + case T_SRV: { + u_int priority, weight, port; + + NS_GET16(priority, cp); + NS_GET16(weight, cp); + NS_GET16(port, cp); + fprintf(dbfp, "\t%u %u %u %s.\n", + priority, weight, port, cp); + break; + } + + case T_WKS: + fputs(inet_ntoa(ina_get(cp)), dbfp); + cp += INADDRSZ; + fputc(' ', dbfp); + proto = protocolname(*cp); + cp += sizeof(char); + (void) fprintf(dbfp, "%s ", proto); + i = 0; + while (cp < cdata + n) { + j = *cp++; + do { + if (j & 0200) + (void) fprintf(dbfp, " %s", + servicename(i, proto)); + j <<= 1; + } while (++i & 07); + } + (void) fprintf(dbfp, "\n"); + break; + + case T_MINFO: + case T_RP: + (void) fprintf(dbfp, "%s.", cp); + cp += strlen((char *) cp) + 1; + (void) fprintf(dbfp, " %s.\n", cp); + break; + + case T_KEY: { + char databuf[16+NS_MD5RSA_MAX_BASE64]; /* 16 for slop */ + u_int keyflags; + + /* get & format key flags */ + keyflags = ns_get16(cp); + (void) fprintf(dbfp, "0x%04x ", keyflags); + cp += INT16SZ; + + /* protocol id */ + (void) fprintf(dbfp, " %u", *cp++); + + /* algorithm id */ + (void) fprintf(dbfp, " %u ", *cp++); + + /* key itself (which may have zero length) */ + n = b64_ntop(cp, (cp1 + n) - cp, databuf, sizeof databuf); + if (n < 0) + fprintf(dbfp, "; BAD BASE64\n"); + else + fprintf(dbfp, "%s\n", databuf); + break; + } + + case T_SIG: { + char databuf[16+NS_MD5RSA_MAX_BASE64]; /* 16 for slop */ + + /* get & format rr type which signature covers */ + (void) fprintf(dbfp,"%s", p_type(ns_get16((u_char*)cp))); + cp += INT16SZ; + + /* algorithm id */ + (void) fprintf(dbfp," %d",*cp++); + + /* labels (# of labels in name) */ + (void) fprintf(dbfp," %d",*cp++); + + /* orig time to live (TTL)) */ + (void) fprintf(dbfp," %u", (u_int32_t)ns_get32((u_char*)cp)); + cp += INT32SZ; + + /* expiration time */ + (void) fprintf(dbfp," %s", p_secstodate(ns_get32((u_char*)cp))); + cp += INT32SZ; + + /* time signed */ + (void) fprintf(dbfp," %s", p_secstodate(ns_get32((u_char*)cp))); + cp += INT32SZ; + + /* Key footprint */ + (void) fprintf(dbfp," %d", ns_get16((u_char*)cp)); + cp += INT16SZ; + + /* signer's name */ + (void) fprintf(dbfp, " %s. ", cp); + cp += strlen((char *) cp) + 1; + + /* signature itself */ + n = b64_ntop(cp, (cdata + n) - cp, databuf, sizeof databuf); + if (n < 0) + fprintf (dbfp, "; BAD BASE64\n"); + else + fprintf (dbfp, "%s\n", databuf); + break; + } + + case T_NXT: + fprintf(dbfp, "%s.", (char *)cp); + i = strlen((char *)cp)+1; + cp += i; + n -= i; + for (i=0; i < n*NS_NXT_BITS; i++) + if (NS_NXT_BIT_ISSET (i, cp)) + fprintf(dbfp, " %s", p_type(i)); + fprintf(dbfp,"\n"); + break; + + case ns_t_cert: { + int databufsize = n * 4 / 3 + 4; + char *databuf = malloc(databufsize); + + if (databuf == NULL) + panic("cert malloc failed", NULL); + + /* Object id */ + (void) fprintf(dbfp,"%d ", ns_get16((u_char*)cp)); + cp += INT16SZ; + + /* Key tag */ + (void) fprintf(dbfp,"%d ", ns_get16((u_char*)cp)); + cp += INT16SZ; + + /* Algorithm id */ + (void) fprintf(dbfp,"%d ", (u_char)*cp); + cp += 1; + + n = b64_ntop(cp, n - 2 * INT16SZ - 1, databuf, databufsize); + if (n < 0) + panic ("cert b64_ntop failed", NULL); + fprintf (dbfp, "%s\n", databuf); + free(databuf); + break; + } + + default: + fprintf (dbfp, "\\# %u", n); + if (n > 0) { + fputs(" ( ", dbfp); + isc_puthexstring(dbfp, cp1, n, + (longname ? 28 : 40), 48, + "\n\t\t\t\t"); + fputs(" )\n", dbfp); + } + + } + if (ferror(dbfp)) { + syslog(LOG_ERR, "%s: %m", tmpname); + cleanup_for_exit(); + exit(XFER_FAIL); + } + return (result); +} + +#ifdef SHORT_FNAMES +/* +** This routine handles creating temporary files with mkstemp +** in the presence of a 14 char filename system. Pathconf() +** does not work over NFS. +*/ +filenamecpy(char *ddtfile, char *optarg) { + int namelen, extra, len; + char *dirname, *filename; + + /* determine the length of filename allowed */ + if((dirname = strrchr(optarg, '/')) == NULL){ + filename = optarg; + } else { + *dirname++ = '\0'; + filename = dirname; + } + namelen = pathconf(dirname == NULL? "." : optarg, _PC_NAME_MAX); + if(namelen <= 0) + namelen = 255; /* length could not be determined */ + if(dirname != NULL) + *--dirname = '/'; + + /* copy a shorter name if it will be longer than allowed */ + extra = (strlen(filename)+strlen(".XXXXXX")) - namelen; + if(extra > 0){ + len = strlen(optarg) - extra; + (void) strncpy(ddtfile, optarg, len); + ddtfile[len] = '\0'; + } else + (void) strcpy(ddtfile, optarg); +} +#endif /* SHORT_FNAMES */ + +DST_KEY * +tsig_key_from_addr(struct in_addr addr) { + tsig_node *n; + for (n = HEAD(tsig_list); n != NULL; n = NEXT(n, link)) + if (memcpy(&addr, &n->addr, sizeof(struct in_addr))) + return n->dst_key; + return NULL; +} + +static u_int32_t +do_section(ns_msg *handle, ns_sect section, int pflag, FILE *file, int *delete) { + int n, sflag, rrnum; + char buf[2048]; /* XXX need to malloc */ + ns_opcode opcode; + ns_rr rr; + const unsigned char *cp; + const unsigned char *eom; + u_int32_t serial = 0; + time_t now; + + time(&now); + + /* + * Print answer records. + */ + sflag = (_res.pfcode & pflag); + if (_res.pfcode && !sflag) + return (-1); + + opcode = (ns_opcode)ns_msg_getflag(*handle, ns_f_opcode); + rrnum = 0; + for (;;) { + if (ns_parserr(handle, section, rrnum, &rr)) { + if (errno != ENODEV) { + fprintf(file, ";; ns_parserr: %s\n", + strerror(errno)); + return (-1); + } else if (rrnum > 0 && sflag != 0 && + (_res.pfcode & RES_PRF_HEAD1)) + putc('\n', file); + break; + } + if (rrnum == 0 && sflag != 0 && (_res.pfcode & RES_PRF_HEAD1)) + fprintf(file, ";; %s SECTION:\n", + p_section(section, opcode)); + if (section == ns_s_qd) + fprintf(file, ";;\t%s, type = %s, class = %s\n", + ns_rr_name(rr), + p_type(ns_rr_type(rr)), + p_class(ns_rr_class(rr))); + else { + int print_record = 1; + if (rr.type == ns_t_soa) { + print_record = 0; + *delete = !*delete; + cp = ns_rr_rdata(rr); + eom = cp + ns_rr_rdlen(rr); + if ((n = dn_skipname(cp, eom)) < 0) { + rrnum++; + continue; + } + cp += n; + if ((n = dn_skipname(cp, eom)) < 0) { + rrnum++; + continue; + } + cp += n; + NS_GET32(serial, cp); + switch (++ixfr_soa) { + case 1: + final_serial = serial; + if (soa_buf == NULL) { + if ((soa_buf = (char *)malloc(2 * PACKETSZ)) == NULL) { + syslog(LOG_INFO, "malloc(%u) failed", 2 * PACKETSZ); + return(-1); + } + n = ns_sprintrr(handle, &rr, NULL, NULL, + soa_buf, 2*PACKETSZ); + if (n < 0) { + fprintf(file, ";; ns_sprintrr: %s\n", + strerror(errno)); + return (-1); + } + } + print_record = 0; + break; + case 2: + fprintf(file, + "zone:\torigin %s class %s serial %u\n", + ns_rr_name(rr), + p_class(ns_rr_class(rr)), + serial); + print_record = 0; + break; + default: + print_record = 0; + break; + } + + } + + if (print_record) { + if (rr.type != ns_t_soa) { + fprintf(file, "update:\t{%s} ", + *delete ? "delete" : "add"); + + n = ns_sprintrr(handle, &rr, NULL, NULL, + buf, sizeof buf); + if (n < 0) { + fprintf(file, ";; ns_sprintrr: %s\n", + strerror(errno)); + return(-1); + } + fputs(buf, file); + fputc('\n', file); + } + } + + } + rrnum++; + } + return (serial); +} + +static int +ixfr_log(const u_char *msg, int len, int *delete, FILE *file, + struct sockaddr_in *sin, u_int32_t *serial_no, int *first_rr) +{ + ns_msg handle; + ns_type type; + ns_class class; + ns_opcode opcode; + ns_rcode rcode; + u_int id; + u_int32_t new_serial = 0; + char time[25]; + ns_rr rr; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + dprintf(1, "ixfr_log() failed\n"); + return (-1); + } + + if (ns_initparse(msg, len, &handle) < 0) { + fprintf(file, ";; ns_initparse: %s\n", strerror(errno)); + dprintf(1, "ixfr_log() failed\n"); + return (-1); + } + opcode = (ns_opcode) ns_msg_getflag(handle, ns_f_opcode); + rcode = (ns_rcode) ns_msg_getflag(handle, ns_f_rcode); + id = ns_msg_id(handle); + + if (ns_parserr(&handle, ns_s_an, 0, &rr)) + { + + (void) fprintf(file,"ns_parserr() failed"); + dprintf(1, "ixfr_log() failed\n"); + return (-1); + } + type = (ns_type)rr.type; + class = (ns_class)rr.rr_class; + + if (*first_rr == 1) { + gettime(&tt); + (void) fprintf(file,"%s", LogSignature); + sprintf(time, "at %lu", (u_long)tt.tv_sec); + fprintf(file, + "[IXFR_UPDATE] id %u from [%s].%d %s (named-xfer pid %ld):\n", + id, inet_ntoa(sin->sin_addr), + ntohs(sin->sin_port), time, (long)getpid()); + (*first_rr)++; + } + new_serial = do_section(&handle, ns_s_an, RES_PRF_ANS, file, delete); + if (type == T_SOA && SEQ_GT(new_serial, *serial_no) && (*delete)) + *serial_no = new_serial; + return (1); +} + +static const char * +tsig_rcode(int rcode) { + static char buffer[64]; + + switch (rcode) { + case ns_r_badkey: + case ns_r_badsig: + case ns_r_badtime: + sprintf(buffer, "message had %s set", p_rcode(rcode)); + return (buffer); + case -ns_r_badkey: + case -ns_r_badsig: + case -ns_r_badtime: + return (p_rcode(-rcode)); + case NS_TSIG_ERROR_NO_TSIG: + return ("no TSIG present"); + default: + break; + } + return ("FORMERR"); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named-xfer/named-xfer.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named-xfer/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named-xfer/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named-xfer/Makefile (revision 109985) @@ -0,0 +1,90 @@ +## Copyright (c) 1996,1999 by Internet Software Consortium +## +## 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. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM 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 +## SOFTWARE. + +# $Id: Makefile,v 8.31 2000/12/23 08:02:54 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g -Wall + +#(net2 and its descendents) +SYSTYPE = freebsd +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +EXE= +LEX = lex -I +SYSLIBS = -ll -lutil +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +AR= ar cru +INSTALL= install +STRIP=-s +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin + +PS=ps +LDFLAGS= +CFLAGS= ${CDEBUG} +CPPFLAGS= -I${PORTINCL} -I${INCL} + +NAMED_OBJS= \ + ../named/db_glue.${O} ../named/ns_glue.${O} ../named/tmp_version.${O} + +PROG= named-xfer +SRCS= ${PROG}.c +OBJS= ${PROG}.${O} + +all: ${PROG}${EXE} + +${PROG}${EXE}: ${OBJS} ${NAMED_OBJS} ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} ${BOUNDS} -o ${PROG}${EXE} ${OBJS} ${NAMED_OBJS} \ + ${LIBBIND} ${SYSLIBS} +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c + +distclean: clean + +clean: FRC + rm -f ${PROG}${EXE} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + +depend: ${SRCS} + mkdep ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${SRCS} + +${DESTDIR}${DESTEXEC}: + mkdir -p ${DESTDIR}${DESTEXEC} + +install: ${DESTDIR}${DESTEXEC} ${PROG}${EXE} + ${INSTALL} ${STRIP} -c ${INSTALL_EXEC} -m 755 ${PROG}${EXE} ${DESTDIR}${DESTEXEC}/${PROG}${EXE} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +tags: FRC + ctags ${SRCS} *.h + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named-xfer/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/dnsquery/dnsquery.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/dnsquery/dnsquery.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/dnsquery/dnsquery.c (revision 109985) @@ -0,0 +1,232 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: dnsquery.c,v 8.19 2002/04/12 03:03:48 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +#include + +extern int errno; +extern int h_errno; +extern char *h_errlist[]; + +struct __res_state res; + +static int +newserver(char *srv, union res_sockaddr_union *u, int ns, int max) { + struct addrinfo *answer = NULL; + struct addrinfo *cur = NULL; + struct addrinfo hint; + short port = htons(NAMESERVER_PORT); + + memset(&hint, 0, sizeof(hint)); + hint.ai_socktype = SOCK_DGRAM; + if (!getaddrinfo(srv, NULL, &hint, &answer)) { + for (cur = answer; cur != NULL; cur = cur->ai_next) { + if (ns >= max) + break; + switch (cur->ai_addr->sa_family) { + case AF_INET6: + u[ns].sin6 = + *(struct sockaddr_in6*)cur->ai_addr; + u[ns++].sin6.sin6_port = port; + break; + case AF_INET: + u[ns].sin = *(struct sockaddr_in*)cur->ai_addr; + u[ns++].sin6.sin6_port = port; + break; + } + } + freeaddrinfo(answer); + } else { + fprintf(stderr, "Bad nameserver (%s)\n", srv); + exit(1); + } + return (ns); +} + +int +main(int argc, char *argv[]) { + char name[MAXDNAME]; + u_char answer[8*1024]; + int c, n; + int nameservers = 0, class, type, len; + union res_sockaddr_union q_nsaddr[MAXNS]; + extern int optind, opterr; + extern char *optarg; + int stream = 0, debug = 0; + + /* set defaults */ + len = MAXDNAME; + gethostname(name, len); + class = C_IN; + type = T_ANY; + + /* if no args, exit */ + if (argc == 1) { + fprintf(stderr, "Usage: %s [-h] host [-n ns] [-t type] [-c class] [-r retry] [-p period] [-s] [-v] [-d] [-a]\n", argv[0]); + exit(1); + } + + /* handle args */ + while ((c = getopt(argc, argv, "c:dh:n:p:r:st:u:v")) != -1) { + switch (c) { + + case 'r' : res.retry = atoi(optarg); + break; + + case 'p' : res.retrans = atoi(optarg); + break; + + case 'h' : if (strlen(optarg) >= sizeof(name)) { + fprintf(stderr, + "Domain name too long (%s)\n", optarg); + exit(1); + } else + strcpy(name, optarg); + break; + + case 'c' : { + int success, proto_class; + + proto_class = sym_ston(__p_class_syms, + optarg, &success); + if (success) + class = proto_class; + else { + fprintf(stderr, "Bad class (%s)\n", optarg); + exit(1); + } + } + break; + + case 't' : { + int success, proto_type; + + proto_type = sym_ston(__p_type_syms, + optarg, &success); + if (success) + type = proto_type; + else { + fprintf(stderr, "Bad type (%s)\n", optarg); + exit(1); + } + } + break; + + case 'd' : debug++; + break; + + case 's' : + case 'v' : stream++; + break; + + case 'n' : + /* + * If we set some nameservers here without + * using gethostbyname() first, then they will + * get overwritten when we do the first query. + * So, we must init the resolver before any + * of this. + */ + if (!(res.options & RES_INIT)) + if (res_ninit(&res) == -1) { + fprintf(stderr, + "res_ninit() failed\n" + ); + exit(1); + } + nameservers = newserver(optarg, q_nsaddr, + nameservers, MAXNS); + break; + + default : fprintf(stderr, + "\tUsage: %s [-n ns] [-h host] [-t type] [-c class] [-r retry] [-p period] [-s] [-v] [-d] [-a]\n", argv[0]); + exit(1); + } + } + if (optind < argc) { + if (strlen(argv[optind]) >= sizeof(name)) { + fprintf(stderr, + "Domain name too long (%s)\n", argv[optind]); + exit(1); + } else { + strcpy(name, argv[optind]); + } + } + + len = sizeof(answer); + + if (!(res.options & RES_INIT)) + if (res_ninit(&res) == -1) { + fprintf(stderr, "res_ninit() failed\n"); + exit(1); + } + + /* + * set these here so they aren't set for a possible call to + * gethostbyname above + */ + if (debug) + res.options |= RES_DEBUG; + if (stream) + res.options |= RES_USEVC; + + /* if the -n flag was used, add them to the resolver's list */ + if (nameservers != 0) + res_setservers(&res, q_nsaddr, nameservers); + + /* + * if the -h arg is fully-qualified, use res_query() since + * using res_search() will lead to use of res_querydomain() + * which will strip the trailing dot + */ + if (name[strlen(name) - 1] == '.') { + n = res_nquery(&res, name, class, type, answer, len); + if (n < 0) { + fprintf(stderr, "Query failed (h_errno = %d) : %s\n", + h_errno, h_errlist[h_errno]); + exit(1); + } + } else if ((n = res_nsearch(&res, name, class, type, + answer, len)) < 0) { + fprintf(stderr, "Query failed (h_errno = %d) : %s\n", + h_errno, h_errlist[h_errno]); + exit(1); + } + res_pquery(&res, answer, n, stdout); + exit(0); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/dnsquery/dnsquery.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/dnsquery/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/dnsquery/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/dnsquery/Makefile (revision 109985) @@ -0,0 +1,85 @@ +## Copyright (c) 1996,1999 by Internet Software Consortium +## +## 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. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM 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 +## SOFTWARE. + +# $Id: Makefile,v 8.26 2000/12/23 08:02:51 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g -Wall + +#(net2 and its descendents) +SYSTYPE = freebsd +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +EXE= +LEX = lex -I +SYSLIBS = -ll -lutil +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +STRIP=-s +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin + +LDFLAGS= +CFLAGS= ${CDEBUG} +CPPFLAGS= -I${PORTINCL} -I${INCL} + +PROG= dnsquery +SRCS= ${PROG}.c +OBJS= ${PROG}.${O} + +all: ${PROG}${EXE} + +${PROG}${EXE}: ${OBJS} ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} ${BOUNDS} -o ${PROG}${EXE} ${OBJS} \ + ${LIBBIND} ${SYSLIBS} + +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c + +distclean: clean + +clean: FRC + rm -f ${PROG}${EXE} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + +depend: ${SRCS} + mkdep ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${SRCS} + +${DESTDIR}${DESTBIN}: + mkdir -p ${DESTDIR}${DESTBIN} + +install: ${DESTDIR}${DESTBIN} ${PROG}${EXE} + ${INSTALL} ${STRIP} -c ${INSTALL_EXEC} -m 755 ${PROG}${EXE} ${DESTDIR}${DESTBIN}/${PROG}${EXE} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +tags: FRC + ctags *.[ch] + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Property changes on: vendor/bind/8.3.4/contrib/bind/bin/dnsquery/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/Makefile (revision 109985) @@ -0,0 +1,94 @@ +## Copyright (c) 1996,1999 by Internet Software Consortium +## +## 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. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM 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 +## SOFTWARE. + +# $Id: Makefile,v 8.31 2001/08/14 05:57:57 marka Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g -Wall + +#(net2 and its descendents) +SYSTYPE = freebsd +TOP = .. +O=o +A=a +INCL = ${TOP}/include +LIBBIND = ${TOP}/lib/libbind.${A} +LIBPORT = ${TOP}/port/libport.${A} +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LEX = lex -I +YACC = yacc +SYSLIBS = -ll -lutil +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +AR= ar cru +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin + +LDFLAGS= + +MARGS = "SYSTYPE=${SYSTYPE}" "SHELL=${SHELL}" "A=${A}" "O=${O}" \ + "CC=${CC}" "LEX=${LEX}" "YACC=${YACC}" "CDEBUG=${CDEBUG}" \ + "SYSLIBS=${SYSLIBS}" "LDFLAGS=${LDFLAGS}" \ + "DESTDIR=${DESTDIR}" "DESTMAN=${DESTMAN}" \ + "DESTBIN=${DESTBIN}" "DESTSBIN=${DESTSBIN}" "DESTEXEC=${DESTEXEC}" \ + "DESTLIB=${DESTLIB}" "DESTINC=${DESTINC}" "DESTETC=${DESTETC}" \ + "DESTRUN=${DESTRUN}" "DESTHELP=${DESTHELP}" \ + "RANLIB=${RANLIB}" "AR=${AR}" "ARPREF=${ARPREF}" "ARSUFF=${ARSUFF}" \ + "INCL=../${INCL}" "PORTINCL=../${PORTINCL}" "EXE=${EXE}" \ + "LIBBIND=../${LIBBIND}" "LIBPORT=../${LIBPORT}" \ + "INSTALL=${INSTALL}" "TOP=../${TOP}" \ + "VER=${VER}" "STRIP=${STRIP}" "PS=${PS}" "INSTALL_LIB=${INSTALL_LIB}" \ + "INSTALL_EXEC=${INSTALL_EXEC}" "BOUNDS=${BOUNDS}" + +CFLAGS= ${CDEBUG} +CPPFLAGS= -I${PORTINCL} -I${INCL} + +SUBDIRS = addr nslookup dig dnsquery host named named-xfer ndc nsupdate \ + mkservdb irpd dnskeygen named-bootconf + +all: + @for x in ${SUBDIRS}; do \ + (cd $$x; pwd; ${MAKE} ${MARGS} $@) || exit 1; \ + done + +install depend tags clean distclean:: + @for x in ${SUBDIRS}; do \ + (cd $$x; pwd; ${MAKE} ${MARGS} $@) || exit 1; \ + done + +distclean:: clean + +clean:: + rm -f *.BAK *.CKP *~ *.orig + +links: FRC + @set -e; \ + for x in $(SUBDIRS); do \ + ( mkdir $$x; cd $$x; pwd; ln -s ../SRC/$$x SRC; \ + cp SRC/Makefile Makefile; chmod +w Makefile; \ + $(MAKE) $(MARGS) links; \ + ) || exit 1; \ + done + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Property changes on: vendor/bind/8.3.4/contrib/bind/bin/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/dnskeygen/dnskeygen.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/dnskeygen/dnskeygen.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/dnskeygen/dnskeygen.c (revision 109985) @@ -0,0 +1,321 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: dnskeygen.c,v 1.14 2001/09/25 04:50:14 marka Exp $"; +#endif /* not lint */ + +/* + * Portions Copyright (c) 1995-1999 by TISLabs at Network Associates, Inc. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND NETWORK ASSOCIATES + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS 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 THE SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include "arpa/nameser.h" + +#include + +#include "port_after.h" + +#define PRINT_SUPPORTED 2 +#ifndef PATH_SEP +#define PATH_SEP '/' +#endif + +static void usage(const char *str, int full); + +static short dsa_sizes[] = {512, 576, 640, 704, 768, 832, 896, 960, 1024, 0}; +static char *prog; + +int +main(int argc, char **argv) { + DST_KEY *pubkey; + char *name=NULL; + int ch; + char str[128]; + int alg = 0; + int zone_key = 0, user_key = 0, end_key = 0, key_type = 0; + int size = -1, exp = 0; + int no_auth = 0, no_conf = 0; + int sign_val = 0, flags = 0, protocol = -1; + int i, err = 0; + extern char *optarg; + + dst_init(); + if ((prog = strrchr(argv[0], PATH_SEP)) == NULL) + prog = strdup(argv[0]); + else + prog = strdup(++prog); + +/* process input arguments */ + while ((ch = getopt(argc, argv, "achiuzn:s:p:D:H:R:F"))!= -1) { + switch (ch) { + case 'a': + no_auth = NS_KEY_NO_AUTH; + break; + case 'c': + no_conf = NS_KEY_NO_CONF; + break; + case 'F': + exp=1; + break; + case 'n': + if (optarg) + name = strdup(optarg); + else + usage("-n not followed by name", 0); + i = strlen(name); + if (name[i-1] != '.') { + printf("** Adding dot to the name to make it" + " fully qualified domain name**\n"); + free(name); + name = malloc(i+2); + strcpy(name, optarg); + strcat(name, "."); + } + break; + case 'p': + if (optarg && isdigit(optarg[0])) + protocol = atoi(optarg); + else + usage("-p flag not followed by a number", 0); + break; + case 's': + /* Default: not signatory key */ + if (optarg && isdigit(optarg[0])) + sign_val = (int) atoi(optarg); + else + usage("-s flag requires a value",0); + break; + case 'h': + end_key = NS_KEY_NAME_ENTITY; + key_type++; + break; + case 'u' : + user_key = NS_KEY_NAME_USER; + key_type++; + break ; + case 'z': + zone_key = NS_KEY_NAME_ZONE; + key_type++; + break; + case 'H': + if (optarg && isdigit(optarg[0])) + size = (int) atoi(optarg); + else + usage("-H flag requires a size",0); + if (alg != 0) + usage("Only ONE alg can be specified", 1); + alg = KEY_HMAC_MD5; + if (!dst_check_algorithm(alg)) + usage("Algorithm HMAC-MD5 not available", + PRINT_SUPPORTED); + break; + case 'R': + if (optarg && isdigit(optarg[0])) + size = (int) atoi(optarg); + else + usage("-R flag requires a size",0); + if (alg != 0) + usage("Only ONE alg can be specified", 1); + alg = NS_ALG_MD5RSA; + if (!dst_check_algorithm(alg)) + usage("Algorithm RSA not available", + PRINT_SUPPORTED); + break; + case 'D': + if (optarg && isdigit(optarg[0])) + size = (int) atoi(optarg); + else + usage("-D flag requires a size", 0); + if (alg != 0) + usage("Only ONE alg can be specified", 1); + alg = NS_ALG_DSS; + if (dst_check_algorithm(alg) == 0) + usage("Algorithm DSS not available", + PRINT_SUPPORTED); + break; + default: + err++; + } /* switch */ + } /* while (getopt) */ + + /* + * Command line parsed make sure required parameters are present + */ + if (name == NULL) + usage("No key name specified -n ", 1); + + if (alg == 0) + usage("No algorithm specififed -{DHR}", 1); + + if (key_type == 0) + usage("Key type -{zhu} must be specified", 1); + else if (key_type > 1) + usage("Only one key type -{zhu} must be specified", 1); + + if (alg == NS_ALG_DSS) + no_conf = NS_KEY_NO_CONF; /* dss keys can not encrypt */ + + if (protocol == -1) { + if (zone_key || end_key) + protocol = NS_KEY_PROT_DNSSEC; + else + protocol = NS_KEY_PROT_EMAIL; + } + if (protocol < 0 || protocol > 255) + usage("Protocol value out of range [0..255]", 0); + + if (sign_val < 0 || sign_val > 15) { + sprintf(str, "%s: Signatory value %d out of range[0..15]\n", + prog, sign_val); + usage(str, 0); + } + /* if any of bits 321 is set bit 0 can not be set*/ + if (sign_val & 0xe) + sign_val &= 0xe; + + /* if a zone key make sure at least one of the signer flags is set */ + if ((protocol == NS_KEY_PROT_DNSSEC) && (sign_val == 0)) + sign_val = 0x01; + + if (no_auth && no_conf) { /* null key specified */ + if (sign_val > 0) + sign_val = 0x0; /* null key can not sign */ + if (size > 0) + size = 0; /* null key must have size 0 */ + } + + if (size > 0) { + if (alg == NS_ALG_MD5RSA){ + if (size < 512 || size > 4096) + usage("Size out of range", 1); + } + else if (exp) + usage("-F can only be specified with -R", 0); + if (alg == NS_ALG_DSS) { + for (i = 0; dsa_sizes[i]; i++) + if (size <= dsa_sizes[i]) + break; + if (size != dsa_sizes[i]) + usage("Invalid DSS key size", 1); + } + } + else if (size < 0) + usage("No size specified", 0); + else /* size == 0 */ + sign_val = 0; + + if (err) + usage("errors encountered/unknown flag", 1); + + flags = no_conf | no_auth | end_key | user_key | zone_key | sign_val; + +/* process defaults */ +#ifdef WARN_NONZONE_SIGNER + if (signer && (user_key | end_key)) + printf("Warning: User/End key is allowed to sign\n"); +#endif + + /* create a public/private key pair */ + if (alg == NS_ALG_MD5RSA) + printf("Generating %d bit RSA Key for %s\n\n",size, name); + else if (alg == NS_ALG_DSS) + printf("Generating %d bit DSS Key for %s\n\n",size, name); + else if (alg == KEY_HMAC_MD5) + printf("Generating %d bit HMAC-MD5 Key for %s\n\n", + size, name); + + /* Make the key + * dst_generate_key_pair will place result in files that it + * knows about K.public and K.private + */ + pubkey = dst_generate_key(name, size, exp, flags, protocol, alg); + + if (pubkey == NULL) { + printf("Failed generating key for %s\n", name); + exit(12); + } + + if (dst_write_key(pubkey, DST_PRIVATE) < 0) { + printf ("Failed to write private key for %s %d %d\n", + name, pubkey->dk_id, pubkey->dk_alg); + exit(12); + } + + if (dst_write_key(pubkey, DST_PUBLIC) <= 0) { + if (access(name, F_OK)) + printf("Not allowed to overwrite existing file\n"); + else + printf("Failed to write public key for %s %d %d\n", + name, pubkey->dk_id, pubkey->dk_alg); + exit(12); + } + + printf("Generated %d bit Key for %s id=%d alg=%d flags=%d\n\n", + size, name, pubkey->dk_id, pubkey->dk_alg, + pubkey->dk_flags); + exit(0); +} + +static void +usage(const char *str, int flag) { + int i; + + printf("\nNo key generated\n"); + if (*str != '\0') + printf("Usage:%s: %s\n",prog, str); + printf("Usage:%s -{DHR} [-F] -{zhu} [-ac] [-p ]" + " [-s ] -n name\n", prog); + if (flag == 0) + exit(2); + printf("\t-D generate DSA/DSS KEY: size must be one of following:\n"); + printf("\t\t"); + for(i = 0; dsa_sizes[i] > 0; i++) + printf(" %d,", dsa_sizes[i]); + printf("\n"); + printf("\t-H generate HMAC-MD5 KEY: size in the range [1..512]:\n"); + printf("\t-R generate RSA KEY: size in the range [512..4096]\n"); + printf("\t-F RSA KEYS only: use large exponent\n"); + + printf("\t-z Zone key \n"); + printf("\t-h Host/Entity key \n"); + printf("\t-u User key \n"); + + printf("\t-a Key CANNOT be used for authentication\n"); + printf("\t-c Key CANNOT be used for encryption\n"); + + printf("\t-p Set protocol field to \n"); + printf("\t\t default: 2 (email) for Host keys, 3 (dnssec) for all others\n"); + printf("\t-s Strength value this key signs DNS records with\n"); + printf("\t\t default: 1 for Zone keys, 0 for all others\n"); + printf("\t-n name: the owner of the key\n"); + + if (flag == PRINT_SUPPORTED) { + printf("Available algorithms are:"); + if (dst_check_algorithm(NS_ALG_MD5RSA) == 1) + printf(" RSA"); + if (dst_check_algorithm(NS_ALG_DSS) == 1) + printf(" DSS"); + if (dst_check_algorithm(KEY_HMAC_MD5) == 1) + printf(" HMAC-MD5"); + printf("\n"); + } + + exit (3); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/dnskeygen/dnskeygen.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/dnskeygen/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/dnskeygen/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/dnskeygen/Makefile (revision 109985) @@ -0,0 +1,86 @@ +## Copyright (c) 1996,1999 by Internet Software Consortium +## +## 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. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM 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 +## SOFTWARE. + +# $Id: Makefile,v 1.7 2000/12/23 08:02:50 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g -Wall + +#(net2 and its descendents) +SYSTYPE = freebsd +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +LEX = lex -I +SYSLIBS = -ll -lutil +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +AR= ar cru +INSTALL= install +STRIP=-s +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin + +PS=ps +LDFLAGS= +CFLAGS= ${CDEBUG} +CPPFLAGS= -I${PORTINCL} -I${INCL} + +PROG= dnskeygen +SRCS= dnskeygen.c +OBJS= dnskeygen.${O} + +all: ${PROG}${EXE} + +${PROG}${EXE}: ${OBJS} ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} ${BOUNDS} -o ${PROG}${EXE} ${OBJS} \ + ${LIBBIND} ${SYSLIBS} +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c + +distclean: clean + +clean: FRC + rm -f ${PROG}${EXE} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + +depend: ${SRCS} + mkdep ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${SRCS} + +${DESTDIR}${DESTEXEC}: + mkdir -p ${DESTDIR}${DESTEXEC} + +install: ${DESTDIR}${DESTEXEC} ${PROG}${EXE} + ${INSTALL} ${STRIP} -c ${INSTALL_EXEC} -m 755 ${PROG}${EXE} ${DESTDIR}${DESTEXEC}/${PROG}${EXE} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +tags: FRC + ctags ${SRCS} *.h + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Property changes on: vendor/bind/8.3.4/contrib/bind/bin/dnskeygen/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/irpd/irpd.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/irpd/irpd.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/irpd/irpd.c (revision 109985) @@ -0,0 +1,2356 @@ +/* + * Copyright(c) 1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* Notes. */ + +#if 0 + +I have to use an AF_INET. Ctl_server should probably take a AF arugment. + +The server has no way to issue any other greeting than HELLO. E.g., would +like to be able to drop connection on greeting if client is not comming +from 127.0.0.1. + +Need to fix client to handle response with body. + +should add iovec with body to the struct ctl_sess? + +should we close connections on some errors (like marshalling errors)? + +getnetbyname falls back to /etc/networks when named not running. Does not +seem to be so for getnetbyaddr + +#endif + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irpd.c,v 1.13 2001/09/25 04:50:17 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef EMPTY +/* Digital UNIX utmp.h defines this. */ +#undef EMPTY +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +/* Macros. */ + +#define ALLDIGITS(s) (strspn((s), "0123456789") == strlen((s))) + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif + +#define MAXNETNAMELEN 256 + +#if !defined(SUN_LEN) +#define SUN_LEN(su) \ + (sizeof (*(su)) - sizeof ((su)->sun_path) + strlen((su)->sun_path)) +#endif + +/* + * This macro is used to initialize a specified field of a net_data struct. + * If the initialization fails then an error response code is sent with a + * description of which field failed to be initialized. + * + * This is only meant for use at the start of the various verb functions. + */ + +#define ND_INIT(nd, field, sess, respcode) \ + do{ if ((nd)->field == 0) { \ + (nd)->field = (*(nd)->irs->field ## _map)(nd->irs); \ + if ((nd)->field == 0) { \ + const char *msg = "net_data " #field " initialization failed"; \ + ctl_response(sess, respcode, msg, CTL_EXIT, NULL, \ + NULL, NULL, NULL, 0); \ + return; \ + } \ + } \ + } while (0) + +/* Data structures. */ + +struct arg_s { + struct iovec * iov; + int iovlen; +}; + +struct response_buff { + char * buff; + size_t bufflen; +}; + +struct client_ctx { + struct net_data * net_data; +}; + +/* Forwards. */ + +static struct response_buff *newbuffer(u_int length); +static void release_buffer(struct response_buff *b); +static struct arg_s *split_string(const char *string); +static void free_args(struct arg_s *args); +static struct client_ctx *make_cli_ctx(void); +static struct net_data *get_net_data(struct ctl_sess *sess); + +static void irpd_gethostbyname(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, + void *uctx); +static void irpd_gethostbyname2(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, + void *uctx); + +static void irpd_gethostbyaddr(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, + void *uctx); +static void irpd_gethostent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_sethostent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_getpwnam(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_getpwuid(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_getpwent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_setpwent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_getnetbyname(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_getnetbyaddr(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_getnetent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_setnetent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_getgrnam(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_getgrgid(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_getgrent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_setgrent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_getservbyname(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, + void *uctx); +static void irpd_getservbyport(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, + void *uctx); +static void irpd_getservent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_setservent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_getprotobyname(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, + void *uctx); +static void irpd_getprotobynumber(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, + void *uctx); +static void irpd_getprotoent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_setprotoent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_getnetgrent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_innetgr(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_setnetgrent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_endnetgrent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_quit(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_help(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_accept(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); +static void irpd_abort(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx); + +static void response_done(struct ctl_sctx *ctx, struct ctl_sess *sess, + void *uap); +static void logger(enum ctl_severity, const char *fmt, ...); + +/* Constants. */ + +static const u_int hello_code = IRPD_WELCOME_CODE; +static const char hello_msg[] = "Welcome to IRPD (v 1)"; +static const u_int unkncode = 500; +static const u_int timeoutcode = 501; +static const u_int irpd_quit_ok = 201; +static const u_int timeout = IRPD_TIMEOUT; + +/* Globals. */ + +static int main_needs_exit = 0; +static evContext ev; + +struct ctl_verb verbs [] = { + { "gethostbyname", irpd_gethostbyname, NULL }, + { "gethostbyname2", irpd_gethostbyname2, NULL }, + { "gethostbyaddr", irpd_gethostbyaddr, NULL }, + { "gethostent", irpd_gethostent, NULL }, + { "sethostent", irpd_sethostent, NULL }, +#ifdef WANT_IRS_PW + { "getpwnam", irpd_getpwnam, NULL }, + { "getpwuid", irpd_getpwuid, NULL }, + { "getpwent", irpd_getpwent, NULL }, + { "setpwent", irpd_setpwent, NULL }, +#endif + { "getnetbyname", irpd_getnetbyname, NULL }, + { "getnetbyaddr", irpd_getnetbyaddr, NULL }, + { "getnetent", irpd_getnetent, NULL }, + { "setnetent", irpd_setnetent, NULL }, +#ifdef WANT_IRS_GR + { "getgrnam", irpd_getgrnam, NULL }, + { "getgrgid", irpd_getgrgid, NULL }, + { "getgrent", irpd_getgrent, NULL }, + { "setgrent", irpd_setgrent, NULL }, +#endif + { "getservbyname", irpd_getservbyname, NULL }, + { "getservbyport", irpd_getservbyport, NULL }, + { "getservent", irpd_getservent, NULL }, + { "setservent", irpd_setservent, NULL }, + + { "getprotobyname", irpd_getprotobyname, NULL }, + { "getprotobynumber", irpd_getprotobynumber, NULL }, + { "getprotoent", irpd_getprotoent, NULL }, + { "setprotoent", irpd_setprotoent, NULL }, + + { "getnetgrent", irpd_getnetgrent, NULL }, + { "innetgr", irpd_innetgr, NULL }, + { "setnetgrent", irpd_setnetgrent, NULL }, + { "endnetgrent", irpd_endnetgrent, NULL }, + { "quit", irpd_quit, NULL }, + { "help", irpd_help, NULL }, + + { "", irpd_accept, NULL }, /* For connection setups. */ + + /* abort is a verb expected by the ctl library. Is called when the + * client drops the connection unexpectedly. + */ + { "abort", irpd_abort, NULL }, + + { NULL, NULL, NULL } +}; + +/* + * An empty string causes the library to use the compiled in + * defaults and to ignore any external files. + */ +const char *conffile = ""; + +/* Public. */ + +int +main(int argc, char **argv) { + struct ctl_sctx *ctx; + struct sockaddr *addr; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un uaddr; +#endif + struct sockaddr_in iaddr; + short port = IRPD_PORT; + char *prog = argv[0]; + const char *sockname = IRPD_PATH; + char *p; + int ch; + size_t socksize; + + addr = (struct sockaddr *)&iaddr; + socksize = sizeof iaddr; + + openlog("iprd", LOG_CONS|LOG_PID, ISC_FACILITY); + while ((ch = getopt(argc, argv, "u:p:c:")) != -1) { + switch(ch) { + case 'c': + conffile = optarg; + break; + + case 'p': + port = strtol(optarg, &p, 10); + if (*p != '\0') { + /* junk in argument */ + syslog(LOG_ERR, "port option not a number"); + exit(1); + } + break; + +#ifndef NO_SOCKADDR_UN + case 'u': + sockname = optarg; + addr = (struct sockaddr *)&uaddr; + socksize = sizeof uaddr; + break; +#endif + + case 'h': + case '?': + default: + fprintf(stderr, "%s [ -c config-file ]\n", prog); + exit(1); + } + } + argc -= optind; + argv += optind; + + memset(&iaddr, 0, sizeof iaddr); + +#ifdef HAVE_SA_LEN + iaddr.sin_len = sizeof iaddr; +#endif + iaddr.sin_family = AF_INET; + iaddr.sin_port = htons(IRPD_PORT); + iaddr.sin_addr.s_addr = htonl(INADDR_ANY); + +#ifndef NO_SOCKADDR_UN + memset(&uaddr, 0, sizeof uaddr); + if (addr == (struct sockaddr *)&uaddr) { + uaddr.sun_family = AF_UNIX; + strncpy(uaddr.sun_path, sockname, sizeof uaddr.sun_path); +#ifdef HAVE_SA_LEN + uaddr.sun_len = SUN_LEN(&uaddr); +#endif + + socksize = SUN_LEN(&uaddr); + + /* XXX what if this file is not currently a socket? */ + unlink(sockname); + } +#endif + + evCreate(&ev); + + ctx = ctl_server(ev, addr, socksize, verbs, + unkncode, timeoutcode, /* IRPD_TIMEOUT */ 30, 5, + IRPD_MAXSESS, logger, NULL); + + INSIST(ctx != NULL); + + while (!main_needs_exit) { + evEvent event; + + INSIST_ERR(evGetNext(ev, &event, EV_WAIT) != -1); + INSIST_ERR(evDispatch(ev, event) != -1); + } + + return (0); +} + + +/* + * static void + * simple_response(struct ctl_sess *sess, u_int code, const char *msg); + * Send back a simple, one-line response to the client. + */ +static void +simple_response(struct ctl_sess *sess, u_int code, const char *msg) { + struct response_buff *b = newbuffer(strlen(msg) + 1); + + if (b == 0) + return; + strcpy(b->buff, msg); + ctl_response(sess, code, b->buff, 0, 0, response_done, b, NULL, 0); +} + +/* + * static void + * send_hostent(struct ctl_sess *sess, struct hostent *ho); + * Send a hostent struct over the wire. If HO is NULL, then + * a "No such host" is sent instead. + */ +static void +send_hostent(struct ctl_sess *sess, struct hostent *ho) { + if (ho == NULL) + simple_response(sess, IRPD_GETHOST_NONE, "No such host"); + else { + struct response_buff *b = newbuffer(0); + + if (irp_marshall_ho(ho, &b->buff, &b->bufflen) != 0) { + simple_response(sess, IRPD_GETHOST_ERROR, + "Internal error"); + logger(ctl_warning, + "Cannot marshall host data for %s\n", + ho->h_name); + release_buffer(b); + } else { + strcat(b->buff, "\r\n"); + + ctl_response(sess, IRPD_GETHOST_OK, "Host found", + 0, 0, response_done, + b, b->buff, strlen(b->buff)); + } + } +} + +/* + * static void + * do_gethostbyname2(struct ctl_sess *sess, struct net_data *nd, + * const char *hostname, int af); + * Look up the given HOSTNAME by Address-Family + * and then send the results to the client connected to + * SESS. + */ +static void +do_gethostbyname2(struct ctl_sess *sess, struct net_data *nd, + const char *hostname, int af) +{ + struct hostent *ho; + + ho = gethostbyname2_p(hostname, af, nd); + send_hostent(sess, ho); +} + +/* + * static void + * irpd_gethostbyname(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Implementation of the GETHOSTBYNAME verb. + */ +static void +irpd_gethostbyname(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + char hname[MAXHOSTNAMELEN]; + struct arg_s *args; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, ho, sess, IRPD_GETHOST_ERROR); + + args = split_string(rest); + if (args->iovlen != 2) { /* len includes NULL at end */ + simple_response(sess, IRPD_GETHOST_ERROR, + "Incorrect usage: GETHOSTBYNAME hostname"); + } else { + if (args->iov[0].iov_len >= sizeof hname) { + simple_response(sess, IRPD_GETHOST_ERROR, + "GETHOSTBYNAME: name too long"); + } else { + strncpy(hname, args->iov[0].iov_base, + args->iov[0].iov_len); + hname[args->iov[0].iov_len] = '\0'; + do_gethostbyname2(sess, netdata, hname, AF_INET); + } + } + free_args(args); +} + +/* + * static void + * irpd_gethostbyname2(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Implementation of the GETHOSTBYNAME2 verb. + */ +static void +irpd_gethostbyname2(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + char hname[MAXHOSTNAMELEN]; + struct arg_s *args; + int af; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, ho, sess, IRPD_GETHOST_ERROR); + + args = split_string(rest); + if (args->iovlen != 3) { /* len includes NULL at end */ + simple_response(sess, IRPD_GETHOST_ERROR, + "Incorrect usage: GETHOSTBYNAME2 hostname AF"); + } else if (args->iov[0].iov_len >= sizeof hname) { + simple_response(sess, IRPD_GETHOST_ERROR, + "GETHOSTBYNAME2: name too long"); + } else { + if (strncasecmp(args->iov[1].iov_base, "af_inet6", 8) == 0) + af = AF_INET6; + else if (strncasecmp(args->iov[1].iov_base, "af_inet", 7) == 0) + af = AF_INET; + else { + simple_response(sess, IRPD_GETHOST_ERROR, + "Unknown address family"); + goto untimely; + } + + strncpy(hname, args->iov[0].iov_base, + args->iov[0].iov_len); + hname[args->iov[0].iov_len] = '\0'; + do_gethostbyname2(sess, netdata, hname, af); + } + + untimely: + free_args(args); +} + +/* + * static void + * irpd_gethostbyaddr(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Implementation of the GETHOSTBYADDR verb. + */ +static void +irpd_gethostbyaddr(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct hostent *ho; + char haddr[MAXHOSTNAMELEN]; + char tmpaddr[NS_IN6ADDRSZ]; + struct arg_s *args; + int af; + int addrlen; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, ho, sess, IRPD_GETHOST_ERROR); + + args = split_string(rest); + if (args->iovlen != 3) { + simple_response(sess, IRPD_GETHOST_ERROR, + "GETHOSTBYADDR addr afamily"); + } else { + if (args->iov[0].iov_len >= sizeof haddr) { + simple_response(sess, IRPD_GETHOST_ERROR, + "Address too long"); + } else { + strncpy(haddr, args->iov[1].iov_base, + args->iov[1].iov_len); + haddr[args->iov[1].iov_len] = '\0'; + if (strcasecmp(haddr, "af_inet") == 0) { + af = AF_INET; + addrlen = NS_INADDRSZ; + } else if (strcasecmp(haddr, "af_inet6") == 0) { + af = AF_INET6; + addrlen = NS_IN6ADDRSZ; + } else { + simple_response(sess, IRPD_GETHOST_ERROR, + "Unknown address family"); + goto untimely; + } + + strncpy(haddr, args->iov[0].iov_base, + args->iov[0].iov_len); + haddr[args->iov[0].iov_len] = '\0'; + + if (inet_pton(af, haddr, tmpaddr) != 1) { + simple_response(sess, IRPD_GETHOST_ERROR, + "Invalid address"); + goto untimely; + } + + ho = gethostbyaddr_p(tmpaddr, addrlen, af, netdata); + send_hostent(sess, ho); + } + } + + untimely: + free_args(args); +} + + +/* + * static void + * irpd_gethostent(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Implementation of the GETHOSTENT verb + */ +static void +irpd_gethostent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct hostent *ho; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, ho, sess, IRPD_GETHOST_ERROR); + + ho = gethostent_p(netdata); + + send_hostent(sess, ho); +} + +/* + * static void + * irpd_sethostent(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Implementation of the SETHOSTENT verb + */ +static void +irpd_sethostent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, ho, sess, IRPD_GETHOST_ERROR); + + sethostent_p(1, netdata); /* always stayopen */ + simple_response(sess, IRPD_GETHOST_SETOK, "ok"); +} + +#ifdef WANT_IRS_PW +/* + * static void + * send_pwent(struct ctl_sess *sess, struct passwd *pw); + * Send PW over the wire, or, if PW is NULL, a "No such + * user" response. + */ +static void +send_pwent(struct ctl_sess *sess, struct passwd *pw) { + if (pw == NULL) { + simple_response(sess, IRPD_GETUSER_NONE, + "No such user"); + } else { + struct response_buff *b = newbuffer(0); + + if (irp_marshall_pw(pw, &b->buff, + &b->bufflen) != 0) { + simple_response(sess, IRPD_GETUSER_ERROR, + "Internal error"); + logger(ctl_warning, "Cant marshall pw\n"); + return; + } + + strcat(b->buff, "\r\n"); + + ctl_response(sess, IRPD_GETUSER_OK, "User found", 0, 0, + response_done, b, b->buff, strlen(b->buff)); + } +} + +/* + * static void + * irpd_getpwnam(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Implementation of the GETPWNAM verb + */ +static void +irpd_getpwnam(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct arg_s *args; + struct passwd *pw; + char username[64]; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, pw, sess, IRPD_GETUSER_ERROR); + + args = split_string(rest); + if (args->iovlen != 2) { /* len includes NULL at end */ + simple_response(sess, IRPD_GETUSER_ERROR, + "GETPWNAM username"); + } else { + if (args->iov[0].iov_len >= sizeof username) { + simple_response(sess, IRPD_GETUSER_ERROR, + "Name too long"); + } else { + strncpy(username, args->iov[0].iov_base, + args->iov[0].iov_len); + username[args->iov[0].iov_len] = '\0'; + + pw = getpwnam_p(username, netdata); + send_pwent(sess, pw); + } + } + + free_args(args); +} + +/* + * static void + * irpd_getpwuid(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Implementation of the GETPWUID verb. + */ +static void +irpd_getpwuid(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct arg_s *args; + struct passwd *pw; + char userid[64]; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, pw, sess, IRPD_GETUSER_ERROR); + + args = split_string(rest); + if (args->iovlen != 2) { /* len includes NULL at end */ + simple_response(sess, IRPD_GETUSER_ERROR, + "GETPWUID uid"); + } else { + if (args->iov[0].iov_len >= sizeof userid) { + simple_response(sess, IRPD_GETUSER_ERROR, + "Name too long"); + } else { + strncpy(userid, args->iov[0].iov_base, + args->iov[0].iov_len); + userid[args->iov[0].iov_len] = '\0'; + + if (!ALLDIGITS(userid)) { + simple_response(sess, IRPD_GETUSER_ERROR, + "Not a uid"); + } else { + uid_t uid; + long lval; + + lval = strtol(userid, 0, 10); + uid = (uid_t)lval; + if ((long)uid != lval) { + /* value was too big */ + simple_response(sess, + IRPD_GETUSER_ERROR, + "Not a valid uid"); + goto untimely; + } + + pw = getpwuid_p(uid, netdata); + send_pwent(sess, pw); + } + } + } + + untimely: + free_args(args); +} + +/* + * static void + * irpd_getpwent(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Implemtnation of the GETPWENT verb. + */ +static void +irpd_getpwent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct passwd *pw; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, pw, sess, IRPD_GETUSER_ERROR); + + pw = getpwent_p(netdata); + send_pwent(sess, pw); +} + +/* + * static void + * irpd_setpwent(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Implemtnation of the SETPWENT verb. + */ +static void +irpd_setpwent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, pw, sess, IRPD_GETUSER_ERROR); + + setpwent_p(netdata); + simple_response(sess, IRPD_GETUSER_SETOK, "ok"); +} +#endif /* WANT_IRS_PW */ + +/* + * static void + * send_nwent(struct ctl_sess *sess, struct nwent *ne); + * Sends a nwent structure over the wire, or "No such + * network" if NE is NULL. + */ +static void +send_nwent(struct ctl_sess *sess, struct nwent *nw) { + if (nw == NULL) { + simple_response(sess, IRPD_GETNET_NONE, "No such net"); + } else { + struct response_buff *b = newbuffer(0); + + if (irp_marshall_nw(nw, &b->buff, + &b->bufflen) != 0) { + simple_response(sess, IRPD_GETNET_ERROR, + "Internal error"); + logger(ctl_warning, "Cant marshall nw\n"); + return; + } + + strcat(b->buff, "\r\n"); + + ctl_response(sess, IRPD_GETNET_OK, "Network found", 0, 0, + response_done, b, b->buff, strlen(b->buff)); + } +} + +/* + * static void + * irpd_getnetbyname(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Implementation of GETNETBYNAME verb. + */ +static void +irpd_getnetbyname(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct arg_s *args; + struct netent *ne; + struct nwent *nw; + char netname[MAXNETNAMELEN]; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, nw, sess, IRPD_GETNET_ERROR); + + args = split_string(rest); + if (args->iovlen != 2) { /* len includes NULL at end */ + simple_response(sess, IRPD_GETNET_ERROR, + "GETNETBYNAME name"); + } else { + if (args->iov[0].iov_len >= sizeof netname) { + simple_response(sess, IRPD_GETNET_ERROR, + "Name too long"); + } else { + strncpy(netname, args->iov[0].iov_base, + args->iov[0].iov_len); + netname[args->iov[0].iov_len] = '\0'; + + ne = getnetbyname_p(netname, netdata); + + /* The public interface only gives us a struct + netent, and we need a struct nwent that irs uses + internally, so we go dig it out ourselves. Yuk + */ + nw = NULL; + if (ne != NULL) { + /* Puke. */ + INSIST(netdata->nw_last == ne); + nw = netdata->nww_last; + } + + send_nwent(sess, nw); + } + } + free_args(args); +} + +/* + * static void + * irpd_getnetbyaddr(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + */ +static void +irpd_getnetbyaddr(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct netent *ne; + struct nwent *nw; + char haddr[MAXHOSTNAMELEN]; + long tmpaddr; + struct arg_s *args; + int af; + int addrlen; + int bits; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, nw, sess, IRPD_GETUSER_ERROR); + + args = split_string(rest); + if (args->iovlen != 3) { + simple_response(sess, IRPD_GETNET_ERROR, + "GETNETBYADDR addr afamily"); + } else { + if (args->iov[0].iov_len >= sizeof haddr) { + simple_response(sess, IRPD_GETNET_ERROR, + "Address too long"); + } else { + strncpy(haddr, args->iov[1].iov_base, + args->iov[1].iov_len); + haddr[args->iov[1].iov_len] = '\0'; + if (strcasecmp(haddr, "af_inet") == 0) { + af = AF_INET; + addrlen = NS_INADDRSZ; + } else if (strcasecmp(haddr, "af_inet6") == 0) { + af = AF_INET6; + addrlen = NS_IN6ADDRSZ; + + /* XXX the interface we use(getnetbyaddr) + * can't handle AF_INET6, so for now we + * bail. + */ + simple_response(sess, IRPD_GETNET_ERROR, + "AF_INET6 unsupported"); + goto untimely; + } else { + simple_response(sess, IRPD_GETNET_ERROR, + "Unknown address family"); + goto untimely; + } + + strncpy(haddr, args->iov[0].iov_base, + args->iov[0].iov_len); + haddr[args->iov[0].iov_len] = '\0'; + + bits = inet_net_pton(af, haddr, + &tmpaddr, sizeof tmpaddr); + if (bits < 0) { + simple_response(sess, IRPD_GETNET_ERROR, + "Invalid address"); + goto untimely; + } + + ne = getnetbyaddr_p(tmpaddr, af, netdata); + + /* The public interface only gives us a struct + netent, and we need a struct nwent that irs uses + internally, so we go dig it out ourselves. Yuk + */ + nw = NULL; + if (ne != NULL) { + /* Puke puke */ + INSIST(netdata->nw_last == ne); + nw = netdata->nww_last; + } + + send_nwent(sess, nw); + } + } + + untimely: + free_args(args); +} + + +/* + * static void + * irpd_getnetent(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Implementation of the GETNETENT verb. + */ +static void +irpd_getnetent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct netent *ne; + struct nwent *nw; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, nw, sess, IRPD_GETNET_ERROR); + + ne = getnetent_p(netdata); + nw = NULL; + if (ne != NULL) { + /* triple puke */ + INSIST(netdata->nw_last == ne); + nw = netdata->nww_last; + } + send_nwent(sess, nw); +} + +/* + * static void + * irpd_setnetent(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Implementation of the SETNETENT verb. + */ +static void +irpd_setnetent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, nw, sess, IRPD_GETNET_ERROR); + + setnetent_p(1, netdata); /* always stayopen */ + simple_response(sess, IRPD_GETNET_SETOK, "ok"); +} + +#ifdef WANT_IRS_GR +/* + * static void + * send_grent(struct ctl_sess *sess, struct group *gr); + * Marshall GR and send as body of response. If GR is NULL + * then a "No such group" response is sent instead. + */ +static void +send_grent(struct ctl_sess *sess, struct group *gr) { + if (gr == NULL) { + simple_response(sess, IRPD_GETGROUP_NONE, + "No such user"); + } else { + struct response_buff *b = newbuffer(0); + + if (irp_marshall_gr(gr, &b->buff, &b->bufflen) != 0) { + simple_response(sess, IRPD_GETGROUP_ERROR, + "Internal error"); + logger(ctl_warning, "Cant marshall gr\n"); + return; + } + + strcat(b->buff, "\r\n"); + + ctl_response(sess, IRPD_GETGROUP_OK, "Group found", 0, 0, + response_done, b, b->buff, strlen(b->buff)); + } +} + +/* + * static void + * irpd_getgrnam(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Implementation of the GETGRNAM verb. + */ +static void +irpd_getgrnam(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct arg_s *args; + struct group *gr; + char groupname[64]; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, gr, sess, IRPD_GETGROUP_ERROR); + + args = split_string(rest); + if (args->iovlen != 2) { /* len includes NULL at end */ + simple_response(sess, IRPD_GETGROUP_ERROR, + "GETGRNAM groupname"); + } else { + if (args->iov[0].iov_len >= sizeof groupname) { + simple_response(sess, IRPD_GETGROUP_ERROR, + "Name too long"); + } else { + strncpy(groupname, args->iov[0].iov_base, + args->iov[0].iov_len); + groupname[args->iov[0].iov_len] = '\0'; + + gr = getgrnam_p(groupname, netdata); + send_grent(sess, gr); + } + } + + free_args(args); +} + +/* + * static void + * irpd_getgrgid(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Implentation of the GETGRGID verb. + */ +static void +irpd_getgrgid(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct arg_s *args; + struct group *gr; + char groupid[64]; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, gr, sess, IRPD_GETGROUP_ERROR); + + args = split_string(rest); + if (args->iovlen != 2) { /* len includes NULL at end */ + simple_response(sess, IRPD_GETGROUP_ERROR, + "GETGRUID gid"); + } else { + if (args->iov[0].iov_len >= sizeof groupid) { + simple_response(sess, IRPD_GETGROUP_ERROR, + "Name too long"); + } else { + strncpy(groupid, args->iov[0].iov_base, + args->iov[0].iov_len); + groupid[args->iov[0].iov_len] = '\0'; + + if (!ALLDIGITS(groupid)) { + simple_response(sess, IRPD_GETGROUP_ERROR, + "Not a gid"); + } else { + gid_t gid; + long lval; + + lval = strtol(groupid, 0, 10); + gid = (gid_t)lval; + if ((long)gid != lval) { + /* value was too big */ + simple_response(sess, + IRPD_GETGROUP_ERROR, + "Not a valid gid"); + goto untimely; + } + + gr = getgrgid_p(gid, netdata); + send_grent(sess, gr); + } + } + } + + untimely: + free_args(args); +} + +/* + * static void + * irpd_getgrent(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Implementation of the GETGRENT verb. + */ +static void +irpd_getgrent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct group *gr; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, gr, sess, IRPD_GETGROUP_ERROR); + + gr = getgrent_p(netdata); + send_grent(sess, gr); +} + +/* + * static void + * irpd_setgrent(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Implementation of the SETGRENT verb. + */ +static void +irpd_setgrent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, gr, sess, IRPD_GETGROUP_ERROR); + + setgrent_p(netdata); + simple_response(sess, IRPD_GETGROUP_SETOK, "ok"); +} +#endif /* WANT_IRS_GR */ + +static void +send_servent(struct ctl_sess *sess, struct servent *serv) { + if (serv == NULL) { + simple_response(sess, IRPD_GETSERVICE_NONE, + "No such service"); + } else { + struct response_buff *b = newbuffer(0); + + if (irp_marshall_sv(serv, &b->buff, + &b->bufflen) != 0) { + simple_response(sess, IRPD_GETSERVICE_ERROR, + "Internal error"); + logger(ctl_warning, "Cant marshall servent\n"); + return; + } + + strcat(b->buff, "\r\n"); + + ctl_response(sess, IRPD_GETSERVICE_OK, "Service found", 0, 0, + response_done, b, b->buff, strlen(b->buff)); + } +} + +static void +irpd_getservbyname(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct arg_s *args; + struct servent *serv; + char servicename[64]; + char protoname[10]; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, sv, sess, IRPD_GETSERVICE_ERROR); + + args = split_string(rest); + if (args->iovlen != 3) { /* len includes NULL at end */ + simple_response(sess, IRPD_GETSERVICE_ERROR, + "GETSERVNAM servicename protocol"); + } else { + if (args->iov[0].iov_len >= sizeof servicename) { + simple_response(sess, IRPD_GETSERVICE_ERROR, + "Invalid service name"); + } else if (args->iov[1].iov_len >= sizeof protoname) { + simple_response(sess, IRPD_GETSERVICE_ERROR, + "Invalid protocol name"); + } else { + strncpy(servicename, args->iov[0].iov_base, + args->iov[0].iov_len); + servicename[args->iov[0].iov_len] = '\0'; + + strncpy(protoname, args->iov[1].iov_base, + args->iov[1].iov_len); + protoname[args->iov[1].iov_len] = '\0'; + + serv = getservbyname_p(servicename, protoname, + netdata); + send_servent(sess, serv); + } + } + + free_args(args); +} + +/* + * static void + * irpd_getservbyport(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Handle the GETSERVBYPORT verb. + */ +static void +irpd_getservbyport(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct arg_s *args; + struct servent *sv; + char portnum[64]; + char protoname[10]; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, sv, sess, IRPD_GETSERVICE_ERROR); + + args = split_string(rest); + if (args->iovlen != 3) { /* len includes NULL at end */ + simple_response(sess, IRPD_GETSERVICE_ERROR, + "GETSERVBYPORT port protocol"); + } else { + if (args->iov[0].iov_len >= sizeof portnum) { + simple_response(sess, IRPD_GETSERVICE_ERROR, + "Invalid port"); + } else if (args->iov[1].iov_len > sizeof protoname - 1) { + simple_response(sess, IRPD_GETSERVICE_ERROR, + "Invalid protocol"); + } else { + strncpy(portnum, args->iov[0].iov_base, + args->iov[0].iov_len); + portnum[args->iov[0].iov_len] = '\0'; + + strncpy(protoname, args->iov[1].iov_base, + args->iov[1].iov_len); + protoname[args->iov[1].iov_len] = '\0'; + + if (!ALLDIGITS(portnum)) { + simple_response(sess, IRPD_GETSERVICE_ERROR, + "Not a port number"); + } else { + short port; + long lval; + + lval = strtol(portnum, 0, 10); + port = (short)lval; + if ((long)port != lval) { + /* value was too big */ + simple_response(sess, + IRPD_GETSERVICE_ERROR, + "Not a valid port"); + goto untimely; + } + port = htons(port); + + sv = getservbyport_p(port, protoname, netdata); + send_servent(sess, sv); + } + } + } + + untimely: + free_args(args); +} + +/* + * static void + * irpd_getservent(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Handle the GETSERVENT verb. + */ +static void +irpd_getservent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct servent *sv; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, sv, sess, IRPD_GETSERVICE_ERROR); + + sv = getservent_p(netdata); + send_servent(sess, sv); +} + +/* + * static void + * irpd_setservent(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Handle the SETSERVENT verb. + */ +static void +irpd_setservent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, sv, sess, IRPD_GETSERVICE_ERROR); + + setservent_p(1, netdata); /* always stay open */ + simple_response(sess, IRPD_GETSERVICE_SETOK, "ok"); +} + +/* + * static void + * send_prent(struct ctl_sess *sess, struct protoent *pr); + * Send the PR structure over the wire. If PR is NULL, then + * the response "No such protocol" is sent instead. + */ +static void +send_prent(struct ctl_sess *sess, struct protoent *pr) { + if (pr == NULL) { + simple_response(sess, IRPD_GETPROTO_NONE, + "No such protocol"); + } else { + struct response_buff *b = newbuffer(0); + + if (irp_marshall_pr(pr, &b->buff, + &b->bufflen) != 0) { + simple_response(sess, IRPD_GETPROTO_ERROR, + "Internal error"); + logger(ctl_warning, "Cant marshall pr\n"); + return; + } + + strcat(b->buff, "\r\n"); + + ctl_response(sess, IRPD_GETPROTO_OK, "Protocol found", 0, 0, + response_done, b, b->buff, strlen(b->buff)); + } +} + +/* + * static void + * irpd_getprotobyname(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Handle the GETPROTOBYNAME verb. + */ +static void +irpd_getprotobyname(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct arg_s *args; + struct protoent *pr; + char protoname[64]; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, pr, sess, IRPD_GETPROTO_ERROR); + + args = split_string(rest); + if (args->iovlen != 2) { /* len includes NULL at end */ + simple_response(sess, IRPD_GETPROTO_ERROR, + "GETPROTOBYNAME protocol"); + } else { + if (args->iov[0].iov_len >= sizeof protoname) { + simple_response(sess, IRPD_GETPROTO_ERROR, + "Name too long"); + } else { + strncpy(protoname, args->iov[0].iov_base, + args->iov[0].iov_len); + protoname[args->iov[0].iov_len] = '\0'; + + pr = getprotobyname_p(protoname, netdata); + send_prent(sess, pr); + } + } + free_args(args); +} + +/* + * static void + * irpd_getprotobynumber(struct ctl_sctx *ctx, + * struct ctl_sess *sess, const struct ctl_verb *verb, + * const char *rest, u_int respflags, const void *respctx, + * void *uctx); + * Handle the GETPROTOBYNUMBER verb. + */ +static void +irpd_getprotobynumber(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct arg_s *args; + struct protoent *pr; + char protonum[64]; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, pr, sess, IRPD_GETPROTO_ERROR); + + args = split_string(rest); + if (args->iovlen != 2) { /* len includes NULL at end */ + simple_response(sess, IRPD_GETPROTO_ERROR, + "GETPROTOBYNUMBER protocol"); + } else { + if (args->iov[0].iov_len >= sizeof protonum) { + simple_response(sess, IRPD_GETGROUP_ERROR, + "Name too long"); + } else { + strncpy(protonum, args->iov[0].iov_base, + args->iov[0].iov_len); + protonum[args->iov[0].iov_len] = '\0'; + + if (!ALLDIGITS(protonum)) { + simple_response(sess, IRPD_GETPROTO_ERROR, + "Not a protocol number"); + } else { + int proto; + long lval; + + lval = strtol(protonum, 0, 10); + proto = (int)lval; + if ((long)proto != lval) { + /* value was too big */ + simple_response(sess, + IRPD_GETPROTO_ERROR, + "Not a valid proto"); + goto untimely; + } + + pr = getprotobynumber_p(proto, netdata); + send_prent(sess, pr); + } + } + } + + untimely: + free_args(args); +} + +/* + * static void + * irpd_getprotoent(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Handle the GETPROTOENT verb. + */ +static void +irpd_getprotoent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct protoent *pr; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, pr, sess, IRPD_GETPROTO_ERROR); + + pr = getprotoent_p(netdata); + send_prent(sess, pr); +} + +/* + * static void + * irpd_setprotoent(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Handle the SETPROTOENT verb. + */ +static void +irpd_setprotoent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, pr, sess, IRPD_GETPROTO_ERROR); + + setprotoent_p(1, netdata); /* always stay open */ + simple_response(sess, IRPD_GETPROTO_SETOK, "ok"); +} + +/* + * static void + * send_pwent(struct ctl_sess *sess, struct passwd *pw); + * Send PW over the wire, or, if PW is NULL, a "No such + * user" response. + */ +static void +send_ngent(struct ctl_sess *sess, const char *host, const char *user, + const char *domain) +{ + struct response_buff *b = newbuffer(0); + + if (irp_marshall_ng(host, user, domain, &b->buff, + &b->bufflen) != 0) { + simple_response(sess, IRPD_GETNETGR_ERROR, + "Internal error"); + logger(ctl_warning, "Cant marshall ng\n"); + return; + } + + strcat(b->buff, "\r\n"); + + ctl_response(sess, IRPD_GETNETGR_OK, "Netgroup entry", 0, 0, + response_done, b, b->buff, strlen(b->buff)); +} + +/* + * static void + * irpd_getnetgrent(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Handle the GETNETGRENT verb. + */ +static void +irpd_getnetgrent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, ng, sess, IRPD_GETNETGR_ERROR); + + if (rest != NULL && strlen(rest) > 0) { + simple_response(sess, IRPD_GETNETGR_ERROR, + "GETNETGRENT"); + } else { + const char *host, *user, *domain; + + if (getnetgrent_p(&host, &user, &domain, netdata) == 1) { + send_ngent(sess, host, user, domain); + } else { + simple_response(sess, IRPD_GETNETGR_NOMORE, + "No more"); + } + } +} + +/* + * static void + * irpd_innetgr(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Handle the INNETGR verb. + */ +static void +irpd_innetgr(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct arg_s *args; + struct net_data *netdata = get_net_data(sess); + const char *host; + const char *user; + const char *domain; + + UNUSED(ctx); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, ng, sess, IRPD_GETNETGR_ERROR); + + args = split_string(rest); + if (args->iovlen != 3) { /* len includes NULL at end */ + simple_response(sess, IRPD_GETNETGR_ERROR, + "INNETGR netgroup ngentry"); + } else { + char *grptmp = memget(args->iov[0].iov_len + 1); + char *ngtmp = memget(args->iov[1].iov_len + 1); + + strncpy(grptmp, args->iov[0].iov_base, args->iov[0].iov_len); + strncpy(ngtmp, args->iov[1].iov_base, args->iov[1].iov_len); + + grptmp[args->iov[0].iov_len] = '\0'; + ngtmp[args->iov[1].iov_len] = '\0'; + + if (irp_unmarshall_ng(&host, &user, &domain, ngtmp) != 0) { + simple_response(sess, IRPD_GETNETGR_ERROR, + "ngentry must be (host,user,domain)"); + } else { + if (innetgr_p(grptmp, host, user, domain, + netdata) == 1) { + simple_response(sess, IRPD_GETNETGR_MATCHES, + "INNETGR matches"); + } else { + simple_response(sess, IRPD_GETNETGR_NOMATCH, + "INNETGR does not match"); + } + } + + memput(grptmp, args->iov[0].iov_len + 1); + memput(ngtmp, args->iov[1].iov_len + 1); + } + + free_args(args); +} + +/* + * static void + * irpd_setnetgrent(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Handle the SETNETGRENT verb. + */ +static void +irpd_setnetgrent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct arg_s *args; + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, ng, sess, IRPD_GETNETGR_ERROR); + + args = split_string(rest); + if (args->iovlen != 2) { /* len includes NULL at end */ + simple_response(sess, IRPD_GETNETGR_ERROR, + "setnetgrent netgroup"); + } else { + setnetgrent_p(rest, netdata); + simple_response(sess, IRPD_GETNETGR_SETOK, + "setnetgrent ok"); + } + + free_args(args); +} + +/* + * static void + * irpd_endnetgrent(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Handle the ENDNETGRENT verb. + */ +static void +irpd_endnetgrent(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + INSIST(netdata != NULL); + + ND_INIT(netdata, ng, sess, IRPD_GETNETGR_ERROR); + + if (rest != NULL && strlen (rest) > 0) { + simple_response(sess, IRPD_GETNETGR_ERROR, + "endnetgrent netgroup"); + } else { + endnetgrent_p(netdata); + simple_response(sess, IRPD_GETNETGR_SETOK, + "endnetgrent ok"); + } +} + +/* + * static void + * irpd_quit(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Handle the QUIT verb. + */ +static void +irpd_quit(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + UNUSED(ctx); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + ctl_response(sess, irpd_quit_ok, "See ya!", CTL_EXIT, NULL, + 0 , NULL, NULL, 0); +} + +/* + * static void + * irpd_help(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Handle the HELP verb. + */ +static void +irpd_help(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + /* XXX should make this do something better (like include required + * arguments. + */ + UNUSED(ctx); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + ctl_sendhelp(sess, 231); +} + +/* + * static void + * irpd_accept(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Handle a new connection. + */ +static void +irpd_accept(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + const struct sockaddr *sa = respctx; + char raddr[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; + int reject = 1; + int response; + const char *respmsg = NULL; + + UNUSED(ctx); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(uctx); + + if (sa->sa_family == AF_UNIX) { + syslog (LOG_INFO, "New AF_UNIX connection"); + reject = 0; + } else if (sa->sa_family == AF_INET) { + const struct sockaddr_in *sin = respctx; + static unsigned long localhost; + static unsigned long zero; + + if (localhost == 0) { + /* yes, this could be done with simple arithmetic... */ + inet_pton(AF_INET, "127.0.0.1", &localhost); + } + + inet_ntop(AF_INET, &sin->sin_addr, raddr, sizeof raddr); + + /* we reject INET connections that are not from the local + * machine. + */ + if (sin->sin_addr.s_addr == zero || + sin->sin_addr.s_addr == localhost) { + reject = 0; + syslog(LOG_INFO, "New connection from %s", raddr); + } else { + syslog(LOG_INFO, "New connection from %s (reject)", + raddr); + respmsg = "Connections from off host not permitted"; + } + } else if (sa->sa_family == AF_INET6) { + /* XXX should do something intelligent here. */ + respmsg = "IPv6 connections not implemented yet."; + syslog(LOG_ERR, "Cannot handle AF_INET6 connections yet"); + } else { + syslog (LOG_ERR, "Unknown peer type: %d", sa->sa_family); + respmsg = "What are you???"; + } + + if (reject) { + response = IRPD_NOT_WELCOME_CODE; + if (respmsg == NULL) { + respmsg = "Go away!"; + } + /* XXX can we be sure that stacked up commands will not be + * processed before the control connection is closed??? + */ + } else { + void *ctx = make_cli_ctx(); + + if (ctx == NULL) { + response = IRPD_NOT_WELCOME_CODE; + respmsg = "Internal error (client context)"; + } else { + response = IRPD_WELCOME_CODE; + if (respmsg == NULL) { + respmsg = "Welcome to IRPD (v 1)"; + } + ctl_setcsctx(sess, ctx); + } + } + ctl_response(sess, response, respmsg, (reject ? CTL_EXIT : 0), NULL, + 0, NULL, NULL, 0); +} + +/* + * static void + * irpd_abort(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, const void *respctx, void *uctx); + * Handle a dropped connection. + */ +static void +irpd_abort(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, const void *respctx, void *uctx) +{ + struct net_data *netdata = get_net_data(sess); + + UNUSED(ctx); + UNUSED(verb); + UNUSED(rest); + UNUSED(respflags); + UNUSED(respctx); + UNUSED(uctx); + + if (netdata != NULL) + net_data_destroy(netdata); +} + +/* + * void + * response_done(struct ctl_sctx *ctx, struct ctl_sess *sess, void *uap) + * UAP is the response_buffer passed through to + * ctl_response. + */ +static void +response_done(struct ctl_sctx *ctx, struct ctl_sess *sess, void *uap) { + UNUSED(ctx); + UNUSED(sess); + release_buffer(uap); +} + +/* + * static void + * logger(enum ctl_severity sev, const char *fmt, ...); + * Logging routine called by the ctl_* functions. For now we + * just spit everything to stderr. + */ + +static void +logger(enum ctl_severity sev, const char *fmt, ...) { + char buffer[1024]; + va_list ap; + int level; + + if (sev == ctl_debug) + return; + + if (sev == ctl_warning) + level = LOG_WARNING; + else if (sev == ctl_error) + level = LOG_ERR; + else { + syslog(LOG_CRIT, "Invalid severity: %d", (int)sev); + exit(1); + } + + va_start(ap, fmt); + +#if 0 + fprintf(stderr, "irpd: "); + vfprintf(stderr, fmt, ap); +#else + if (vsprintf(buffer, fmt, ap) > (int)(sizeof (buffer) - 1)) { + syslog(LOG_CRIT, "Buffer overrun in logger"); + va_end(ap); + abort(); + } + syslog(level, "%s", buffer); +#endif + va_end(ap); +} + +/* + * static struct response_buff * + * newbuffer(u_int length); + * Create a structure to hold an allocated buffer. We do + * this so we can get the size to deallocate later. + * Returns: + * Pointer to the structure + */ +static struct response_buff * +newbuffer(u_int length) { + struct response_buff *h; + + h = memget(sizeof *h); + if (h == NULL) { + errno = ENOMEM; + return (NULL); + } + + h->buff = NULL; + h->bufflen = length; + + if (length > 0) { + h->buff = memget(h->bufflen); + if (h->buff == NULL) { + memput(h, sizeof *h); + errno = ENOMEM; + return (NULL); + } + memset(h->buff, 0, h->bufflen); + } + + return (h); +} + +/* + * static void + * release_buffer(struct response_buff *b); + * Free up a buffer allocated with newbuffer. + */ +static void +release_buffer(struct response_buff *b) { + memset(b->buff, 0, b->bufflen); + memput(b->buff, b->bufflen); + + memset(b, 0, sizeof *b); + memput(b, sizeof *b); +} + +/* + * static struct arg_s * + * split_string(const char *string); + * Create an array of iovecs(last one having NULL fields) + * pointing into STRING at the non-whitespace sections. The + * iovecs are stashed inside a structure so we can get the + * size back later at deallocation time. Iovecs are used to avoid + * modifying the argument with added nulls. + * Returns: + * Pointer to the wrapper structure. Must be given to free_args() + * when done + */ +static struct arg_s * +split_string(const char *string) { + struct iovec *iovs; + const char *p; + int i, c, iswh; + struct arg_s *a; + + /* count + 1 of the number of runs of non-whitespace. */ + for (iswh = 1, i = 1, p = string ; p != NULL && *p ; p++) { + if (iswh && !isspace(*p)) { + iswh = 0; + i++; + } else if (!iswh && isspace(*p)) { + iswh = 1; + } + } + + iovs = memget(sizeof (struct iovec) * i); + if (iovs == NULL) { + errno = ENOMEM; + return (NULL); + } + + a = memget(sizeof *a); + if (a == NULL) { + errno = ENOMEM; + memput(iovs, sizeof (struct iovec) * i); + return (NULL); + } + a->iov = iovs; + a->iovlen = i; + + for (c = 0, p = string ; p != NULL && *p ; c++) { + while (isspace(*p)) { + p++; + } + + if (*p == '\0') + break; + + DE_CONST(p, iovs[c].iov_base); + + while (*p && !isspace(*p)) { + p++; + } + iovs[c].iov_len = p - (char *)iovs[c].iov_base; + } + INSIST(c == i - 1); + iovs[c].iov_base = NULL; + iovs[c].iov_len = 0; + + return (a); +} + +/* + * static void + * free_args(struct arg_s *args); + * Free up the argument structure created with + * split_string(). + */ + +static void +free_args(struct arg_s *args) { + memput(args->iov, sizeof (struct iovec) * args->iovlen); + memput(args, sizeof *args); +} + +static struct client_ctx * +make_cli_ctx(void) { + struct client_ctx *p = memget (sizeof *p); + + if (p == NULL) + return (NULL); + + p->net_data = net_data_create(conffile); + + return (p); +} + +static struct net_data * +get_net_data(struct ctl_sess *sess) { + struct client_ctx *ctx = ctl_getcsctx(sess); + + INSIST(ctx != NULL); + INSIST(ctx->net_data != NULL); + + return (ctx->net_data); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/irpd/irpd.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/irpd/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/irpd/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/irpd/Makefile (revision 109985) @@ -0,0 +1,101 @@ +## Copyright (c) 1996, 1997 by Internet Software Consortium +## +## 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. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM 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 +## SOFTWARE. + +# $Id: Makefile,v 1.7 2000/12/23 08:02:52 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g -Wall + +#(net2 and its descendents) +SYSTYPE = freebsd +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +EXE= +LEX = lex -I +YACC = yacc -d +SYSLIBS = -ll -lutil +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +DESTETC= /etc +DESTRUN= /var/run +AR= ar cru +INSTALL= install +STRIP=-s + +PS=ps +LDFLAGS= +CFLAGS= ${CDEBUG} +CPPFLAGS= -I${PORTINCL} -I${INCL} -I${TOP}/lib/irs ${DEFS} + +VER= LOCAL-`date +%y%m%d.%H%M%S` +HOSTNAMECMD= hostname || uname -n + +PROG= irpd +HDRS= +SRCS= irpd.c +OBJS= irpd.${O} + +all: ${PROG}${EXE} + +${PROG}${EXE}: irpd.${O} tmp_version.${O} ${LIBBIND} + ${CC} ${CDEBUG} ${LDFLAGS} -o ${PROG}${EXE} ${OBJS} tmp_version.${O} \ + ${LIBBIND} ${SYSLIBS} +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c + +tmp_version.${O}: tmp_version.c + +tmp_version.c: version.c Makefile ../Makefile ${SRCS} ${HDRS} + (u=$${USER-root} d=`pwd` h=`${HOSTNAMECMD}` t=`date`; \ + sed -e "s|%WHEN%|$${t}|" -e "s|%VERSION%|"${VER}"|" \ + -e "s|%WHOANDWHERE%|$${u}@$${h}:$${d}|" \ + < version.c > tmp_version.c); sleep 1 + +distclean: clean + +clean: FRC + rm -f ${PROG}${EXE} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + rm -f tmp_version.c tmp_version.${O} + +depend: ${SRCS} + mkdep ${CPPFLAGS} -I${INCL} -I${PORTINCL} -I${TOP}/lib/irs ${DEFS} ${SRCS} + +${DESTDIR}${DESTSBIN}: + mkdir -p ${DESTDIR}${DESTSBIN} + +install: ${DESTDIR}${DESTSBIN} ${PROG}${EXE} + ${INSTALL} ${STRIP} -c -m 755 ${PROG}${EXE} ${DESTDIR}${DESTSBIN}/${PROG}${EXE} + +links: FRC + @ln -s SRC/*.[chy] SRC/test .; rm -f ns_parser.[ch] + +tags: FRC + ctags ${SRCS} *.h + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Property changes on: vendor/bind/8.3.4/contrib/bind/bin/irpd/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/irpd/irs-irpd.conf =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/irpd/irs-irpd.conf (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/irpd/irs-irpd.conf (revision 109985) @@ -0,0 +1,11 @@ +# Private irs config file for irpd so that it doesn't get configured to +# talk to itself. +passwd local +group local +services local +protocols local +hosts dns continue +hosts local +networks dns continue +networks local +netgroup local Property changes on: vendor/bind/8.3.4/contrib/bind/bin/irpd/irs-irpd.conf ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/irpd/version.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/irpd/version.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/irpd/version.c (revision 109985) @@ -0,0 +1,25 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#ifndef lint +char sccsid[] = "@(#)named %VERSION% %WHEN% %WHOANDWHERE%"; +char rcsid[] = "$Id: version.c,v 1.1 1999/01/18 07:47:17 vixie Exp $"; +#endif /* not lint */ + +char Version[] = "named %VERSION% %WHEN%\n\t%WHOANDWHERE%"; +char ShortVersion[] = "%VERSION%"; + Property changes on: vendor/bind/8.3.4/contrib/bind/bin/irpd/version.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/mkservdb/mkservdb.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/mkservdb/mkservdb.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/mkservdb/mkservdb.c (revision 109985) @@ -0,0 +1,176 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: mkservdb.c,v 1.10 2001/06/18 14:42:46 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1998,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#ifdef IRS_LCL_SV_DB +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../include/irs.h" +#include "../../lib/irs/irs_p.h" +#include "../../include/isc/misc.h" + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +#ifndef IRS_LCL_SV_DB +main(int argc, char **argv) { + fprintf(stderr, "%s: not supported on this architecture\n", argv[0]); + exit(1); +} + +#else + +#define _PATH_SERVICES_DB_TMP _PATH_SERVICES_DB ".new" + +struct servent *getnextent(FILE *); + +int +main(int argc, char **argv) { + DB *db; + DBT key; + DBT data; + const char *filename = _PATH_SERVICES; + const char *tmpdatabase = _PATH_SERVICES_DB_TMP; + const char *database = _PATH_SERVICES_DB; + char dbuf[1024]; + char kbuf[512]; + u_short *ports; + struct lcl_sv lcl_sv; + struct servent *sv; + int n, r; + char *p; + + unlink(tmpdatabase); + + if (argc > 1) + filename = argv[1]; + + lcl_sv.fp = fopen(filename, "r"); + if (lcl_sv.fp == NULL) + err(1, "%s", filename); + + db = dbopen(tmpdatabase, O_CREAT|O_RDWR, 0444, DB_BTREE, NULL); + if (db == NULL) + err(1, "%s", tmpdatabase); + + while ((sv = irs_lclsv_fnxt(&lcl_sv)) != NULL) { + if (sv->s_proto == NULL) + continue; + + key.data = kbuf; + data.data = dbuf; + + /* Note that (sizeof "/") == 2. */ + if (strlen(sv->s_name) + sizeof "/" + strlen(sv->s_proto) + > sizeof kbuf) + continue; + key.size = SPRINTF((kbuf, "%s/%s", sv->s_name, sv->s_proto))+1; + + ((u_short *)dbuf)[0] = sv->s_port; + p = dbuf; + p += sizeof(u_short); + if (sv->s_aliases) + for (n = 0; sv->s_aliases[n]; ++n) { + strcpy(p, sv->s_aliases[n]); + p += strlen(p) + 1; + } + data.size = p - dbuf; + + if ((r = db->put(db, &key, &data, R_NOOVERWRITE))) { + if (r < 0) + errx(1, "failed to write %s", (char *)key.data); + else + warnx("will not overwrite %s", (char *)key.data); + } + for (n = 0; sv->s_aliases[n]; ++n) { + if (strlen(sv->s_aliases[n]) + sizeof "/" + + strlen(sv->s_proto) > sizeof kbuf) + continue; + key.size = SPRINTF((kbuf, "%s/%s", + sv->s_aliases[n], sv->s_proto))+1; + if ((r = db->put(db, &key, &data, R_NOOVERWRITE))) { + if (r < 0) + errx(1, "failed to write %s", + (char *)key.data); + else + warnx("will not overwrite %s", + (char *)key.data); + } + } + + ports = (u_short *)kbuf; + ports[0] = 0; + ports[1] = sv->s_port; + strcpy((char *)(ports+2), sv->s_proto); + key.size = sizeof(u_short) * 2 + strlen((char *)(ports+2)) + 1; + + if (strlen(sv->s_name) + sizeof "/" + strlen(sv->s_proto) + > sizeof dbuf) + continue; + p = dbuf; + p += SPRINTF((p, "%s/%s", sv->s_name, sv->s_proto)) + 1; + if (sv->s_aliases != NULL) + for (n = 0; sv->s_aliases[n] != NULL; n++) + if ((p + strlen(sv->s_aliases[n]) + 1) - dbuf + <= (int)sizeof dbuf) { + strcpy(p, sv->s_aliases[n]); + p += strlen(p) + 1; + } + data.size = p - dbuf; + + if ((r = db->put(db, &key, &data, R_NOOVERWRITE))) { + if (r < 0) + errx(1, "failed to write %d/%s", + ntohs(sv->s_port), sv->s_proto); + else + warnx("will not overwrite %d/%s", + ntohs(sv->s_port), sv->s_proto); + } + } + db->close(db); + if (isc_movefile(tmpdatabase, database)) + err(1, "rename %s -> %s", tmpdatabase, database); + exit(0); +} + +#endif Property changes on: vendor/bind/8.3.4/contrib/bind/bin/mkservdb/mkservdb.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/mkservdb/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/mkservdb/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/mkservdb/Makefile (revision 109985) @@ -0,0 +1,84 @@ +## Copyright (c) 1998,1999 by Internet Software Consortium +## +## 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. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM 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 +## SOFTWARE. + +# $Id: Makefile,v 1.8 2000/12/23 08:02:52 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g -Wall + +#(net2 and its descendents) +SYSTYPE = freebsd +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +LEX = lex -I +SYSLIBS = -ll -lutil +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +STRIP=-s +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin + +LDFLAGS= +CFLAGS= ${CDEBUG} +CPPFLAGS= -I${PORTINCL} -I${INCL} + +PROG= mkservdb +SRCS= ${PROG}.c +OBJS= ${PROG}.${O} + +all: ${PROG}${EXE} + +${PROG}${EXE}: ${OBJS} ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} ${BOUNDS} -o ${PROG}${EXE} ${OBJS} \ + ${LIBBIND} ${SYSLIBS} + +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c + +distclean: clean + +clean: FRC + rm -f ${PROG}${EXE} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + +depend: ${SRCS} + mkdep ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${SRCS} + +${DESTDIR}${DESTBIN}: + mkdir -p ${DESTDIR}${DESTBIN} + +install: ${DESTDIR}${DESTBIN} ${PROG}${EXE} + ${INSTALL} ${STRIP} -c ${INSTALL_EXEC} -m 755 ${PROG}${EXE} ${DESTDIR}${DESTBIN}/${PROG}${EXE} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +tags: FRC + ctags *.[ch] + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Property changes on: vendor/bind/8.3.4/contrib/bind/bin/mkservdb/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named-bootconf/named-bootconf.sh =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named-bootconf/named-bootconf.sh (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named-bootconf/named-bootconf.sh (revision 109985) @@ -0,0 +1,321 @@ +#!/bin/sh +# +# $NetBSD: named-bootconf.sh,v 1.5 1998/12/15 01:00:53 tron Exp $ +# +# Copyright (c) 1995, 1998 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Matthias Scheler. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 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 NetBSD +# Foundation, Inc. and its contributors. +# 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 SUCH DAMAGE. + +## Copyright (c) 1999 by Internet Software Consortium +## +## 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. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM 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 +## SOFTWARE. + +if [ ${OPTIONFILE-X} = X ]; then + OPTIONFILE=/tmp/.options.`date +%s`.$$ + ZONEFILE=/tmp/.zones.`date +%s`.$$ + COMMENTFILE=/tmp/.comments.`date +%s`.$$ + export OPTIONFILE ZONEFILE COMMENTFILE + touch $OPTIONFILE $ZONEFILE $COMMENTFILE + DUMP=1 +else + DUMP=0 +fi + +while read CMD ARGS; do + class= + CMD=`echo "${CMD}" | tr '[A-Z]' '[a-z]'` + case $CMD in + \; ) + echo \# $ARGS >>$COMMENTFILE + ;; + cache ) + set - X $ARGS + shift + if [ $# -eq 2 ]; then + (echo "" + cat $COMMENTFILE + echo "zone \"$1\" {" + echo " type hint;" + echo " file \"$2\";" + echo "};") >>$ZONEFILE + rm -f $COMMENTFILE + touch $COMMENTFILE + fi + ;; + directory ) + set - X $ARGS + shift + if [ $# -eq 1 ]; then + (cat $COMMENTFILE + echo " directory \"$1\";") >>$OPTIONFILE + rm -f $COMMENTFILE + touch $COMMENTFILE + + DIRECTORY=$1 + export DIRECTORY + fi + ;; + forwarders ) + (cat $COMMENTFILE + echo " forwarders {" + for ARG in $ARGS; do + echo " $ARG;" + done + echo " };") >>$OPTIONFILE + rm -f $COMMENTFILE + touch $COMMENTFILE + ;; + include ) + if [ "$ARGS" != "" ]; then + (cd ${DIRECTORY-.}; cat $ARGS) | $0 + fi + ;; + limit ) + ARGS=`echo "${ARGS}" | tr '[A-Z]' '[a-z]'` + set - X $ARGS + shift + if [ $# -eq 2 ]; then + cat $COMMENTFILE >>$OPTIONFILE + case $1 in + datasize | files | transfers-in | transfers-per-ns ) + echo " $1 $2;" >>$OPTIONFILE + ;; + esac + rm -f $COMMENTFILE + touch $COMMENTFILE + fi + ;; + options ) + ARGS=`echo "${ARGS}" | tr '[A-Z]' '[a-z]'` + cat $COMMENTFILE >>$OPTIONFILE + for ARG in $ARGS; do + case $ARG in + fake-iquery ) + echo " fake-iquery yes;" >>$OPTIONFILE + ;; + forward-only ) + echo " forward only;" >>$OPTIONFILE + ;; + no-fetch-glue ) + echo " fetch-glue no;" >>$OPTIONFILE + ;; + no-recursion ) + echo " recursion no;" >>$OPTIONFILE + ;; + no-round-robin ) # HP extention + echo " rrset-order {" >>$OPTIONFILE + echo " class ANY type ANY name \"*\" order fixed;" >>$OPTIONFILE + echo " };" >>$OPTIONFILE + ;; + esac + done + rm -f $COMMENTFILE + touch $COMMENTFILE + ;; + primary|primary/* ) + case $CMD in + primary/chaos ) + class="chaos " + ;; + primary/hs ) + class="hesiod " + ;; + esac + set - X $ARGS + shift + if [ $# -eq 2 ]; then + (echo "" + cat $COMMENTFILE + echo "zone \"$1\" ${class}{" + echo " type master;" + echo " file \"$2\";" + echo "};") >>$ZONEFILE + rm -f $COMMENTFILE + touch $COMMENTFILE + fi + ;; + secondary|secondary/* ) + case $CMD in + secondary/chaos ) + class="chaos " + ;; + secondary/hs ) + class="hesiod " + ;; + esac + set - X $ARGS + shift + if [ $# -gt 1 ]; then + ZONE=$1 + shift + PRIMARIES="" + while [ $# -gt 1 ]; do + PRIMARIES="$PRIMARIES $1" + shift + done + (echo "" + cat $COMMENTFILE + echo "zone \"$ZONE\" ${class}{" + echo " type slave;" + if expr x"$1" : '^x[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' > /dev/null + then + PRIMARIES="$PRIMARIES $1" + else + echo " file \"$1\";" + fi + echo " masters {" + for PRIMARY in $PRIMARIES; do + echo " $PRIMARY;" + done + echo " };" + echo "};") >>$ZONEFILE + rm -f $COMMENTFILE + touch $COMMENTFILE + fi + ;; + stub|stub/* ) + case $CMD in + stub/chaos ) + class="chaos " + ;; + stub/hs ) + class="hesiod " + ;; + esac + set - X $ARGS + shift + if [ $# -gt 1 ]; then + ZONE=$1 + shift + PRIMARIES="" + while [ $# -gt 1 ]; do + PRIMARIES="$PRIMARIES $1" + shift + done + (echo "" + cat $COMMENTFILE + echo "zone \"$ZONE\" ${class}{" + echo " type stub;" + if expr x"$1" : '^x[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' > /dev/null + then + PRIMARIES="$PRIMARIES $1" + else + echo " file \"$1\";" + fi + echo " masters {" + for PRIMARY in $PRIMARIES; do + echo " $PRIMARY;" + done + echo " };" + echo "};") >>$ZONEFILE + rm -f $COMMENTFILE + touch $COMMENTFILE + fi + ;; + slave ) + cat $COMMENTFILE >>$OPTIONFILE + echo " forward only;" >>$OPTIONFILE + rm -f $COMMENTFILE + touch $COMMENTFILE + ;; + sortlist ) + (cat $COMMENTFILE + echo " topology {" + for ARG in $ARGS; do + case $ARG in + *.0.0.0 ) + echo " $ARG/8;" + ;; + *.0.0 ) + echo " $ARG/16;" + ;; + *.0 ) + echo " $ARG/24;" + ;; + * ) + echo " $ARG;" + ;; + esac + done + echo " };") >>$OPTIONFILE + rm -f $COMMENTFILE + touch $COMMENTFILE + ;; + tcplist | xfrnets ) + (cat $COMMENTFILE + echo " allow-transfer {" + for ARG in $ARGS; do + case $ARG in + *.0.0.0 ) + echo " $ARG/8;" + ;; + *.0.0 ) + echo " $ARG/16;" + ;; + *.0 ) + echo " $ARG/24;" + ;; + * ) + echo " $ARG;" + ;; + esac + done + echo " };") >>$OPTIONFILE + rm -f $COMMENTFILE + touch $COMMENTFILE + ;; + esac +done + +if [ $DUMP -eq 1 ]; then + echo "" + echo "options {" + cat $OPTIONFILE + echo "};" + cat $ZONEFILE $COMMENTFILE + + rm -f $OPTIONFILE $ZONEFILE $COMMENTFILE +fi + +exit 0 Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named-bootconf/named-bootconf.sh ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named-bootconf/test.boot =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named-bootconf/test.boot (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named-bootconf/test.boot (revision 109985) @@ -0,0 +1,30 @@ +directory /var/named +forwarders 1.2.3.4 1.2.3.5 +limit datasize 10000000 +limit files 1000 +limit transfers-in 100 +limit transfers-per-ns 20 +; no-round-robin in HP specific +options no-round-robin fake-iquery forward-only no-fetch-glue no-recursion +slave +tcplist 10.0.0.1 +xfrnets 10.0.0.2 +cache . rootservers +primary example.net example.net.db +secondary example.com 127.0.0.1 example.com.db +stub example.org 127.0.0.1 example.org.db +primary/IN example.net example.net.db +secondary/IN example.com 127.0.0.1 example.com.db +stub/IN example.org 127.0.0.1 example.org.db +secondary/IN example.com 127.0.0.1 +stub/IN example.org 127.0.0.1 +primary/CHAOS example.net example.net.db +secondary/CHAOS example.com 127.0.0.1 example.com.db +stub/CHAOS example.org 127.0.0.1 example.org.db +secondary/CHAOS example.com 127.0.0.1 +stub/CHAOS example.org 127.0.0.1 +primary/HS example.net example.net.db +secondary/HS example.com 127.0.0.1 example.com.db +stub/HS example.org 127.0.0.1 example.org.db +secondary/HS example.com 127.0.0.1 +stub/HS example.org 127.0.0.1 Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named-bootconf/test.boot ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named-bootconf/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named-bootconf/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named-bootconf/Makefile (revision 109985) @@ -0,0 +1,77 @@ +## Copyright (c) 1999 by Internet Software Consortium +## +## 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. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM 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 +## SOFTWARE. + +# $Id: Makefile,v 1.3 2000/12/23 08:02:53 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g -Wall + +#(net2 and its descendents) +SYSTYPE = freebsd +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +LEX = lex -I +SYSLIBS = -ll -lutil +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +STRIP=-s +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin + +LDFLAGS= +CFLAGS= ${CDEBUG} +CPPFLAGS= -I${PORTINCL} -I${INCL} + +PROG= named-bootconf + +all: ${PROG} + +${PROG}: ${PROG}.sh Makefile + cp ${PROG}.sh ${PROG} + chmod +x ${PROG} + +distclean: clean + +clean: FRC + rm -f ${PROG} + rm -f *.BAK *.CKP *~ *.orig + +depend: + +${DESTDIR}${DESTSBIN}: + mkdir -p ${DESTDIR}${DESTSBIN} + +install: ${DESTDIR}${DESTSBIN} ${PROG} + ${INSTALL} -c -m 755 ${PROG} ${DESTDIR}${DESTSBIN}/${PROG} + +links: FRC + @set -e; ln -s SRC/*.sh . + +tags: + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named-bootconf/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/named-bootconf/Grot/named-bootconf.pl =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/named-bootconf/Grot/named-bootconf.pl (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/named-bootconf/Grot/named-bootconf.pl (revision 109985) @@ -0,0 +1,324 @@ +#!/usr/bin/perl + +## Copyright (c) 1996-1999 by Internet Software Consortium +## +## 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. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM 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 +## SOFTWARE. + +## $Id: named-bootconf.pl,v 1.2 1999/01/08 19:27:35 vixie Exp $ + +# This is a filter. Input is a named.boot. Output is a named.conf. + +$new_config = ""; + +$have_options = 0; +%options = (); +%options_comments = (); +@topology = (); +@topology_comments = (); +@bogus = (); +@bogus_comments = (); +@transfer_acl = (); +@transfer_comments = (); +$logging = ""; + +while(<>) { + next if /^$/; + + # skip comment-only lines + if (/^\s*;+\s*(.*)$/) { + $new_config .= "// $1\n"; + next; + } + + # handle continued lines + while (/\\$/) { + s/\\$/ /; + $_ .= <>; + } + + chop; + + # deal with lines ending in a coment + if (s/\s*;+\s*(.*)$//) { + $comment = "// $1"; + } else { + $comment = ""; + } + + ($directive, @rest) = split; + + $class = ""; + if ($directive =~ /^(.*)\/(.*)$/) { + $directive = $1; + $class = $2; + } + + if ($directive eq "primary") { + $zname = shift(@rest); + &maybe_print_comment("","\n"); + $new_config .= "zone \"$zname\" "; + if ($class ne "") { + $new_config .= "$class "; + } + $new_config .= "{\n"; + $new_config .= "\ttype master;\n"; + $filename = shift(@rest); + $new_config .= "\tfile \"$filename\";\n"; + $new_config .= "};\n\n"; + } elsif ($directive eq "secondary" || $directive eq "stub") { + if ($directive eq "secondary") { + $type = "slave"; + } else { + $type = "stub"; + } + $zname = shift(@rest); + &maybe_print_comment("","\n"); + $new_config .= "zone \"$zname\" "; + if ($class ne "") { + $new_config .= "$class "; + } + $new_config .= "{\n"; + $new_config .= "\ttype $type;\n"; + $filename = pop(@rest); + if ($filename =~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) { + push(@rest, $filename); + $filename = ""; + } else { + $new_config .= "\tfile \"$filename\";\n"; + } + $new_config .= "\tmasters {\n"; + foreach $master (@rest) { + $new_config .= "\t\t$master;\n"; + } + $new_config .= "\t};\n"; + $new_config .= "};\n\n"; + } elsif ($directive eq "cache") { + $zname = shift(@rest); + &maybe_print_comment("","\n"); + $new_config .= "zone \"$zname\" {\n"; + $new_config .= "\ttype hint;\n"; + $filename = shift(@rest); + $new_config .= "\tfile \"$filename\";\n"; + $new_config .= "};\n\n"; + } elsif ($directive eq "directory") { + $options{"directory"} = "\"$rest[0]\""; + $options_comments{"directory"} = $comment; + $have_options = 1; + } elsif ($directive eq "check-names") { + $type = shift(@rest); + if ($type eq "primary") { + $type = "master"; + } elsif ($type eq "secondary") { + $type = "slave"; + } + $action = shift(@rest); + $options{"check-names $type"} = $action; + $options_comments{"check-names $type"} = $comment; + $have_options = 1; + } elsif ($directive eq "forwarders") { + $options{"forwarders"}="{\n"; + foreach $forwarder (@rest) { + $options{"forwarders"} .= "\t\t$forwarder;\n"; + } + $options{"forwarders"} .= "\t}"; + $options_comments{"forwarders"} = $comment; + $have_options = 1; + } elsif ($directive eq "slave") { + &handle_options("forward-only"); + } elsif ($directive eq "options") { + &handle_options(@rest); + } elsif ($directive eq "limit") { + &handle_limit(@rest); + } elsif ($directive eq "include") { + $new_config .= + "// make sure your include is still in the right place\n"; + $comment = "\t" . $comment; + $new_config .= "include \"$rest[0]\";$comment\n\n"; + } elsif ($directive eq "xfrnets" || $directive eq "tcplist") { + if ($comment ne "") { + $comment = "\t$comment"; + } + foreach $elt (@rest) { + push(@transfer_acl, $elt); + push(@transfer_comments, $comment); + } + $have_options = 1; + } elsif ($directive eq "sortlist") { + if ($comment ne "") { + $comment = "\t$comment"; + } + foreach $elt (@rest) { + push(@topology, $elt); + push(@topology_comments, $comment); + } + } elsif ($directive eq "bogusns") { + if ($comment ne "") { + $comment = "\t$comment"; + } + foreach $elt (@rest) { + push(@bogus, $elt); + push(@bogus_comments, $comment); + } + } elsif ($directive eq "max-fetch") { + $options{"transfers-in"}=$rest[0]; + $options_comments{"transfers-in"}=$comment; + $have_options = 1; + } else { + $new_config .= "// NOTE: unconverted directive '$directive @rest'\n\n"; + } +} + +print "// generated by named-bootconf.pl\n\n"; +if ($have_options) { + print "options {\n"; + foreach $option (sort(keys(%options))) { + print "\t$option $options{$option};"; + if ($options_comments{$option} ne "") { + print "\t$options_comments{$option}"; + } + print "\n"; + } + if (@transfer_acl > 0) { + print "\tallow-transfer {\n"; + for ($i = 0; $i <= $#transfer_acl; $i++) { + &print_maybe_masked("\t\t", $transfer_acl[$i], + $transfer_comments[$i]); + } + print "\t};\n"; + } + print "\t/* +\t * If there is a firewall between you and nameservers you want +\t * to talk to, you might need to uncomment the query-source +\t * directive below. Previous versions of BIND always asked +\t * questions using port 53, but BIND 8.1 uses an unprivileged +\t * port by default. +\t */ +\t// query-source address * port 53; +"; + + print "};\n\n"; +} +if ($logging ne "") { + print "logging {\n$logging};\n\n"; +} +if (@topology > 0) { + print "// Note: the following will be supported in a future release.\n"; + print "/*\n"; + print "host { any; } {\n\ttopology {\n"; + for ($i = 0; $i <= $#topology; $i++) { + &print_maybe_masked("\t\t", $topology[$i], + $topology_comments[$i]); + } + print "\t};\n};\n"; + print "*/\n"; + print "\n"; +} +if (@bogus > 0) { + for ($i = 0; $i <= $#bogus; $i++) { + print "server $bogus[$i] { bogus yes; };$bogus_comments[$i]\n"; + } + print "\n"; +} +print $new_config; + +exit 0; + +sub maybe_print_comment { + $prefix = shift; + $suffix = shift; + if ($comment ne "") { + $new_config .= sprintf("%s%s%s", $prefix, $comment, $suffix); + } +} + +sub handle_options { + foreach $option (@_) { + if ($option eq "forward-only") { + $options{"forward"}="only"; + $options_comments{"forward"}=$comment; + $have_options = 1; + } elsif ($option eq "no-recursion") { + $options{"recursion"}="no"; + $options_comments{"recursion"}=$comment; + $have_options = 1; + } elsif ($option eq "no-fetch-glue") { + $options{"fetch-glue"}="no"; + $options_comments{"fetch-glue"}=$comment; + $have_options = 1; + } elsif ($option eq "fake-iquery") { + $options{"fake-iquery"}="yes"; + $options_comments{"fake-iquery"}=$comment; + $have_options = 1; + } elsif ($option eq "query-log") { + if ($comment ne "") { + $logging .= "\t$comment\n"; + } + $logging .= "\tcategory queries { default_syslog; };\n"; + } else { + $options{"// NOTE: unconverted option '$option'"}=""; + $options_comments{"// NOTE: unconverted option '$option'"}= + $comment; + $have_options = 1; + } + } +} + +sub handle_limit { + $limit = shift; + if ($limit eq "datasize" || $limit eq "transfers-in" + || $limit eq "transfers-per-ns" || $limit eq "files") { + $options{$limit}=$_[0]; + $options_comments{$limit}=$comment; + $have_options = 1; + } else { + $options{"// NOTE: unconverted limit '$limit @_'"}=""; + $options_comments{"// NOTE: unconverted limit '$limit @_'"}=$comment; + $have_options = 1; + } +} + +sub print_maybe_masked { + # this assumes a contiguous netmask starting at the MSB + $prefix = shift; + $elt = shift; + $elt_comment = shift; + if ($elt =~ /^(.*)&(.*)$/) { + $address = $1; + $mask = $2; + ($m1,$m2,$m3,$m4) = split(/\./, $mask); + $mask_val = ($m1 << 24) + ($m2 << 16) +($m3 << 8) + $m4; + $zero_bits = 0; + while (($mask_val % 2) == 0) { + $mask_val /= 2; + $zero_bits++; + } + $mask_bits = 32 - $zero_bits; + } else { + $address = $elt; + ($a1,$a2,$a3,$a4) = split(/\./, $address); + if ($a1 < 128) { + $mask_bits = 8; + } elsif ($a1 < 192) { + $mask_bits = 16; + } else { + $mask_bits = 24; + } + } + + print "$prefix$address"; + if ($mask_bits != 32) { + print "/$mask_bits"; + } + print ";$elt_comment\n"; +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/named-bootconf/Grot/named-bootconf.pl ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/nsupdate/nsupdate.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/nsupdate/nsupdate.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/nsupdate/nsupdate.c (revision 109985) @@ -0,0 +1,682 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: nsupdate.c,v 8.27 2001/06/18 14:43:46 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "port_after.h" +#include "../named/db_defs.h" + +/* XXX all of this stuff should come from libbind.a */ + +/* + * Map class and type names to number + */ +struct map { + char token[10]; + int val; +}; + +struct map class_strs[] = { + { "in", C_IN }, + { "chaos", C_CHAOS }, + { "hs", C_HS }, +}; +#define M_CLASS_CNT (sizeof(class_strs) / sizeof(struct map)) + +struct map type_strs[] = { + { "a", T_A }, + { "ns", T_NS }, + { "cname", T_CNAME }, + { "soa", T_SOA }, + { "mb", T_MB }, + { "mg", T_MG }, + { "mr", T_MR }, + { "null", T_NULL }, + { "wks", T_WKS }, + { "ptr", T_PTR }, + { "hinfo", T_HINFO }, + { "minfo", T_MINFO }, + { "mx", T_MX }, + { "txt", T_TXT }, + { "rp", T_RP }, + { "afsdb", T_AFSDB }, + { "x25", T_X25 }, + { "isdn", T_ISDN }, + { "rt", T_RT }, + { "nsap", T_NSAP }, + { "nsap_ptr", T_NSAP_PTR }, + { "sig", T_SIG }, + { "key", T_KEY }, + { "px", T_PX }, + { "loc", T_LOC }, + { "nxt", T_NXT }, + { "eid", T_EID }, + { "nimloc", T_NIMLOC }, + { "srv", T_SRV }, + { "atma", T_ATMA }, + { "naptr", T_NAPTR }, + { "kx", ns_t_kx }, + { "cert", ns_t_cert }, + { "aaaa", ns_t_aaaa }, +}; +#define M_TYPE_CNT (sizeof(type_strs) / sizeof(struct map)) + +struct map section_strs[] = { + { "zone", S_ZONE }, + { "prereq", S_PREREQ }, + { "update", S_UPDATE }, + { "reserved", S_ADDT }, +}; +#define M_SECTION_CNT (sizeof(section_strs) / sizeof(struct map)) + +struct map opcode_strs[] = { + { "nxdomain", NXDOMAIN }, + { "yxdomain", YXDOMAIN }, + { "nxrrset", NXRRSET }, + { "yxrrset", YXRRSET }, + { "delete", DELETE }, + { "add", ADD }, +}; +#define M_OPCODE_CNT (sizeof(opcode_strs) / sizeof(struct map)) + +static int getcharstring(char *, char *, int, int, int); +static char *progname; + +static void usage(void); +static int getword_str(char *, int, char **, char *); + +static struct __res_state res; + +int dns_findprimary (res_state, char *, struct ns_tsig_key *, char *, + int, struct in_addr *); + +/* + * format of file read by nsupdate is kept the same as the log + * file generated by updates, so that the log file can be fed + * to nsupdate to reconstruct lost updates. + * + * file is read on line at a time using fgets() rather than + * one word at a time using getword() so that it is easy to + * adapt nsupdate to read piped input from other scripts + * + * overloading of class/type has to be deferred to res_update() + * because class is needed by res_update() to determined the + * zone to which a resource record belongs + */ +int +main(int argc, char **argv) { + FILE *fp = NULL; + char buf[BUFSIZ], buf2[BUFSIZ]; + char dnbuf[MAXDNAME], data[MAXDATA]; + char *r_dname, *cp, *startp, *endp, *svstartp; + char section[15], opcode[10]; + int i, c, n, n1, inside, lineno = 0, vc = 0, + debug = 0, r_size, r_section, r_opcode, + prompt = 0, ret = 0, stringtobin = 0; + int16_t r_class, r_type; + u_int32_t r_ttl; + struct map *mp; + ns_updrec *rrecp; + ns_updque listuprec; + extern int getopt(); + extern char *optarg; + extern int optind, opterr, optopt; + ns_tsig_key key; + char *keyfile=NULL, *keyname=NULL; + + progname = argv[0]; + + while ((c = getopt(argc, argv, "dsvk:n:")) != -1) { + switch (c) { + case 'v': + vc = 1; + break; + case 'd': + debug = 1; + break; + case 's': + stringtobin = 1; + break; + case 'k': { + /* -k keydir:keyname */ + char *colon; + + if ((colon=strchr(optarg, ':'))==NULL) { + fprintf(stderr, "key option argument should be keydir:keyname\n"); + exit(1); + } + keyname=colon+1; + keyfile=optarg; + *colon='\0'; + break; + } + case 'n': + keyname=optarg; + break; + default: + usage(); + } + } + + INIT_LIST(listuprec); + + if (keyfile) { +#ifdef PARSE_KEYFILE + if ((fp=fopen(keyfile, "r"))==NULL) { + perror("open keyfile"); + exit(1); + } + /* now read the header info from the file */ + if ((i=fread(buf, 1, BUFSIZ, fp)) < 5) { + fclose(fp); + exit(1); + } + fclose(fp); + fp=NULL; + + p=buf; + + n=strlen(p); /* get length of strings */ + n1=strlen("Private-key-format: v"); + if (n1 > n || strncmp(buf, "Private-key-format: v", n1)) { + fprintf(stderr, "Invalid key file format\n"); + exit(1); /* not a match */ + } + p+=n1; /* advance pointer */ + sscanf((char *)p, "%d.%d", &file_major, &file_minor); + /* should do some error checking with these someday */ + while (*p++!='\n'); /* skip to end of line */ + + n=strlen(p); /* get length of strings */ + n1=strlen("Algorithm: "); + if (n1 > n || strncmp(p, "Algorithm: ", n1)) { + fprintf(stderr, "Invalid key file format\n"); + exit(1); /* not a match */ + } + p+=n1; /* advance pointer */ + if (sscanf((char *)p, "%d", &alg)!=1) { + fprintf(stderr, "Invalid key file format\n"); + exit(1); + } + while (*p++!='\n'); /* skip to end of line */ + + n=strlen(p); /* get length of strings */ + n1=strlen("Key: "); + if (n1 > n || strncmp(p, "Key: ", n1)) { + fprintf(stderr, "Invalid key file format\n"); + exit(1); /* not a match */ + } + p+=n1; /* advance pointer */ + pp=p; + while (*pp++!='\n'); /* skip to end of line, terminate it */ + *--pp='\0'; + + key.data=malloc(1024*sizeof(char)); + key.len=b64_pton(p, key.data, 1024); + + strcpy(key.name, keyname); + strcpy(key.alg, "HMAC-MD5.SIG-ALG.REG.INT"); +#else + /* use the dst* routines to parse the key files + * + * This requires that both the .key and the .private files + * exist in your cwd, so the keyfile parmeter here is + * assumed to be a path in which the K*.{key,private} files + * exist. + */ + DST_KEY *dst_key; + char cwd[PATH_MAX+1]; + + if (getcwd(cwd, PATH_MAX)==NULL) { + perror("unable to get current directory"); + exit(1); + } + if (chdir(keyfile)<0) { + fprintf(stderr, "unable to chdir to %s: %s\n", keyfile, + strerror(errno)); + exit(1); + } + + dst_init(); + dst_key = dst_read_key(keyname, + 0 /* not used for private keys */, + KEY_HMAC_MD5, DST_PRIVATE); + if (!dst_key) { + fprintf(stderr, "dst_read_key: error reading key\n"); + exit(1); + } + key.data=malloc(1024*sizeof(char)); + dst_key_to_buffer(dst_key, key.data, 1024); + key.len=dst_key->dk_key_size; + + strcpy(key.name, keyname); + strcpy(key.alg, "HMAC-MD5.SIG-ALG.REG.INT"); + + if (chdir(cwd)<0) { + fprintf(stderr, "unable to chdir to %s: %s\n", cwd, + strerror(errno)); + exit(1); + } +#endif + } + + if ((argc - optind) == 0) { + /* no file specified, read from stdin */ + ret = system("tty -s"); + if (ret == 0) /* terminal */ + prompt = 1; + else /* stdin redirect from a file or a pipe */ + prompt = 0; + } else { + /* file specified, open it */ + /* XXX - currently accepts only one filename */ + if ((fp = fopen(argv[optind], "r")) == NULL) { + fprintf(stderr, "error opening file: %s\n", argv[optind]); + exit (1); + } + } + for (;;) { + + inside = 1; + if (prompt) + fprintf(stdout, "> "); + if (!fp) + cp = fgets(buf, sizeof buf, stdin); + else + cp = fgets(buf, sizeof buf, fp); + if (cp == NULL) /* EOF */ + break; + lineno++; + + /* get rid of the trailing newline */ + n = strlen(buf); + buf[--n] = '\0'; + + startp = cp; + endp = strchr(cp, ';'); + if (endp != NULL) + endp--; + else + endp = cp + n - 1; + + /* verify section name */ + if (!getword_str(section, sizeof section, &startp, endp)) { + /* empty line */ + inside = 0; + } + if (inside) { + /* inside the same update packet, + * continue accumulating records */ + r_section = -1; + n1 = strlen(section); + if (section[n1-1] == ':') + section[--n1] = '\0'; + for (mp = section_strs; mp < section_strs+M_SECTION_CNT; mp++) + if (!strcasecmp(section, mp->token)) { + r_section = mp->val; + break; + } + if (r_section == -1) { + fprintf(stderr, "incorrect section name: %s\n", section); + exit (1); + } + if (r_section == S_ZONE) { + fprintf(stderr, "section ZONE not permitted\n"); + exit (1); + } + /* read operation code */ + if (!getword_str(opcode, sizeof opcode, &startp, endp)) { + fprintf(stderr, "failed to read operation code\n"); + exit (1); + } + r_opcode = -1; + if (opcode[0] == '{') { + n1 = strlen(opcode); + for (i = 0; i < n1; i++) + opcode[i] = opcode[i+1]; + if (opcode[n1-2] == '}') + opcode[n1-2] = '\0'; + } + for (mp = opcode_strs; mp < opcode_strs+M_OPCODE_CNT; mp++) { + if (!strcasecmp(opcode, mp->token)) { + r_opcode = mp->val; + break; + } + } + if (r_opcode == -1) { + fprintf(stderr, "incorrect operation code: %s\n", opcode); + exit (1); + } + /* read owner's domain name */ + if (!getword_str(dnbuf, sizeof dnbuf, &startp, endp)) { + fprintf(stderr, "failed to read owner name\n"); + exit (1); + } + r_dname = dnbuf; + r_ttl = (r_opcode == ADD) ? (~0U) : 0; + r_type = -1; + r_class = C_IN; /* default to IN */ + r_size = 0; + + (void) getword_str(buf2, sizeof buf2, &startp, endp); + + if (isdigit(buf2[0])) { /* ttl */ + r_ttl = strtoul(buf2, 0, 10); + if (errno == ERANGE && r_ttl == ULONG_MAX) { + fprintf(stderr, "oversized ttl: %s\n", buf2); + exit (1); + } + (void) getword_str(buf2, sizeof buf2, &startp, endp); + } + + if (buf2[0]) { /* possibly class */ + for (mp = class_strs; mp < class_strs+M_CLASS_CNT; mp++) { + if (!strcasecmp(buf2, mp->token)) { + r_class = mp->val; + (void) getword_str(buf2, sizeof buf2, &startp, endp); + break; + } + } + } + /* + * type and rdata field may or may not be required depending + * on the section and operation + */ + switch (r_section) { + case S_PREREQ: + if (r_ttl) { + fprintf(stderr, "nonzero ttl in prereq section: %lu\n", + (u_long)r_ttl); + r_ttl = 0; + } + switch (r_opcode) { + case NXDOMAIN: + case YXDOMAIN: + if (buf2[0]) { + fprintf (stderr, "invalid field: %s, ignored\n", + buf2); + exit (1); + } + break; + case NXRRSET: + case YXRRSET: + if (buf2[0]) + for (mp = type_strs; mp < type_strs+M_TYPE_CNT; mp++) + if (!strcasecmp(buf2, mp->token)) { + r_type = mp->val; + break; + } + if (r_type == -1) { + fprintf (stderr, "invalid type for RRset: %s\n", + buf2); + exit (1); + } + if (r_opcode == NXRRSET) + break; + /* + * for RRset exists (value dependent) case, + * nonempty rdata field will be present. + * simply copy the whole string now and let + * res_update() interpret the various fields + * depending on type + */ + cp = startp; + while (cp <= endp && isspace(*cp)) + cp++; + r_size = endp - cp + 1; + break; + default: + fprintf (stderr, + "unknown operation in prereq section\"%s\"\n", + opcode); + exit (1); + } + break; + case S_UPDATE: + switch (r_opcode) { + case DELETE: + r_ttl = 0; + r_type = T_ANY; + /* read type, if specified */ + if (buf2[0]) + for (mp = type_strs; mp < type_strs+M_TYPE_CNT; mp++) + if (!strcasecmp(buf2, mp->token)) { + r_type = mp->val; + svstartp = startp; + (void) getword_str(buf2, sizeof buf2, + &startp, endp); + if (buf2[0]) /* unget preference */ + startp = svstartp; + break; + } + /* read rdata portion, if specified */ + cp = startp; + while (cp <= endp && isspace(*cp)) + cp++; + r_size = endp - cp + 1; + break; + case ADD: + if (r_ttl == ~0U) { + fprintf (stderr, + "ttl must be specified for record to be added: %s\n", buf); + exit (1); + } + /* read type */ + if (buf2[0]) + for (mp = type_strs; mp < type_strs+M_TYPE_CNT; mp++) + if (!strcasecmp(buf2, mp->token)) { + r_type = mp->val; + break; + } + if (r_type == -1) { + fprintf(stderr, + "invalid type for record to be added: %s\n", buf2); + exit (1); + } + /* read rdata portion */ + cp = startp; + while (cp < endp && isspace(*cp)) + cp++; + r_size = endp - cp + 1; + if (r_size <= 0) { + fprintf(stderr, + "nonempty rdata field needed to add the record at line %d\n", + lineno); + exit (1); + } + break; + default: + fprintf(stderr, + "unknown operation in update section \"%s\"\n", opcode); + exit (1); + } + break; + default: + fprintf(stderr, + "unknown section identifier \"%s\"\n", section); + exit (1); + } + + if ( !(rrecp = res_mkupdrec(r_section, r_dname, r_class, + r_type, r_ttl)) || + (r_size > 0 && !(rrecp->r_data = (u_char *)malloc(r_size))) ) { + if (rrecp) + res_freeupdrec(rrecp); + fprintf(stderr, "saverrec error\n"); + exit (1); + } + if (stringtobin) { + switch(r_opcode) { + case T_HINFO: + if (!getcharstring(buf,(char *)data,2,2,lineno)) + exit(1); + cp = data; + break; + case T_ISDN: + if (!getcharstring(buf,(char *)data,1,2,lineno)) + exit(1); + cp = data; + break; + case T_TXT: + if (!getcharstring(buf,(char *)data,1,0,lineno)) + exit(1); + cp = data; + break; + case T_X25: + if (!getcharstring(buf,(char *)data,1,1,lineno)) + exit(1); + cp = data; + break; + default: + break; + } + } + rrecp->r_opcode = r_opcode; + rrecp->r_size = r_size; + (void) strncpy((char *)rrecp->r_data, cp, r_size); + APPEND(listuprec, rrecp, r_link); + } else { /* end of an update packet */ + (void) res_ninit(&res); + if (vc) + res.options |= RES_USEVC | RES_STAYOPEN; + if (debug) + res.options |= RES_DEBUG; + if (!EMPTY(listuprec)) { + n = res_nupdate(&res, HEAD(listuprec), + keyfile != NULL ? &key : NULL); + if (n < 0) + fprintf(stderr, "failed update packet\n"); + while (!EMPTY(listuprec)) { + ns_updrec *tmprrecp = HEAD(listuprec); + + UNLINK(listuprec, tmprrecp, r_link); + if (tmprrecp->r_size != 0) + free((char *)tmprrecp->r_data); + res_freeupdrec(tmprrecp); + } + } + } + } /* for */ + return (0); +} + +static void +usage() { + fprintf(stderr, "Usage: %s [ -k keydir:keyname ] [-d] [-v] [file]\n", + progname); + exit(1); +} + +/* + * Get a whitespace delimited word from a string (not file) + * into buf. modify the start pointer to point after the + * word in the string. + */ +static int +getword_str(char *buf, int size, char **startpp, char *endp) { + char *cp; + int c; + + for (cp = buf; *startpp <= endp; ) { + c = **startpp; + if (isspace(c) || c == '\0') { + if (cp != buf) /* trailing whitespace */ + break; + else { /* leading whitespace */ + (*startpp)++; + continue; + } + } + (*startpp)++; + if (cp >= buf+size-1) + break; + *cp++ = (u_char)c; + } + *cp = '\0'; + return (cp != buf); +} + +#define MAXCHARSTRING 255 + +static int +getcharstring(char *buf, char *data, + int minfields, int maxfields, int lineno) +{ + int nfield = 0, n = 0, i; + + do { + nfield++; + i = 0; + if (*buf == '"') { + buf++; + while(buf[i] && buf[i] != '"') + i++; + } else { + while(isspace(*buf)) + i++; + } + if (i > MAXCHARSTRING) { + fprintf(stderr, + "%d: RDATA field %d too long", + lineno, nfield); + return(0); + } + if (n + i + 1 > MAXDATA) { + fprintf(stderr, + "%d: total RDATA too long", lineno); + return(0); + } + data[n]=i; + memmove(data + 1 + n, buf, i); + buf += i + 1; + n += i + 1; + while(*buf && isspace(*buf)) + buf++; + } while (nfield < maxfields && *buf); + + if (nfield < minfields) { + fprintf(stderr, + "%d: expected %d RDATA fields, only saw %d", + lineno, minfields, nfield); + return (0); + } + + return (n); +} Property changes on: vendor/bind/8.3.4/contrib/bind/bin/nsupdate/nsupdate.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/bin/nsupdate/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/bin/nsupdate/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/bin/nsupdate/Makefile (revision 109985) @@ -0,0 +1,85 @@ +## Copyright (c) 1996,1999 by Internet Software Consortium +## +## 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. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM 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 +## SOFTWARE. + +# $Id: Makefile,v 8.26 2000/12/23 08:02:55 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g -Wall + +#(net2 and its descendents) +SYSTYPE = freebsd +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +EXE= +LEX = lex -I +SYSLIBS = -ll -lutil +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +STRIP=-s +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin + +LDFLAGS= +CFLAGS= ${CDEBUG} +CPPFLAGS= -I${PORTINCL} -I${INCL} + +PROG= nsupdate +SRCS= ${PROG}.c +OBJS= ${PROG}.${O} + +all: ${PROG}${EXE} + +${PROG}${EXE}: ${OBJS} ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} ${BOUNDS} -o ${PROG}${EXE} ${OBJS} \ + ${LIBBIND} ${SYSLIBS} + +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c + +distclean: clean + +clean: FRC + rm -f ${PROG}${EXE} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + +depend: ${SRCS} + mkdep ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${SRCS} + +${DESTDIR}${DESTBIN}: + mkdir -p ${DESTDIR}${DESTBIN} + +install: ${DESTDIR}${DESTBIN} ${PROG}${EXE} + ${INSTALL} ${STRIP} -c ${INSTALL_EXEC} -m 755 ${PROG}${EXE} ${DESTDIR}${DESTBIN}/${PROG}${EXE} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +tags: FRC + ctags *.[ch] + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Property changes on: vendor/bind/8.3.4/contrib/bind/bin/nsupdate/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/named.conf.5 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/named.conf.5 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/named.conf.5 (revision 109985) @@ -0,0 +1,2134 @@ +.\" Copyright (c) 1999-2000 by Internet Software Consortium +.\" +.\" 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. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\" CONSORTIUM 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 +.\" SOFTWARE. +.Dd January 7, 1999 +.Dt NAMED.CONF 5 +.Os BSD 4 +.Sh NAME +.Nm named.conf +.Nd configuration file for +.Xr named 8 +.Sh OVERVIEW +BIND 8 is much more configurable than previous release of BIND. There +are entirely new areas of configuration, such as access control lists +and categorized logging. Many options that previously applied to all +zones can now be used selectively. These features, plus a +consideration of future configuration needs led to the creation of a +new configuration file format. +.Ss General Syntax +A BIND 8 configuration consists of two general features, statements +and comments. All statements end with a semicolon. Many statements +can contain substatements, which are each also terminated with a +semicolon. +.Pp +The following statements are supported: +.Bl -tag -width 0n +.It Ic logging +specifies what the server logs, and where the log messages are sent +.It Ic options +controls global server configuration options and sets defaults for other +statements +.It Ic zone +defines a zone +.It Ic acl +defines a named IP address matching list, for access control and other uses +.It Ic key +specifies key information for use in authentication and authorization +.It Ic trusted-keys +defines DNSSEC keys that are preconfigured into the server and implicitly +trusted +.It Ic server +sets certain configuration options for individual remote servers +.It Ic controls +declares control channels to be used by the +.Nm ndc +utility +.It Ic include +includes another file +.El +.Pp +The +.Ic logging +and +.Ic options +statements may only occur once per configuration, while the rest may +appear numerous times. Further detail on each statement is provided +in individual sections below. +.Pp +Comments may appear anywhere that whitespace may appear in a BIND +configuration file. To appeal to programmers of all kinds, they can +be written in C, C++, or shell/perl constructs. +.Pp +C-style comments start with the two characters +.Li /* +(slash, star) and end with +.Li */ +(star, slash). +Because they are completely delimited with these characters, +they can be used to comment only a portion of a line or to span +multiple lines. +.Pp +C-style comments cannot be nested. For example, the following is +not valid because the entire comment ends with the first +.Li */ : +.Bd -literal -offset indent +/* This is the start of a comment. + This is still part of the comment. +/* This is an incorrect attempt at nesting a comment. */ + This is no longer in any comment. */ +.Ed +.Pp +C++-style comments start with the two characters +.Li // +(slash, slash) and continue to the end of the physical line. +They cannot be continued across multiple physical lines; to have +one logical comment span multiple lines, each line must use the +.Li // +pair. For example: +.Bd -literal -offset indent +// This is the start of a comment. The next line +// is a new comment, even though it is logically +// part of the previous comment. +.Ed +.Pp +Shell-style (or perl-style, if you prefer) comments start with the +character +.Li # +(hash or pound or number or octothorpe or whatever) and continue to +the end of the physical line, like C++ comments. For example: +.Bd -literal -offset indent +# This is the start of a comment. The next line +# is a new comment, even though it is logically +# part of the previous comment. +.Ed +.Pp +.Em WARNING : +you cannot use the +.Li ; +(semicolon) character to start a comment such as you would in a zone +file. The semicolon indicates the end of a configuration statement, +so whatever follows it will be interpreted as the start of the next +statement. +.Ss Converting from BIND 4.9.x +BIND 4.9.x configuration files can be converted to the new format +by using +.Pa src/bin/named/named-bootconf , +a shell script that is part of the BIND 8.2.x source kit. +.Sh DOCUMENTATION DEFINITIONS +Described below are elements used throughout the BIND configuration +file documentation. Elements which are only associated with one +statement are described only in the section describing that statement. +.Bl -tag -width 0n +.It Va acl_name +The name of an +.Va address_match_list +as defined by the +.Ic acl +statement. +.It Va address_match_list +A list of one or more +.Va ip_addr , +.Va ip_prefix , +.Va key_id , +or +.Va acl_name +elements, as described in the +.Sx ADDRESS MATCH LISTS +section. +.It Va dotted-decimal +One or more integers valued 0 through 255 separated only by dots +(``.''), such as +.Li 123 , +.Li 45.67 +or +.Li 89.123.45.67 . +.It Va domain_name +A quoted string which will be used as a DNS name, for example +.Qq Li my.test.domain . +.It Va path_name +A quoted string which will be used as a pathname, such as +.Qq Li zones/master/my.test.domain . +.It Va ip_addr +An IP address with exactly four elements in +.Va dotted-decimal +notation. +.It Va ip_port +An IP port +.Va number . +.Va number is limited to +.Li 0 +through +.Li 65535 , +with values below 1024 typically restricted to +root-owned processes. In some cases an asterisk (``*'') character +can be used as a placeholder to select a random high-numbered port. +.It Va ip_prefix +An IP network specified in +.Va dotted-decimal +form, followed by ``/'' +and then the number of bits in the netmask. E.g. +.Li 127/8 +is +the network +.Li 127.0.0.0 +with netmask +.Li 255.0.0.0 . +.Li 1.2.3.0/28 +is network +.Li 1.2.3.0 +with netmask +.Li 255.255.255.240. +.It Va key_name +A string representing the name of a shared key, to be used for transaction +security. +.It Va number +A non-negative integer with an entire range limited by the range of a +C language signed integer (2,147,483,647 on a machine with 32 bit +integers). Its acceptable value might further be limited by the +context in which it is used. +.It Va size_spec +A +.Va number , +the word +.Li unlimited , +or the word +.Li default . +.Pp +The maximum value of +.Va size_spec +is that of unsigned long integers on the machine. +.Li unlimited +requests unlimited use, or the maximum available amount. +.Li default +uses the limit that was in force when the server was started. +.Pp +A +.Va number +can optionally be followed by a scaling factor: +.Li K +or +.Li k +for kilobytes, +.Li M +or +.Li m +for megabytes, and +.Li G +or +.Li g +for gigabytes, which scale by 1024, 1024*1024, and 1024*1024*1024 +respectively. +.Pp +Integer storage overflow is currently silently ignored during +conversion of scaled values, resulting in values less than intended, +possibly even negative. Using +.Li unlimited +is the best way to safely set a really large number. +.It Va yes_or_no +Either +.Li yes +or +.Li no . +The words +.Li true +and +.Li false +are also accepted, as are the numbers +.Li 1 and +.Li 0 . +.El +.Sh ADDRESS MATCH LISTS +.Ss Syntax +.Bd -literal +\fIaddress_match_list\fR = 1\&*\fIaddress_match_element\fR +.Pp +\fIaddress_match_element\fR = [ \&"!\&" ] ( \fIaddress_match_list\fR / + \fIip_address\fR / \fIip_prefix\fR / + \fIacl_name\fR / \&"key \&" \fIkey_id\fR ) \&";\&" +.Ed +.Ss Definition and Usage +Address match lists are primarily used to determine access control for +various server operations. They are also used to define priorities +for querying other nameservers and to set the addresses on which +.Nm named +will listen for queries. +The elements which constitute an address match list can be any +of the following: +.Bl -bullet +.It +an +.Va ip-address +(in +.Va dotted-decimal +notation, +.It +an +.Va ip-prefix +(in the '/'-notation), +.It +A +.Va key_id , +as defined by the +.Ic key +statement, +.It +the name of an address match list previously defined with +the +.Ic acl +statement, or +.It +another +.Va address_match_list . +.El +.Pp +Elements can be negated with a leading exclamation mark (``!''), and +the match list names +.Li any , +.Li none , +.Li localhost +and +.Li localnets +are predefined. More information on those names can be found in the +description of the +.Ic acl +statement. +.Pp +The addition of the +.Ic key +clause made the name of this syntactic element something of a +misnomer, since security keys can be used to validate access without +regard to a host or network address. Nonetheless, the term ``address +match list'' is still used throughout the documentation. +.Pp +When a given IP address or prefix is compared to an address match +list, the list is traversed in order until an element matches. The +interpretation of a match depends on whether the list is being used +for access control, defining +.Ic listen-on +ports, or as a topology, and whether the element was +negated. +.Pp +When used as an access control list, a non-negated match allows access +and a negated match denies access. If there is no match at all in the +list, access is denied. The clauses +.Ic allow-query , +.Ic allow-transfer , +.Ic allow-update , +.Ic allow-recursion , +and +.Ic blackhole +all use address match lists like this. Similarly, the +.Ic listen-on +option will cause the server to not accept queries on any of the +machine's addresses which do not match the list. +.Pp +When used with the +.Ic topology +option, a non-negated match returns a distance based on its position on +the list (the closer the match is to the start of the list, the +shorter the distance is between it and the server). A negated match +will be assigned the maximum distance from the server. If there is no +match, the address will get a distance which is further than any +non-negated list element, and closer than any negated element. +.Pp +Because of the first-match aspect of the algorithm, an element that +defines a subset of another element in the list should come before the +broader element, regardless of whether either is negated. For +example, in +.Dl 1.2.3/24; !1.2.3.13 +the 1.2.3.13 element is completely useless, because the algorithm will +match any lookup for 1.2.3.13 to the 1.2.3/24 element. Using +.Dl !1.2.3.13; 1.2.3/24 +fixes that problem by having 1.2.3.13 blocked by the negation but all +other 1.2.3.* hosts fall through. +.Sh THE LOGGING STATEMENT +.Ss Syntax +.Bd -literal +logging { + [ channel \fIchannel_name\fR { + ( file \fIpath_name\fR + [ versions ( \fInumber\fR | unlimited ) ] + [ size \fIsize_spec\fR ] + | syslog ( kern | user | mail | daemon | auth | syslog | lpr | + news | uucp | cron | authpriv | ftp | + local0 | local1 | local2 | local3 | + local4 | local5 | local6 | local7 ) + | null ); +.Pp + [ severity ( critical | error | warning | notice | + info | debug [ \fIlevel\fR ] | dynamic ); ] + [ print-category \fIyes_or_no\fR; ] + [ print-severity \fIyes_or_no\fR; ] + [ print-time \fIyes_or_no\fR; ] + }; ] +.Pp + [ category \fIcategory_name\fR { + \fIchannel_name\fR; [ \fIchannel_name\fR; ... ] + }; ] + ... +}; +.Ed +.Ss Definition and Usage +The +.Ic logging +statement configures a wide variety of logging options for the nameserver. +Its +.Ic channel +phrase associates output methods, format options and +severity levels with a name that can then be used with the +.Ic category +phrase to select how various classes of messages are logged. +.Pp +Only one +.Ic logging +statement is used to define as many channels and categories as are wanted. +If there are multiple logging statements in a configuration, the first +defined determines the logging, and warnings are issued for the +others. If there is no logging statement, the logging configuration +will be: +.Bd -literal + logging { + category default { default_syslog; default_debug; }; + category panic { default_syslog; default_stderr; }; + category packet { default_debug; }; + category eventlib { default_debug; }; + }; +.Ed +.Pp +The logging configuration is established as soon as the +.Ic logging +statement is parsed. If you want to redirect +messages about processing of the entire configuration file, the +.Ic logging +statement must appear first. Even if you do not +redirect configuration file parsing messages, we recommend +always putting the +.Ic logging +statement first so that this rule need not be consciously recalled if +you ever do want the parser's messages relocated. +.Ss The channel phrase +All log output goes to one or more ``channels''; you can make as many +of them as you want. +.Pp +Every channel definition must include a clause that says whether +messages selected for the channel go to a file, to a particular syslog +facility, or are discarded. It can optionally also limit the message +severity level that will be accepted by the channel (default is +.Li info ) , +and whether to include a time stamp generated by +.Nm named , +the category name, or severity level. The default is not to include +any of those three. +.Pp +The word +.Li null +as the destination option for the +channel will cause all messages sent to it to be discarded; other +options for the channel are meaningless. +.Pp +The +.Ic file +clause can include limitations both on how +large the file is allowed to become, and how many versions of the file +will be saved each time the file is opened. +.Pp +The +.Ic size +option for files is simply a hard ceiling on +log growth. If the file ever exceeds the size, then +.Nm named +will just not write anything more to it until the file is reopened; +exceeding the size does not automatically trigger a reopen. The +default behavior is to not limit the size of the file. +.Pp +If you use the +.Ic version +logfile option, then +.Nm named +will retain that many backup versions of the file +by renaming them when opening. For example, if you choose to keep 3 +old versions of the file lamers.log then just before it is opened +lamers.log.1 is renamed to lames.log.2, lamers.log.0 is renamed to +lamers.log.1, and lamers.log is renamed to lamers.log.0. No rolled +versions are kept by default; any existing log file is simply appended. +The +.Li unlimited +keyword is synonymous with +.Li 99 +in current BIND releases. Example usage of size and versions options: +.Bd -literal + channel an_example_level { + file "lamers.log" versions 3 size 20m; + print-time yes; + print-category yes; + }; +.Ed +.Pp +The argument for the +.Ic syslog +clause is a syslog facility as described in the +.Xr syslog 3 +manual page. How +.Nm syslogd +will handle messages sent to this facility is described in the +.Xr syslog.conf 5 +manual page. If you have a system which uses a very old version of +syslog that only uses two arguments to the +.Fn openlog +function, then this clause is silently ignored. +.Pp +The +.Ic severity +clause works like syslog's ``priorities'', except that they can also be +used if you are writing straight to a file rather than using +syslog. Messages which are not at least of the severity level given +will not be selected for the channel; messages of higher severity +levels will be accepted. +.Pp +If you are using syslog, then the +.Pa syslog.conf +priorities will also determine what eventually passes through. +For example, defining a channel facility and severity as +.Li daemon +and +.Li debug +but only logging +.Li daemon.warning +via +.Pa syslog.conf +will cause messages of severity +.Li info +and +.Li notice +to be dropped. If the situation were reversed, with +.Nm named +writing messages of only +.Li warning +or higher, then +.Nm syslogd +would print all messages it received from the channel. +.Pp +The server can supply extensive debugging information when it is in +debugging mode. If the server's global debug level is greater than +zero, then debugging mode will be active. The global debug level is +set either by starting the +.Nm named +server with the +.Fl d +flag followed by a positive integer, or by sending the running server the +.Dv SIGUSR1 +signal (for example, by using +.Ic ndc trace ) . +The global debug level can be set to +zero, and debugging mode turned off, by sending the server the +.Dv SIGUSR2 +signal (as with +.Ic ndc notrace ) . +All debugging messages in the server have a +debug level, and higher debug levels give more more detailed output. +Channels that specify a specific debug severity, e.g. +.Bd -literal + channel specific_debug_level { + file \&"foo\&"; + severity debug 3; + }; +.Ed +.Pp +will get debugging output of level 3 or less any time the +server is in debugging mode, regardless of the global debugging level. +Channels with +.Li dynamic +severity use the server's global level to determine what messages to +print. +.Pp +If +.Ic print-time +has been turned on, then the date and time will be logged. +.Ic print-time +may be specified for a syslog channel, but is usually pointless since +syslog also prints the date and time. +If +.Ic print-category +is requested, then the category of the message will be logged as well. +Finally, if +.Ic print-severity +is on, then the severity level of the message will be logged. The +.Ic print- +options may be used +in any combination, and will always be printed in the following order: +time, category, severity. Here is an example where all three +.Ic print- +options are on: +.Bd -literal + 28-Apr-1997 15:05:32.863 default: notice: Ready to answer queries. +.Ed +.Pp +There are four predefined channels that are used for +default logging as follows. How they are used +used is described in the next section, +.Sx The category phrase . +.Bd -literal + channel default_syslog { + syslog daemon; # send to syslog's daemon facility + severity info; # only send priority info and higher + }; +.Pp + channel default_debug { + file \&"named.run\&"; # write to named.run in the working directory + # Note: stderr is used instead of \&"named.run\&" + # if the server is started with the -f option. + severity dynamic; # log at the server's current debug level + }; +.Pp + channel default_stderr { # writes to stderr + file \&"\&"; # this is illustrative only; there's currently + # no way of specifying an internal file + # descriptor in the configuration language. + severity info; # only send priority info and higher + }; +.Pp + channel null { + null; # toss anything sent to this channel + }; +.Ed +.Pp +Once a channel is defined, it cannot be redefined. Thus you cannot +alter the built-in channels directly, but you can modify the default +logging by pointing categories at channels you have defined. +.Ss The category phrase +There are many categories, so you can send the logs you want to see +wherever you want, without seeing logs you don't want. If you don't +specify a list of channels for a category, then log messages in that +category will be sent to the +.Li default +category instead. +If you don't specify a default category, the following ``default +default'' is used: +.Bd -literal + category default { default_syslog; default_debug; }; +.Ed +.Pp +As an example, let's say you want to log security events to a file, +but you also want keep the default logging behavior. You'd specify +the following: +.Bd -literal + channel my_security_channel { + file \&"my_security_file\&"; + severity info; + }; + category security { my_security_channel; + default_syslog; default_debug; }; +.Ed +.Pp +To discard all messages in a category, specify the +.Li null +channel: +.Bd -literal + category lame-servers { null; }; + category cname { null; }; +.Ed +.Pp +The following categories are available: +.Bl -tag -width 0n +.It Ic default +The catch-all. Many things still aren't classified into categories, +and they all end up here. Also, if you don't specify any channels for +a category, the default category is used instead. If you do not +define the default category, the following definition is used: +.Dl category default { default_syslog; default_debug; }; +.It Ic config +High-level configuration file processing. +.It Ic parser +Low-level configuration file processing. +.It Ic queries +A short log message is generated for every query the server receives. +.It Ic lame-servers +Messages like ``Lame server on ...'' +.It Ic statistics +Statistics. +.It Ic panic +If the server has to shut itself down due to an internal problem, it +will log the problem in this category as well as in the problem's native +category. If you do not define the panic category, the following definition +is used: +.Dl category panic { default_syslog; default_stderr; }; +.It Ic update +Dynamic updates. +.It Ic update-security +Denied dynamic updates due to access controls. +.It Ic ncache +Negative caching. +.It Ic xfer-in +Zone transfers the server is receiving. +.It Ic xfer-out +Zone transfers the server is sending. +.It Ic db +All database operations. +.It Ic eventlib +Debugging info from the event system. Only one channel may be specified for +this category, and it must be a file channel. If you do not define the +eventlib category, the following definition is used: +.Dl category eventlib { default_debug; }; +.It Ic packet +Dumps of packets received and sent. Only one channel may be specified for +this category, and it must be a file channel. If you do not define the +packet category, the following definition is used: +.Dl category packet { default_debug; }; +.It Ic notify +The NOTIFY protocol. +.It Ic cname +Messages like ``... points to a CNAME''. +.It Ic security +Approved/unapproved requests. +.It Ic os +Operating system problems. +.It Ic insist +Internal consistency check failures. +.It Ic maintenance +Periodic maintenance events. +.It Ic load +Zone loading messages. +.It Ic response-checks +Messages arising from response checking, such as +``Malformed response ...'', ``wrong ans. name ...'', +``unrelated additional info ...'', ``invalid RR type ...'', +and ``bad referral ...''. +.El +.Sh THE OPTIONS STATEMENT +.Ss Syntax +.Bd -literal +options { + [ hostname \fIhostname_string\fR; ] + [ version \fIversion_string\fR; ] + [ directory \fIpath_name\fR; ] + [ named-xfer \fIpath_name\fR; ] + [ dump-file \fIpath_name\fR; ] + [ memstatistics-file \fIpath_name\fR; ] + [ pid-file \fIpath_name\fR; ] + [ statistics-file \fIpath_name\fR; ] + [ auth-nxdomain \fIyes_or_no\fR; ] + [ deallocate-on-exit \fIyes_or_no\fR; ] + [ dialup \fIyes_or_no\fR; ] + [ fake-iquery \fIyes_or_no\fR; ] + [ fetch-glue \fIyes_or_no\fR; ] + [ has-old-clients \fIyes_or_no\fR; ] + [ host-statistics \fIyes_or_no\fR; ] + [ host-statistics-max \fInumber\fR; ] + [ multiple-cnames \fIyes_or_no\fR; ] + [ notify ( \fIyes_or_no\fR | explicit ); ] + [ suppress-initial-notify \fIyes_or_no\fR; ] + [ recursion \fIyes_or_no\fR; ] + [ rfc2308-type1 \fIyes_or_no\fR; ] + [ use-id-pool \fIyes_or_no\fR; ] + [ treat-cr-as-space \fIyes_or_no\fR; ] + [ also-notify \fIyes_or_no\fR; ] + [ forward ( only | first ); ] + [ forwarders { [ \fIin_addr\fR ; [ \fIin_addr\fR ; ... ] ] }; ] + [ check-names ( master | slave | response ) ( warn | fail | ignore ); ] + [ allow-query { \fIaddress_match_list\fR }; ] + [ allow-recursion { \fIaddress_match_list\fR }; ] + [ allow-transfer { \fIaddress_match_list\fR }; ] + [ blackhole { \fIaddress_match_list\fR }; ] + [ listen-on [ port \fIip_port\fR ] { \fIaddress_match_list\fR }; ] + [ query-source [ address ( \fIip_addr\fR | * ) ] + [ port ( \fIip_port\fR | * ) ] ; ] + [ lame-ttl \fInumber\fR; ] + [ max-transfer-time-in \fInumber\fR; ] + [ max-ncache-ttl \fInumber\fR; ] + [ min-roots \fInumber\fR; ] + [ serial-queries \fInumber\fR; ] + [ transfer-format ( one-answer | many-answers ); ] + [ transfers-in \fInumber\fR; ] + [ transfers-out \fInumber\fR; ] + [ transfers-per-ns \fInumber\fR; ] + [ transfer-source \fIip_addr\fR; ] + [ maintain-ixfr-base \fIyes_or_no\fR; ] + [ max-ixfr-log-size \fInumber\fR; ] + [ coresize \fIsize_spec\fR ; ] + [ datasize \fIsize_spec\fR ; ] + [ files \fIsize_spec\fR ; ] + [ stacksize \fIsize_spec\fR ; ] + [ cleaning-interval \fInumber\fR; ] + [ heartbeat-interval \fInumber\fR; ] + [ interface-interval \fInumber\fR; ] + [ statistics-interval \fInumber\fR; ] + [ topology { \fIaddress_match_list\fR }; ] + [ sortlist { \fIaddress_match_list\fR }; ] + [ rrset-order { \fIorder_spec\fR ; [ \fIorder_spec\fR ; ... ] }; ] + [ preferred-glue ( A | AAAA ); ] +}; +.Ed +.Ss Definition and Usage +The options statement sets up global options to be used by +BIND. This statement may appear at only once in a +configuration file; if more than one occurrence is found, the +first occurrence determines the actual options used, +and a warning will be generated. If there is no options statement, +an options block with each option set to its default will be used. +.Ss Server Information +.Bl -tag -width 0n +.It Ic hostname +This defaults to the hostname of the machine hosting the nameserver as found by gethostname(). +Its prime purpose is to be able to identify which of a number of anycast +servers is actually answering your queries by sending a txt query for +.Pa hostname.bind +in class chaos to the anycast server and geting back a unique name. +Setting +the hostname to a empty string ("") will disable processing of the queries. +.It Ic version +The version the server should report via the ndc command or via a query of +name +.Pa version.bind +in class chaos. +The default is the real version number of the server, +but some server operators prefer the string ( +.Ic surely you must be joking +). +.El +.Ss Pathnames +.Bl -tag -width 0n +.It Ic directory +The working directory of the server. Any non-absolute +pathnames in the configuration file will be taken as relative to this +directory. The default location for most server output files +(e.g. +.Pa named.run ) +is this directory. If a directory is not +specified, the working directory defaults to +.Pa \&. , +the directory from which the +server was started. The directory specified should be an absolute path. +.It Ic named-xfer +The pathname to the named-xfer program that the server uses for +inbound zone transfers. If not specified, the default is +system dependent (e.g. +.Pa /usr/sbin/named-xfer +). +.It Ic dump-file +The pathname of the file the server dumps the database to when it +receives +.Dv SIGINT +signal (as sent by +.Ic ndc dumpdb +). If not specified, the default is +.Pa named_dump.db . +.It Ic memstatistics-file +The pathname of the file the server writes memory usage statistics to +on exit, if +.Ic deallocate-on-exit +is +.Li yes . +If not specified, the default is +.Pa named.memstats . +.It Ic pid-file +The pathname of the file the server writes its process ID in. If not +specified, the default is operating system dependent, but is usually +.Pa /var/run/named.pid +or +.Pa /etc/named.pid . +The pid-file is used by programs like +.Nm ndc +that want to send signals to the running nameserver. +.It Ic statistics-file +The pathname of the file the server appends statistics to when it +receives +.Dv SIGILL +signal (from +.Ic ndc stats ) . +If not specified, the default is +.Pa named.stats . +.El +.Ss Boolean Options +.Bl -tag -width 0n +.It Ic auth-nxdomain +If +.Li yes , +then the +.Li AA +bit is always set on +.Dv NXDOMAIN +responses, even if the server is not actually authoritative. +The default is +.Li no . +Turning +.Lc auth-nxdomain +will allow older clients that require +.Li AA +to be set to accept +.Dv NXDOMAIN +responses to work. +.It Ic deallocate-on-exit +If +.Li yes , +then when the server exits it will painstakingly deallocate every +object it allocated, and then write a memory usage report to the +.Ic memstatistics-file . +The default is +.Li no , +because it is faster to let the operating system clean up. +.Ic deallocate-on-exit +is handy for detecting memory leaks. +.It Ic dialup +If +.Li yes , +then the server treats all zones as if they are doing zone transfers +across a dial on demand dialup link, which can be brought up by +traffic originating from this server. This has different effects +according to zone type and concentrates the zone maintenance so that +it all happens in a short interval, once every +.Ic heartbeat-interval +and hopefully during the one call. +It also suppresses some of the normal zone maintenance traffic. +The default is +.Li no . +The +.Ic dialup +option may also be specified in the +.Ic zone +statement, in which +case it overrides the +.Ic options dialup +statement. +.Pp +If the zone is a +.Ic master +then the server will send out +.Dv NOTIFY +request to all the slaves. +This will trigger the zone up to date checking in the slave (providing +it supports +.Dv NOTIFY ) +allowing the slave +to verify the zone while the call us up. +.Pp +If the zone is a +.Ic slave +or +.Ic stub +then the server will suppress the zone regular zone up to date queries +and only perform the when the +.Ic heartbeat-interval +expires. +.It Ic fake-iquery +If +.Li yes , +the server will simulate the obsolete DNS query type +.Dv IQUERY . +The default is +.Li no . +.It Ic fetch-glue +If +.Li yes +(the default), the server will fetch ``glue'' resource +records it doesn't have when constructing the additional data section of +a response. +.Ic fetch-glue no +can be used in conjunction with +.Ic recursion no +to prevent the server's cache from growing or +becoming corrupted (at the cost of requiring more work from the client). +.It Ic has-old-clients +Setting the option to +.Li yes , +is equivalent to setting the following three options: +.Ic auth-nxdomain yes ; , +.Ic maintain-ixfr-base yes ; , +and +.Ic rfc2308-type1 no ; +.Pp +The use of +.Ic has-old-clients +with +.Ic auth-nxdomain , +.Ic maintain-ixfr-base , +and +.Ic rfc2308-type1 +is order dependant. +.It Ic host-statistics +If +.Li yes , +then statistics are kept for every host that the the nameserver +interacts with. The default is +.Li no . +.Em Note : +turning on +.Ic host-statistics +can consume huge amounts of memory. +.It Ic maintain-ixfr-base +If +.Li yes , +a IXFR database file is kept for all dynamicaly updated zones. +This enables the server to answer IXFR queries which can speed up +zone transfers enormously. +The default is +.Li no . +.It Ic multiple-cnames +If +.Li yes , +then multiple CNAME resource records will be +allowed for a domain name. The default is +.Li no . +Allowing multiple CNAME records is against standards and is not recommended. +Multiple CNAME support is available because previous versions of BIND +allowed multiple CNAME records, and these records have been used for load +balancing by a number of sites. +.It Ic notify +If +.Li yes +(the default), DNS NOTIFY messages are sent when a +zone the server is authoritative for changes. The use of NOTIFY +speeds convergence between the master and its slaves. Slave servers +that receive a NOTIFY message and understand it will contact the +master server for the zone and see if they need to do a zone transfer, and +if they do, they will initiate it immediately. +If +.Li explicit , +the DNS NOTIFY messages will only be sent to the addresses in the +.Ic also-notify +list. +The +.Ic notify +option may also be specified in the +.Ic zone +statement, in which case it overrides the +.Ic options notify +statement. +.It Ic suppress-initial-notify +If +.Li yes , +suppress the initial notify messages when the server first loads. +The default is +.Li no . +.It Ic recursion +If +.Li yes , +and a DNS query requests recursion, then the +server will attempt to do all the work required to answer the query. +If recursion is not on, the server will return a referral to the +client if it doesn't know the answer. The default is +.Li yes . +See also +.Ic fetch-glue +above. +.It Ic rfc2308-type1 +If +.Li yes, +the server will send NS records along with the SOA record for negative +answers. You need to set this to no if you have an old BIND server using +you as a forwarder that does not understand negative answers which contain +both SOA and NS records or you have an old version of sendmail. The correct +fix is to upgrade the broken server or sendmail. The default is +.Li no . +.It Ic use-id-pool +If +.Li yes, +the server will keep track of its own outstanding query ID's to avoid duplication +and increase randomness. This will result in 128KB more memory being consumed +by the server. The default is +.Li no . +.It Ic treat-cr-as-space +If +.Li yes, +the server will treat CR characters the same way it treats a space +or tab. This may be necessary when loading zone files on a UNIX system +that were generated on an NT or DOS machine. The default is +.Li no . +.El +.Ss Also-Notify +.Ic also-notify +.Pp +Defines a global list of IP addresses that also get sent NOTIFY messages +whenever a fresh copy of the zone is loaded. This helps to ensure that copies of +the zones will quickly converge on ``stealth'' servers. If an +.Ic also-notify +list is given in a +.Ic zone +statement, it will override the +.Ic options also-notify +statement. When a +.Ic zone notify +statement is set to +.Ic no , +the IP addresses in +the global +.Ic also-notify +list will not get sent NOTIFY messages for that zone. +The default is the empty list (no global notification list). +.Ss Forwarding +The forwarding facility can be used to create a large site-wide +cache on a few servers, reducing traffic over links to external +nameservers. It can also be used to allow queries by servers that do +not have direct access to the Internet, but wish to look up exterior +names anyway. Forwarding occurs only on those queries for which the +server is not authoritative and does not have the answer in its cache. +.Bl -tag -width 0n +.It Ic forward +This option is only meaningful if the +.Ic forwarders +list is +not empty. A value of +.Li first , +the default, causes the +server to query the forwarders first, and if that doesn't answer the +question the server will then look for the answer itself. If +.Li only +is specified, the server will only query the forwarders. +.It Ic forwarders +Specifies the IP addresses to be used for forwarding. The default is the +empty list (no forwarding). +.El +.Pp +Forwarding can also be configured on a per-zone basis, allowing for +the global forwarding options to be overridden in a variety of ways. +You can set particular zones to use different forwarders, or have +different +.Ic forward only/first +behavior, or to not forward +at all. See +.Sx THE ZONE STATEMENT +section for more information. +.Pp +Future versions of BIND 8 will provide a more powerful forwarding +system. The syntax described above will continue to be supported. +.Ss Name Checking +The server can check domain names based upon their expected client contexts. +For example, a domain name used as a hostname can be checked for compliance +with the RFCs defining valid hostnames. +.Pp +Three checking methods are available: +.Bl -tag -width 0n +.It Ic ignore +No checking is done. +.It Ic warn +Names are checked against their expected client contexts. Invalid names are +logged, but processing continues normally. +.It Ic fail +Names are checked against their expected client contexts. Invalid names are +logged, and the offending data is rejected. +.El +.Pp +The server can check names three areas: master zone files, slave +zone files, and in responses to queries the server has initiated. If +.Ic check-names response fail +has been specified, and +answering the client's question would require sending an invalid name +to the client, the server will send a +.Dv REFUSED +response code to the client. +.Pp +The defaults are: +.Bd -literal + check-names master fail; + check-names slave warn; + check-names response ignore; +.Ed +.Pp +.Ic check-names +may also be specified in the +.Ic zone +statement, in which case it overrides the +.Ic options check-names +statement. When used in a +.Ic zone +statement, the area is not specified (because it can be deduced from +the zone type). +.Ss Access Control +Access to the server can be restricted based on the IP address of the +requesting system or via shared secret keys. See +.Sx ADDRESS MATCH LISTS +for details on how to specify access criteria. +.Bl -tag -width 0n +.It Ic allow-query +Specifies which hosts are allowed to ask ordinary questions. +.Ic allow-query +may also be specified in the +.Ic zone +statement, in which case it overrides the +.Ic options allow-query +statement. If not specified, the default is to allow queries +from all hosts. +.Bl -tag -width 0n +.It Ic allow-recursion +Specifies which hosts are allowed to ask recursive questions. +If not specified, the default is to allow recursive queries +from all hosts. +.It Ic allow-transfer +Specifies which hosts are allowed to receive zone transfers from the +server. +.Ic allow-transfer +may also be specified in the +.Ic zone +statement, in which case it overrides the +.Ic options allow-transfer +statement. If not specified, the default +is to allow transfers from all hosts. +.It Ic blackhole +Specifies a list of addresses that the server will not accept queries from +or use to resolve a query. Queries from these addresses will not be +responded to. +.El +.El +.Ss Interfaces +The interfaces and ports that the server will answer queries from may +be specified using the +.Ic listen-on +option. +.Ic listen-on +takes an optional port, and an address match list. +The server will listen on all interfaces allowed by the address match +list. If a port is not specified, port 53 will be used. +.Pp +Multiple +.Ic listen-on +statements are allowed. For example, +.Bd -literal + listen-on { 5.6.7.8; }; + listen-on port 1234 { !1.2.3.4; 1.2/16; }; +.Ed +.Pp +will enable the nameserver on port 53 for the IP address 5.6.7.8, and +on port 1234 of an address on the machine in net 1.2 that is not +1.2.3.4. +.Pp +If no +.Ic listen-on +is specified, the server will listen on port +53 on all interfaces. +.Ss Query Address +If the server doesn't know the answer to a question, it will query +other nameservers. +.Ic query-source +specifies the address and port used for such queries. If +.Ic address +is +.Li * +or is omitted, a wildcard IP address +( +.Dv INADDR_ANY ) +will be used. If +.Va port +is +.Li * +or is omitted, a random unprivileged port will be used. +The default is +.Dl query-source address * port *; +.Pp +Note: +.Ic query-source +currently applies only to UDP queries; +TCP queries always use a wildcard IP address and a random unprivileged +port. +.Ss Zone Transfers +.Bl -tag -width 0n +.It Ic max-transfer-time-in +Inbound zone transfers ( +.Nm named-xfer +processes) running +longer than this many minutes will be terminated. +The default is 120 minutes (2 hours). +.It Ic transfer-format +The server supports two zone transfer methods. +.Li one-answer +uses one DNS message per resource record +transferred. +.Li many-answers +packs as many resource records +as possible into a message. +.Li many-answers +is more efficient, but is only known to be understood by BIND 8.1 and +patched versions of BIND 4.9.5. The default is +.Li one-answer . +.Ic transfer-format +may be overridden on a per-server basis by using the +.Ic server +statement. +.It Ic transfers-in +The maximum number of inbound zone transfers that can be running +concurrently. The default value is 10. Increasing +.Ic transfers-in +may speed up the convergence of slave zones, +but it also may increase the load on the local system. +.It Ic transfers-out +This option will be used in the future to limit the number of +concurrent outbound zone transfers. It is checked for syntax, but is +otherwise ignored. +.It Ic transfers-per-ns +The maximum number of inbound zone transfers ( +.Nm named-xfer +processes) that can be concurrently transferring from a given remote +nameserver. The default value is 2. Increasing +.Ic transfers-per-ns +may speed up the convergence of slave zones, but it also may increase +the load on the remote nameserver. +.Ic transfers-per-ns +may be overridden on a per-server basis by using the +.Ic transfers +phrase of the +.Ic server +statement. +.It Ic transfer-source +.Nm transfer-source +determines which local address will be bound to the TCP connection used to fetch all zones +transferred inbound by the server. If not set, it defaults to a system controlled value which will usually be the address of the interface ``closest to`` the remote end. This +address must appear in the remote end's +.Nm allow-transfer +option for the zones being transferred, if one is specified. This statement sets the +.Nm transfer-source +for all zones, but can be overriden on a per-zone basis by includinga +.Nm transfer-source +statement within the zone block in the configuration file. +.El +.Ss Resource Limits +The server's usage of many system resources can be limited. Some +operating systems don't support some of the limits. On such systems, +a warning will be issued if the unsupported limit is used. Some +operating systems don't support limiting resources, and on these systems +a +.D1 cannot set resource limits on this system +message will +be logged. +.Pp +Scaled values are allowed when specifying resource limits. For +example, +.Li 1G +can be used instead of +.Li 1073741824 +to specify a limit of one gigabyte. +.Li unlimited +requests unlimited use, or the maximum +available amount. +.Li default +uses the limit that was in +force when the server was started. +See the definition of +.Va size_spec +in the +.Sx DOCUMENTATION DEFINITIONS +section for more details. +.Bl -tag -width 0n +.It Ic coresize +The maximum size of a core dump. The default value is +.Li default . +.It Ic datasize +The maximum amount of data memory the server may use. The default +value is +.Li default . +.It Ic files +The maximum number of files the server may have open concurrently. +The default value is +.Li unlimited . +Note that on some operating systems the server cannot set an unlimited +value and cannot determine the maximum number of open files the kernel +can support. On such systems, choosing +.Li unlimited +will cause the server to use +the larger of the +.Va rlim_max +from +.Fn getrlimit RLIMIT_NOFILE +and the value returned by +.Fn sysconf _SC_OPEN_MAX . +If the +actual kernel limit is larger than this value, use +.Ic limit files +to specify the limit explicitly. +.It Ic max-ixfr-log-size +The +.Li max-ixfr-log-size +will be used in a future release of the server to limit the size of the transaction +log kept for Incremental Zone Transfer. +.It Ic stacksize +The maximum amount of stack memory the server may use. The default value is +.Li default . +.El +.Ss Periodic Task Intervals +.Bl -tag -width 0n +.It Ic cleaning-interval +The server will remove expired resource records from the cache every +.Ic cleaning-interval +minutes. The default is 60 minutes. If set +to 0, no periodic cleaning will occur. +.It Ic heartbeat-interval +The server will perform zone maintenance tasks for all zones marked +.Ic dialup yes +whenever this interval expires. +The default is 60 minutes. Reasonable values are up to 1 day (1440 minutes). +If set to 0, no zone maintenance for these zones will occur. +.It Ic interface-interval +The server will scan the network interface list every +.Ic interface-interval +minutes. The default is 60 minutes. +If set to 0, interface scanning will only occur when the configuration +file is loaded. After the scan, listeners will be started on any new +interfaces (provided they are allowed by the +.Ic listen-on +configuration). Listeners on interfaces that have gone away will be +cleaned up. +.It Ic statistics-interval +Nameserver statistics will be logged every +.Ic statistics-interval +minutes. The default is 60. If set to 0, no statistics will be logged. +.El +.Ss Topology +All other things being equal, when the server chooses a nameserver +to query from a list of nameservers, it prefers the one that is +topologically closest to itself. The +.Ic topology +statement takes an address match list and interprets it in a special way. +Each top-level list element is assigned a distance. +Non-negated elements get a distance based on +their position in the list, where the closer the match is to the start +of the list, the shorter the distance is between it and the server. A +negated match will be assigned the maximum distance from the server. +If there is no match, the address will get a distance which is further +than any non-negated list element, and closer than any negated +element. For example, +.Bd -literal + topology { + 10/8; + !1.2.3/24; + { 1.2/16; 3/8; }; + }; +.Ed +.Pp +will prefer servers on network 10 the most, followed by hosts on +network 1.2.0.0 (netmask 255.255.0.0) and network 3, with the exception +of hosts on network 1.2.3 (netmask 255.255.255.0), which is preferred least +of all. +.Pp +The default topology is +.Dl topology { localhost; localnets; }; +.Ss Resource Record sorting +When returning multiple RRs, the nameserver will normally return them in +.Ic Round Robin , +i.e. after each request, the first RR is put to the end of the list. +As the order of RRs is not defined, this should not cause any problems. +.Pp +The client resolver code should re-arrange the RRs as appropriate, i.e. using +any addresses on the local net in preference to other addresses. However, not all +resolvers can do this, or are not correctly configured. +.Pp +When a client is using a local server, the sorting can be performed in the server, +based on the client's address. This only requires configuring the nameservers, +not all the clients. +.Pp +The +.Ic sortlist +statement takes an address match list and interprets it even more +specially than the +.Ic topology +statement does. +.Pp +Each top level statement in the sortlist must itself be an explicit address match +list with one or two elements. The first element (which may be an IP address, +an IP prefix, an ACL name or nested address match list) of each top level list is +checked against the source address of the query until a match is found. +.Pp +Once the source address of the query has been matched, if the top level +statement contains only one element, the actual primitive element that +matched the source address is used to select the address in the response to +move to the beginning of the response. If the statement is a list of two elements, +the second element is treated like the address match list in a topology +statement. Each top level element is assigned a distance and the address in the +response with the minimum distance is moved to the beginning of the response. +.Pp +In the following example, any queries received from any of the addresses of the +host itself will get responses preferring addresses on any of the locally +connected networks. Next most preferred are addresses on the 192.168.1/24 +network, and after that either the 192.168.2/24 or 192.168.3/24 network with no +preference shown between these two networks. Queries received from a host on +the 192.168.1/24 network will prefer other addresses on that network to the +192.168.2/24 and 192.168.3/24 networks. Queries received from a host on the +192.168.4/24 or the 192.168.5/24 network will only prefer other addresses on +their directly connected networks. +.Bd -literal +sortlist { + { localhost; // IF the local host + { localnets; // THEN first fit on the + 192.168.1/24; // following nets + { 192,168.2/24; 192.168.3/24; }; }; }; + { 192.168.1/24; // IF on class C 192.168.1 + { 192.168.1/24; // THEN use .1, or .2 or .3 + { 192.168.2/24; 192.168.3/24; }; }; }; + { 192.168.2/24; // IF on class C 192.168.2 + { 192.168.2/24; // THEN use .2, or .1 or .3 + { 192.168.1/24; 192.168.3/24; }; }; }; + { 192.168.3/24; // IF on class C 192.168.3 + { 192.168.3/24; // THEN use .3, or .1 or .2 + { 192.168.1/24; 192.168.2/24; }; }; }; + { { 192.168.4/24; 192.168.5/24; }; // if .4 or .5, prefer that net + }; +}; +.Ed +.Pp +The following example will give reasonable behaviour for the local host and +hosts on directly connected networks. It is similar to the behavior of the +address sort in BIND 4.9.x. Responses sent to queries from the local host will +favor any of the directly connected networks. Responses sent to queries from +any other hosts on a directly connected network will prefer addresses on that +same network. Responses to other queries will not be sorted. +.Bd -literal +sortlist { + { localhost; localnets; }; + { localnets; }; +}; +.Ed +.Ss RRset Ordering +When multiple records are returned in an answer it may be useful to configure +the order the records are placed into the response. For example the records for +a zone might be configured to always be returned in the order they are defined +in the zone file. Or perhaps a random shuffle of the records as they are +returned is wanted. The rrset-order statement permits configuration of the +ordering made of the records in a multiple record response. The default, if no +ordering is defined, is a cyclic ordering (round robin). +.Pp +An +.Ic order_spec +is defined as follows: +.Bd -literal + [ \fIclass class_name\fR ][ \fItype type_name\fR ][ \fIname\fR "FQDN" ] \fIorder\fR ordering +.Ed +.Pp +If no class is specified, the default is +.Ic ANY . +If no +.Li Ictype +is specified, the default is +.Ic ANY . +If no name is specified, the default is "*". +.Pp +The legal values for +.Ic ordering +are: +.Bl -tag -width indent +.It Ic fixed +Records are returned in the order they are defined in the zone file. +.It Ic random +Records are returned in some random order. +.It Ic cyclic +Records are returned in a round-robin order. +.El +.Pp +For example: +.Bd -literal + rrset-order { + class IN type A name "rc.vix.com" order random; + order cyclic; + }; +.Ed +.Pp +will cause any responses for type A records in class IN that have "rc.vix.com" as +a suffix, to always be returned in random order. All other records are returned +in cyclic order. +.Pp +If multiple +.Ic rrset-order +statements appear, they are not combined--the last one applies. +.Pp +If no +.Ic rrset-order +statement is specified, a default one of: +.Bd -literal + rrset-order { class ANY type ANY name "*" order cyclic ; }; +.Ed +.Pp +is used. +.Ss Glue Ordering +When running a root nameserver it is sometimes necessary to ensure that other +nameservers that are priming are successful. +This requires that glue A records for at least of the nameservers are returned +in the answer to a priming query. +This can be achieved by setting +.Ic preferred-glue A; +which will add A records before other types in the additional section. +.Ss Tuning +.Bl -tag -width 0n +.It Ic lame-ttl +Sets the number of seconds to cache a lame server indication. 0 disables +caching. Default is 600 (10 minutes). Maximum value is 1800 (30 minutes) +.It Ic max-ncache-ttl +To reduce network traffic and increase performance the server store negative +answers. +.Ic max-ncache-ttl +is used to set a maximum retention time +for these answers in the server is seconds. The default +.Ic max-ncache-ttl +is 10800 seconds (3 hours). +.Ic max-ncache-ttl +cannot exceed the maximum retention time for ordinary (positive) +answers (7 days) and will be silently truncated to 7 days if set to a +value which is greater that 7 days. +.It Ic min-roots +The minimum number of root servers that is required for a request for the root +servers to be accepted. Default is 2. +.El +.Sh THE ZONE STATEMENT +.Ss Syntax +.Bd -literal +zone \fIdomain_name\fR [ ( in | hs | hesiod | chaos ) ] { + type master; + file \fIpath_name\fR; + [ check-names ( warn | fail | ignore ); ] + [ allow-update { \fIaddress_match_list\fR }; ] + [ allow-query { \fIaddress_match_list\fR }; ] + [ allow-transfer { \fIaddress_match_list\fR }; ] + [ forward ( only | first ); ] + [ forwarders { [ \fIip_addr\fR ; [ \fIip_addr\fR ; ... ] ] }; ] + [ dialup \fIyes_or_no\fR; ] + [ notify ( \fIyes_or_no\fR | explicit ); ] + [ also-notify { \fIip_addr\fR; [ \fIip_addr\fR; ... ] }; + [ pubkey \fInumber\fR \fInumber\fR \fInumber\fR \fIstring\fR; ] +}; +.Pp +zone \fIdomain_name\fR [ ( in | hs | hesiod | chaos ) ] { + type ( slave | stub ); + [ file \fIpath_name\fR; ] + masters [ port \fIip_port\fR ] { \fIip_addr\fR [ key \fIkey_id\fR ]; [ ... ] }; + [ check-names ( warn | fail | ignore ); ] + [ allow-update { \fIaddress_match_list\fR }; ] + [ allow-query { \fIaddress_match_list\fR }; ] + [ allow-transfer { \fIaddress_match_list\fR }; ] + [ forward ( only | first ); ] + [ forwarders { [ \fIip_addr\fR ; [ \fIip_addr\fR ; ... ] ] }; ] + [ transfer-source \fIip_addr\fR; ] + [ max-transfer-time-in \fInumber\fR; ] + [ notify \fIyes_or_no\fR; ] + [ also-notify { \fIip_addr\fR; [ \fIip_addr\fR; ... ] }; + [ pubkey \fInumber\fR \fInumber\fR \fInumber\fR \fIstring\fR; ] +}; +.Pp +zone \fIdomain_name\fR [ ( in | hs | hesiod | chaos ) ] { + type forward; + [ forward ( only | first ); ] + [ forwarders { [ \fIip_addr\fR ; [ \fIip_addr\fR ; ... ] ] }; ] + [ check-names ( warn | fail | ignore ); ] +}; +.Pp +zone \&".\&" [ ( in | hs | hesiod | chaos ) ] { + type hint; + file \fIpath_name\fR; + [ check-names ( warn | fail | ignore ); ] +}; +.Ed +.Ss Definition and Usage +The +.Ic zone +statement is used to define how information about particular DNS zones +is managed by the server. There are five different zone types. +.Bl -tag -width 0n +.It Ic master +The server has a master copy of the data for the zone and will be able +to provide authoritative answers for it. +.It Ic slave +A +.Ic slave +zone is a replica of a master zone. The +.Ic masters +list specifies one or more IP addresses that the slave contacts to +update its copy of the zone. If a +.Ic port +is specified then checks to see if the zone is current and zone transfers +will be done to the port given. If +.Ic file +is specified, then the replica will be written to the named file. +Use of the +.Ic file +clause is highly recommended, since it often speeds server startup +and eliminates a needless waste of bandwidth. +.It Ic stub +A +.Ic stub +zone is like a slave zone, except that it replicates +only the NS records of a master zone instead of the entire zone. +.It Ic forward +A +.Ic forward +zone is used to direct all queries in it to other servers, as described in +.Sx THE OPTIONS STATEMENT +section. The specification of options in such a zone will override +any global options declared in the +.Ic options +statement. +.Pp +If either no +.Ic forwarders +clause is present in the zone or an empty list for +.Ic forwarders +is given, then no forwarding will be done for the zone, cancelling the +effects of any +.Ic forwarders +in the +.Ic options +statement. +Thus if you want to use this type of zone to change only the behavior of +the global +.Ic forward +option, and not the servers used, then you also need to respecify the +global forwarders. +.It Ic hint +The initial set of root nameservers is specified using a +.Ic hint +zone. When the server starts up, it uses the root hints +to find a root nameserver and get the most recent list of root nameservers. +.El +.Pp +Note: previous releases of BIND used the term +.Ic primary +for a master zone, +.Ic secondary +for a slave zone, and +.Ic cache +for a hint zone. +.Ss Classes +The zone's name may optionally be followed by a class. If a class is not +specified, class +.Ic in +(for "internet"), is assumed. This is correct for the vast majority +of cases. +.Pp +The +.Ic hesiod +class is for an information service from MIT's Project Athena. It is +used to share information about various systems databases, such as +users, groups, printers and so on. More information can be found at +ftp://athena-dist.mit.edu/pub/ATHENA/usenix/athena_changes.PS. +The keyword +.Ic hs +is a synonym for +.Ic hesiod . +.Pp +Another MIT development was CHAOSnet, a LAN protocol created in the +mid-1970s. It is still sometimes seen on LISP stations and other +hardware in the AI community, and zone data for it can be specified +with the +.Ic chaos +class. +.Ss Options +.Bl -tag -width 0n +.It Ic check-names +See the subsection on +.Sx Name Checking +in +.Sx THE OPTIONS STATEMENT . +.It Ic allow-query +See the description of +.Ic allow-query +in the +.Sx Access Control +subsection of +.Sx THE OPTIONS STATEMENT . +.It Ic allow-update +Specifies which hosts are allowed to submit Dynamic DNS updates to the +server. The default is to deny updates from all hosts. +.It Ic allow-transfer +See the description of +.Ic allow-transfer +in the +.Sx Access Control +subsection of +.Sx THE OPTIONS STATEMENT . +.It Ic transfer-source +.Ic transfer-source +determines which local address will be bound to the TCP connection +used to fetch this zone. If not set, it defaults to a system +controlled value which will usually be the address of the interface +``closest to'' the remote end. This address must appear in the remote end's +.Ic allow-transfer +option for this zone if one is specified. +.It Ic max-transfer-time-in +See the description of +.Ic max-transfer-time-in +in the +.Sx Zone Transfers +subsection of +.Sx THE OPTIONS STATEMENT . +.It Ic dialup +See the description of +.Ic dialup +in the +.Sx Boolean Options +subsection of +.Sx THE OPTIONS STATEMENT . +.It Ic notify +See the description of +.Sx notify +in the +.Sx Boolean Options +subsection of the +.Sx THE OPTIONS STATEMENT . +.It Ic also-notify +.Ic also-notify +is only meaningful if +.Ic notify +is active for this zone. +The set of machines that will receive a DNS NOTIFY message for this +zone is made up of all the listed nameservers for the zone (other than +the primary master) plus any IP addresses specified with +.Ic also-notify . +.Ic also-notify +is not meaningful for +.Ic stub +zones. The default is the empty list. +.It Ic forward +.Ic forward +is only meaningful if the zone has a +.Ic forwarders +list. The +.Ic only +value causes the lookup to fail after trying the +.Ic forwarders +and getting no answer, while +.Ic first +would allow a normal lookup to be tried. +.It Ic forwarders +The +.Ic forwarders +option in a zone is used to override the list of global forwarders. +If it is not specified in a zone of type +.Ic forward , +.Em no +forwarding is done for the zone; the global options are not used. +.It Ic pubkey +The DNSSEC flags, protocol, and algorithm are specified, as well as a base-64 +encoded string representing the key. +.El +.Sh THE ACL STATEMENT +.Ss Syntax +.Bd -literal +acl \fIname\fR { + \fIaddress_match_list\fR +}; +.Ed +.Ss Definition and Usage +The +.Ic acl +statement creates a named address match list. +It gets its name from a primary use of address match lists: Access +Control Lists (ACLs). +.Pp +Note that an address match list's name must be defined with +.Ic acl +before it can be used elsewhere; no forward +references are allowed. +.Pp +The following ACLs are built-in: +.Bl -tag -width 0n +.It Ic any +Allows all hosts. +.It Ic none +Denies all hosts. +.It Ic localhost +Allows the IP addresses of all interfaces on the system. +.It Ic localnets +Allows any host on a network for which the system has an interface. +.El +.Sh THE KEY STATEMENT +.Ss Syntax +.Bd -literal +key \fIkey_id\fR { + algorithm \fIalgorithm_id\fR; + secret \fIsecret_string\fR; +}; +.Ed +.Ss Definition and Usage +The +.Ic key +statement defines a key ID which can be used in a +.Ic server +statement to associate a method of authentication with a particular +name server that is more rigorous than simple IP address matching. +A key ID must be created with the +.Ic key +statement before it can be used in a +.Ic server +definition or an address match list. +.Pp +The +.Va algorithm_id +is a string that specifies a +security/authentication algorithm. +.Va secret_string +is the secret to be used by the algorithm, +and is treated as a base-64 encoded string. +It should go without saying, but probably can't, +that if you have +.Va secret_string 's +in your +.Pa named.conf , +then it should not be readable by anyone but the superuser. +.Sh THE TRUSTED-KEYS STATEMENT +.Ss Syntax +.Bd -literal +trusted-keys { + [ \fIdomain_name\fR \fIflags\fR \fIprotocol\fR \fIalgorithm\fR \fIkey\fR; ] +}; +.Ed +.Ss Definition and Usage +The +.Ic trusted-keys +statement is for use with DNSSEC-style security, originally specified +in RFC 2065. DNSSEC is meant to +provide three distinct services: key distribution, data origin +authentication, and transaction and request authentication. A +complete description of DNSSEC and its use is beyond the scope of this +document, and readers interested in more information should start with +RFC 2065 and then continue with the Internet Drafts available at +http://www.ietf.org/ids.by.wg/dnssec.html. +.Pp +Each trusted key is associated with a domain name. Its attributes are +the non-negative integral +.Va flags , +.Va protocol , +and +.Va algorithm , +as well as a base-64 encoded string representing the +.Va key . +.Pp +Any number of trusted keys can be specified. +.Sh THE SERVER STATEMENT +.Ss Syntax +.Bd -literal +server \fIip_addr\fR { + [ edns \fIyes_or_no\fR; ] + [ bogus \fIyes_or_no\fR; ] + [ support-ixfr \fIyes_or_no\fR; ] + [ transfers \fInumber\fR; ] + [ transfer-format ( one-answer | many-answers ); ] + [ keys { \fIkey_id\fR [ \fIkey_id\fR ... ] }; ] +}; +.Ed +.Ss Definition and Usage +The server statement defines the characteristics to be +associated with a remote name server. +.Pp +If you discover that a server does not support EDNS you can prevent +named making EDNS queries to it by specifying +.Ic edns +.Ic no; . +The default value of +.Ic edns +is +.Ic yes . +.Pp +If you discover that a server is giving out bad data, marking it as +.Ic bogus +will prevent further queries to it. The default value of +.Ic bogus +is +.Li no . +.Pp +If the server supports IXFR you can tell named to attempt to +perform a IXFR style zone transfer by specifing +.Ic support-ixfr +.Li yes . +The default value of +.Ic support-ixfr +is +.Li no . +.Pp +The server supports two zone transfer methods. The first, +.Ic one-answer , +uses one DNS message per resource record transferred. +.Ic many-answers +packs as many resource records as possible into a message. +.Ic many-answers +is more efficient, but is only known to be understood by BIND 8.1 and +patched versions of BIND 4.9.5. You can specify which method to use +for a server with the +.Ic transfer-format +option. If +.Ic transfer-format +is not specified, the +.Ic transfer-format +specified by the +.Ic options +statement will be used. +.Pp +The +.Ic transfers +will be used in a future release of the server to limit the number of +concurrent in-bound zone transfers from the specified server. It is +checked for syntax but is otherwise ignored. +.Pp +The +.Ic keys +clause is used to identify a +.Va key_id +defined by the +.Ic key +statement, to be used for transaction security when talking to the +remote server. +The +.Ic key +statememnt must come before the +.Ic server +statement that references it. +.Pp +The +.Ic keys +statement is intended for future use by the +server. It is checked for syntax but is otherwise ignored. +.Sh THE CONTROLS STATEMENT +.Ss Syntax +.Bd -literal +controls { + [ inet \fIip_addr\fR + port \fIip_port\fR + allow { \fIaddress_match_list\fR; }; ] + [ unix \fIpath_name\fR + perm \fInumber\fR + owner \fInumber\fR + group \fInumber\fR; ] +}; +.Ed +.Ss Definition and Usage +The +.Ic controls +statement declares control channels to be used by system +administrators to affect the operation of the local name server. +These control channels are used by the +.Nm ndc +utility to send commands +to and retrieve non-DNS results from a name server. +.Pp +A +.Ic unix +control channel is a FIFO in the file system, and access to it is +controlled by normal file system permissions. It is created by +.Nm named +with the specified file mode bits (see +.Xr chmod 1 ) , +user and group owner. Note that, unlike +.Nm chmod , +the mode bits specified for +.Ic perm +will normally have a leading +.Li 0 +so the number is interpreted as octal. Also note that the user and +group ownership specified as +.Ic owner +and +.Ic group +must be given as numbers, not names. +It is recommended that the +permissions be restricted to administrative personnel only, or else any +user on the system might be able to manage the local name server. +.Pp +An +.Ic inet +control channel is a TCP/IP socket accessible to the Internet, created +at the specified +.Va ip_port +on the specified +.Va ip_addr . +Modern +.Nm telnet +clients are capable of speaking directly to these +sockets, and the control protocol is ARPAnet-style text. +It is recommended that 127.0.0.1 be the only +.Va ip_addr +used, and this only if you trust all non-privileged users on the local +host to manage your name server. +.Sh THE INCLUDE STATEMENT +.Ss Syntax +.Bd -literal +include \fIpath_name\fR; +.Ed +.Ss Definition and Usage +The +.Ic include +statement inserts the specified file at the point that the +.Ic include +statement is encountered. It cannot be used within another statement, +though, so a line such as +.Dl acl internal_hosts { include "internal_hosts.acl"; }; +is not allowed. +.Pp +Use +.Ic include +to break the configuration up into easily-managed chunks. +For example: +.Bd -literal +include "/etc/security/keys.bind"; +include "/etc/acls.bind"; +.Ed +.Pp +could be used at the top of a BIND configuration file in order to +include any ACL or key information. +.Pp +Be careful not to type +``#include'', like you would in a C program, because +``#'' is used to start a comment. +.Sh EXAMPLES +The simplest configuration file that is still realistically useful is +one which simply defines a hint zone that has a full path to the root +servers file. +.Bd -literal +zone \&".\&" in { + type hint; + file \&"/var/named/root.cache\&"; +}; +.Ed +.Pp +Here's a more typical real-world example. +.Bd -literal +/* + * A simple BIND 8 configuration + */ +.Pp +logging { + category lame-servers { null; }; + category cname { null; }; +}; +.Pp +options { + directory \&"/var/named\&"; +}; +.Pp +controls { + inet * port 52 allow { any; }; // a bad idea + unix \&"/var/run/ndc\&" perm 0600 owner 0 group 0; // the default +}; +.Pp +zone \&"isc.org\&" in { + type master; + file \&"master/isc.org\&"; +}; +.Pp +zone \&"vix.com\&" in { + type slave; + file \&"slave/vix.com\&"; + masters { 10.0.0.53; }; +}; +.Pp +zone \&"0.0.127.in-addr.arpa\&" in { + type master; + file \&"master/127.0.0\&"; +}; +.Pp +zone \&".\&" in { + type hint; + file \&"root.cache\&"; +}; +.Ed +.Sh FILES +.Bl -tag -width 0n -compact +.It Pa /etc/named.conf +The BIND 8 +.Nm named +configuration file. +.El +.Sh SEE ALSO +.Xr named 8 , +.Xr ndc 8 Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/named.conf.5 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/resolver.3 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/resolver.3 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/resolver.3 (revision 109985) @@ -0,0 +1,608 @@ +.\" Copyright (c) 1985, 1995 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" 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. +.\" +.\" @(#)resolver.3 6.5 (Berkeley) 6/23/90 +.\" $Id: resolver.3,v 8.17 2002/08/07 03:47:33 marka Exp $ +.\" +.Dd July 4, 2000 +.Dt RESOLVER @LIB_NETWORK_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm res_ninit , +.Nm res_ourserver_p , +.Nm fp_resstat , +.Nm res_hostalias , +.Nm res_pquery , +.Nm res_nquery , +.Nm res_nsearch , +.Nm res_nquerydomain , +.Nm res_nmkquery , +.Nm res_nsend , +.Nm res_nupdate , +.Nm res_nmkupdate , +.Nm res_nclose , +.Nm res_nsendsigned , +.Nm res_findzonecut , +.Nm dn_comp , +.Nm dn_expand , +.Nm hstrerror , +.Nm res_init , +.Nm res_isourserver , +.Nm fp_nquery , +.Nm p_query , +.Nm hostalias , +.Nm res_query , +.Nm res_search , +.Nm res_querydomain , +.Nm res_mkquery , +.Nm res_send , +.Nm res_update , +.Nm res_close , +.Nm herror +.Nd resolver routines +.Sh SYNOPSIS +.Fd #include +.Fd #include +.Fd #include +.Fd #include +.Vt typedef struct __res_state *res_state ; +.Pp +.Fn res_ninit "res_state statp" +.Fn res_ourserver_p "const res_state statp" "const struct sockaddr_in *addr" +.Fn fp_resstat "const res_state statp" "FILE *fp" +.Fn res_hostalias "const res_state statp" "const char *name" "char *buf" "size_t buflen" +.Fn res_pquery "const res_state statp" "const u_char *msg" "int msglen" "FILE *fp" +.Fn res_nquery "res_state statp" "const char *dname" "int class" "int type" "u_char *answer" "int anslen" +.Fn res_nsearch "res_state statp" "const char *dname" "int class" "int type" "u_char * answer" "int anslen" +.Fn res_nquerydomain "res_state statp" "const char *name" "const char *domain" "int class" "int type" "u_char *answer" "int anslen" +.Fo res_nmkquery +.Fa "res_state statp" +.Fa "int op" +.Fa "const char *dname" +.Fa "int class" +.Fa "int type" +.Fa "const u_char *data" +.Fa "int datalen" +.Fa "const u_char *newrr" +.Fa "u_char *buf" +.Fa "int buflen" +.Fc +.Fn res_nsend "res_state statp" "const u_char *msg" "int msglen" "u_char *answer" "int anslen" +.Fn res_nupdate "res_state statp" "ns_updrec *rrecp_in" +.Fn res_nmkupdate "res_state statp" "ns_updrec *rrecp_in" "u_char *buf" "int buflen" +.Fn res_nclose "res_state statp" +.Fn res_nsendsigned "res_state statp" "const u_char *msg" "int msglen" "ns_tsig_key *key" "u_char *answer" "int anslen" +.Fn res_findzonecut "res_state statp" "const char *dname" "ns_class class" "int options" "char *zname" "size_t zsize" "struct in_addr *addrs" "int naddrs" +.Fn dn_comp "const char *exp_dn" "u_char *comp_dn" "int length" "u_char **dnptrs" "u_char **lastdnptr" +.Fn dn_expand "const u_char *msg" "const u_char *eomorig" "const u_char *comp_dn" "char *exp_dn" "int length" +.Fn hstrerror "int err" +.Ss DEPRECATED +.Fd #include +.Fd #include +.Fd #include +.Fd #include +.Fn res_init "void" +.Fn res_isourserver "const struct sockaddr_in *addr" +.Fn fp_nquery "const u_char *msg" "int msglen" "FILE *fp" +.Fn p_query "const u_char *msg" "FILE *fp" +.Fn hostalias "const char *name" +.Fn res_query "const char *dname" "int class" "int type" "u_char *answer" "int anslen" +.Fn res_search "const char *dname" "int class" "int type" "u_char *answer" "int anslen" +.Fn res_querydomain "const char *name" "const char *domain" "int class" "int type" "u_char *answer" "int anslen" +.Fo res_mkquery +.Fa "int op" +.Fa "const char *dname" +.Fa "int class" +.Fa "int type" +.Fa "const char *data" +.Fa "int datalen" +.Fa "struct rrec *newrr" +.Fa "u_char *buf" +.Fa "int buflen" +.Fc +.Fn res_send "const u_char *msg" "int msglen" "u_char *answer" "int anslen" +.Fn res_update "ns_updrec *rrecp_in" +.Fn res_close "void" +.Fn herror "const char *s" +.Sh DESCRIPTION +These routines are used for making, sending and interpreting +query and reply messages with Internet domain name servers. +.Pp +State information is kept in +.Fa statp +and is used to control the behavior of these functions. +.Fa statp +should be set to all zeros prior to the first call to any of these functions. +.Pp +The functions +.Fn res_init , +.Fn res_isourserver , +.Fn fp_nquery , +.Fn p_query , +.Fn hostalias , +.Fn res_query , +.Fn res_search , +.Fn res_querydomain , +.Fn res_mkquery , +.Fn res_send , +.Fn res_update , +.Fn res_close +and +.Fn herror +are deprecated and are supplied for compatability with old source +code. +They use global configuration and state information that is +kept in the structure +.Ft _res +rather than that referenced through +.Ft statp . +.Pp +Most of the values in +.Ft statp +and +.Ft _res +are initialized on the first call to +.Fn res_ninit +/ +.Fn res_init +to reasonable defaults and can be ignored. +Options +stored in +.Ft statp->options +/ +.Ft _res.options +are defined in +.Pa resolv.h +and are as follows. +Options are stored as a simple bit mask containing the bitwise +.Dq OR +of the options enabled. +.Bl -tag -width "RES_DEB" +.It Dv RES_INIT +True if the initial name server address and default domain name are +initialized (i.e., +.Fn res_ninit +/ +.Fn res_init +has been called). +.It Dv RES_DEBUG +Print debugging messages. +.It Dv RES_AAONLY +Accept authoritative answers only. +Should continue until it finds an authoritative answer or finds an error. +Currently this is not implemented. +.It Dv RES_USEVC +Use TCP connections for queries instead of UDP datagrams. +.It Dv RES_STAYOPEN +Used with +.Dv RES_USEVC +to keep the TCP connection open between queries. +This is useful only in programs that regularly do many queries. +UDP should be the normal mode used. +.It Dv RES_IGNTC +Ignore truncation errors, i.e., don't retry with TCP. +.It Dv RES_RECURSE +Set the recursion-desired bit in queries. +This is the default. +(\c +.Fn res_nsend +/ +.Fn res_send +does not do iterative queries and expects the name server +to handle recursion.) +.It Dv RES_DEFNAMES +If set, +.Fn res_nsearch +/ +.Fn res_search +will append the default domain name to single-component names +(those that do not contain a dot). +This option is enabled by default. +.It Dv RES_DNSRCH +If this option is set, +.Fn res_nsearch +/ +.Fn res_search +will search for host names in the current domain and in parent domains; see +.Xr hostname @DESC_EXT@ . +This is used by the standard host lookup routine +.Xr gethostbyname @LIB_NETWORK_EXT@ . +This option is enabled by default. +.It Dv RES_NOALIASES +This option turns off the user level aliasing feature controlled by +the +.Ev HOSTALIASES +environment variable. +Network daemons should set this option. +.It Dv RES_USE_INET6 +This option causes +.Xr gethostbyname @LIB_NETWORK_EXT@ +to look for AAAA records before looking for A records if none are found. +.It Dv RES_ROTATE +This options causes the +.Fn res_nsend +/ +.Fn res_send +to rotate the list of nameservers in +.Fa statp->nsaddr_list +/ +.Fa _res.nsaddr_list . +.It Dv RES_KEEPTSIG +This option causes +.Fn res_nsendsigned +to leave the message unchanged after TSIG verification; otherwise the TSIG +record would be removed and the header updated. +.It Dv RES_NOTLDQUERY +This option causes +.Fn res_nsearch +to not attempt to resolve a unqualified name as if it were a top level +domain (TLD). +This option can cause problems if the site has "localhost" as a TLD rather +than having localhost on one or more elements of the search list. +This option has no effect if neither +.Dv RES_DEFNAMES +or +.Dv RES_DNSRCH +is set. +.El +.Pp +The +.Fn res_ninit +/ +.Fn res_init +routine +reads the configuration file (if any; see +.Xr resolver @FORMAT_EXT@ ) +to get the default domain name, search list and +the Internet address of the local name server(s). +If no server is configured, the host running the resolver is tried. +The current domain name is defined by the hostname +if not specified in the configuration file; +it can be overridden by the environment variable +.Ev LOCALDOMAIN . +This environment variable may contain several blank-separated +tokens if you wish to override the +.Dq search list +on a per-process basis. This is similar to the +.Ic search +command in the configuration file. +Another environment variable +.Pq Dq Ev RES_OPTIONS +can be set to override certain internal resolver options which are otherwise +set by changing fields in the +.Ft statp +/ +.Ft _res +structure or are inherited from the configuration file's +.Ic options +command. The syntax of the +.Dq Ev RES_OPTIONS +environment variable is explained in +.Xr resolver @FORMAT_EXT@ . +Initialization normally occurs on the first call +to one of the other resolver routines. +.Pp +The +.Fn res_nquery +/ +.Fn res_query +functions provides interfaces to the server query mechanism. +They constructs a query, sends it to the local server, +awaits a response, and makes preliminary checks on the reply. +The query requests information of the specified +.Fa type +and +.Fa class +for the specified fully-qualified domain name +.Fa dname . +The reply message is left in the +.Fa answer +buffer with length +.Fa anslen +supplied by the caller. +.Fn res_nquery +/ +.Fn res_query +return -1 on error or the length of the answer. +.Pp +The +.Fn res_nsearch +/ +.Fn res_search +routines make a query and awaits a response like +.Fn res_nquery +/ +.Fn res_query , +but in addition, it implements the default and search rules +controlled by the +.Dv RES_DEFNAMES +and +.Dv RES_DNSRCH +options. +It returns the length of the first successful reply which is stored in +.Ft answer +or -1 on error. +.Pp +The remaining routines are lower-level routines used by +.Fn res_nquery +/ +.Fn res_query . +The +.Fn res_nmkquery +/ +.Fn res_mkquery +functions +constructs a standard query message and places it in +.Fa buf . +It returns the size of the query, or \-1 if the query is +larger than +.Fa buflen . +The query type +.Fa op +is usually +.Dv QUERY , +but can be any of the query types defined in +.Pa . +The domain name for the query is given by +.Fa dname . +.Fa Newrr +is currently unused but is intended for making update messages. +.Pp +The +.Fn res_nsend +/ +.Fn res_send +/ +.Fn res_nsendsigned +routines +sends a pre-formatted query and returns an answer. +It will call +.Fn res_ninit +/ +.Fn res_init +if +.Dv RES_INIT +is not set, send the query to the local name server, and +handle timeouts and retries. Additionally, +.Fn res_nsendsigned +will use TSIG signatures to add authentication to the query and verify the +response. In this case, only one nameserver will be contacted. +The length of the reply message is returned, or \-1 if there were errors. +.Pp +.Fn res_nquery +/ +.Fn res_query , +.Fn res_nsearch +/ +.Fn res_search +and +.Fn res_nsend +/ +.Fn res_send +return a length that may be bigger than +.Fa anslen . +In that case the query should be retried with a bigger buffer. +NOTE the answer to the second query may be larger still so supplying +a buffer that bigger that the answer returned by the previous +query is recommended. +.Pp +.Fa answer +MUST be big enough to receive a maximum UDP response from the server or +parts of the answer will be silently discarded. +The default maximum UDP response size is 512 bytes. +.Pp +The function +.Fn res_ourserver_p +returns true when +.Fa inp +is one of the servers in +.Fa statp->nsaddr_list +/ +.Fa _res.nsaddr_list . +.Pp +The functions +.Fn fp_nquery +/ +.Fn p_query +print out the query and any answer in +.Fa msg +on +.Fa fp . +.Fn p_query +is equivalent to +.Fn fp_nquery +with +.Fa msglen +set to 512. +.Pp +The function +.Fn fp_resstat +prints out the active flag bits in +.Fa statp->options +preceeded by the text ";; res options:" on +.Fa file . +.Pp +The functions +.Fn res_hostalias +/ +.Fn hostalias +lookup up name in the file referred to by the +.Ev HOSTALIASES +files return a fully qualified hostname if found or NULL if +not found or an error occurred. +.Fn res_hostalias +uses +.Fa buf +to store the result in, +.Fn hostalias +uses a static buffer. +.Pp +The functions +.Fn res_nupdate +/ +.Fn res_update +take a list of ns_updrec +.Fa rrecp_in . +Identifies the containing zone for each record and groups the records +according to containing zone maintaining in zone order then sends and update +request to the servers for these zones. The number of zones updated is +returned or -1 on error. Note that +.Fn res_nupdate +will perform TSIG authenticated dynamic update operations if the key is not +NULL. +.Pp +The function +.Fn res_findzonecut +discovers the closest enclosing zone cut for a specified domain name, +and finds the IP addresses of the zone's master servers. +.Pp +The functions +.Fn res_nmkupdate +/ +.Fn res_mkupdate +take a linked list of ns_updrec +.Fa rrecp_in +and construct a UPDATE message in +.Fa buf . +.Fn res_nmkupdate +/ +.Fn res_mkupdate +return the length of the constructed message on no error or one of the +following error values. +.Bl -inset -width "-5" +.It -1 +An error occurred parsing +.Fa rrecp_in . +.It -2 +The buffer +.Fa buf +was too small. +.It -3 +The first record was not a zone section or there was a section order problem. +The section order is S_ZONE, S_PREREQ and S_UPDATE. +.It -4 +A number overflow occurred. +.It -5 +Unknown operation or no records. +.El +.Pp +The functions +.Fn res_nclose +/ +.Fn res_close +close any open files referenced through +.Fa statp +/ +.Fa _res . +.Pp +The +.Fn dn_comp +function +compresses the domain name +.Fa exp_dn +and stores it in +.Fa comp_dn . +The size of the compressed name is returned or \-1 if there were errors. +The size of the array pointed to by +.Fa comp_dn +is given by +.Fa length . +The compression uses +an array of pointers +.Fa dnptrs +to previously-compressed names in the current message. +The first pointer points to +to the beginning of the message and the list ends with +.Dv NULL . +The limit to the array is specified by +.Fa lastdnptr . +A side effect of +.Fn dn_comp +is to update the list of pointers for labels inserted into the message +as the name is compressed. If +.Fa dnptr +is +.Dv NULL , +names are not compressed. If +.Fa lastdnptr +is +.Dv NULL , +the list of labels is not updated. +.Pp +The +.Fn dn_expand +entry +expands the compressed domain name +.Fa comp_dn +to a full domain name. +The compressed name is contained in a query or reply message; +.Fa msg +is a pointer to the beginning of the message. +.Fa eomorig +is a pointer to the first location after the message. +The uncompressed name is placed in the buffer indicated by +.Fa exp_dn +which is of size +.Fa length . +The size of compressed name is returned or \-1 if there was an error. +.Pp +The variables +.Ft statp->res_h_errno +/ +.Ft _res.res_h_errno +and external variable +.Ft h_errno +is set whenever an error occurs during resolver operation. The following +definitions are given in +.Pa : +.Bd -literal +#define NETDB_INTERNAL -1 /* see errno */ +#define NETDB_SUCCESS 0 /* no problem */ +#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */ +#define TRY_AGAIN 2 /* Non-Authoritative not found, or SERVFAIL */ +#define NO_RECOVERY 3 /* Non-Recoverable: FORMERR, REFUSED, NOTIMP */ +#define NO_DATA 4 /* Valid name, no data for requested type */ +.Ed +.Pp +The +.Fn herror +function writes a message to the diagnostic output consisting of the string +parameter +.Fa s , +the constant string ": ", and a message corresponding to the value of +.Ft h_errno . +.Pp +The +.Fn hstrerror +function returns a string which is the message text corresponding to the +value of the +.Fa err +parameter. +.Sh FILES +.Bl -tag -width "/etc/resolv.conf " +.It Pa /etc/resolv.conf +See +.Xr resolver @FORMAT_EXT@ . +.El +.Sh SEE ALSO +.Xr gethostbyname @LIB_NETWORK_EXT@ , +.Xr hostname @DESC_EXT@ , +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr resolver @FORMAT_EXT@ ; +RFC1032, RFC1033, RFC1034, RFC1035, RFC974; +SMM:11, +.Dq Name Server Operations Guide for Sy BIND Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/resolver.3 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/dig.1 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/dig.1 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/dig.1 (revision 109985) @@ -0,0 +1,704 @@ +.\" $Id: dig.1,v 8.9 2002/06/18 01:53:43 marka Exp $ +.\" +.\" ++Copyright++ 1993 +.\" - +.\" Copyright (c) 1993 +.\" 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 +.\" are met: +.\" 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 +.\" SUCH DAMAGE. +.\" - +.\" 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 +.\" SOFTWARE. +.\" - +.\" --Copyright-- +.\" +.\" Distributed with 'dig' version 2.0 from University of Southern +.\" California Information Sciences Institute (USC-ISI). +.\" +.\" dig.1 2.0 (USC-ISI) 8/30/90 +.\" +.Dd August 30, 1990 +.Dt DIG @CMD_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm dig +.Nd send domain name query packets to name servers +.Sh SYNOPSIS +.Nm dig +.Op Ic @ Ns Ar server +.Ar domain +.Op Aq Ar query-type +.Op Aq Ar query-class +.Op Ic + Ns Aq Ar query-option +.Op Fl Aq Ar dig-option +.Op Ar %comment +.Sh DESCRIPTION +.Ic Dig +(domain information groper) is a flexible command line tool +which can be used to gather information from the Domain +Name System servers. +.Ic Dig +has two modes: simple interactive mode +for a single query, and batch mode which executes a query for +each in a list of several query lines. All query options are +accessible from the command line. +.Pp +The usual simple use of +.Ic dig +will take the form: +.Pp +.Bd -ragged -offset indent-two +.Ic dig @ Ns Ar server domain query-type query-class +.Ed +.Pp +where: +.Bl -tag -width Fl +.It Ar server +may be either a domain name or a raw (IPv4 / IPv6) +Internet address. If this optional field is omitted, +.Ic dig +will attempt to use the default name server for your machine. +.sp 1 +.Em Note : +If a domain name is specified, this will be resolved +using the domain name system resolver (i.e., BIND). If your +system does not support DNS, you may +.Em have +to specify a +dot-notation address. Alternatively, if there is a server +at your disposal somewhere, all that is required is that +.Pa /etc/resolv.conf +be present and indicate where the default +name servers reside, so that +.Ar server +itself can be resolved. See +.Xr resolver @FORMAT_EXT@ +for information on +.Pa /etc/resolv.conf . +.Sy WARNING : +Changing +.Pa /etc/resolv.conf +will affect both the standard resolver library and +.Pq potentially +several programs which use it. +As an option, the user may set the +environment variable +.Ev LOCALRES +to name a file which is to +be used instead of +.Pa /etc/resolv.conf +.Po Ns Ev LOCALRES +is specific to the +.Ic dig +resolver and is not referenced by the standard resolver +.Pc . +If the +.Ev LOCALRES +variable is not set or the specified file +is not readable, then +.Pa /etc/resolv.conf +will be used. +.It Ar domain +is the domain name for which you are requesting information. +See the +.Fl x +option (documented in the +.Sx OTHER OPTIONS +subsection of this section) for convenient way to specify reverse address +query. +.It Ar query-type +is the type of information (DNS query type) that +you are requesting. If omitted, the default is +.Dq Ar a +.Pq Dv T_A = Ar address . +The following types are recognized: +.Pp +.Bl -hang -width "hinfo T_HINFO " -compact +.It Ar a\ \ \ \ \ \ Dv T_A +network address +.It Ar any\ \ \ \ Dv T_ANY +all/any information about specified domain +.It Ar mx\ \ \ \ \ Dv T_MX +mail exchanger for the domain +.It Ar ns\ \ \ \ \ Dv T_NS +name servers +.It Ar soa\ \ \ \ Dv T_SOA +zone of authority record +.It Ar hinfo\ \ Dv T_HINFO +host information +.It Ar axfr\ \ \ Dv T_AXFR +zone transfer (must ask an authoritative server) +.It Ar txt\ \ \ \ Dv T_TXT +arbitrary number of strings +.El +.Pp +(See RFC 1035 for the complete list.) +.It Ar query-class +is the network class requested in the query. If +omitted, the default is +.Dq Ar in +.Pq Dv C_IN = Ar Internet . +The following classes are recognized: +.Pp +.Bl -tag -width "hinfo T_HINFO " -compact +.It Ar in\ \ \ \ \ Dv C_IN +Internet class domain +.It Ar any\ \ \ \ Dv C_ANY +all/any class information +.El +.Pp +(See RFC 1035 for the complete list.) +.Pp +.Em Note : +.Dq Ar Any +can be used to specify a +.Em class +and/or a +.Em type +of query. +.Ic Dig +will parse the first occurrence of +.Dq Ar any +to mean +.Ar query-type = Dv T_ANY . +To specify +.Ar query-class = Dv C_ANY , +you must either specify +.Dq any +twice, or set +.Ar query-class +using the +.Fl c +option (see below). +.El +.Ss OTHER OPTIONS +.Bl -tag -width Fl +.It % Ns Ar ignored-comment +.Dq % +is used to included an argument that is simply not +parsed. This may be useful if running +.Ic dig +in batch +mode. Instead of resolving every +.Ar @server-domain-name +in a list of queries, you can avoid the overhead of doing +so, and still have the domain name on the command line +as a reference. Example: +.Pp +.Bd -ragged -offset indent-two +.Ic dig @128.9.0.32 %venera.isi.edu mx isi.edu +.Ed +.Pp +.It Fl Aq Ar dig option +.Dq Fl +is used to specify an option which affects the operation of +.Ic dig . +The following options are currently +available (although not guaranteed to be useful): +.Bl -tag -width Fl +.It Fl x Ar dot-notation-address +Convenient form to specify inverse address mapping. +Instead of +.Dq Ic dig 32.0.9.28.in-addr.arpa , +one can simply +.Dq Ic dig -x 28.9.0.32 . +.It Fl x Ar IPv6-address +Convenient form to specify inverse address mapping. +Instead of +.Dq Ic dig 1.0.0.0.0.0.0.0.0.0.0.0. 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa , +one can simply +.Dq Ic dig -x ::1 . +.It Fl f Ar file +File for +.Ic dig +batch mode. The file contains a list +of query specifications +( +.Ns Ic dig +command lines) which are to be executed successively. Lines beginning with +.Sq \&; , +.Sq # , +or +.Sq \en +are ignored. Other options +may still appear on command line, and will be in +effect for each batch query. +.It Fl T Ar time +Time in seconds between start of successive +queries when running in batch mode. Can be used +to keep two or more batch +.Ic dig +commands running +roughly in sync. Default is zero. +.It Fl p Ar port +Port number. Query a name server listening to a +non-standard port number. Default is 53. +.It Fl P Ns Bq Ar ping-string +After query returns, execute a +.Xr ping @SYS_OPS_EXT@ +command for response time comparison. This rather +unelegantly makes a call to the shell. The last +three lines of statistics is printed for the +command: +.Pp +.Bd -ragged -offset indent-two +.Ic ping Fl s server_name 56 3 +.Ed +.Pp +If the optional +.Dq Ar ping_string +is present, it +replaces +.Dq Ic ping Fl s +in the shell command. +.It Fl t Ar query-type +Specify type of query. May specify either an +integer value to be included in the type field +or use the abbreviated mnemonic as discussed +above (i.e., +.Ar mx = Dv T_MX ) . +.It Fl c Ar query-class +Specify class of query. May specify either an +integer value to be included in the class field +or use the abbreviated mnemonic as discussed +above (i.e., in = C_IN). +.It Fl k Ar keydir:keyname +Sign the query with the TSIG key named keyname +that is in the directory keydir. +.It Fl envsav +This flag specifies that the +.Ic dig +environment +(defaults, print options, etc.), after +all of the arguments are parsed, should be saved +to a file to become the default environment. +This is useful if you do not like the standard set of +defaults and do not desire to include a +large number of options each time +.Ic dig +is used. The environment consists of resolver state +variable flags, timeout, and retries as well as the flags detailing +.Ic dig +output (see below). +If the shell environment variable +.Ev LOCALDEF +is set to the name of a file, this is where the default +.Ic dig +environment is saved. If not, the file +.Dq Pa DiG.env +is created in the current working directory. +.Pp +.Em Note : +.Ev LOCALDEF +is specific to the +.Ic dig +resolver, +and will not affect operation of the standard +resolver library. +.Pp +Each time +.Ic dig +is executed, it looks for +.Dq Pa ./DiG.env +or the file specified by the shell environment variable +.Ev LOCALDEF . +If such file exists and is readable, then the +environment is restored from this file before any arguments are parsed. +.It Fl envset +This flag only affects batch query runs. When +.Dq Fl envset +is specified on a line in a +.Ic dig +batch file, the +.Ic dig +environment after the arguments are parsed +becomes the default environment for the duration of +the batch file, or until the next line which specifies +.Dq Fl envset . +.It Xo +.Fl Op Cm no +.Ns Cm stick +.Xc +This flag only affects batch query runs. +It specifies that the +.Ic dig +environment (as read initially +or set by +.Dq Fl envset +switch) is to be restored before each query (line) in a +.Ic dig +batch file. +The default +.Dq Fl nostick +means that the +.Ic dig +environment does not stick, hence options specified on a single line +in a +.Ic dig +batch file will remain in effect for +subsequent lines (i.e. they are not restored to the +.Dq sticky +default). +.El +.It Ic + Ns Aq Ar query-option +.Dq + +is used to specify an option to be changed in the query packet or to change +.Ic dig +output specifics. Many of these are the same parameters accepted by +.Xr nslookup @SYS_OPS_EXT@ . +If an option requires a parameter, the form is as follows: +.Pp +.Bd -ragged -offset indent-two +.Ic + +.Ns Ar keyword +.Ns Op = Ns Ar value +.Ed +.Pp +Most keywords can be abbreviated. Parsing of the +.Dq + +options is very simplistic \(em a value must not be +separated from its keyword by white space. The following +keywords are currently available: +.Pp +Keyword Abbrev. Meaning [default] +.Pp +.Bl -tag -width "[no]primary (ret) " -compact +.It Xo +.Op Cm no +.Ns Cm debug\ \ \ \ +.Pq Cm deb +.Xc +turn on/off debugging mode +.Bq Cm deb +.It Xo +.Op Cm no +.Ns Cm d2\ \ \ \ \ \ \ \ \ \ +.Xc +turn on/off extra debugging mode +.Bq Cm nod2 +.It Xo +.Op Cm no +.Ns Cm recurse\ \ +.Pq Cm rec +.Xc +use/don't use recursive lookup +.Bq Cm rec +.It Xo +.Cm retry= Ns Ar # +.Cm \ \ \ \ \ +.Pq Cm ret +.Xc +set number of retries to # +.Bq 4 +.It Xo +.Cm time= Ns Ar # +.Cm \ \ \ \ \ \ +.Pq Cm ti +.Xc +set timeout length to # seconds +.Bq 4 +.It Xo +.Op Cm no +.Ns Cm ko +.Xc +keep open option (implies vc) +.Bq Cm noko +.It Xo +.Op Cm no +.Ns Cm vc +.Xc +use/don't use virtual circuit +.Bq Cm novc +.It Xo +.Op Cm no +.Ns Cm defname\ \ +.Pq Cm def +.Xc +use/don't use default domain name +.Bq Cm def +.It Xo +.Op Cm no +.Ns Cm search\ \ \ +.Pq Cm sea +.Xc +use/don't use domain search list +.Bq Cm sea +.It Xo +.Cm domain= Ns Ar NAME\ \ +.Pq Cm do +.Xc +set default domain name to +.Ar NAME +.It Xo +.Op Cm no +.Ns Cm ignore\ \ \ +.Pq Cm i +.Xc +ignore/don't ignore trunc. errors +.Bq Cm noi +.It Xo +.Op Cm no +.Ns Cm primary\ \ +.Pq Cm pr +.Xc +use/don't use primary server +.Bq Cm nopr +.It Xo +.Op Cm no +.Ns Cm aaonly\ \ \ +.Pq Cm aa +.Xc +authoritative query only flag +.Bq Cm noaa +.It Xo +.Op Cm no +.Ns Cm cmd +.Xc +echo parsed arguments +.Bq Cm cmd +.It Xo +.Op Cm no +.Ns Cm stats\ \ \ \ +.Pq Cm st +.Xc +print query statistics +.Bq Cm st +.It Xo +.Op Cm no +.Ns Cm Header\ \ \ +.Pq Cm H +.Xc +print basic header +.Bq Cm H +.It Xo +.Op Cm no +.Ns Cm header\ \ \ +.Pq Cm he +.Xc +print header flags +.Bq Cm he +.It Xo +.Op Cm no +.Ns Cm ttlid\ \ \ \ +.Pq Cm tt +.Xc +print TTLs +.Bq Cm tt +.It Xo +.Op Cm no +.Ns Cm trunc\ \ \ \ +.Pq Cm tr +.Xc +truncate origin from names +.Bq Cm tr +.It Xo +.Op Cm no +.Ns Cm cl +.Xc +print class info +.Bq Cm nocl +.It Xo +.Op Cm no +.Ns Cm qr +.Xc +print outgoing query +.Bq Cm noqr +.It Xo +.Op Cm no +.Ns Cm reply\ \ \ \ +.Pq Cm rep +.Xc +print reply +.Bq Cm rep +.It Xo +.Op Cm no +.Ns Cm ques\ \ \ \ \ +.Pq Cm qu +.Xc +print question section +.Bq Cm qu +.It Xo +.Op Cm no +.Ns Cm answer\ \ \ +.Pq Cm an +.Xc +print answer section +.Bq Cm an +.It Xo +.Op Cm no +.Ns Cm author\ \ \ +.Pq Cm au +.Xc +print authoritative section +.Bq Cm au +.It Xo +.Op Cm no +.Ns Cm addit\ \ \ \ +.Pq Cm ad +.Xc +print additional section +.Bq Cm ad +.It Xo +.Op Cm no +.Ns Cm dnssec\ \ \ +.Pq Cm \ddn +.Xc +set the DNSSEC OK bit in the OPT pseudo record +.Bq Cm nodn +.It Cm pfdef +set to default print flags +.It Cm pfmin +set to minimal default print flags +.It Cm pfset= Ns Ar # +set print flags to # +(# can be hex/octal/decimal) +.It Cm pfand= Ns Ar # +bitwise and print flags with # +.It Cm pfor= Ns Ar # +bitwise or print flags with # +.El +.Pp +The +.Cm retry +and +.Cm time +options affect the retransmission strategy used by the resolver +library when sending datagram queries. The algorithm is as follows: +.Pp +.Bd -literal -offset indent +for i = 0 to retry - 1 + for j = 1 to num_servers + send_query + wait((time * (2**i)) / num_servers) + end +end +.Ed +.Pp +(Note: +.Ic dig +always uses a value of 1 for +.Dq Li num_servers . ) +.El +.Ss DETAILS +.Ic Dig +once required a slightly modified version of the BIND +.Xr resolver @LIB_NETWORK_EXT@ +library. As of BIND 4.9, BIND's resolver has been augmented to work +properly with +.Ic dig . +Essentially, +.Ic dig +is a straight-forward +(albeit not pretty) effort of parsing arguments and setting appropriate +parameters. +.Ic Dig +uses +.Xr resolver @LIB_NETWORK_EXT@ +routines +.Fn res_init , +.Fn res_mkquery , +.Fn res_send +as well as accessing the +.Ft _res +structure. +.Sh ENVIRONMENT +.Bl -tag -width "LOCALRES " -compact +.It Ev LOCALRES +file to use in place of Pa /etc/resolv.conf +.It Ev LOCALDEF +default environment file +.El +.Pp +See also the explanation of the +.Fl envsav , +.Fl envset , +and +.Xo +.Fl Op Cm no +.Ns Cm stick +.Xc +options, above. +.Sh FILES +.Bl -tag -width "/etc/resolv.conf " -compact +.It Pa /etc/resolv.conf +initial domain name and name server addresses +.It Pa \./DiG.env +default save file for default options +.El +.Sh SEE ALSO +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr resolver @LIB_NETWORK_EXT@ , +.Xr resolver @FORMAT_EXT@ , +.Xr nslookup @SYS_OPS_EXT@ . +.Sh STANDARDS +RFC 1035. +.Sh AUTHOR +Steve Hotz +hotz@isi.edu +.Sh ACKNOWLEDGMENTS +.Ic Dig +uses functions from +.Xr nslookup @SYS_OPS_EXT@ +authored by Andrew Cherenson. +.Sh BUGS +.Ic Dig +has a serious case of "creeping featurism" -- the result of +considering several potential uses during it's development. It would +probably benefit from a rigorous diet. Similarly, the print flags +and granularity of the items they specify make evident their +rather ad hoc genesis. +.Pp +.Ic Dig +does not consistently exit nicely (with appropriate status) +when a problem occurs somewhere in the resolver +.Po +.Sy NOTE : +most of the common exit cases are handled +.Pc . +This is particularly annoying when running in +batch mode. If it exits abnormally (and is not caught), the entire +batch aborts; when such an event is trapped, +.Ic dig +simply +continues with the next query. Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/dig.1 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/dnsquery.1 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/dnsquery.1 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/dnsquery.1 (revision 109985) @@ -0,0 +1,180 @@ +.\" $Id: dnsquery.1,v 8.5 2002/06/18 02:04:54 marka Exp $ +.\" +.\"Copyright (c) 1995,1996,1999 by Internet Software Consortium +.\" +.\"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. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM 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 +.\"SOFTWARE. +.\" +.Dd March 10, 1990 +.Dt DNSQUERY @CMD_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm dnsquery +.Nd query domain name servers using resolver +.Sh SYNOPSIS +.Nm dnsquery +.Op Fl n Ar nameserver +.Op Fl t Ar type +.Op Fl c Ar class +.Op Fl r Ar retry +.Op Fl p Ar period +.Op Fl d +.Op Fl s +.Op Fl v +.Ar host +.Sh DESCRIPTION +The +.Ic dnsquery +program is a general interface to nameservers via +BIND resolver library calls. The program supports +queries to the nameserver with an opcode of QUERY. +This program is intended to be a replacement or +supplement to programs like nstest, nsquery and +nslookup. All arguments except for +.Ar host +and +.Ar nameserver +are treated without case-sensitivity. +.Sh OPTIONS +.Bl -tag -width Fl +.It Fl n Ar nameserver +The nameserver to be used in the query. Nameservers can appear as either +Internet addresses of the form +.Ar ( w.x.y.z +or +.Ar xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx ) +or can appear as domain names. +(Default: as specified in +.Pa /etc/resolv.conf . ) +.It Fl t Ar type +The type of resource record of interest. Types include: +.Bl -tag -width "AFSDB " -compact -offset indent +.It Ar A +address +.It Ar NS +nameserver +.It Ar CNAME +canonical name +.It Ar PTR +domain name pointer +.It Ar SOA +start of authority +.It Ar WKS +well-known service +.It Ar HINFO +host information +.It Ar MINFO +mailbox information +.It Ar MX +mail exchange +.It Ar RP +responsible person +.It Ar MG +mail group member +.It Ar AFSDB +DCE or AFS server +.It Ar ANY +wildcard +.El +.Pp +Note that any case may be used. (Default: +.Ar ANY . ) +.It Fl c Ar class +The class of resource records of interest. +Classes include: +.Bl -tag -width "CHAOS " -compact -offset indent +.It Ar IN +Internet +.It Ar HS +Hesiod +.It Ar CHAOS +Chaos +.It Ar ANY +wildcard +.El +.Pp +Note that any case may be used. (Default: +.Ar IN . ) +.It Fl r Ar retry +The number of times to retry if the nameserver is +not responding. (Default: 4.) +.It Fl p Ar period +Period to wait before timing out. (Default: +.Dv RES_TIMEOUT . ) +.It Fl d +Turn on debugging. This sets the +.Dv RES_DEBUG +bit of the resolver's +.Ft options +field. (Default: no debugging.) +.It Fl s +Use a +.Em stream +rather than a packet. This uses a TCP stream connection with +the nameserver rather than a UDP datagram. This sets the +.Dv RES_USEVC +bit of the resolver's +.Ft options +field. (Default: UDP datagram.) +.It Fl v +Synonym for the +.Dq Fl s +flag. +.It Ar host +The name of the host (or domain) of interest. +.El +.Sh FILES +.Bl -tag -width " " -compact +.It Pa /etc/resolv.conf +to get the default ns and search lists +.It Pa +list of usable RR types and classes +.It Pa +list of resolver flags +.El +.Sh DIAGNOSTICS +If the resolver fails to answer the query and debugging has not been +turned on, +.Ic dnsquery +will simply print a message like: +.Dl Query failed (rc = 1) : Unknown host +.Pp +The value of the return code is supplied by +.Ft h_errno . +.Sh SEE ALSO +.Xr nslookup @SYS_OPS_EXT@ , +.Xr nstest @CMD_EXT@ , +.Xr nsquery @CMD_EXT@ , +.Xr named @SYS_OPS_EXT@ , +.Xr resolver @FORMAT_EXT@ . +.Sh AUTHOR +Bryan Beecher +.Sh BUGS +Queries of a class other than +.Ar IN +can have interesting results +since ordinarily a nameserver only has a list of root nameservers +for class +.Ar IN +resource records. +.Pp +.Ic Dnsquery +uses a call to +.Fn inet_addr +to determine if the argument +for the +.Dq Fl n +option is a valid Internet address. Unfortunately, +.Fn inet_addr +seems to cause a segmentation fault with some (bad) +IP addresses (e.g., 1.2.3.4.5). Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/dnsquery.1 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/host.1 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/host.1 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/host.1 (revision 109985) @@ -0,0 +1,316 @@ +.\" ++Copyright++ 1993 +.\" - +.\" Copyright (c) 1993 +.\" 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 +.\" are met: +.\" 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 +.\" SUCH DAMAGE. +.\" - +.\" 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 +.\" SOFTWARE. +.\" - +.\" --Copyright-- +.\" $Id: host.1,v 8.7 2002/06/18 02:39:26 marka Exp $ +.Dd December 15, 1994 +.Dt HOST @CMD_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm host +.Nd look up host names using domain server +.Sh SYNOPSIS +.Nm host +.Op Fl l +.Op Fl v +.Op Fl w +.Op Fl r +.Op Fl d +.Op Fl t Ar querytype +.Op Fl a +.Ar host +.Op Ar server +.Sh DESCRIPTION +.Ic Host +looks for information about Internet hosts. It gets this information +from a set of interconnected servers that are spread across the +world. By default, it simply converts between host names and +Internet addresses. However, with the +.Dq Fl t +or +.Dq Fl a +options, it can be used +to find all of the information about this host that is maintained +by the domain server. +.Pp +The arguments can be either host names or host numbers. The program +first attempts to interpret them as host numbers. If this fails, +it will treat them as host names. A host number consists of +IPv4 dotted decimal quad (127.0.0.1) or IPv6 raw address (::1). +A host name consists of names separated by dots, e.g. topaz.rutgers.edu. +Unless the name ends in a dot, the local domain +is automatically tacked on the end. Thus, a Rutgers user can say +.Pp +.D1 Ic host topaz +.Pp +and it will actually look up "topaz.rutgers.edu". +If this fails, the name is tried unchanged (in this case, "topaz"). +This same convention is used for mail and other network utilities. +The actual suffix to tack on the end is obtained +by looking at the results of a +.Xr hostname @CMD_EXT@ +call, and using everything +starting at the first dot. (See below for a description of +.Sx CUSTOMIZING HOST NAME LOOKUP . ) +.Pp +The first argument is the host name you want to look up. +If this is a number, an +.Dq inverse query +is done, i.e. the domain +system looks in a separate set of databases used to convert numbers +to names. +.Pp +The second argument is optional. It +allows you to specify a particular server to query. If you don't +specify this argument, the default server (normally the local machine) +is used. +.Pp +If a name is specified, you may see output of three different kinds. +Here is an example that shows all of them: +.Pp +.D1 Ic % host sun4 +.Dl sun4.rutgers.edu is a nickname for ATHOS.RUTGERS.EDU +.Dl ATHOS.RUTGERS.EDU has address 128.6.5.46 +.Dl ATHOS.RUTGERS.EDU has address 128.6.4.4 +.Dl ATHOS.RUTGERS.EDU mail is handled by ARAMIS.RUTGERS.EDU +.Pp +The user has typed the command +.Dq Ic host sun4 . +The first line indicates that the name +.Dq Li sun4.rutgers.edu +is actually a nickname. The official host name is +.Dq Li ATHOS.RUTGERS.EDU . +The next two lines show the +address. If a system has more than one network interface, there +will be a separate address for each. The last line indicates +that +.Li ATHOS.RUTGERS.EDU +does not receive its own mail. Mail for +it is taken by +.Li ARAMIS.RUTGERS.EDU . +There may be more than one +such line, since some systems have more than one other system +that will handle mail for them. Technically, every system that +can receive mail is supposed to have an entry of this kind. If +the system receives its own mail, there should be an entry +the mentions the system itself; for example, +.Pp +.D1 Li XXX mail is handled by XXX +.Pp +However, many systems that receive +their own mail do not bother to mention that fact. If a system +has a +.Dq Li mail is handled by +entry, but no address, this indicates +that it is not really part of the Internet, but a system that is +on the network will forward mail to it. Systems on Usenet, Bitnet, +and a number of other networks have entries of this kind. +.Sh OPTIONS +There are a number of options that can be used before the +host name. Most of these options are meaningful only to the +staff who have to maintain the domain database. +.Bl -tag -width Fl +.It Fl w +This causes +.Ic host +to wait forever for a response. Normally +it will time out after approximate one minute. +.It Fl v +Use "verbose" format for printout. This +is the official domain master file format, which is documented +in the man page for +.Xr @INDOT@named @SYS_OPS_EXT@ . +Without this option, output still follows +this format in general terms, but some attempt is made to make it +more intelligible to normal users. Without +.Dq Fl v , +any "a", "mx", and "cname" records +are written out as "has address", "mail is handled by", and +"is a nickname for" (respectively), and TTL and class fields are not shown. +.It Fl r +Turn off recursion in the request. +This means that the name server will return only data it has in +its own database. It will not ask other servers for more +information. +.It Fl d +Turn on debugging. Network transactions are shown in detail. +.It Fl s +Chase signatures back to parent key (DNSSEC). +.It Fl t Ar querytype +Allows you to specify a particular +.Ar querytype +of information +to be looked up. The arguments are defined in the man page for +.Xr @INDOT@named @SYS_OPS_EXT@ . +Currently-supported types include: +.Dq Cm a , +.Dq Cm aaaa , +.Dq Cm ns , +.Dq Cm md , +.Dq Cm mf , +.Dq Cm cname , +.Dq Cm soa , +.Dq Cm mb , +.Dq Cm mg , +.Dq Cm mr , +.Dq Cm null , +.Dq Cm wks , +.Dq Cm ptr , +.Dq Cm hinfo , +.Dq Cm minfo , +.Dq Cm mx , +.Dq Cm uinfo , +.Dq Cm uid , +.Dq Cm gid , +.Dq Cm unspec . +Additionally, the wildcard, which may be written +as either +.Dq Cm any +or +.Dq Cm * , +can be used to specify any (all) of the above types. +Types must be given in lower case. +Note that the default is to look first for +.Dq Cm a , +and then +.Dq Cm mx , +except that if the verbose option is turned on, the default is only +.Dq Cm a . +The +.Dq Fl t +option is particularly useful for filtering information returned by +.Ic host ; +see the explanation of the +.Dq Fl l +option, below, for more information. +.It Fl a +.Dq all ; +this is equivalent to +.Dq Fl v Fl t Cm any . +.It Fl l +List a complete domain; e.g.: +.Pp +.D1 Ic host -l rutgers.edu +.Pp +will give a listing of all hosts in the rutgers.edu domain. The +.Dq Fl t +option is used to filter what information is presented, as you +would expect. The default is address information, which also +include PTR and NS records. The command +.Pp +.D1 Ic host -l -v -t any rutgers.edu +.Pp +will give a complete download of the zone data for rutgers.edu, +in the official master file format. (However the SOA record is +listed twice, for arcane reasons.) +.Pp +.Sy NOTE : +.Dq Fl l +is implemented by +doing a complete zone transfer and then filtering out the information +the you have asked for. This command should be used only if it +is absolutely necessary. +.El +.Sh CUSTOMIZING HOST NAME LOOKUP +In general, if the name supplied by the user does not +have any dots in it, a default domain is appended to the end. +This domain can be defined in +.Pa /etc/resolv.conf , +but is normally derived +by taking the local hostname after its first dot. The user can override +this, and specify a different default domain, using the environment +variable +.Ev LOCALDOMAIN . +In addition, the user can supply his own abbreviations for host names. +They should be in a file consisting of one line per abbreviation. +Each line contains an abbreviation, a space, and then the full +host name. The name file must be contained in the +.Ev HOSTALIASES +environment variable. +.Sh ENVIRONMENT +.Bl -tag -width "/etc/resolv.conf " -compact +.It Ev HOSTALIASES +Name of file containing +.Pq Ar host alias , full hostname +pairs. +.El +.Sh FILES +.Bl -tag -width "/etc/resolv.conf " -compact +.It Pa /etc/resolv.conf +See +.Xr resolver @FORMAT_EXT@ . +.El +.Sh SEE ALSO +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr resolver @FORMAT_EXT@ . +.Sh BUGS +Unexpected effects can happen when you type a name that is not +part of the local domain. Please always keep in mind the +fact that the local domain name is tacked onto the end of every +name, unless it ends in a dot. Only if this fails is the name +used unchanged. +.Pp +The +.Dq Fl l +option only tries the first name server listed for the +domain that you have requested. If this server is dead, you +may need to specify a server manually. E.g., to get a listing +of foo.edu, you could try +.Pp +.D1 Ic host -t ns foo.edu +.Pp +to get a list of all the name servers for foo.edu, and then try +.Pp +.D1 Ic host -l foo.edu xxx +.Pp +for all +.Dq Ic xxx +on the list of name servers, until you find one that works. Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/host.1 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/dnskeygen.1 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/dnskeygen.1 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/dnskeygen.1 (revision 109985) @@ -0,0 +1,132 @@ +.\" Copyright (c) 1996,1999 by Internet Software Consortium +.\" +.\" 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. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\" CONSORTIUM 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 +.\" SOFTWARE. +.\" +.\" $Id: dnskeygen.1,v 8.8 2002/04/22 04:27:19 marka Exp $ +.\" +.Dd December 2, 1998 +.Dt DNSKEYGEN @CMD_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm dnskeygen +.Nd "generate public, private, and shared secret keys for DNS Security" +.Sh SYNOPSIS +.Nm dnskeygen +.Oo +.Fl Op Cm DHR +.Ar size +.Oc +.Op Fl F +.Op Fl Cm zhu +.Op Fl Cm a +.Op Fl Cm c +.Op Fl Cm p Ar num +.Op Fl Cm s Ar num +.Fl n Ar name +.Sh DESCRIPTION +.Ic Dnskeygen +(DNS Key Generator) is a tool to generate and maintain keys for DNS Security +within the DNS (Domain Name System). +.Nm Dnskeygen +can generate public and private keys to authenticate zone data, and shared +secret keys to be used for Request/Transaction signatures. +.Bl -tag -width Fl +.It Fl D +Dnskeygen will generate a +.Ic DSA/DSS +key. +.Dq size +must be one of [512, 576, 640, 704, 768, 832, 896, 960, 1024]. +.It Fl H +Dnskeygen will generate an +.Ic HMAC-MD5 +key. +.Dq size +must be between 128 and 504. +.It Fl R +Dnskeygen will generate an +.Ic RSA +key. +.Dq size +must be between 512 and 4096. +.It Fl F +.Ic ( RSA only ) +Use a large exponent for key generation. +.It Fl z Fl h Fl u +These flags define the type of key being generated: Zone (DNS validation) key, +Host (host or service) key or User (e.g. email) key, respectively. +Each key is only allowed to be one of these. +.It Fl a +Indicates that the key +.Ic CANNOT +be used for authentication. +.It Fl c +Indicates that the key +.Ic CANNOT +be used for encryption. +.It Fl p Ar num +Sets the key's protocol field to +.Ar num ; +the default is +.Ic 3 +(DNSSEC) if +.Dq Fl z +or +.Dq Fl h +is specified and +.Ic 2 +(EMAIL) otherwise. Other accepted values are +.Ic 1 +(TLS), +.Ic 4 +(IPSEC), and +.Ic 255 +(ANY). +.It Fl s Ar num +Sets the key's strength field to +.Ar num ; +the default is +.Sy 0 . +.It Fl n Ar name +Sets the key's name to +.Ar name . +.El +.Ss DETAILS +.Ic Dnskeygen +stores each key in two files: +.Pa K++.private +and +.Pa K++.key +The file +.Pa K++.private +contains the private key in a portable format. The file +.Pa K++.key +contains the public key in the DNS zone file format: +.Pp +.D1 Ar IN KEY +.Pp +.Sh ENVIRONMENT +No environmental variables are used. +.Sh SEE ALSO +.Em RFC 2065 +on secure DNS and the +.Em TSIG +Internet Draft. +.Sh AUTHOR +Olafur Gudmundsson (ogud@tis.com). +.Sh ACKNOWLEDGMENTS +The underlying cryptographic math is done by the DNSSAFE and/or Foundation +Toolkit libraries. +.Sh BUGS +None are known at this time Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/dnskeygen.1 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/getaddrinfo.3 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/getaddrinfo.3 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/getaddrinfo.3 (revision 109985) @@ -0,0 +1,360 @@ +.\" Copyright (c) 1983, 1987, 1991, 1993 +.\" 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 +.\" are met: +.\" 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 +.\" SUCH DAMAGE. +.\" +.\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95 +.\" $Id: getaddrinfo.3,v 8.3 2001/12/28 04:24:15 marka Exp $ +.\" +.Dd May 25, 1995 +.Dt GETADDRINFO @LIB_NETWORK_EXT@ +.Os KAME +.Sh NAME +.Nm getaddrinfo +.Nm freeaddrinfo , +.Nm gai_strerror +.Nd nodename-to-address translation in protocol-independent manner +.Sh SYNOPSIS +.Fd #include +.Fd #include +.Ft int +.Fn getaddrinfo "const char *nodename" "const char *servname" \ +"const struct addrinfo *hints" "struct addrinfo **res" +.Ft void +.Fn freeaddrinfo "struct addrinfo *ai" +.Ft "char *" +.Fn gai_strerror "int ecode" +.Sh DESCRIPTION +The +.Fn getaddrinfo +function is defined for protocol-independent nodename-to-address translation. +It performs functionality of +.Xr gethostbyname @LIB_NETWORK_EXT@ +and +.Xr getservbyname @LIB_NETWORK_EXT@ , +in more sophisticated manner. +.Pp +The addrinfo structure is defined as a result of including the +.Li +header: +.Bd -literal -offset +struct addrinfo { * + int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for nodename */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ +}; +.Ed +.Pp +The +.Fa nodename +and +.Fa servname +arguments are pointers to null-terminated strings or +.Dv NULL . +One or both of these two arguments must be a +.Pf non Dv -NULL +pointer. +In the normal client scenario, both the +.Fa nodename +and +.Fa servname +are specified. +In the normal server scenario, only the +.Fa servname +is specified. +A +.Pf non Dv -NULL +.Fa nodename +string can be either a node name or a numeric host address string +(i.e., a dotted-decimal IPv4 address or an IPv6 hex address). +A +.Pf non Dv -NULL +.Fa servname +string can be either a service name or a decimal port number. +.Pp +The caller can optionally pass an +.Li addrinfo +structure, pointed to by the third argument, +to provide hints concerning the type of socket that the caller supports. +In this +.Fa hints +structure all members other than +.Fa ai_flags , +.Fa ai_family , +.Fa ai_socktype , +and +.Fa ai_protocol +must be zero or a +.Dv NULL +pointer. +A value of +.Dv PF_UNSPEC +for +.Fa ai_family +means the caller will accept any protocol family. +A value of 0 for +.Fa ai_socktype +means the caller will accept any socket type. +A value of 0 for +.Fa ai_protocol +means the caller will accept any protocol. +For example, if the caller handles only TCP and not UDP, then the +.Fa ai_socktype +member of the hints structure should be set to +.Dv SOCK_STREAM +when +.Fn getaddrinfo +is called. +If the caller handles only IPv4 and not IPv6, then the +.Fa ai_family +member of the +.Fa hints +structure should be set to +.Dv PF_INET +when +.Fn getaddrinfo +is called. +If the third argument to +.Fn getaddrinfo +is a +.Dv NULL +pointer, this is the same as if the caller had filled in an +.Li addrinfo +structure initialized to zero with +.Fa ai_family +set to PF_UNSPEC. +.Pp +Upon successful return a pointer to a linked list of one or more +.Li addrinfo +structures is returned through the final argument. +The caller can process each +.Li addrinfo +structure in this list by following the +.Fa ai_next +pointer, until a +.Dv NULL +pointer is encountered. +In each returned +.Li addrinfo +structure the three members +.Fa ai_family , +.Fa ai_socktype , +and +.Fa ai_protocol +are the corresponding arguments for a call to the +.Fn socket +function. +In each +.Li addrinfo +structure the +.Fa ai_addr +member points to a filled-in socket address structure whose length is +specified by the +.Fa ai_addrlen +member. +.Pp +If the +.Dv AI_PASSIVE +bit is set in the +.Fa ai_flags +member of the +.Fa hints +structure, then the caller plans to use the returned socket address +structure in a call to +.Fn bind . +In this case, if the +.Fa nodename +argument is a +.Dv NULL +pointer, then the IP address portion of the socket +address structure will be set to +.Dv INADDR_ANY +for an IPv4 address or +.Dv IN6ADDR_ANY_INIT +for an IPv6 address. +.Pp +If the +.Dv AI_PASSIVE +bit is not set in the +.Fa ai_flags +member of the +.Fa hints +structure, then the returned socket address structure will be ready for a +call to +.Fn connect +.Pq for a connection-oriented protocol +or either +.Fn connect , +.Fn sendto , +or +.Fn sendmsg +.Pq for a connectionless protocol . +In this case, if the +.Fa nodename +argument is a +.Dv NULL +pointer, then the IP address portion of the +socket address structure will be set to the loopback address. +.Pp +If the +.Dv AI_CANONNAME +bit is set in the +.Fa ai_flags +member of the +.Fa hints +structure, then upon successful return the +.Fa ai_canonname +member of the first +.Li addrinfo +structure in the linked list will point to a null-terminated string +containing the canonical name of the specified +.Fa nodename . +.Pp +If the +.Dv AI_NUMERICHOST +bit is set in the +.Fa ai_flags +member of the +.Fa hints +structure, then a +.Pf non Dv -NULL +.Fa nodename +string must be a numeric host address string. +Otherwise an error of +.Dv EAI_NONAME +is returned. +This flag prevents any type of name resolution service (e.g., the DNS) +from being called. +.Pp +All of the information returned by +.Fn getaddrinfo +is dynamically allocated: +the +.Li addrinfo +structures, and the socket address structures and canonical node name +strings pointed to by the addrinfo structures. +To return this information to the system the function +Fn freeaddrinfo +is called. +The +.Fa addrinfo +structure pointed to by the +.Fa ai argument +is freed, along with any dynamic storage pointed to by the structure. +This operation is repeated until a +.Dv NULL +.Fa ai_next +pointer is encountered. +.Pp +To aid applications in printing error messages based on the +.Dv EAI_xxx +codes returned by +.Fn getaddrinfo , +.Fn gai_strerror +is defined. +The argument is one of the +.Dv EAI_xxx +values defined earlier and the return value points to a string describing +the error. +If the argument is not one of the +.Dv EAI_xxx +values, the function still returns a pointer to a string whose contents +indicate an unknown error. +.Sh FILES +.Bl -tag -width /etc/resolv.conf -compact +.It Pa /etc/hosts +.It Pa /etc/host.conf +.It Pa /etc/resolv.conf +.El +.Sh DIAGNOSTICS +Error return status from +.Fn getaddrinfo +is zero on success and non-zero on errors. +Non-zero error codes are defined in +.Li , +and as follows: +.Pp +.Bl -tag -width EAI_ADDRFAMILY -compact +.It Dv EAI_ADDRFAMILY +address family for nodename not supported +.It Dv EAI_AGAIN +temporary failure in name resolution +.It Dv EAI_BADFLAGS +invalid value for ai_flags +.It Dv EAI_FAIL +non-recoverable failure in name resolution +.It Dv EAI_FAMILY +ai_family not supported +.It Dv EAI_MEMORY +memory allocation failure +.It Dv EAI_NODATA +no address associated with nodename +.It Dv EAI_NONAME +nodename nor servname provided, or not known +.It Dv EAI_SERVICE +servname not supported for ai_socktype +.It Dv EAI_SOCKTYPE +ai_socktype not supported +.It Dv EAI_SYSTEM +system error returned in errno +.El +.Pp +If called with proper argument, +.Fn gai_strerror +returns a pointer to a string describing the given error code. +If the argument is not one of the +.Dv EAI_xxx +values, the function still returns a pointer to a string whose contents +indicate an unknown error. +.Sh SEE ALSO +.Xr getnameinfo @LIB_NETWORK_EXT@ , +.Xr gethostbyname @LIB_NETWORK_EXT@ , +.Xr getservbyname @LIB_NETWORK_EXT@ , +.Xr hosts @FORMAT_EXT@ , +.Xr services @FORMAT_EXT@ , +.Xr hostname @DESC_EXT@ , +.Xr named @SYS_OPS_EXT@ +.Pp +R. Gilligan, S. Thomson, J. Bound, and W. Stevens, +``Basic Socket Interface Extensions for IPv6,'' RFC2133, April 1997. +.Sh HISTORY +The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit. +.Sh STANDARDS +The +.Fn getaddrinfo +function is defined IEEE POSIX 1003.1g draft specification, +and documented in ``Basic Socket Interface Extensions for IPv6'' +(RFC2133). +.Sh BUGS +The text was shamelessly copied from RFC2133. Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/getaddrinfo.3 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/gethostbyname.3 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/gethostbyname.3 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/gethostbyname.3 (revision 109985) @@ -0,0 +1,242 @@ +.\" Copyright (c) 1983, 1987 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" 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. +.\" +.\" @(#)gethostbyname.3 6.12 (Berkeley) 6/23/90 +.\" +.Dd June 23, 1990 +.Dt GETHOSTBYNAME @LIB_NETWORK_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm gethostbyname , +.Nm gethostbyaddr , +.Nm gethostent , +.Nm sethostent , +.Nm endhostent , +.Nm herror +.Nd get network host entry +.Sh SYNOPSIS +.Fd #include +.Ft extern int +.Fa h_errno ; +.Pp +.Ft struct hostent * +.Fn gethostbyname "char *name" +.Ft struct hostent * +.Fn gethostbyname2 "char *name" "int af" +.Ft struct hostent * +.Fn gethostbyaddr "char *addr" "int len, type" +.Ft struct hostent * +.Fn gethostent +.Fn sethostent "int stayopen" +.Fn endhostent +.Fn herror "char *string" +.Sh DESCRIPTION +.Fn Gethostbyname , +.Fn gethostbyname2 , +and +.Fn gethostbyaddr +each return a pointer to a +.Ft hostent +structure (see below) describing an internet host +referenced by name or by address, as the function names indicate. +This structure contains either the information obtained from the name server, +.Xr @INDOT@named @SYS_OPS_EXT@ , +or broken-out fields from a line in +.Pa /etc/hosts . +If the local name server is not running, these routines do a lookup in +.Pa /etc/hosts . +.Bd -literal -offset indent +struct hostent { + char *h_name; /* official name of host */ + char **h_aliases; /* alias list */ + int h_addrtype; /* host address type */ + int h_length; /* length of address */ + char **h_addr_list; /* list of addresses from name server */ +}; + +#define h_addr h_addr_list[0] /* address, for backward compatibility */ +.Ed +.Pp +The members of this structure are: +.Bl -tag -width "h_addr_list" +.It h_name +Official name of the host. +.It h_aliases +A zero-terminated array of alternate names for the host. +.It h_addrtype +The type of address being returned; usually +.Dv AF_INET . +.It h_length +The length, in bytes, of the address. +.It h_addr_list +A zero-terminated array of network addresses for the host. +Host addresses are returned in network byte order. +.It h_addr +The first address in +.Li h_addr_list ; +this is for backward compatibility. +.El +.Pp +When using the nameserver, +.Fn gethostbyname +will search for the named host in each parent domain given in the +.Dq Li search +directive of +.Xr resolv.conf @FORMAT_EXT@ +unless the name contains a dot +.Pq Dq \&. . +If the name contains no dot, and if the environment variable +.Ev HOSTALIASES +contains the name of an alias file, the alias file will first be searched +for an alias matching the input name. +See +.Xr hostname @DESC_EXT@ +for the domain search procedure and the alias file format. +.Pp +.Fn Gethostbyname2 +is an evolution of +.Fn gethostbyname +intended to allow lookups in address families other than +.Dv AF_INET , +for example, +.Dv AF_INET6 . +Currently, the +.Fa af +argument must be specified as +.Dv AF_INET +else the function will return +.Dv NULL +after having set +.Ft h_errno +to +.Dv NETDB_INTERNAL . +.Pp +.Fn Sethostent +may be used to request the use of a connected TCP socket for queries. +If the +.Fa stayopen +flag is non-zero, +this sets the option to send all queries to the name server using TCP +and to retain the connection after each call to +.Fn gethostbyname +or +.Fn gethostbyaddr . +Otherwise, queries are performed using UDP datagrams. +.Pp +.Fn Endhostent +closes the TCP connection. +.Sh ENVIRONMENT +.Bl -tag -width "HOSTALIASES " -compact +.It Ev HOSTALIASES +Name of file containing +.Pq Ar host alias , full hostname +pairs. +.El +.Sh FILES +.Bl -tag -width "HOSTALIASES " -compact +.It Pa /etc/hosts +See +.Xr hosts @FORMAT_EXT@ . +.El +.Sh DIAGNOSTICS +.Pp +Error return status from +.Fn gethostbyname +and +.Fn gethostbyaddr +is indicated by return of a null pointer. +The external integer +.Ft h_errno +may then be checked to see whether this is a temporary failure +or an invalid or unknown host. +The routine +.Fn herror +can be used to print an error message describing the failure. +If its argument +.Fa string +is non-NULL, it is printed, followed by a colon and a space. +The error message is printed with a trailing newline. +.Pp +.Ft h_errno +can have the following values: +.Bl -tag -width "HOST_NOT_FOUND " -offset indent +.It Dv NETDB_INTERNAL +This indicates an internal error in the library, unrelated to the network +or name service. +.Ft errno +will be valid in this case; see +.Xr perror @SYSCALL_EXT@ . +.It Dv HOST_NOT_FOUND +No such host is known. +.It Dv TRY_AGAIN +This is usually a temporary error +and means that the local server did not receive +a response from an authoritative server. +A retry at some later time may succeed. +.It Dv NO_RECOVERY +Some unexpected server failure was encountered. +This is a non-recoverable error, as one might expect. +.It Dv NO_DATA +The requested name is valid but does not have an IP address; +this is not a temporary error. +This means that the name is known to the name server but there is no address +associated with this name. +Another type of request to the name server using this domain name +will result in an answer; +for example, a mail-forwarder may be registered for this domain. +.El +.Sh SEE ALSO +.Xr hosts @FORMAT_EXT@ , +.Xr hostname @DESC_EXT@ , +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr resolver @LIB_NETWORK_EXT@ , +.Xr resolver @FORMAT_EXT@ . +.Sh CAVEAT +.Pp +.Fn Gethostent +is defined, and +.Fn sethostent +and +.Fn endhostent +are redefined, +when +.Pa libc +is built to use only the routines to lookup in +.Pa /etc/hosts +and not the name server: +.Bd -ragged -offset indent +.Pp +.Fn Gethostent +reads the next line of +.Pa /etc/hosts , +opening the file if necessary. +.Pp +.Fn Sethostent +is redefined to open and rewind the file. If the +.Fa stayopen +argument is non-zero, +the hosts data base will not be closed after each call to +.Fn gethostbyname +or +.Fn gethostbyaddr . +.Pp +.Fn Endhostent +is redefined to close the file. +.Ed +.Sh BUGS +All information is contained in a static area so it must be copied if it is +to be saved. Only the Internet address format is currently understood. Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/gethostbyname.3 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/getipnodebyname.3 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/getipnodebyname.3 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/getipnodebyname.3 (revision 109985) @@ -0,0 +1,227 @@ +.\" Copyright (c) 1996,1999 by Internet Software Consortium +.\" +.\" 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. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\" CONSORTIUM 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 +.\" SOFTWARE. +.\" +.\" Copyright (c) 1983, 1987 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" 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. +.Dd September 17, 1999 +.Dt GETIPNODEBYNAME @LIB_NETWORK_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm getipnodebyname , +.Nm getipnodebyaddr +.Nd get network host entry +.br +.Nm freehostent +.Nd free network host entry +.Sh SYNOPSIS +.Fd #include +.Pp +.Ft struct hostent * +.Fn getipnodebyname "const char *name" "int af" "int flags" "int *error" +.Ft struct hostent * +.Fn getipnodebyaddr "const void *addr" "size_t len" "int af" "int *error" +.Ft void +.Fn freehostent "struct hostent *he" +.Sh DESCRIPTION +.Fn Getipnodebyname , +and +.Fn getipnodebyaddr +each return a pointer to a +.Ft hostent +structure (see below) describing an internet host +referenced by name or by address, as the function names indicate. +This structure contains either the information obtained from the name server, +.Xr @INDOT@named @SYS_OPS_EXT@ , +or broken-out fields from a line in +.Pa /etc/hosts . +If the local name server is not running, these routines do a lookup in +.Pa /etc/hosts . +.Bd -literal -offset indent +struct hostent { + char *h_name; /* official name of host */ + char **h_aliases; /* alias list */ + int h_addrtype; /* host address type */ + int h_length; /* length of address */ + char **h_addr_list; /* list of addresses from name server */ +}; + +#define h_addr h_addr_list[0] /* address, for backward compatibility */ +.Ed +.Pp +The members of this structure are: +.Bl -tag -width "h_addr_list" +.It h_name +Official name of the host. +.It h_aliases +A zero-terminated array of alternate names for the host. +.It h_addrtype +The type of address being returned. +.It h_length +The length, in bytes, of the address. +.It h_addr_list +A zero-terminated array of network addresses for the host. +Host addresses are returned in network byte order. +.It h_addr +The first address in +.Li h_addr_list ; +this is for backward compatibility. +.El +.Pp +This structure should be freed after use by calling +.Fn freehostent . +.Pp +When using the nameserver, +.Fn getiphostbyaddr +will search for the named host in each parent domain given in the +.Dq Li search +directive of +.Xr resolv.conf @FORMAT_EXT@ +unless the name contains a dot +.Pq Dq \&. . +If the name contains no dot, and if the environment variable +.Ev HOSTALIASES +contains the name of an alias file, the alias file will first be searched +for an alias matching the input name. +See +.Xr hostname @DESC_EXT@ +for the domain search procedure and the alias file format. +.Pp +.Fn Getiphostbyaddr +can be told to look for IPv4 addresses, IPv6 addresses or both IPv4 and IPv6. +If IPv4 addresses only are to be looked up then +.Fa af +should be set to +.Dv AF_INET , +otherwise it should be set to +.Dv AF_INET6 . +.Pp +There are three flags that can be set +.Bl -tag -width "AI_ADDRCONFIG" +.It Dv AI_V4MAPPED +Return IPv4 addresses if no IPv6 addresses are found. +This flag is ignored unless +.Fa af +is +.Dv AF_INET6 . +.It Dv AI_ALL +Return IPv4 addresses as well IPv6 addresses if +.Dv AI_V4MAPPED +is set. +This flag is ignored unless +.Fa af +is +.Dv AF_INET6 . +.It Dv AI_ADDRCONFIG +Only return addresses of a given type if the system has an active interface +with that type. +.El +.Pp +Also +.Dv AI_DEFAULT +is defined to be +.Dv (AI_V4MAPPED|AI_ADDRCONFIG) . +.Pp +.Fn Getipnodebyaddr +will lookup IPv4 mapped and compatible addresses in the IPv4 name +space and IPv6 name space +.Pp +.Fn Freehostent +frees the hostent structure allocated be +.Fn getipnodebyname +and +.Fn getipnodebyaddr . +The structures returned by +.Fn gethostbyname , +.Fn gethostbyname2 , +.Fn gethostbyaddr +and +.Fn gethostent +should not be passed to +.Fn freehostent +as they are pointers to static areas. +.Sh ENVIRONMENT +.Bl -tag -width "HOSTALIASES " -compact +.It Ev HOSTALIASES +Name of file containing +.Pq Ar host alias , full hostname +pairs. +.El +.Sh FILES +.Bl -tag -width "HOSTALIASES " -compact +.It Pa /etc/hosts +See +.Xr hosts @FORMAT_EXT@ . +.El +.Sh DIAGNOSTICS +.Pp +Error return status from +.Fn getipnodebyname +and +.Fn getipnodebyaddr +is indicated by return of a null pointer. +In this case +.Ft error +may then be checked to see whether this is a temporary failure +or an invalid or unknown host. +.Ft errno +can have the following values: +.Bl -tag -width "HOST_NOT_FOUND " -offset indent +.It Dv NETDB_INTERNAL +This indicates an internal error in the library, unrelated to the network +or name service. +.Ft errno +will be valid in this case; see +.Xr perror @SYSCALL_EXT@ . +.It Dv HOST_NOT_FOUND +No such host is known. +.It Dv TRY_AGAIN +This is usually a temporary error +and means that the local server did not receive +a response from an authoritative server. +A retry at some later time may succeed. +.It Dv NO_RECOVERY +Some unexpected server failure was encountered. +This is a non-recoverable error, as one might expect. +.It Dv NO_ADDRESS +The requested name is valid but does not have an IP address; +this is not a temporary error. +This means that the name is known to the name server but there is no address +associated with this name. +Another type of request to the name server using this domain name +will result in an answer; +for example, a mail-forwarder may be registered for this domain. +.El +.Sh SEE ALSO +.Xr hosts @FORMAT_EXT@ , +.Xr hostname @DESC_EXT@ , +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr resolver @LIB_NETWORK_EXT@ , +.Xr resolver @FORMAT_EXT@ , +.Xr gethostbyname @LIB_NETWORK_EXT@ , +.Xr RFC2553 . Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/getipnodebyname.3 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/getnameinfo.3 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/getnameinfo.3 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/getnameinfo.3 (revision 109985) @@ -0,0 +1,103 @@ +.\" $Id: getnameinfo.3,v 8.2 2001/12/28 04:24:16 marka Exp $ +.\" +.\"Copyright (c) 1998,1999 by Internet Software Consortium +.\" +.\"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. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM 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 +.\"SOFTWARE. +.\" +.Dd January 11, 1999 +.Dt GETRNAMEINFO @LIB_NETWORK_EXT@ +.Sh NAME +.Nm getnameinfo +.Nd address-to-name translation in protocol-independent manner +.Sh SYNOPSIS +.Fd #include +.Fd #include +.Ft int +.Fn getnameinfo "const struct sockaddr *sa" "socklen_t salen" \ +"char *host" "size_t hostlen" "char *serv" "size_t servlen" "int flags" +.Sh DESCRIPTION +The +.Fn getnameinfo +function is defined for protocol-independent address-to-nodename translation. +It performs functionality of +.Xr gethostbyaddr @LIB_NETWORK_EXT@ +and +.Xr getservbyport @LIB_NETWORK_EXT@ +in more sophisticated manner. +.Pp +The +.Fa sa +arguement is a pointer to a generic socket address structure of size +.Fa salen . +The arguements +.Fa host +and +.Fa serv +are pointers to buffers to hold the return values. +Their sizes are specified by +.Fa hostlen +and +.Fa servlen +repectively. +Either +.Fa host +or +.Fa serv +may be +.Dv NULL +if the hostname or service name is not required. +.Pp +The +.Fa flags +arguement modifies the behaviour of +.Fn getnameinfo +as follows: +.Pp +If +.Dv NI_NOFQDN +is set only the unqualified hostname is returned for local fully +qualified names. +.Pp +If +.Dv NI_NUMERICHOST +is set then the numeric form of the hostname is returned. +.Pp +If +.Dv NI_NAMEREQD +is set, then a error is returned if the hostname cannot be looked up. +.Pp +If +.Dv NI_NUMERICSERV +is set then the service is returned in numeric form. +.Pp +If +.Dv NI_DGRAM +is set then the service is UDP based rather than TCP based. +.Sh SEE ALSO +.Xr getaddrinfo @LIB_NETWORK_EXT@ , +.Xr gethostbyaddr @LIB_NETWORK_EXT@ , +.Xr getservbyport @LIB_NETWORK_EXT@ , +.Xr hosts @FORMAT_EXT@ , +.Xr services @FORMAT_EXT@ , +.Xr hostname @DESC_EXT@ , +.Xr named @SYS_OPS_EXT@ +.Pp +R. Gilligan, S. Thomson, J. Bound, and W. Stevens, +``Basic Socket Interface Extensions for IPv6,'' RFC2133, April 1997. +.Sh STANDARDS +The +.Fn getaddrinfo +function is defined IEEE POSIX 1003.1g draft specification, +and documented in ``Basic Socket Interface Extensions for IPv6'' +(RFC2133). Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/getnameinfo.3 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/getnetent.3 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/getnetent.3 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/getnetent.3 (revision 109985) @@ -0,0 +1,154 @@ +.\" $Id: getnetent.3,v 8.6 2001/12/28 04:24:17 marka Exp $ +.\" +.\"Copyright (c) 1995,1996,1999 by Internet Software Consortium +.\" +.\"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. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM 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 +.\"SOFTWARE. +.\" +.Dd May 20, 1996 +.Dt GETNETENT @LIB_NETWORK_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm getnetent , +.Nm getnetbyaddr , +.Nm getnetbyname , +.Nm setnetent , +.Nm endnetent +.Nd get networks entry +.Sh SYNOPSIS +.Fd #include +.Ft struct netent * +.Fn getnetent +.Ft struct netent * +.Fn getnetbyname "char name" +.Ft struct netent * +.Fn getnetbyaddr "unsigned long net" "int type" +.Ft void +.Fn setnetent "int stayopen" +.Ft void +.Fn endnetent +.Sh DESCRIPTION +The +.Fn getnetent , +.Fn getnetbyname , +and +.Fn getnetbyaddr +subroutines +each return a pointer to an object with the following structure +containing the broken-out fields of a line in the +.Pa networks +database. +.Bd -literal -offset indent +struct netent { + char *n_name; /* official name of net */ + char **n_aliases; /* alias list */ + int n_addrtype; /* net number type */ + long n_net; /* net number */ +}; +.Ed +.Pp +The members of this structure are: +.Bl -tag -width "n_addrtype" +.It n_name +The official name of the network. +.It n_aliases +A zero-terminated list of alternate names for the network. +.It n_addrtype +The type of the network number returned: +.Dv AF_INET . +.It n_net +The network number. Network numbers are returned in machine byte +order. +.El +.Pp +If the +.Fa stayopen +flag on a +.Fn setnetent +subroutine is NULL, the +.Pa networks +database is opened. Otherwise, the +.Fn setnetent +has the effect of rewinding the +.Pa networks +database. +The +.Fn endnetent +subroutine may be called to +close the +.Pa networks +database when processing is complete. +.Pp +The +.Fn getnetent +subroutine simply reads the next +line while +.Fn getnetbyname +and +.Fn getnetbyaddr +search until a matching +.Fa name +or +.Fa net +number is found +(or until +.Dv EOF +is encountered). The +.Fa type must be +.Dv AF_INET . +The +.Fn getnetent +subroutine keeps a pointer in the database, allowing +successive calls to be used to search the entire file. +.Pp +Before a +.Ic while +loop using +.Fn getnetent , +a call to +.Fn setnetent +must be made +in order to perform initialization; a call to +.Fn endnetent +must be used after the loop. Both +.Fn getnetbyname +and +.Fn getnetbyaddr +make calls to +.Fn setnetent +and +.Fn endnetent . +.Sh FILES +.Pa /etc/networks +.Sh DIAGNOSTICS +Null pointer (0) returned on +.Dv EOF +or error. +.Sh SEE ALSO +.Xr networks @FORMAT_EXT@ , +RFC 1101. +.Sh HISTORY +The +.Fn "getnetent" , +.Fn "getnetbyaddr" , +.Fn "getnetbyname" , +.Fn "setnetent" , +and +.Fn "endnetent" +functions appeared in +.Bx 4.2 . +.Sh BUGS +The data space used by these functions is static; if future use requires the +data, it should be copied before any subsequent calls to these functions +overwrite it. Only Internet network numbers are currently understood. +Expecting network numbers to fit in no more than 32 bits is probably naive. Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/getnetent.3 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/hostname.7 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/hostname.7 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/hostname.7 (revision 109985) @@ -0,0 +1,168 @@ +.\" Copyright (c) 1987 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" 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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +.\" +.\" @(#)hostname.7 6.4 (Berkeley) 1/16/90 +.\" +.Dd February 16, 1994 +.Dt HOSTNAME @DESC_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm hostname +.Nd host name resolution description +.Sh DESCRIPTION +Hostnames are domains. A domain is a hierarchical, dot-separated list +of subdomains. For example, the machine +.Dq Li monet , +in the +.Dq Li Berkeley +subdomain of the +.Dq Li EDU +subdomain of the Internet Domain Name System would be represented as +.Pp +.Dl monet.Berkeley.EDU +.Pp +(with no trailing dot). +.Pp +Hostnames are often used with network client and server programs, +which must generally translate the name to an address for use. +(This task is usually performed by the library routine +.Xr gethostbyname @LIB_NETWORK_EXT@ . ) +The default method for resolving hostnames by the Internet name resolver is +to follow RFC 1535's security recommendations. Actions can be taken +by the administrator to override these recommendations and to have the +resolver behave the same as earlier, non-RFC 1535 +resolvers. +.Pp +The default method (using RFC 1535 guidelines) follows: +.Pp +If the name consists of a single component, i.e. contains no dot, and if the +environment variable +.Dq Ev HOSTALIASES +is set to the name of a file, +that file is searched for a string matching the input hostname. The file +should consist of lines made up of two strings separated by white-space, the +first of which is the hostname alias, and the second of which is the complete +hostname to be substituted for that alias. If a case-insensitive match is +found between the hostname to be resolved and the first field of a line in +the file, the substituted name is looked up with no further processing. +.Pp +If there is at least one dot in the name, then the name is first tried +.Dq as-is . +The number of dots to cause this action is configurable by setting the +threshold using the +.Dq Li ndots +option in +.Pa /etc/resolv.conf +(default: 1). If the name ends with a dot, the trailing dot is +removed, and the remaining name is looked up (regardless of the setting of +the +.Li ndots +option), without further processing. +.Pp +If the input name does not end with a trailing dot, it is looked up by +searching through a list of domains until a match is found. If neither the +search option in the +.Pa /etc/resolv.conf +file or the +.Dq Ev LOCALDOMAIN +environment variable is used, then the +search list of domains contains only the full domain specified by the +.Li domain +option (in +.Pa /etc/resolv.conf ) +or the domain used in the local hostname (see +.Xr hostname @CMD_EXT@ +and +.Xr resolver @FORMAT_EXT@ ) . +For example, if the +.Dq Li domain +option is set to +.Li CS.Berkeley.EDU , +then only +.Li CS.Berkeley.EDU +will be in the search list, and this will be the only +domain appended to the partial hostname. For example, if +.Dq Li lithium +is the name to be resolved, this would make +.Li lithium.CS.Berkeley.EDU +the only name to be tried using the search list. +.Pp +If the +.Li search +option is used in +.Pa /etc/resolv.conf +or the environment variable +.Dq Ev LOCALDOMAIN +is set by the user, then +the search list will include what is set by these methods. For +example, if the +.Dq Li search +option contained +.Pp +.Dl CS.Berkeley.EDU CChem.Berkeley.EDU Berkeley.EDU +.Pp +then the partial hostname (e.g., +.Dq Li lithium ) +will be tried with +.Em each +domain name appended (in the same order specified); the resulting hostnames +that would be tried are: +.Bd -literal -offset indent +lithium.CS.Berkeley.EDU +lithium.CChem.Berkeley.EDU +lithium.Berkeley.EDU +.Ed +.Pp +The environment variable +.Dq Ev LOCALDOMAIN +overrides the +.Dq Li search +and +.Dq Li domain +options, and if both +.Li search +and +.Li domain +options are present in the resolver configuration file, then only the +.Em last +one listed is used (see +.Xr resolver @FORMAT_EXT@ ) . +.Pp +If the name was not previously tried +.Dq as-is +(i.e., it fell below the +.Dq Li ndots +threshold or did not contain a dot), then the name as +originally provided is attempted. +.Sh ENVIRONMENT +.Bl -tag -width "/etc/resolv.conf " +.It Ev LOCALDOMAIN +Affects domains appended to partial hostnames. +.It Ev HOSTALIASES +Name of file containing +.Pq Ar host alias , full hostname +pairs. +.El +.Sh FILES +.Bl -tag -width "/etc/resolv.conf " -compact +.It Pa /etc/resolv.conf +See +.Xr resolve @FORMAT_EXT@ . +.El +.Sh SEE ALSO +.Xr gethostbyname @LIB_NETWORK_EXT@ , +.Xr resolver @FORMAT_EXT@ , +.Xr mailaddr @DESC_EXT@ , +.Xr @INDOT@named @SYS_OPS_EXT@ . Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/hostname.7 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/inet_cidr.3 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/inet_cidr.3 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/inet_cidr.3 (revision 109985) @@ -0,0 +1,94 @@ +.\" $Id: inet_cidr.3,v 8.3 2001/08/08 07:50:06 marka Exp $ +.\" +.\"Copyright (c) 1998,1999 by Internet Software Consortium +.\" +.\"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. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM 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 +.\"SOFTWARE. +.\" +.Dd October 19, 1998 +.Dt INET_CIDR @LIB_NETWORK_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm inet_cidr_ntop , +.Nm inet_cidr_pton +.Nd network translation routines +.Sh SYNOPSIS +.Fd #include +.Fd #include +.Fd #include +.Fd #include +.Fn inet_cidr_ntop "int af" "const void *src" "int bits" "char *dst" "size_t size" +.Fn inet_cidr_pton "int af" "const char *src" "void *dst" "int *bits" +.Sh DESCRIPTION +These routines are used for converting addresses to and from network and +presentation forms with CIDR (Classless Inter-Domain Routing) representation, +embedded net mask. +.Pp +.Bd -literal + 130.155.16.1/20 +.Ed +.\" ::ffff:130.155.16.1/116 +.Pp +.Fn inet_cidr_ntop +converts an address from network to presentation format. +.Pp +.Ft af +describes the type of address that is being passed in +.Ft src . +.\"Currently defined types are AF_INET and AF_INET6. +Currently only AF_INET is supported. +.Pp +.Ft src +is an address in network byte order, its length is determined from +.Ft af . +.Pp +.Ft bits +specifies the number of bits in the netmask unless it is -1 in which case +the CIDR representation is omitted. +.Pp +.Ft dst +is a caller supplied buffer of at least +.Ft size +bytes. +.Pp +.Fn inet_cidr_ntop +returns +.Ft dst +on success or NULL. +Check errno for reason. +.Pp +.Fn inet_cidr_pton +converts and address from presentation format, with optional CIDR +reperesentation, to network format. +The resulting address is zero filled if there were insufficint bits in +.Ft src . +.Pp +.Ft af +describes the type of address that is being passed in via +.Ft src +and determines the size of +.Ft dst . +.Pp +.Ft src +is an address in presentation format. +.Pp +.Ft bits +returns the number of bits in the netmask or -1 if a CIDR representation was +not supplied. +.Pp +.Fn inet_cidr_pton +returns 0 on succces or -1 on error. +Check errno for reason. +ENOENT indicates an invalid netmask. +.Sh SEE ALSO +.Xr intro 2 Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/inet_cidr.3 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/mailaddr.7 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/mailaddr.7 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/mailaddr.7 (revision 109985) @@ -0,0 +1,179 @@ +.\" Copyright (c) 1983, 1987 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" 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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +.\" +.\" @(#)mailaddr.7 6.5 (Berkeley) 2/14/89 +.\" +.Dd February 14, 1989 +.Dt MAILADDR @DESC_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm mailaddr +.Nd mail addressing description +.Sh DESCRIPTION +Mail addresses are based on the ARPANET protocol listed at the end of this +manual page. These addresses are in the general format +.Pp +.Bd -ragged -offset indent-two +.Li user@domain +.Ed +.Pp +where a domain is a hierarchical, dot-separated list of subdomains. For +example, the address +.Pp +.Bd -ragged -offset indent-two +.Li eric@monet.berkeley.edu +.Ed +.Pp +is normally interpreted from right to left: the message should go to the +ARPA name tables (which do not correspond exactly to the physical ARPANET), +then to the Berkeley gateway, after which it should go to the local host +.Dq Li monet . +When the message reaches +.Li monet , +it is delivered to the user +.Dq Li eric . +.Pp +Unlike some other forms of addressing, this does not imply any routing. +Thus, although this address is specified as an ARPA address, it might +travel by an alternate route if that were more convenient or efficient. +For example, at Berkeley, the associated message would probably go directly +to +.Li monet +over the Ethernet rather than going via the Berkeley ARPANET gateway. +.Ss Abbreviation +.Pp +Under certain circumstances, it may not be necessary to type the entire +domain name. In general, anything following the first dot may be omitted +if it is the same as the domain from which you are sending the message. +For example, a user on +.Dq Li calder.berkeley.edu +could send to +.Dq Li eric@monet +without adding the +.Dq Li berkeley.edu +since it is the same on both sending and receiving hosts. +.Pp +Certain other abbreviations may be permitted as special cases. For +example, at Berkeley, ARPANET hosts may be referenced without adding the +.Dq Li berkeley.edu +as long as their names do not conflict with a local host name. +.Ss Compatibility +.Pp +Certain old address formats are converted to the new format to provide +compatibility with the previous mail system. In particular, +.Bd -ragged -offset indent-two +.Li user@host.ARPA +.Ed +.Pp +is allowed and +.Bd -ragged -offset indent-two +.Li host:user +.Ed +.Pp +is converted to +.Bd -ragged -offset indent-two +.Li user@host +.Ed +.Pp +in order to be consistent with the +.Xr rcp @CMD_EXT@ +command. +.Pp +Also, the syntax +.Bd -ragged -offset indent-two +.Li host!user +.Ed +.Pp +is converted to: +.Bd -ragged -offset indent-two +.Li user@host.UUCP +.Ed +.Pp +This is normally converted back to the +.Dq Li host!user +form before being sent on, for compatibility with older UUCP hosts. +.Pp +The current implementation is not able to route messages automatically through +the UUCP network. Until that time you must explicitly tell the mail system +which hosts to send your message through to get to your final destination. +.Ss Case Distinctions +.Pp +Domain names (i.e., anything after the +.Dq Li @ +sign) may be given in any mixture +of upper and lower case with the exception of UUCP hostnames. Most hosts +accept any combination of case in user names, with the notable exception of +MULTICS sites. +.Ss Route-addrs. +.Pp +Under some circumstances it may be necessary to route a message through +several hosts to get it to the final destination. Normally this routing +is done automatically, but sometimes it is desirable to route the message +manually. Addresses which show these relays are termed +.Dq route-addrs . +These use the syntax: +.Bd -ragged -offset indent-two +.Li <@hosta,@hostb:user@hostc> +.Ed +.Pp +This specifies that the message should be sent to +.Li hosta , +from there to +.Li hostb , +and finally to +.Li hostc . +This path is forced even if there is a more efficient path to +.Li hostc . +.Pp +Route-addrs occur frequently on return addresses, since these are generally +augmented by the software at each host. It is generally possible to ignore +all but the +.Dq Li user@domain +part of the address to determine the actual sender. +.Ss Postmaster +.Pp +Every site is required to have a user or user alias designated +.Dq Li postmaster +to which problems with the mail system may be addressed. +.Ss Other Networks +.Pp +Some other networks can be reached by giving the name of the network as the +last component of the domain. +.Em This is not a standard feature +and may +.Em not +be supported at all sites. For example, messages to CSNET or BITNET sites +can often be sent to +.Dq Li user@host.CSNET +or +.Dq Li user@host.BITNET , +respectively. +.Sh BUGS +The RFC822 group syntax +.Pq Dq Li group:user1,user2,user3; +is not supported except in the special case of +.Dq LI group:; +because of a conflict with old berknet-style addresses. +.Pp +Route-Address syntax is grotty. +.Pp +UUCP- and ARPANET-style addresses do not coexist politely. +.Sh SEE ALSO +.Xr mail @CMD_EXT@ , +.Xr sendmail @SYS_OPS_EXT@ ; +Crocker, D. H., RFC822, +.Do +Standard for the Format of Arpa Internet Text Messages +.Dc . Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/mailaddr.7 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/mkdep.1 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/mkdep.1 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/mkdep.1 (revision 109985) @@ -0,0 +1,82 @@ +.\" Copyright (c) 1987 Regents of the University of California. +.\" All rights reserved. +.\" +.\" 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. +.\" +.\" @(#)mkdep.1 5.8 (Berkeley) 10/24/88 +.\" +.Dd October 24, 1988 +.Dt MKDEP @CMD_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm mkdep +.Nd construct Makefile dependency list +.Sh SYNOPSIS +.Nm mkdep +.Op Fl ap +.Op Fl f Ar depend_file +.Op Ar flags +.Ar +.Sh DESCRIPTION +.Ic Mkdep +takes a set of flags for the C compiler and a list +of C source files as arguments and constructs a set of +.Li include +file dependencies which are written into the file +.Pa depend_file , +or +.Dq Pa .depend +by default. An example of its use in a +.Pa Makefile +might be: +.Bd -literal -offset indent +CFLAGS= -O -DDEBUG -I../include -I. +SRCS= file1.c file2.c + +depend: + mkdep ${CFLAGS} ${SRCS} +.Ed +.Pp +where the macro +.Dq Li SRCS +is the list of C source files and the macro +.Dq Li CFLAGS +is the list of flags for the C compiler. +.Pp +If the +.Dq Fl p +option is provided, +.Ic mkdep +produces dependencies +of the form +.Dq Li program: program.c +so that subsequent calls to +.Xr make @CMD_EXT@ +will produce +.Dq Pa program +directly from its C module rather than using an intermediate +.Dq Pa \&.o +module. This is useful in directories which +contain many programs, each of whose source is contained in a single +C module. +.Pp +The +.Dq Fl a +option causes appending to the output file, so that multiple +.Ic mkdep Ns 's +may be run from a single +.Pa Makefile . +.Sh SEE ALSO +.Xr cc @CMD_EXT@ , +.Xr cpp @CMD_EXT@ , +.Xr make @CMD_EXT@ . Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/mkdep.1 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/named-bootconf.8 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/named-bootconf.8 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/named-bootconf.8 (revision 109985) @@ -0,0 +1,69 @@ +.\" $NetBSD: named-bootconf.8,v 1.1 1998/11/19 21:11:45 tron Exp $ +.\" +.\" Copyright (c) 1998 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This documentation is derived from software contributed to The NetBSD +.\" Foundation by Matthias Scheler. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 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 NetBSD +.\" Foundation, Inc. and its contributors. +.\" 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 SUCH DAMAGE. +.\" +.\" Copyright (c) 1999 by Internet Software Consortium +.\" +.\" 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. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\" CONSORTIUM 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 +.\" SOFTWARE. +.Dd November 19, 1998 +.Dt NAMED-BOOTCONF 8 +.Os NetBSD +.Sh NAME +.Nm named-bootconf +.Nd convert name server configuration files +.Sh SYNOPSIS +.Nm +.Sh DESCRIPTION +.Nm +converts named configuration files from BIND 4 format to BIND 8 format. +.Sh EXAMPLES +named-bootconf < named.boot > named.conf +.Sh BUGS +Comments from the source file will not always appear at the appropriate place +in the target file. +.Sh SEE ALSO +.Xr named 8 , +.Xr named.conf 5 Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/named-bootconf.8 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/named-xfer.8 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/named-xfer.8 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/named-xfer.8 (revision 109985) @@ -0,0 +1,183 @@ +.\" ++Copyright++ 1985 +.\" - +.\" Copyright (c) 1985 +.\" 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 +.\" are met: +.\" 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 +.\" SUCH DAMAGE. +.\" - +.\" 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 +.\" SOFTWARE. +.\" - +.\" Portions Copyright (c) 1999 by Check Point Software Technologies, Inc. +.\" +.\" 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 Check Point Software Technologies Incorporated 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 CHECK POINT SOFTWARE TECHNOLOGIES +.\" INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +.\" INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +.\" IN NO EVENT SHALL CHECK POINT SOFTWARE TECHNOLOGIES INCORPRATED +.\" 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 SOFTWARE. +.\" +.\" --Copyright-- +.\" +.\" from named.8 6.6 (Berkeley) 2/14/89 +.\" +.Dd June 26, 1993 +.Dt @XFER_INDOT_U@NAMED-XFER @SYS_OPS_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm @XFER_INDOT@named-xfer +.Nd ancillary agent for inbound zone transfers +.Sh SYNOPSIS +.Nm named-xfer +.Fl z Ar zone_to_transfer +.Fl f Ar db_file +.Fl s Ar serial_no +.Op Fl d Ar debuglevel +.Op Fl l Ar debug_log_file +.Op Fl i Ar ixfr_file +.Op Fl t Ar trace_file +.Op Fl p Ar port# +.Op Fl S +.Ar nameserver +.Op Sy axfr | ixfr +.Sh DESCRIPTION +.Ic Named-xfer +is an ancillary program executed by +.Xr @INDOT@named @SYS_OPS_EXT@ +to perform an inbound zone transfer. It is rarely executed directly, and then +only by system administrators who are trying to debug a zone transfer problem. +See RFC's 1033, 1034, and 1035 for more information on the Internet +name-domain system. +.Pp +Options are: +.Bl -tag -width Fl +.It Fl z Ar zone_to_transfer +specifies the name of the zone to be transferred. +.It Fl f Ar db_file +specifies the name of the +.Ar db_file +into which the zone should be dumped +when it is received from the primary server. +.It Fl s Ar serial_no +specifies the serial number of our current copy of this zone. If the +.Sy SOA RR +we get from the primary server does not have a serial +number higher than this, the transfer will be aborted. +.It Fl d Ar debuglevel +Print debugging information. +The +.Ar debuglevel +is a number determines the level of messages printed. +.It Fl l Ar debug_log_file +Specifies a log file for debugging messages. The default is system- +dependent but is usually in +.Pa /var/tmp +or +.Pa /usr/tmp . +Note that this only applies if +.Dq Fl d +is also specified. +.It Fl i Ar ixfr_file +Specifies the name of the +.Ar ixfr_file +into which the zone changes from Incremental Zone Transfer (IXFR) +should be dumped when it is received from the primary server. +.It Fl t Ar trace_file +Specifies a +.Ar trace_file +which will contain a protocol trace of the zone +transfer. This is probably only of interest to people debugging the name +server itself. +.It Fl p Ar port# +Use a different port number. The default is the standard port number +as returned by +.Xr getservbyname @LIB_NETWORK_EXT@ +for the service +.Dq Li domain . +.It Fl S +Perform a restricted transfer of only the SOA, NS records and glue A records +for the zone. The SOA record will not be loaded by +.Xr @INDOT@named @SYS_OPS_EXT@ +but will be used to +determine when to verify the NS records. See the +.Dq Li stubs +directive in +.Xr @INDOT@named @SYS_OPS_EXT@ +for more information. +.El +.Pp +Additional arguments are taken as name server addresses in so-called +.Dq dotted-quad +syntax +.Em only ; +no host name are allowed here. At least one address must be specified. +Any additional addresses will be tried, in order, if the first one fails +to transfer to us successfully. +The +.Sy axfr +or +.Sy ixfr +after name server address designates the type of zone transfer to perform. +Use +.Sy axfr +for a full zone transfer or +.Sy ixfr +for an incremental zone transfer. +.Sh SEE ALSO +.Xr hostname @DESC_EXT@ , +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr resolver @LIB_NETWORK_EXT@ , +.Xr resolver @FORMAT_EXT@ , +RFC 882, RFC 883, RFC 973, RFC 974, RFC 1033, RFC 1034, RFC 1035, +RFC 1123, RFC 1995 +.Dq Name Server Operations Guide for Sy BIND . Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/named-xfer.8 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/named.8 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/named.8 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/named.8 (revision 109985) @@ -0,0 +1,445 @@ +.\" ++Copyright++ 1985, 1996 +.\" - +.\" Copyright (c) 1985, 1996 +.\" 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 +.\" are met: +.\" 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 +.\" SUCH DAMAGE. +.\" - +.\" 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 +.\" SOFTWARE. +.\" - +.\" --Copyright-- +.\" +.\" @(#)named.8 6.6 (Berkeley) 2/14/89 +.\" +.Dd February 1, 1996 +.Dt @INDOT_U@named @SYS_OPS_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm @INDOT@named +.Nd Internet domain name server (DNS) +.Sh SYNOPSIS +.Nm @INDOT@named +.Op Fl d Ar debuglevel +.Op Fl p Ar port# +.Oo Fl Po +.Cm b Ns \&| Ns Cm c +.Pc +.Ar config_file +.Oc +.Op Fl f q r v +.Op Fl u Ar user_name +.Op Fl g Ar group_name +.Op Fl t Ar directory +.Op Fl w Ar directory +.Op Ar config_file +.Sh DESCRIPTION +.Ic Named +is the Internet domain name server. +See RFC's 1033, 1034, and 1035 for more information on the Internet +name-domain system. Without any arguments, +.Ic named +will read the default configuration file +.Pa /etc/named.conf , +read any initial data, and listen for queries. A +.Ar config_file +argument given at the end of the command line will override any +.Ar config_file +specified by using the +.Dq Fl b +or +.Dq Fl c +flags. +.Pp +.Sy NOTE : +Several of +.Nm named Ns 's +options, and much more of its behaviour, can be controlled in the configuration +file. Please refer to the configuration file guide included with this +.Sy BIND +distribution for further information. +.Pp +Options are: +.Bl -tag -width Fl +.It Fl d Ar debuglevel +Print debugging information. +The +.Ar debuglevel +is a number determines the level of messages printed. If negative, +.Ar debuglevel +is set to +.Dq 1 . +.Pp +.Sy NOTE : +The new debugging framework is considerably more sophisticated than it +was in older versions of +.Nm @INDOT@named . +The configuration file's +.Dq Li logging +statement allows for multiple, distinct levels of debugging for each of +a large set of categories of events (such as queries, transfers in or out, +etc.). Please refer to the configuration file guide included with this +.Sy BIND +distribution for further information about these extensive new capabilities. +.It Fl p Ar port# +Use the specified remote port number; this is the port number to which +.Nm @INDOT@named +will send queries. The default value is the standard port number, i.e., +the port number returned by +.Xr getservbyname @LIB_NETWORK_EXT@ +for service +.Dq Li domain . +.Pp +.Sy NOTE : +Previously, the syntax +.Dq Fl p Ar port# Ns Op Ar \&/localport# +was supported; the first port was that used when contacting +.Em remote +servers, and the second one was the service port bound by the +.Em local +instance of +.Nm @INDOT_U@named . +The current usage is equivalent to the old usage without the +.Ar localport# +specified; this functionality can be specified with the +.Dq Li listen-on +clause of the configuration file's +.Dq Li options +statement. +.It Xo Fl Po +.Cm b Ns \&| Ns Cm c +.Pc Ar config_file +.Xc +Use an alternate +.Ar config_file ; +this argument is overridden by any +.Ar config_file +which is specified at the end of the command line. +The default value is +.Pa /etc/named.conf . +.It Fl f +Run this process in the foreground; don't +.Xr fork @SYSCALL_EXT@ +and daemonize. (The default is to daemonize.) +.It Fl q +Trace all incoming queries if +.Nm @INDOT_U@named +has been compiled with +.Li QRYLOG +defined. +.Pp +.Sy NOTE : +This option is deprecated in favor of the +.Dq Li queries +.Em logging category +of the configuration file's +.Dq Li logging +statement; for more information, please refer to the configuration file guide +included with this distribution of +.Sy BIND . +.It Fl r +Turns recursion off in the server. Answers can come only from local +(primary or secondary) zones. This can be used on root servers. +The default is to use recursion. +.Pp +.Sy NOTE : +This option can be overridden by and is deprecated in favor of the +.Dq Li recursion +clause of the configuration file's +.Dq Li options +statement. +.It Fl v +Report the version and exit. +.It Fl u Ar user_name +Specifies the user the server should run as after it initializes. The value +specified may be either a username or a numeric user id. If the +.Dq Fl g +flag is not specified, then the group id used will be the primary group of +the user specified (initgroups() is called, so all of the user's groups will +be available to the server). +.Pp +.It Fl g Ar group_name +Specifies the group the server should run as after it initializes. The value +specified may be either a groupname or a numeric group id. +.Pp +.It Fl t Ar directory +Specifies the directory the server should chroot() into as soon as it is +finshed processing command line arguments. +.Pp +.It Fl w Ar directory +Sets the working directory of the server. The +.Dq Li directory +clause of the configuration file's +.Dq Li options +statement overrides any value specified on the command line. +The default working directory is the current directory +.Pq Dq \&. . +.El +.Pp +Any additional argument is taken as the name of the configuration file, for +compatibility with older implementations; as noted above, this argument +overrides any +.Ar config_file +specified by the use of the +.Dq Fl b +or +.Dq Fl c +flags. If no further argument is given, then the default configuration file +is used +.Pq Pa /etc/named.conf . +.Ss Master File Format +The master file consists of control information and a list of resource +records for objects in the zone of the forms: +.Bd -literal -offset indent +$INCLUDE +$ORIGIN +$TTL + +.Ed +.Pp +where: +.Bl -tag -width "opt_domain " +.It Ar domain +is +.Dq Li .\& +for root, +.Dq Li @ +for the current origin, or a standard domain name. If +.Ar domain +is a standard domain name that does +.Em not +end with +.Dq Li \&. , +the current origin is appended to the domain. Domain names ending with +.Dq Li .\& +are unmodified. +.It Ar opt_domain +This field is used to define an origin for the data in an included file. +It is equivalent to placing an +.Li $ORIGIN +statement before the first line of the included file. The field is optional. +Neither the +.Ar opt_domain +field nor +.Li $ORIGIN +statements in the included file modify the current origin for this file. +.It Ar ttl +A integer number that sets the default time-to-live for future records without +an explicit ttl. +.It Ar opt_ttl +An optional integer number for the time-to-live field. +If not set the ttl is taken from the last $TTL statement. +If no $TTL statement has occurred then the SOA minimum value is used and a +warning is generated. +.It Ar opt_class +The object address type; currently only one type is supported, +.Dv IN , +for objects connected to the DARPA Internet. +.It Ar type +This field contains one of the following tokens; the data expected in the +.Ar resource_record_data +field is in parentheses: +.Bl -tag -width "HINFO " -offset indent +.It Dv A +a host address (dotted-quad IP address) +.It Dv NS +an authoritative name server (domain) +.It Dv MX +a mail exchanger (domain), preceded by a preference value (0..32767), +with lower numeric values representing higher logical preferences. +.It Dv CNAME +the canonical name for an alias (domain) +.It Dv SOA +marks the start of a zone of authority (domain of originating host, +domain address of maintainer, a serial number and the following +parameters in seconds: refresh, retry, expire and minimum TTL (see RFC 883 +and RFC 2308)). +.It Dv NULL +a null resource record (no format or data) +.It Dv RP +a Responsible Person for some domain name (mailbox, TXT-referral) +.It Dv PTR +a domain name pointer (domain) +.It Dv HINFO +host information (cpu_type OS_type) +.El +.El +.Pp +Resource records normally end at the end of a line, +but may be continued across lines between opening and closing parentheses. +Comments are introduced by semicolons and continue to the end of the line. +.Pp +.Sy NOTE : +There are other resource record types not shown here. You should +consult the +.Sy BIND +Operations Guide +.Pq Dq BOG +for the complete +list. Some resource record types may have been standardized in newer RFC's +but not yet implemented in this version of +.Sy BIND . +.Ss SOA Record Format +Each master zone file should begin with an SOA record for the zone. +An example SOA record is as follows: +.Bd -literal +@ IN SOA ucbvax.Berkeley.EDU. rwh.ucbvax.Berkeley.EDU. ( + 1989020501 ; serial + 10800 ; refresh + 3600 ; retry + 3600000 ; expire + 86400 ) ; minimum +.Ed +.Pp +The SOA specifies a serial number, which should be incremented each time the +master file is changed. Note that the serial number can be given as a +dotted number, but this is a +.Em very +unwise thing to do since the +translation to normal integers is via concatenation rather than +multiplication and addition. You can spell out the year, month, day of +month, and 0..99 version number and still fit inside the unsigned 32-bit +size of this field. (It's true that we will have to rethink this strategy in +the year 4294, but we're not worried about it.) +.Pp +Secondary servers +check the serial number at intervals specified by the refresh time in +seconds; if the serial number changes, a zone transfer will be done to load +the new data. If a master server cannot be contacted when a refresh is due, +the retry time specifies the interval at which refreshes should be attempted. +If a master server cannot be contacted within the interval given by the +expire time, all data from the zone is discarded by secondary servers. The +minimum value is the cache time-to-live for negative answers (RFC 2308). +.Sh NOTES +The boot file directives +.Dq Li domain +and +.Dq Li suffixes +have been +obsoleted by a more useful, resolver-based implementation of +suffixing for partially-qualified domain names. The prior mechanisms +could fail under a number of situations, especially when then local +nameserver did not have complete information. +.Pp +The following signals have the specified effect when sent to the +server process using the +.Xr kill @CMD_EXT@ +command: +.Pp +.Bl -tag -width "SIGWINCH" +.It Dv SIGHUP +Causes server to read +.Pa named.conf +and reload the database. If the server +is built with the +.Li FORCED_RELOAD +compile-time option, then +.Dv SIGHUP +will +also cause the server to check the serial number on all secondary zones; +normally, the serial numbers are only checked at the SOA-specified intervals. +.It Dv SIGINT +Dumps the current data base and cache to +.Dq Pa /var/tmp/named_dump.db +or the value of +.Dv _PATH_DUMPFILE . +.It Dv SIGILL +Dumps statistics data into +.Pa named.stats +if the server is compiled with +.Li -DSTATS . +Statistics data is appended to the file. +.It Dv SIGSYS +Dumps the profiling data in +.Pa /var/tmp +if the server is compiled with profiling (server forks, chdirs and exits). +.It Dv SIGTERM +Saves any modified dynamic zones to the file system, and shuts down the server. +.It Dv SIGUSR1 +Turns on debugging; each +.Dv SIGUSR1 +increments debug level. +.Po +.Dv SIGEMT +on older systems without +.Dv SIGUSR1 . +.Pc +.It Dv SIGUSR2 +Turns off debugging completely. +.Po +.Dv SIGFPE +on older systems without +.Dv SIGUSR2 . +.Pc +.It Dv SIGWINCH +Toggles logging of all incoming queries via +.Xr syslog @LIB_C_EXT@ +(requires server to have been built with the +.Li QRYLOG +option). +.El +.Sh FILES +.Bl -tag -width "/var/tmp/named_dump.db (_PATH_DUMPFILE) " -compact +.It Pa /etc/named.conf +default name server configuration file +.It Pa /var/run/named.pid Pq Dv _PATH_PIDFILE +the process id +.It Pa /var/tmp/named_dump.db Pq Dv _PATH_DUMPFILE +dump of the name server database +.It Pa /var/tmp/named.run Pq file: Dv _PATH_DEBUG +debug output +.It Pa /var/tmp/named.stats Pq file: Dv _PATH_STATS +nameserver statistics data +.El +.Sh SEE ALSO +.Xr named.conf @FORMAT_EXT@ , +.Xr gethostbyname @LIB_NETWORK_EXT@ , +.Xr hostname @DESC_EXT@ , +.Xr kill @CMD_EXT@ , +.Xr resolver @LIB_NETWORK_EXT@ , +.Xr resolver @FORMAT_EXT@ , +.Xr signal @LIB_C_EXT@ , +RFC 882, RFC 883, RFC 973, RFC 974, RFC 1033, RFC 1034, RFC 1035, RFC 1123, +RFC 2308 +.Dq Name Server Operations Guide for Sy BIND Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/named.8 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/ndc.8 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/ndc.8 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/ndc.8 (revision 109985) @@ -0,0 +1,133 @@ +.\" Copyright (c) 1998,1999 by Internet Software Consortium +.\" +.\" 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. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\" CONSORTIUM 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 +.\" SOFTWARE. +.\" +.Dd December 31, 1998 +.Dt @INDOT_U@NDC @SYS_OPS_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm ndc +.Nd name daemon control program +.Sh SYNOPSIS +.Nm ndc +.Op Fl c Ar channel +.Op Fl l Ar localsock +.Op Fl p Ar pidfile +.Op Fl d +.Op Fl q +.Op Fl s +.Op Fl t +.Op Ar command +.Sh DESCRIPTION +This command allows the system administrator to control the operation +of a name server. If no +.Ar command +is given, +.Ic ndc +will prompt for commands until it reads EOF. +.Pp +Options are: +.Bl -tag -width Fl +.It Fl c Ar channel +Specifies the rendezvous point for the control channel. The default is +.Pa /var/run/ndc +(a UNIX domain socket which is also the server's default control channel). +If the desired control channel is a TCP/IP socket, then the format of the +.Ar channel +argument is +.Sy ipaddr/port +(for example, +.Sy 127.0.0.1/54 +would be TCP port 54 on the local host.) +.It Fl l Ar localsock +This option will +.Xr bind 2 +the client side of the control channel to a specific address. Servers can +be configured to reject connections which do not come from specific addresses. +The format is the same as for +.Ar channel +(see above). +.It Fl p Ar pidfile +For backward compatibility with older name servers, +.Ic ndc +is able to use UNIX signals for control communications. This capability is +optional in modern name servers and will disappear altogether at some future +time. Note that the available +.Ar command +set is narrower when the signal interface is used. A likely +.Ar pidfile +argument would be something like +.Pa /var/run/named.pid . +.It Fl d +Turns on debugging output, which is of interest mainly to developers. +.It Fl q +Suppresses prompts and result text. +.It Fl s +Suppresses nonfatal error announcements. +.It Fl t +Turns on protocol and system tracing, useful in installation debugging. +.El +.Sh COMMANDS +Several commands are built into +.Ic ndc , +but the full set of commands supported by the name server is dynamic and +should be discovered using the +.Ar help +command (see below). Builtin commands are: +.Bl -tag -width Fl +.It Ar /help +Provides help for builtin commands. +.It Ar /exit +Exit from +.Ic ndc +command interpreter. +.It Ar /trace +Toggle tracing (see +.Fl t +description above). +.It Ar /debug +Toggle debugging (see +.Fl d +description above). +.It Ar /quiet +Toggle quietude (see +.Fl q +description above). +.It Ar /silent +Toggle silence (see +.Fl s +description above). +.El +.Sh NOTES +If running in +.Ar pidfile +mode, any arguments to +.Ar start +and +.Ar restart +commands are passed to the new +.Ic @INDOT@named +on its command line. If running in +.Ar channel +mode, there is no +.Ar start +command and the +.Ar restart +command just tells the name server to +.Xr execvp @LIB_C_EXT@ +itself. +.Sh AUTHOR +Paul Vixie (Internet Software Consortium) +.Sh SEE ALSO +.Xr @INDOT@named @SYS_OPS_EXT@ , Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/ndc.8 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/nslookup.8 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/nslookup.8 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/nslookup.8 (revision 109985) @@ -0,0 +1,535 @@ +.\" +.\" ++Copyright++ 1985, 1989 +.\" - +.\" Copyright (c) 1985, 1989 +.\" 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 +.\" are met: +.\" 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 +.\" SUCH DAMAGE. +.\" - +.\" 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 +.\" SOFTWARE. +.\" - +.\" --Copyright-- +.\" +.\" @(#)nslookup.8 5.3 (Berkeley) 6/24/90 +.\" +.Dd June 24, 1990 +.Dt NSLOOKUP @SYS_OPS_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm nslookup +.Nd query Internet name servers interactively +.Sh SYNOPSIS +.Nm nslookup +.Op Fl option Ar ... +.Op Ar host-to-find | Fl Op Ar server +.Sh DESCRIPTION +.Ic Nslookup +is a program to query Internet domain name servers. +.Ic Nslookup +has two modes: interactive and non-interactive. +Interactive mode allows the user to query name servers for +information about various hosts and domains or to print a list of hosts +in a domain. +Non-interactive mode is used to print just the name and requested information +for a host or domain. +.Sh ARGUMENTS +Interactive mode is entered in the following cases: +.Bl -tag -width "a) " +.It a) +when no arguments are given (the default name server will be used), +.It b) +when the first argument is a hyphen (-) and the second argument +is the host name or Internet address of a name server. +.El +.Pp +Non-interactive mode is used when the name or Internet address +of the host to be looked up +is given as the first argument. The optional second argument specifies +the host name or address of a name server. +.Pp +The options listed under the +.Dq Li set +command below can be specified in +the +.Pa .nslookuprc +file in the user's home directory if they are listed +one per line. Options can also be specified +on the command line if they precede the arguments and are prefixed with +a hyphen. For example, to change the default query type to host information, +and the initial timeout to 10 seconds, type: +.Bd -literal -offset indent + nslookup -query=hinfo -timeout=10 +.Ed +.Sh INTERACTIVE COMMANDS +Commands may be interrupted at any time by typing a control-C. +To exit, type a control-D +.Pq Dv EOF +or type +.Li exit . +The command line length must be less than 256 characters. +To treat a built-in command as a host name, +precede it with an escape character +.Pq .&\\ . +.Sy N.B.: An unrecognized command will be interpreted as a host name. +.Bl -tag -width "lserver" +.It Ar host Op Ar server +Look up information for +.Ar host +using the current default server or using +.Ar server , +if specified. +If +.Ar host +is an Internet address and the query type is +.Dv A +or +.Dv PTR , +the name of the host is returned. +If +.Ar host +is a name and does not have a trailing period, the default +domain name is appended to the name. (This behavior depends on the state of the +.Ic set +options +.Ic domain , srchlist , defname , +and +.Ic search . ) +.Pp +To look up a host not in the current domain, append a period to +the name. +.It Ic server Ar domain +.It Ic lserver Ar domain +Change the default server to +.Ar domain ; +.Ic lserver +uses the initial server to look up information about +.Ar domain , +while +.Ic server +uses the current default server. +If an authoritative answer can't be found, the names of servers +that might have the answer are returned. +.It Ic root +Changes the default server to the server for the root of the domain name space. +Currently, the host +.Li ns.internic.net +is used. +(This command is a synonym for +.Dq Ic lserver ns.internic.net . ) +The name of the root server can be changed with the +.Dq Ic set root +command. +.It Xo Ic finger Op Ar name +.Op Ic > Ar filename +.Xc +.It Xo Ic finger Op Ar name +.Op Ic >> Ar filename +.Xc +Connects with the finger server on the current host. +The current host is defined when a previous lookup for a host +was successful and returned address information (see the +.Dq Ic set querytype Ns = Ns Dv A +command). +The +.Ar name +is optional. +.Ic > +and +.Ic >> +can be used to redirect output in the usual manner. +.It Xo Ic ls Op Ar option +.Ar domain Op Ic > Ar filename +.Xc +.It Xo Ic ls Op Ar option +.Ar domain Op Ic >> Ar filename +.Xc +List the information available for +.Ar domain , +optionally creating or appending to +.Ar filename . +The default output contains host names and their Internet addresses. +.Ar Option +can be one of the following: +.Bl -tag -width "-a " +.It Fl t Ar querytype +lists all records of the specified type (see +.Ar querytype +below). +.It Fl a +lists aliases of hosts in the domain; +synonym for +.Dq Fl t Dv CNAME . +.It Fl d +lists all records for the domain; +synonym for +.Dq Fl t Dv ANY . +.It Fl h +lists CPU and operating system information for the domain; +synonym for +.Dq Fl t Dv HINFO . +.It Fl s +lists well-known services of hosts in the domain; +synonym for +.Dq Fl t Dv WKS . +.El +.Pp +When output is directed to a file, hash marks are printed for every +50 records received from the server. +.It Ic view Ar filename +Sorts and lists the output of previous +.Ic ls +command(s) with +.Xr more @CMD_EXT@ . +.It Ic help +.It Ic ?\& +Prints a brief summary of commands. +.It Ic exit +Exits the program. +.It Xo +.Ic set +.Ar keyword Ns Op = Ns Ar value +.Xc +This command is used to change state information that affects the lookups. +Valid keywords are: +.Bl -tag -width "class=v" +.It Ic all +Prints the current values of the frequently-used options to +.Ic set . +Information about the current default server and host is also printed. +.It Ic class Ns = Ns Ar value +Change the query class to one of: +.Bl -tag -width "HESIOD " +.It Dv IN +the Internet class +.It Dv CHAOS +the Chaos class +.It Dv HESIOD +the MIT Athena Hesiod class +.It Dv ANY +wildcard (any of the above) +.El +.Pp +The class specifies the protocol group of the information. +.Pp +(Default = +.Dv IN ; +abbreviation = +.Ic cl ) +.It Xo +.Oo Ic no Oc Ns Ic debug +.Xc +Turn debugging mode on. A lot more information is printed about the +packet sent to the server and the resulting answer. +.Pp +(Default = +.Ic nodebug ; +abbreviation = +.Oo Ic no Oc Ns Ic deb ) +.It Xo +.Oo Ic no Oc Ns Ic d2 +.Xc +Turn exhaustive debugging mode on. +Essentially all fields of every packet are printed. +.Pp +(Default = +.Ic nod2 ) +.It Ic domain Ns = Ns Ar name +Change the default domain name to +.Ar name . +The default domain name is appended to a lookup request depending on the +state of the +.Ic defname +and +.Ic search +options. +The domain search list contains the parents of the default domain if it has +at least two components in its name. +For example, if the default domain +is CC.Berkeley.EDU, the search list is CC.Berkeley.EDU and Berkeley.EDU. +Use the +.Dq Ic set srchlist +command to specify a different list. +Use the +.Dq Ic set all +command to display the list. +.Pp +(Default = value from +.Xr hostname @CMD_EXT@ , +.Pa /etc/resolv.conf , +or +.Ev LOCALDOMAIN ; +abbreviation = +.Ic do ) +.It Xo +.Sm off +.Ic srchlist No = +.Ar name1 No / +.Ar name2 No / +.Ar ... +.Sm on +.Xc +Change the default domain name to +.Ar name1 +and the domain search list +to +.Ar name1 , name2 , +etc. A maximum of 6 names separated by slashes (/) +can be specified. +For example, +.Bd -literal -offset indent +set srchlist=lcs.MIT.EDU/ai.MIT.EDU/MIT.EDU +.Ed +.Pp +sets the domain to lcs.MIT.EDU and the search list to the three names. +This command overrides the +default domain name and search list of the +.Dq Ic set domain +command. +Use the +.Dq Ic set all +command to display the list. +.Pp +(Default = value based on +.Xr hostname @CMD_EXT@ , +.Pa /etc/resolv.conf , +or +.Ev LOCALDOMAIN ; +abbreviation = +.Ic srchl ) +.It Xo +.Oo Ic no Oc Ns Ic defname +.Xc +If set, append the default domain name to a single-component lookup request +(i.e., one that does not contain a period). +.Pp +(Default = +.Ic defname ; +abbreviation = +.Oo Ic no Oc Ns Ic defname ) +.It Xo +.Oo Ic no Oc Ns Ic search +.Xc +If the lookup request contains at least one period but +.Em doesn't +end with a trailing period, append the domain names in the domain search list +to the request until an answer is received. +.Pp +(Default = +.Ic search ; +abbreviation = +.Oo Ic no Oc Ns Ic sea ) +.It Ic port Ns = Ns Ar value +Change the default TCP/UDP name server port to +.Ar value . +.Pp +(Default = 53; +abbreviation = +.Ic \&po ) +.It Ic querytype Ns = Ns Ar value +.It Ic type Ns = Ns Ar value +Change the type of information query to one of: +.Bl -tag -width "HINFO " +.It Dv A +the host's Internet address. +.It Dv CNAME +the canonical name for an alias. +.It Dv HINFO +the host CPU and operating system type. +.It Dv MINFO +the mailbox or mail list information. +.It Dv MX +the mail exchanger. +.It Dv NS +the name server for the named zone. +.It Dv PTR +the host name if the query is an Internet address; +otherwise, the pointer to other information. +.It Dv SOA +the domain's +.Dq start-of-authority +information. +.It Dv TXT +the text information. +.It Dv UINFO +the user information. +.It Dv WKS +the supported well-known services. +.El +.Pp +Other types +.Dv ( ANY , AXFR , MB , +.Dv MD , MF , NULL ) +are described in the RFC-1035 document. +.Pp +(Default = +.Dv A ; +abbreviations = +.Ic q , ty ) +.It Xo +.Oo Ic no Oc Ns Ic recurse +.Xc +Tell the name server to query other servers if it does not have the +information. +.Pp +(Default = +.Ic recurse ; +abbreviation = +.Oo Ic no Oc Ns Ic rec ) +.It Ic retry Ns = Ns Ar number +Set the number of retries to +.Ar number . +When a reply to a request is not received within a certain +amount of time (changed with +.Dq Ic set timeout ) , +the timeout period is doubled and the request is resent. +The retry value controls how many times a request is resent before giving up. +.Pp +(Default = 4, abbreviation = +.Ic ret ) +.It Ic root Ns = Ns Ar host +Change the name of the root server to +.Ar host . +This affects the +.Dq Ic root +command. +.Pp +(Default = +.Ic ns.internic.net. ; +abbreviation = +.Ic ro ) +.It Ic timeout Ns = Ns Ar number +Change the initial timeout interval for waiting for a reply to +.Ar number +seconds. Each retry doubles the timeout period. +.Pp +(Default = 5 seconds; abbreviation = +.Ic ti ) +.It Xo +.Oo Ic no Oc Ns Ic vc +.Xc +Always use a virtual circuit when sending requests to the server. +.Pp +(Default = +.Ic novc ; +abbreviation = +.Oo Ic no Oc Ns Ic v ) +.It Xo +.Oo Ic no Oc Ns Ic ignoretc +.Xc +Ignore packet truncation errors. +.Pp +(Default = +.Ic noignoretc ; +abbreviation = +.Oo Ic no Oc Ns Ic ig ) +.El +.El +.Sh DIAGNOSTICS +If the lookup request was not successful, an error message is printed. +Possible errors are: +.Bl -tag -width "Timed" +.It Li Timed out +The server did not respond to a request after a certain amount of +time (changed with +.Dq Ic set timeout Ns = Ns Ar value ) +and a certain number of retries (changed with +.Do +.Ic set retry Ns = Ns Ar value +.Dc ) . +.It Li \&No response from server +No name server is running on the server machine. +.It Li \&No records +The server does not have resource records of the current query type for the +host, although the host name is valid. +The query type is specified with the +.Dq Ic set querytype +command. +.It Li Non-existent domain +The host or domain name does not exist. +.It Li Connection refused +.It Li Network is unreachable +The connection to the name or finger server could not be made +at the current time. +This error commonly occurs with +.Ic ls +and +.Ic finger +requests. +.It Li Server failure +The name server found an internal inconsistency in its database +and could not return a valid answer. +.It Li Refused +The name server refused to service the request. +.It Li Format error +The name server found that the request packet was not in the proper format. +It may indicate an error in +.Nm nslookup . +.El +.Sh FILES +.Bl -tag -width "/usr/share/misc/nslookup.helpXXX" -compact +.It Pa /etc/resolv.conf +initial domain name and name server addresses +.It Pa $HOME/.nslookuprc +user's initial options +.It Pa /usr/share/misc/nslookup.help +summary of commands +.El +.Sh ENVIRONMENT +.Bl -tag -width "HOSTALIASESXXXX" -compact +.It Ev HOSTALIASES +file containing host aliases +.It Ev LOCALDOMAIN +overrides default domain +.El +.Sh SEE ALSO +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr resolver @LIB_NETWORK_EXT@ , +.Xr resolver @FORMAT_EXT@ ; +RFC-1034, +.Dq Domain Names - Concepts and Facilities ; +RFC-1035, +.Dq Domain Names - Implementation and Specification . +.Sh AUTHOR +Andrew Cherenson Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/nslookup.8 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/nsupdate.8 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/nsupdate.8 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/nsupdate.8 (revision 109985) @@ -0,0 +1,203 @@ +.\" $Id: nsupdate.8,v 8.8 2002/04/22 04:38:04 marka Exp $ +.\" +.\"Copyright (c) 1999 by Internet Software Consortium +.\" +.\"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. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM 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 +.\"SOFTWARE. +.Dd March 5, 1999 +.Dt NSUPDATE @SYS_OPS_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm nsupdate +.Nd update Internet name servers interactively +.Sh SYNOPSIS +.Nm nsupdate +.Op Fl k Ar keydir:keyname +.Op Fl d +.Op Fl v +.Op Ar filename +.Sh DESCRIPTION +.Ic Nsupdate +is a program to update Internet domain name servers +supporting dynamic update. +.Ic Nsupdate +uses the DNS resolver library to pass messages +to a DNS server requesting the additional or deletion of +DNS resource records (RRs). +.Ic Nsupdate +reads input from +.Ar filename +or standard input. +.Sh ARGUMENTS +.Bl -tag -width Fl +.It Fl k +Sign updates with TSIG. +.It Fl d +Debug mode. +.It Fl v +Virtual circuit - use TCP to communication with server. +Default is UDP. +.El +.Sh INPUT FORMAT +.Ic Nsupdate +reads input records, one per line, +each line contributing a resource record to an +update request. +All domain names used in a single update request +must belong to the same DNS zone. +Updates are sent to the master server as defined in the SOA +MNAME field. +A blank line causes the accumulated +records to be formated into a single update request +and transmitted to the zone's authoritative name servers. +Additional records may follow, +which are formed into additional, +completely independent update requests. +For the last request to be transmitted, a blank line +must end the input. +.Pp +Records take one of two general forms. +.Em Prerequisite +records specify conditions that must be satisfied before +the request will be processed. +.Em Update +records specify changes to be made to the DNS database. +A update request consists of zero or more prerequisites +and one or more updates. +Each update request is processed atomically - +all prerequisites must be satisfied, then all updates +will be performed. +.Pp +.Ic Nsupdate +understands the following input record formats: +.Pp +.Bl -hang +.It Ic prereq nxdomain Va domain-name +Requires that no RR of any type exists with name +.Va domain-name . +.It Ic prereq yxdomain Va domain-name +Requires that at least one RR named +.Va domain-name +must exist. +.It Xo +.Ic prereq nxrrset Va domain-name Op class +.Va type +.Xc +Requires that no RR exists of the specified +.Va type +and +.Va domain-name . +.It Xo +.Ic prereq yxrrset +.Va domain-name Op Va class +.Va type Op Va data... +.Xc +Requires that a RR exists of the specified +.Va type +and +.Va domain-name . +If +.Va data +is specified, it must match exactly. +.It Xo +.Ic update delete +.Va domain-name Op Va class +.Op Va type Op Va data... +.Xc +Deletes RRs named +.Va domain-name . +If +.Va type +(and possibly +.Va data ) +is specified, +only matching records will be deleted. +.It Xo +.Ic update add +.Va domain-name ttl Op Va class +.Va type data... +.Xc +Adds a new RR with specified +.Va ttl , type , +and +.Va data . +.El +.Sh EXAMPLES +The following example illustrates the interactive use of +.Ic nsupdate +to change an IP address by deleting any existing A records +for a domain name and then inserting a new one. +Since no prerequisites are specified, +the new record will be added even if +there were no existing records to delete. +Note the +trailing blank line, required to process the request. +.Bd -literal -offset indent +$ nsupdate +> update delete test.example.com A +> update add test.example.com 3600 A 10.1.1.1 +> +.Ed +.Pp +In this example, a CNAME alias is added to the database +only if there are no existing A or CNAME records for +the domain name. +.Bd -literal -offset indent +$ nsupdate +> prereq nxrrset www.example.com A +> prereq nxrrset www.example.com CNAME +> update add www.example.com 3600 CNAME test.example.com +> +.Ed +.Pp +In this example, the nsupdate will be signed with the key "mykey", which +is in the directory "/var/named/keys". +.Bd -literal -offset indent +$ nsupdate -k /var/named/keys:mykey +> update add ftp.example.com 60 A 192.168.5.1 +> +.Ed +.Sh DIAGNOSTICS +.Bl -hang +.It Qq send error +Typically indicates that the authoritative nameservers could not be reached +.It Qq failed update packet +Typically indicates that the nameserver has rejected the update, +either because the nameserver doesn't support dynamic update, +or due to an authentication failure +.It Qq res_mkupdate: packet size = Va size +(and no other messages) +The update was successfully received and authenticated by the nameserver. +The prerequisites, however, may have prevented the update from actually +being performed. The only way to determine if the update was performed +is to use debug mode +.Fl ( d ) +and examine the status field in the nameserver's reply. +.El +.Sh FILES +.Bl -hang +.It Pa /etc/resolv.conf +initial domain name and name server addresses +.El +.Sh SEE ALSO +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr resolver @LIB_NETWORK_EXT@ , +.Xr resolver @FORMAT_EXT@ ; +RFC-1034, +.Dq Domain Names - Concepts and Facilities ; +RFC-1035, +.Dq Domain Names - Implementation and Specification ; +RFC-2136, +Dynamic Updates in the Domain Name System. +.Sh AUTHOR +Brent Baccala Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/nsupdate.8 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/resolver.5 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/resolver.5 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/resolver.5 (revision 109985) @@ -0,0 +1,240 @@ +.\" Copyright (c) 1986 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" 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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +.\" +.\" @(#)resolver.5 5.9 (Berkeley) 12/14/89 +.\" $Id: resolver.5,v 8.9 2001/12/28 04:24:21 marka Exp $ +.\" +.Dd November 11, 1993 +.Dt RESOLVER @FORMAT_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm resolver +.Nd resolver configuration file +.Sh SYNOPSIS +.Pa /etc/resolv.conf +.Sh DESCRIPTION +The +.Nm resolver +is a set of routines in the C library +.Pq Xr resolve @LIB_NETWORK_EXT@ +that provide access to the Internet Domain Name System. +The +.Nm resolver +configuration file contains information that is read +by the +.Nm resolver +routines the first time they are invoked by a process. +The file is designed to be human readable and contains a list of +keywords with values that provide various types of +.Nm resolver +information. +.Pp +On a normally configured system, this file should not be necessary. +The only name server to be queried will be on the local machine, +the domain name is determined from the host name, +and the domain search path is constructed from the domain name. +.Pp +The different configuration directives are: +.Bl -tag -width "nameser" +.It Li nameserver +Internet address (in dot notation) of a name server that the +.Nm resolver +should query. Up to +.Dv MAXNS +(see +.Pa ) +name servers may be listed, one per keyword. +If there are multiple servers, the +.Nm resolver +library queries them in the order listed. +If no +.Li nameserver +entries are present, the default is to use the name server on the local machine. +(The algorithm used is to try a name server, and if the query times out, +try the next, until out of name servers, +then repeat trying all the name servers +until a maximum number of retries are made). +.It Li domain +Local domain name. +Most queries for names within this domain can use short names +relative to the local domain. +If no +.Li domain +entry is present, the domain is determined from the local host name returned by +.Xr gethostname @BSD_SYSCALL_EXT@ ; +the domain part is taken to be everything after the first +.Sq \&. . +Finally, if the host name does not contain a domain part, the root +domain is assumed. +.It Li search +Search list for host-name lookup. +The search list is normally determined from the local domain name; +by default, it contains only the local domain name. +This may be changed by listing the desired domain search path +following the +.Li search +keyword with spaces or tabs separating the names. +Most +.Nm resolver +queries will be attempted using each component +of the search path in turn until a match is found. +Note that this process may be slow and will generate a lot of network +traffic if the servers for the listed domains are not local, +and that queries will time out if no server is available +for one of the domains. +.Pp +The search list is currently limited to six domains +with a total of 256 characters. +.It Li sortlist +Allows addresses returned by gethostbyname to be sorted. +A +.Li sortlist +is specified by IP address netmask pairs. The netmask is +optional and defaults to the natural netmask of the net. The IP address +and optional network pairs are separated by slashes. Up to 10 pairs may +be specified. For example: +.Bd -literal -offset indent +sortlist 130.155.160.0/255.255.240.0 130.155.0.0 +.Ed +.It Li options +Allows certain internal +.Nm resolver +variables to be modified. +The syntax is +.D1 Li options Ar option ... +where +.Ar option +is one of the following: +.Bl -tag -width "ndots:n " +.It Li debug +sets +.Dv RES_DEBUG +in +.Ft _res.options . +.It Li ndots: Ns Ar n +sets a threshold for the number of dots which +must appear in a name given to +.Fn res_query +(see +.Xr resolver @LIB_NETWORK_EXT@ ) +before an +.Em initial absolute query +will be made. The default for +.Ar n +is +.Dq 1 , +meaning that if there are +.Em any +dots in a name, the name will be tried first as an absolute name before any +.Em search list +elements are appended to it. +.It Li timeout: Ns Ar n +sets the amount of time the resolver will wait for a response from a remote +name server before retrying the query via a different name server. Measured in +seconds, the default is +.Dv RES_TIMEOUT +(see +.Pa ) . +.It Li attempts: Ns Ar n +sets the number of times the resolver will send a query to its name servers +before giving up and returning an error to the calling application. The +default is +.Dv RES_DFLRETRY +(see +.Pa ) . +.It Li rotate +sets +.Dv RES_ROTATE +in +.Ft _res.options , +which causes round robin selection of nameservers from among those listed. +This has the effect of spreading the query load among all listed servers, +rather than having all clients try the first listed server first every time. +.It Li no-check-names +sets +.Dv RES_NOCHECKNAME +in +.Ft _res.options , +which disables the modern BIND checking of incoming host names and mail names +for invalid characters such as underscore (_), non-ASCII, or control characters. +.It Li inet6 +sets +.Dv RES_USE_INET6 +in +.Ft _res.options . +This has the effect of trying a AAAA query before an A query inside the +.Ft gethostbyname +function, and of mapping IPv4 responses in IPv6 ``tunnelled form'' if no +AAAA records are found but an A record set exists. +.It Li no-tld-query +sets +.Dv RES_NOTLDQUERY +in +.Ft _res.options . +This option causes +.Fn res_nsearch +to not attempt to resolve a unqualified name as if it were a top level +domain (TLD). +This option can cause problems if the site has "localhost" as a TLD rather +than having localhost on one or more elements of the search list. +This option has no effect if neither +.Dv RES_DEFNAMES +or +.Dv RES_DNSRCH +is set. +.El +.El +.Pp +The +.Li domain +and +.Li search +keywords are mutually exclusive. +If more than one instance of these keywords is present, +the last instance wins. +.Pp +The +.Li search +keyword of a system's +.Pa resolv.conf +file can be +overridden on a per-process basis by setting the environment variable +.Dq Ev LOCALDOMAIN +to a space-separated list of search domains. +.Pp +The +.Li options +keyword of a system's +.Pa resolv.conf +file can be amended on a per-process basis by setting the environment variable +.Dq Ev RES_OPTIONS to a space-separated list of +.Nm resolver +options as explained above under +.Li options . +.Pp +The keyword and value must appear on a single line, and the keyword +(e.g., +.Li nameserver ) +must start the line. The value follows the keyword, separated by white space. +.Sh FILES +.Pa /etc/resolv.conf +.Pa +.Sh SEE ALSO +.Xr gethostbyname @LIB_NETWORK_EXT@ , +.Xr hostname @DESC_EXT@ , +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr resolver @LIB_NETWORK_EXT@ , +.Xr resolver @FORMAT_EXT@ . +.Dq Name Server Operations Guide for Sy BIND Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/resolver.5 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/tsig.3 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/tsig.3 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/tsig.3 (revision 109985) @@ -0,0 +1,240 @@ +.\" $Id: tsig.3,v 8.3 2001/08/08 07:50:19 marka Exp $ +.\" +.\"Copyright (c) 1995-1999 by Internet Software Consortium +.\" +.\"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. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM 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 +.\"SOFTWARE. +.\" +.Dd January 1, 1996 +.Os BSD 4 +.Dt TSIG @SYSCALL_EXT@ +.Sh NAME +.Nm ns_sign , +.Nm ns_sign_tcp , +.Nm ns_sign_tcp_init , +.Nm ns_verify , +.Nm ns_verify_tcp , +.Nm ns_verify_tcp_init , +.Nm ns_find_tsig +.Nd TSIG system +.Sh SYNOPSIS +.Ft int +.Fo ns_sign +.Fa "u_char *msg" +.Fa "int *msglen" +.Fa "int msgsize" +.Fa "int error" +.Fa "void *k" +.Fa "const u_char *querysig" +.Fa "int querysiglen" +.Fa "u_char *sig" +.Fa "int *siglen" +.Fa "time_t in_timesigned" +.Fc +.Ft int +.Fn ns_sign_tcp "u_char *msg" "int *msglen" "int msgsize" "int error" \ + "ns_tcp_tsig_state *state" "int done" +.Ft int +.Fn ns_sign_tcp_init "void *k" "const u_char *querysig" "int querysiglen" \ + "ns_tcp_tsig_state *state" +.Ft int +.Fo ns_verify +.Fa "u_char *msg" +.Fa "int *msglen" +.Fa "void *k" +.Fa "const u_char *querysig" +.Fa "int querysiglen" +.Fa "u_char *sig" +.Fa "int *siglen" +.Fa "time_t in_timesigned" +.Fa "int nostrip" +.Fc +.Ft int +.Fn ns_verify_tcp "u_char *msg" "int *msglen" "ns_tcp_tsig_state *state" \ + "int required" +.Ft int +.Fn ns_verify_tcp_init "void *k" "const u_char *querysig" "int querysiglen" \ + "ns_tcp_tsig_state *state" +.Ft u_char * +.Fn ns_find_tsig "u_char *msg" "u_char *eom" +.Sh DESCRIPTION +The TSIG routines are used to implement transaction/request security of +DNS messages. +.Pp +.Fn ns_sign +and +.Fn ns_verify +are the basic routines. +.Fn ns_sign_tcp +and +.Fn ns_verify_tcp +are used to sign/verify TCP messages that may be split into multiple packets, +such as zone transfers, and +.Fn ns_sign_tcp_init , +.Fn ns_verify_tcp_init +initialize the state structure necessary for TCP operations. +.Fn ns_find_tsig +locates the TSIG record in a message, if one is present. +.Pp +.Fn ns_sign +.Bl -tag -width "in_timesigned" -compact -offset indent +.It Dv msg +the incoming DNS message, which will be modified +.It Dv msglen +the length of the DNS message, on input and output +.It Dv msgsize +the size of the buffer containing the DNS message on input +.It Dv error +the value to be placed in the TSIG error field +.It Dv key +the (DST_KEY *) to sign the data +.It Dv querysig +for a response, the signature contained in the query +.It Dv querysiglen +the length of the query signature +.It Dv sig +a buffer to be filled with the generated signature +.It Dv siglen +the length of the signature buffer on input, the signature length on output +.El +.Pp +.Fn ns_sign_tcp +.Bl -tag -width "in_timesigned" -compact -offset indent +.It Dv msg +the incoming DNS message, which will be modified +.It Dv msglen +the length of the DNS message, on input and output +.It Dv msgsize +the size of the buffer containing the DNS message on input +.It Dv error +the value to be placed in the TSIG error field +.It Dv state +the state of the operation +.It Dv done +non-zero value signifies that this is the last packet +.El +.Pp +.Fn ns_sign_tcp_init +.Bl -tag -width "in_timesigned" -compact -offset indent +.It Dv k +the (DST_KEY *) to sign the data +.It Dv querysig +for a response, the signature contained in the query +.It Dv querysiglen +the length of the query signature +.It Dv state +the state of the operation, which this initializes +.El +.Pp +.Fn ns_verify +.Bl -tag -width "in_timesigned" -compact -offset indent +.It Dv msg +the incoming DNS message, which will be modified +.It Dv msglen +the length of the DNS message, on input and output +.It Dv key +the (DST_KEY *) to sign the data +.It Dv querysig +for a response, the signature contained in the query +.It Dv querysiglen +the length of the query signature +.It Dv sig +a buffer to be filled with the signature contained +.It Dv siglen +the length of the signature buffer on input, the signature length on output +.It Dv nostrip +non-zero value means that the TSIG is left intact +.El +.Pp +.Fn ns_verify_tcp +.Bl -tag -width "in_timesigned" -compact -offset indent +.It Dv msg +the incoming DNS message, which will be modified +.It Dv msglen +the length of the DNS message, on input and output +.It Dv state +the state of the operation +.It Dv required +non-zero value signifies that a TSIG record must be present at this step +.El +.Pp +.Fn ns_verify_tcp_init +.Bl -tag -width "in_timesigned" -compact -offset indent +.It Dv k +the (DST_KEY *) to verify the data +.It Dv querysig +for a response, the signature contained in the query +.It Dv querysiglen +the length of the query signature +.It Dv state +the state of the operation, which this initializes +.El +.Pp +.Fn ns_find_tsig +.Bl -tag -width "in_timesigned" -compact -offset indent +.It Dv msg +the incoming DNS message +.It Dv msglen +the length of the DNS message +.El +.Sh RETURN VALUES +.Fn ns_find_tsig +returns a pointer to the TSIG record if one is found, and NULL otherwise. +.Pp +All other routines return 0 on success, modifying arguments when necessary. +.Pp +.Fn ns_sign +and +.Fn ns_sign_tcp +return the following errors: +.Bl -tag -width "NS_TSIG_ERROR_NO_SPACE" -compact -offset indent +.It Dv (-1) +bad input data +.It Dv (-ns_r_badkey) +The key was invalid, or the signing failed +.It Dv NS_TSIG_ERROR_NO_SPACE +the message buffer is too small. +.El +.Pp +.Fn ns_verify +and +.Fn ns_verify_tcp +return the following errors: +.Bl -tag -width "NS_TSIG_ERROR_NO_SPACE" -compact -offset indent +.It Dv (-1) +bad input data +.It Dv NS_TSIG_ERROR_FORMERR +The message is malformed +.It Dv NS_TSIG_ERROR_NO_TSIG +The message does not contain a TSIG record +.It Dv NS_TSIG_ERROR_ID_MISMATCH +The TSIG original ID field does not match the message ID +.It Dv (-ns_r_badkey) +Verification failed due to an invalid key +.It Dv (-ns_r_badsig) +Verification failed due to an invalid signature +.It Dv (-ns_r_badtime) +Verification failed due to an invalid timestamp +.It Dv ns_r_badkey +Verification succeeded but the message had an error of BADKEY +.It Dv ns_r_badsig +Verification succeeded but the message had an error of BADSIG +.It Dv ns_r_badtime +Verification succeeded but the message had an error of BADTIME +.El +.Pp +.Sh SEE ALSO +.Xr resolver 3 . +.Sh AUTHORS +Brian Wellington, TISLabs at Network Associates +.\" .Sh BUGS Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/tsig.3 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/Makefile (revision 109985) @@ -0,0 +1,423 @@ +## 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 +## SOFTWARE. + +## Portions Copyright (c) 1996,1999 by Internet Software Consortium +## +## 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. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM 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 +## SOFTWARE. + +# +# Makefile to install the BIND manual entries. +# +# Default Configuration: +# There are a set of default assignments immediately following this +# note. These defaults are for BSD4.4, BSD/386, other net2-alikes, +# and will install manual entries with following characteristics: +# o They will be catable (i.e., passed through nroff) +# o They will be installed in the directories +# /usr/share/man/catN, where N is 1, 3, 5, 7, 8 +# o They will have an extension of `.0' +# +# Don't change these defaults. Instead, following the default configuration +# are sets of commented values for particular systems that can be used +# to override the default values. +# + +# +# Target directory for the manual directory tree. Eg., may be used to +# specify the path of an NFS-mounted directory for common files. +# +DESTDIR= + +# +# Default location for manual section directories. +# +DESTMAN= /usr/share/man + +# +# Install manuals in ${MANDIR}N. For systems that generate catable manual +# entries on the fly, use +# MANDIR = man +# +MANDIR = cat + +# +# Default extension for manual entries. To install the manual entries under +# their `real' extensions use +# CATEXT = $$N +# +CATEXT = 0 + +# +# Command to install manual entries +# +INSTALL= install + +# +# `install' options to set Owner and Group for manual entries. Eg. for +# BSD `install' use +# MAN_OWNER = -o bin +# MAN_GROUP = -g bin +# +MAN_OWNER = +MAN_GROUP = + +SHELL= /bin/sh + +INDOT= +XFER_INDOT= +# +# Uppercase versions of the above variables (`INDOT_U' and `XFER_INDOT_U') +# are defined for use in `.TH' lines. +# + +# +# Command used to generate a manual entry. By default this produces catable +# manual entries. +# +# For systems that store manuals in MDOC form (eg modern BSD systems) and +# can generate catable manual entries on the fly the following assignment +# can be used. +# MANROFF = cat +# +MANROFF = ( tbl | nroff -mandoc ) + +# +# Default extensions for installed manual entries. The following variables +# have been defined to allow BIND's manual entries to be installed in the +# right place for a given platform. +# +# CMD_EXT = extension for user commands (eg, dig) +# LIB_NETWORK_EXT = extension for network library routines (eg, +# gethostbyname) +# FORMAT_EXT = extension for files describing file formats +# (eg, resolver) +# DESC_EXT = extension for descriptive files (eg, mailaddr) +# SYS_OPS_EXT = extension system operation and maintenance commands +# and applications. (eg, named, named-xfer, syslog) +# +# Associated with each variable is an additional variable with the suffix +# `_DIR' that specifies the suffix to ${MANDIR}. It's needed because on +# some systems, eg., Ultrix, multiple subsections (eg 3x, 3m 3n) are +# stored in generic manual section directories (eg., man3). +# +# Associated with each variable is an additional variable with the suffix +# `_U' which gives the upper case form of the variable for use in `.TH' +# commands. Useful for platforms (such as Solaris 2) that include letters +# in manual sections. +# +CMD_EXT = 1 +CMD_EXT_DIR = ${CMD_EXT} +LIB_NETWORK_EXT = 3 +LIB_NETWORK_EXT_DIR = ${LIB_NETWORK_EXT} +FORMAT_EXT = 5 +FORMAT_EXT_DIR = ${FORMAT_EXT} +DESC_EXT = 7 +DESC_EXT_DIR = ${DESC_EXT} +SYS_OPS_EXT = 8 +SYS_OPS_EXT_DIR = ${SYS_OPS_EXT} + +# +# Additional variables are defined for cross-references within manual +# entries: +# SYSCALL_EXT = extension for system calls +# BSD_SYSCALL_EXT = extension for BSD-specifc system calls. On some +# systems (eg Ultrix) these appear in section 2. +# On other system (eg SunOS 5) these are implemented +# via a BSD-compatibility library and appear in +# section 3. +# LIB_C_EXT = extension for C library routines (eg, signal) +# +SYSCALL_EXT = 2 +SYSCALL_EXT_DIR = ${SYSCALL_EXT} +BSD_SYSCALL_EXT = 2 +BSD_SYSCALL_EXT_DIR = ${BSD_SYSCALL_EXT} +LIB_C_EXT = 3 +LIB_C_EXT_DIR = ${LIB_C_EXT} + +###################################################################### +# +# No user changes needed past this point. +# +###################################################################### +# +# This sed command is used to update the manual entries so they refer to +# the appropriate section of the manual for a given platform. +# +EXT_SED_CMD = INDOT_U=`echo "${INDOT}"|tr "[a-z]" "[A-Z]"`; \ + export INDOT_U; \ + XFER_INDOT_U=`echo "${XFER_INDOT}"|tr "[a-z]" "[A-Z]"`; \ + export XFER_INDOT_U; \ + CMD_EXT_U=`echo "${CMD_EXT}"|tr "[a-z]" "[A-Z]"`; \ + export CMD_EXT_U; \ + SYS_OPS_EXT_U=`echo "${SYS_OPS_EXT}"|tr "[a-z]" "[A-Z]"`; \ + export SYS_OPS_EXT_U; \ + LIB_NETWORK_EXT_U=`echo "${LIB_NETWORK_EXT}"|tr "[a-z]" "[A-Z]"`; \ + export LIB_NETWORK_EXT_U; \ + FORMAT_EXT_U=`echo "${FORMAT_EXT}"|tr "[a-z]" "[A-Z]"`; \ + export FORMAT_EXT_U; \ + DESC_EXT_U=`echo "${DESC_EXT}"|tr "[a-z]" "[A-Z]"`; \ + export DESC_EXT_U; \ + SYSCALL_EXT_U=`echo "${SYSCALL_EXT}"|tr "[a-z]" "[A-Z]"`; \ + export SYSCALL_EXT_U; \ + BSD_SYSCALL_EXT_U=`echo "${BSD_SYSCALL_EXT}"|tr "[a-z]" "[A-Z]"`; \ + export BSD_SYSCALL_EXT_U; \ + LIB_C_EXT_U=`echo "${LIB_C_EXT}"|tr "[a-z]" "[A-Z]"`; \ + export LIB_C_EXT_U; \ + sed -e "s/@INDOT@/${INDOT}/g" \ + -e "s/@INDOT_U@/$${INDOT_U}/g" \ + -e "s/@XFER_INDOT@/${XFER_INDOT}/g" \ + -e "s/@XFER_INDOT_U@/$${XFER_INDOT_U}/g" \ + -e "s/@CMD_EXT@/${CMD_EXT}/g" \ + -e "s/@CMD_EXT_U@/$${CMD_EXT_U}/g" \ + -e "s/@LIB_NETWORK_EXT@/${LIB_NETWORK_EXT}/g" \ + -e "s/@LIB_NETWORK_EXT_U@/$${LIB_NETWORK_EXT_U}/g" \ + -e "s/@FORMAT_EXT@/${FORMAT_EXT}/g" \ + -e "s/@FORMAT_EXT_U@/$${FORMAT_EXT_U}/g" \ + -e "s/@DESC_EXT@/${DESC_EXT}/g" \ + -e "s/@DESC_EXT_U@/$${DESC_EXT_U}/g" \ + -e "s/@SYS_OPS_EXT@/${SYS_OPS_EXT}/g" \ + -e "s/@SYS_OPS_EXT_U@/$${SYS_OPS_EXT_U}/g" \ + -e "s/@SYSCALL_EXT@/${SYSCALL_EXT}/g" \ + -e "s/@SYSCALL_EXT_U@/$${SYSCALL_EXT_U}/g" \ + -e "s/@BSD_SYSCALL_EXT@/${BSD_SYSCALL_EXT}/g" \ + -e "s/@BSD_SYSCALL_EXT_U@/$${BSD_SYSCALL_EXT_U}/g" \ + -e "s/@LIB_C_EXT@/${LIB_C_EXT}/g" \ + -e "s/@LIB_C_EXT_U@/$${LIB_C_EXT_U}/g" + +# +# Command used to produce manual entries +# +MK_MANFILE = ( ${EXT_SED_CMD} | ${MANROFF} ) + +# +# Extensions for the generated manual entries +# +OUT_EXT = lst +CMD_OUT_EXT = ${OUT_EXT}${CMD_EXT} +LIB_NETWORK_OUT_EXT = ${OUT_EXT}${LIB_NETWORK_EXT} +FORMAT_OUT_EXT = ${OUT_EXT}${FORMAT_EXT} +DESC_OUT_EXT = ${OUT_EXT}${DESC_EXT} +SYS_OPS_OUT_EXT = ${OUT_EXT}${SYS_OPS_EXT} + +# +# User command manual entries +# +CMD_BASE = dig host dnsquery dnskeygen +CMD_SRC_EXT = 1 +CMD_SRC = dig.${CMD_SRC_EXT} \ + host.${CMD_SRC_EXT} \ + dnsquery.${CMD_SRC_EXT} \ + dnskeygen.${CMD_SRC_EXT} +CMD_OUT = dig.${CMD_OUT_EXT} \ + host.${CMD_OUT_EXT} \ + dnsquery.${CMD_OUT_EXT} \ + dnskeygen.${CMD_OUT_EXT} + +# +# named manual entries +# +NAMED_BASE = named ndc +SYS_OPS_SRC_EXT = 8 +NAMED_SRC = named.${SYS_OPS_SRC_EXT} ndc.${SYS_OPS_SRC_EXT} +NAMED_OUT = named.${SYS_OPS_OUT_EXT} ndc.${SYS_OPS_OUT_EXT} + +# +# named-xfer manual entry +# +NAMED_XFER_BASE = named-xfer +NAMED_XFER_SRC = named-xfer.${SYS_OPS_SRC_EXT} +NAMED_XFER_OUT = named-xfer.${SYS_OPS_OUT_EXT} + +# +# named-bootconf manual entry +# +NAMED_BOOTCONF_BASE = named-bootconf +NAMED_BOOTCONF_SRC = named-bootconf.${SYS_OPS_SRC_EXT} +NAMED_BOOTCONF_OUT = named-bootconf.${SYS_OPS_OUT_EXT} + +# +# nslookup manual entry +# +NSLOOKUP_BASE = nslookup +NSLOOKUP_SRC = nslookup.${SYS_OPS_SRC_EXT} +NSLOOKUP_OUT = nslookup.${SYS_OPS_OUT_EXT} + +# +# nsupdate manual entry +# +NSUPDATE_BASE = nsupdate +NSUPDATE_SRC = nsupdate.${SYS_OPS_SRC_EXT} +NSUPDATE_OUT = nsupdate.${SYS_OPS_OUT_EXT} + +# +# Network library routines manual entries +# +LIB_NETWORK_BASE = gethostbyname inet_cidr resolver hesiod getnetent \ + tsig getaddrinfo getnameinfo getipnodebyname +LIB_NETWORK_SRC_EXT = 3 +LIB_NETWORK_SRC = gethostbyname.${LIB_NETWORK_SRC_EXT} \ + inet_cidr.${LIB_NETWORK_SRC_EXT} \ + resolver.${LIB_NETWORK_SRC_EXT} \ + hesiod.${LIB_NETWORK_SRC_EXT} \ + getnetent.${LIB_NETWORK_SRC_EXT} \ + tsig.${LIB_NETWORK_SRC_EXT} \ + getaddrinfo.${LIB_NETWORK_SRC_EXT} \ + getnameinfo.${LIB_NETWORK_SRC_EXT} \ + getipnodebyname.${LIB_NETWORK_SRC_EXT} +LIB_NETWORK_OUT = gethostbyname.${LIB_NETWORK_OUT_EXT} \ + inet_cidr.${LIB_NETWORK_OUT_EXT} \ + resolver.${LIB_NETWORK_OUT_EXT} \ + hesiod.${LIB_NETWORK_OUT_EXT} \ + getnetent.${LIB_NETWORK_OUT_EXT} \ + tsig.${LIB_NETWORK_OUT_EXT} \ + getaddrinfo.${LIB_NETWORK_OUT_EXT} \ + getnameinfo.${LIB_NETWORK_OUT_EXT} \ + getipnodebyname.${LIB_NETWORK_OUT_EXT} + +# +# File format manual entries +# +FORMAT_BASE = resolver irs.conf named.conf +FORMAT_SRC_EXT = 5 +FORMAT_SRC = resolver.${FORMAT_SRC_EXT} \ + irs.conf.${FORMAT_SRC_EXT} \ + named.conf.${FORMAT_SRC_EXT} +FORMAT_OUT = resolver.${FORMAT_OUT_EXT} \ + irs.conf.${FORMAT_OUT_EXT} \ + named.conf.${FORMAT_OUT_EXT} + +# +# Feature Description manual entries +# +DESC_BASE = hostname mailaddr +DESC_SRC_EXT = 7 +DESC_SRC = hostname.${DESC_SRC_EXT} mailaddr.${DESC_SRC_EXT} +DESC_OUT = hostname.${DESC_OUT_EXT} mailaddr.${DESC_OUT_EXT} + +.SUFFIXES: .${CMD_SRC_EXT} .${CMD_OUT_EXT} \ + .${SYS_OPS_SRC_EXT} .${SYS_OPS_OUT_EXT} \ + .${LIB_NETWORK_SRC_EXT} .${LIB_NETWORK_OUT_EXT} \ + .${FORMAT_SRC_EXT} .${FORMAT_OUT_EXT} \ + .${DESC_SRC_EXT} .${DESC_OUT_EXT} + +.${CMD_SRC_EXT}.${CMD_OUT_EXT}: + @echo "$*.${CMD_SRC_EXT} -> $*.${CMD_OUT_EXT}" + @${MK_MANFILE} <$*.${CMD_SRC_EXT} >$*.${CMD_OUT_EXT} + +.${SYS_OPS_SRC_EXT}.${SYS_OPS_OUT_EXT}: + @echo "$*.${SYS_OPS_SRC_EXT} -> $*.${SYS_OPS_OUT_EXT}" + @${MK_MANFILE} <$*.${SYS_OPS_SRC_EXT} >$*.${SYS_OPS_OUT_EXT} + +.${LIB_NETWORK_SRC_EXT}.${LIB_NETWORK_OUT_EXT}: + @echo "$*.${LIB_NETWORK_SRC_EXT} -> $*.${LIB_NETWORK_OUT_EXT}" + @${MK_MANFILE} <$*.${LIB_NETWORK_SRC_EXT} >$*.${LIB_NETWORK_OUT_EXT} + +.${FORMAT_SRC_EXT}.${FORMAT_OUT_EXT}: + @echo "$*.${FORMAT_SRC_EXT} -> $*.${FORMAT_OUT_EXT}" + @${MK_MANFILE} <$*.${FORMAT_SRC_EXT} >$*.${FORMAT_OUT_EXT} + +.${DESC_SRC_EXT}.${DESC_OUT_EXT}: + @echo "$*.${DESC_SRC_EXT} -> $*.${DESC_OUT_EXT}" + @${MK_MANFILE} <$*.${DESC_SRC_EXT} >$*.${DESC_OUT_EXT} + +OUTFILES = ${CMD_OUT} ${NAMED_OUT} ${NAMED_XFER_OUT} ${NSLOOKUP_OUT} \ + ${NSUPDATE_OUT} ${LIB_NETWORK_OUT} ${FORMAT_OUT} ${DESC_OUT} \ + ${NAMED_BOOTCONF_OUT} + +all: ${OUTFILES} + +install: ${OUTFILES} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${CMD_EXT_DIR} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${SYS_OPS_EXT_DIR} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${LIB_NETWORK_EXT_DIR} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${FORMAT_EXT_DIR} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${DESC_EXT_DIR} + @set -x; N=${CMD_EXT}; for f in ${CMD_BASE}; do \ + ${INSTALL} -c -m 444 ${MAN_OWNER} ${MAN_GROUP} \ + $${f}.${CMD_OUT_EXT} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${CMD_EXT_DIR}/$${f}.${CATEXT}; \ + done + @set -x; N=${SYS_OPS_EXT}; for f in ${NAMED_BASE}; do \ + ${INSTALL} -c -m 444 ${MAN_OWNER} ${MAN_GROUP} \ + $${f}.${SYS_OPS_OUT_EXT} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${SYS_OPS_EXT_DIR}/${INDOT}$${f}.${CATEXT}; \ + done + @set -x; N=${SYS_OPS_EXT}; for f in ${NAMED_XFER_BASE}; do \ + ${INSTALL} -c -m 444 ${MAN_OWNER} ${MAN_GROUP} \ + $${f}.${SYS_OPS_OUT_EXT} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${SYS_OPS_EXT_DIR}/${XFER_INDOT}$${f}.${CATEXT}; \ + done + @set -x; N=${SYS_OPS_EXT}; for f in ${NAMED_BOOTCONF_BASE}; do \ + ${INSTALL} -c -m 444 ${MAN_OWNER} ${MAN_GROUP} \ + $${f}.${SYS_OPS_OUT_EXT} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${SYS_OPS_EXT_DIR}/${XFER_INDOT}$${f}.${CATEXT}; \ + done + @set -x; N=${SYS_OPS_EXT}; for f in ${NSLOOKUP_BASE}; do \ + ${INSTALL} -c -m 444 ${MAN_OWNER} ${MAN_GROUP} \ + $${f}.${SYS_OPS_OUT_EXT} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${SYS_OPS_EXT_DIR}/$${f}.${CATEXT}; \ + done + @set -x; N=${SYS_OPS_EXT}; for f in ${NSUPDATE_BASE}; do \ + ${INSTALL} -c -m 444 ${MAN_OWNER} ${MAN_GROUP} \ + $${f}.${SYS_OPS_OUT_EXT} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${SYS_OPS_EXT_DIR}/$${f}.${CATEXT}; \ + done + @set -x; N=${LIB_NETWORK_EXT}; for f in ${LIB_NETWORK_BASE}; do \ + ${INSTALL} -c -m 444 ${MAN_OWNER} ${MAN_GROUP} \ + $${f}.${LIB_NETWORK_OUT_EXT} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${LIB_NETWORK_EXT_DIR}/$${f}.${CATEXT}; \ + done + @set -x; N=${FORMAT_EXT}; for f in ${FORMAT_BASE}; do \ + ${INSTALL} -c -m 444 ${MAN_OWNER} ${MAN_GROUP} \ + $${f}.${FORMAT_OUT_EXT} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${FORMAT_EXT_DIR}/$${f}.${CATEXT}; \ + done + @set -x; N=${DESC_EXT}; for f in ${DESC_BASE}; do \ + ${INSTALL} -c -m 444 ${MAN_OWNER} ${MAN_GROUP} \ + $${f}.${DESC_OUT_EXT} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${DESC_EXT_DIR}/$${f}.${CATEXT}; \ + done + +${DESTDIR}${DESTMAN}/${MANDIR}${CMD_EXT_DIR} \ +${DESTDIR}${DESTMAN}/${MANDIR}${SYS_OPS_EXT_DIR} \ +${DESTDIR}${DESTMAN}/${MANDIR}${LIB_NETWORK_EXT_DIR} \ +${DESTDIR}${DESTMAN}/${MANDIR}${FORMAT_EXT_DIR} \ +${DESTDIR}${DESTMAN}/${MANDIR}${DESC_EXT_DIR}: + mkdir $@ + +links: FRC + @set -ex; ln -s SRC/*.[0-9] . + +depend: + +clean: + rm -f *~ *.BAK *.CKP *.orig + rm -f ${OUTFILES} + +FRC: Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/hesiod.3 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/hesiod.3 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/hesiod.3 (revision 109985) @@ -0,0 +1,129 @@ +.\" $Id: hesiod.3,v 8.1 1999/04/12 02:47:00 vixie Exp $ +.\" +.\" Copyright 1988, 1996 by the Massachusetts Institute of Technology. +.\" +.\" Permission to use, copy, modify, and distribute this +.\" software and its documentation for any purpose and without +.\" fee is hereby granted, provided that the above copyright +.\" notice appear in all copies and that both that copyright +.\" notice and this permission notice appear in supporting +.\" documentation, and that the name of M.I.T. not be used in +.\" advertising or publicity pertaining to distribution of the +.\" software without specific, written prior permission. +.\" M.I.T. makes no representations about the suitability of +.\" this software for any purpose. It is provided "as is" +.\" without express or implied warranty. +.\" +.TH HESIOD 3 "30 November 1996" +.SH NAME +hesiod, hesiod_init, hesiod_resolve, hesiod_free_list, hesiod_to_bind, hesiod_end \- Hesiod name server interface library +.SH SYNOPSIS +.nf +.B #include +.PP +.B int hesiod_init(void **\fIcontext\fP) +.B char **hesiod_resolve(void *\fIcontext\fP, const char *\fIname\fP, +.B const char *\fItype\fP) +.B void hesiod_free_list(void *\fIcontext\fP, char **\fIlist\fP); +.B char *hesiod_to_bind(void *\fIcontext\fP, const char *\fIname\fP, +.B const char *\fItype\fP) +.B void hesiod_end(void *\fIcontext\fP) +.fi +.SH DESCRIPTION +This family of functions allows you to perform lookups of Hesiod +information, which is stored as text records in the Domain Name +Service. To perform lookups, you must first initialize a +.IR context , +an opaque object which stores information used internally by the +library between calls. +.I hesiod_init +initializes a context, storing a pointer to the context in the +location pointed to by the +.I context +argument. +.I hesiod_end +frees the resources used by a context. +.PP +.I hesiod_resolve +is the primary interface to the library. If successful, it returns a +list of one or more strings giving the records matching +.I name +and +.IR type . +The last element of the list is followed by a NULL pointer. It is the +caller's responsibility to call +.I hesiod_free_list +to free the resources used by the returned list. +.PP +.I hesiod_to_bind +converts +.I name +and +.I type +into the DNS name used by +.IR hesiod_resolve . +It is the caller's responsibility to free the returned string using +.IR free . +.SH RETURN VALUES +If successful, +.I hesiod_init +returns 0; otherwise it returns \-1 and sets +.I errno +to indicate the error. On failure, +.I hesiod_resolve +and +.I hesiod_to_bind +return NULL and set the global variable +.I errno +to indicate the error. +.SH ENVIRONMENT +If the environment variable +.B HES_DOMAIN +is set, it will override the domain in the Hesiod configuration file. +If the environment variable +.B HESIOD_CONFIG +is set, it specifies the location of the Hesiod configuration file. +.SH SEE ALSO +`Hesiod - Project Athena Technical Plan -- Name Service', named(8), +hesiod.conf(5) +.SH ERRORS +Hesiod calls may fail because of: +.IP ENOMEM +Insufficient memory was available to carry out the requested +operation. +.IP ENOEXEC +.I hesiod_init +failed because the Hesiod configuration file was invalid. +.IP ECONNREFUSED +.I hesiod_resolve +failed because no name server could be contacted to answer the query. +.IP EMSGSIZE +.I hesiod_resolve +failed because the query or response was too big to fit into the +packet buffers. +.IP ENOENT +.I hesiod_resolve +failed because the name server had no text records matching +.I name +and +.IR type , +or +.I hesiod_to_bind +failed because the +.I name +argument had a domain extension which could not be resolved with type +``rhs-extension'' in the local Hesiod domain. +.SH AUTHOR +Steve Dyer, IBM/Project Athena +.br +Greg Hudson, MIT Team Athena +.br +Copyright 1987, 1988, 1995, 1996 by the Massachusetts Institute of Technology. +.SH BUGS +The strings corresponding to the +.I errno +values set by the Hesiod functions are not particularly indicative of +what went wrong, especially for +.I ENOEXEC +and +.IR ENOENT . Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/hesiod.3 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/man/irs.conf.5 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/man/irs.conf.5 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/man/irs.conf.5 (revision 109985) @@ -0,0 +1,201 @@ +.\" Copyright (c) 1996,1999 by Internet Software Consortium +.\" +.\" 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. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\" CONSORTIUM 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 +.\" SOFTWARE. +.\" +.\" Copyright (c) 1986, 1991, 1993 +.\" 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 +.\" are met: +.\" 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 +.\" SUCH DAMAGE. +.\" +.\" $Id: irs.conf.5,v 8.4 1999/01/18 07:46:45 vixie Exp $ +.\" +.Dd November 16, 1997 +.Dt IRS.CONF 5 +.Os BIND 8.1 +.Sh NAME +.Nm irs.conf +.Nd Information Retrieval System configuration file +.Sh SYNOPSIS +.Nm irs.conf +.Sh DESCRIPTION +The +.Xr irs 3 +functions are a set of routines in the C library which provide access to +various system maps. +The maps that irs currently controls are the following: passwd, group, +services, protocols, hosts, networks and netgroup. +When a program first calls a function that accesses one of these maps, +the irs configuration file is read, +and the source of each map is determined for the life of the process. +.Pp +If this file does not exist, +the irs routines default to using local sources for all information, +with the exception of the host and networks maps, +which use the Domain Name System (DNS). +.Pp +Each record in the file consists of one line. +A record consists of a map-name, an access-method and possibly a (comma +delimited) set of options, +separated by tabs or spaces. +Blank lines, and text between a # and a newline are ignored. +.Pp +Available maps: +.Bd -literal -offset indent +Map name Information in map +========= ================================== +passwd User authentication information +group User group membership information +services Network services directory +protocols Network protocols directory +hosts Network hosts directory +networks Network "network names" directory +netgroup Network "host groups" directory +.Ed +.Pp +Available access methods: +.Bd -literal -offset indent +Access method Description +============= ================================================= +local Use a local file, usually in /etc +dns Use the domain name service (includes hesiod) +nis Use the Sun-compatible Network Information Service +irp Use the IRP daemon on the localhost. +.Ed +.Pp +Available options: +.Bd -literal -offset indent +Option Description +======== ================================================ +continue don't stop searching if you can't find something +merge don't stop searching if you CAN find something +.Ed +.Pp +The continue option creates +.Dq "union namespaces" +whereby subsequent access methods of the same map type can be tried +if a name cannot be found using earlier access methods. +This can be quite confusing in the case of host names, +since the name to address and address to name mappings can be visibly +asymmetric even though the data used by any given access method is +entirely consistent. This behavior is, therefore, not the default. +.Pp +The merge option only affects lookups in the groups map. +If set, subsequent access methods will be tried in order to cause +local users to appear in NIS (or other remote) groups in addition +to the local groups. +.Sh EXAMPLE +.Bd -literal -offset indent +# Get password entries from local file, or failing that, NIS +passwd local continue +passwd nis + +# Build group membership from both local file, and NIS. +group local continue,merge +group nis + +# Services comes from just the local file. +services local + +protocols local + +# Hosts comes first from DNS, failing that, the local file +hosts dns continue +hosts local + +# Networks comes first from the local file, and failing +# that the, irp daemon +networks local continue +networks irp + +netgroup local +.Ed +.Sh NOTES +If a local user needs to be in the local host's +.Dq wheel +group but not in every host's +.Dq wheel +group, put them in the local host's +.Pa /etc/group +.Dq wheel +entry and set up the +.Dq groups +portion of your +.Pa /etc/irs.conf +file as: +.Bd -literal -offset indent +group local continue,merge +group nis +.Ed +.Pp +NIS takes a long time to time out. +Especially for hosts if you use the +.Fl d +option to your server's +.Dq ypserv +daemon. +.Pp +It is important that the +.Pa irs.conf +file contain an entry for each map. +If a map is not mentioned in the +.Pa irs.conf +file, all queries to that map will fail. +.Pp +The classic NIS mechanism for specifying union namespaces is to add an entry +to a local map file whose name is ``+''. In IRS, this is done via ``continue'' +and/or ``merge'' map options. While this results in a small incompatibility +when local map files are imported from non-IRS systems to IRS systems, there +are compensating advantages in security and configurability. +.Sh FILES +.Bl -tag -width /etc/irs.confXXXX -compact +.It Pa /etc/irs.conf +The file +.Nm irs.conf +resides in +.Pa /etc . +.El +.Sh SEE ALSO +.Xr groups 5 , +.Xr hosts 5 , +.Xr netgroup 5 , +.Xr networks 5 , +.Xr passwd 5 , +.Xr protocols 5 , +.Xr services 5 Property changes on: vendor/bind/8.3.4/contrib/bind/doc/man/irs.conf.5 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/misc/rfc2317-notes.txt =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/misc/rfc2317-notes.txt (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/misc/rfc2317-notes.txt (revision 109985) @@ -0,0 +1,105 @@ +Message-Id: <200005230246.WAA03750@hrothgar.gw.com> +To: ... +Subject: Notes on RFC-2317 +Date: Mon, 22 May 2000 22:46:55 -0400 +From: Kimmo Suominen + +Hi! + +I wrote down some notes on RFC-2317. I've had discussions with all of +you regarding classless IN-ADDR.ARPA delegations, and I would very much +appreciate any comments you may have. Please feel free to forward this +to other parties as you see necessary or appropriate. + +The goal of these notes is to try and clarify the reasoning behind the +recommendations I've been making on implementing RFC-2317 delegations. +In particular the following issues keep coming up with again and again +with each vendor: + + - why use "-" instead of "/" + - why use particular NS records + - why delegate within IN-ADDR.ARPA + +I am hoping that the these notes could eventually be used to convince +ISPs to provide an efficient and smooth implementation of RFC-2317 with +the least amount of headache for the end-user. + +Regards, ++ Kim + + + +NOTES ON IMPLEMENTING CLASSLESS IN-ADDR.ARPA DELEGATION PER RFC-2317 + +1. Selecting the CNAME target zone + + RFC-2317 shows an example case where the target zone is a delegated + sub-zone of the IN-ADDR.ARPA zone for the natural class C network. + This will allow for the NS records for the zone can be independently + selected (see benefits described below). An example of such a zone + would be 0-28.150.80.204.IN-ADDR.ARPA. + + Now pay careful attention to the last paragraph of RFC-2317. There + are broken resolver implementations that apply the "valid host name" + restrictions on the CNAME target (it should only be applied to the + PTR target name). To avoid problems with such implementations it + is best to use a character that is allowed in a hostname. I prefer + using a hyphen, as I did in the example above. + + Some ISPs may at first refuse to delegate these zones (without any + explanation). Approach such ISPs with the reasoning in here first, + but if that fails consider using your "forward" zone as a fallback. + + There is nothing magic about the IN-ADDR.ARPA zone for RFC-2317 + delegations. You will have to sacrifice the optimization provided + by a correct IN-ADDR.ARPA delegation, but you will still retain + the ease of local administration for all name changes. + + I recommend using a dedicated subdomain for the PTR records, e.g. if + your "forward" domain is "HOME.GW.COM" use "REV.HOME.GW.COM" for the + PTR records. + +2. Selecting the NS records + + The NS records for the delegated zone should include all the NS + records of the parent zone, in addition to any NS records pointing + to the public name servers the delegate may want to use. Having the + name servers of the parent zone secondary the delegated zone allows + them to have the necessary authoritative data to return the CNAME + target in the additional records of a response to a PTR record query + (minimizing the number of queries needed to resolve an address). + + This can be achieved using any zone (i.e. even a subdomain of your + "forward" domain), of course. However, having the ISP delegate an + IN-ADDR.ARPA zone for your PTR records rather than you delegating a + zone to your ISP maintains the logical "owner" and "delegate" roles. + + If the primary server for the delegated zone is not permanently on + the Internet (e.g. a dial-on-demand connection) then you would not + want to advertise it in the NS records. It would just be a stealth + server which the advertised secondaries poll for updates. + +3. Example delegation + + To delegate our example zone 0-28.150.80.204.IN-ADDR.ARPA first look + at the NS records of the parent zone 150.80.204.IN-ADDR.ARPA. Let's + say they are the following: + + $ORIGIN 150.80.204.IN-ADDR.ARPA. + @ IN NS GRENDEL.GW.COM. + IN NS PYRY.GW.COM. + + To delegate 204.80.150.0/28 to SRV.HOME.GW.COM you would then insert + these records in the parent zone data: + + $ORIGIN 150.80.204.IN-ADDR.ARPA. + 0-28 IN NS SRV.HOME.GW.COM. + IN NS GRENDEL.GW.COM. + IN NS PYRY.GW.COM. + $GENERATE 0-15 $ IN CNAME $.0-28.150.80.204.IN-ADDR.ARPA. + + The necessary modifications to /etc/named.conf will be left as an + exercise to the reader. + +Kimmo Suominen +Global Wire Oy Property changes on: vendor/bind/8.3.4/contrib/bind/doc/misc/rfc2317-notes.txt ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/misc/FAQ.1of2 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/misc/FAQ.1of2 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/misc/FAQ.1of2 (revision 109985) @@ -0,0 +1,1939 @@ +Path: senator-bedfellow.mit.edu!bloom-beacon.mit.edu!news-out.cwix.com!news1.cwix.com!newsfeed.cwix.com!204.59.152.222!news-peer.gip.net!news.gsl.net!gip.net!news.idt.net!newsin.iconnet.net!IConNet!not-for-mail +From: cdp2582@hertz.njit.edu (Chris Peckham) +Newsgroups: comp.protocols.tcp-ip.domains,comp.answers,news.answers,comp.protocols.dns.bind +Subject: comp.protocols.tcp-ip.domains Frequently Asked Questions (FAQ) (Part 1 of 2) +Supersedes: +Followup-To: comp.protocols.tcp-ip.domains +Organization: NJIT.EDU - New Jersey Institute of Technology, Newark, NJ, USA +Lines: 1919 +Sender: cdp@chipmunk.iconnet.net +Approved: news-answers-request@MIT.EDU +Distribution: world +Expires: Thursday, 18 Mar 99 15:18:37 EDT +Message-ID: +Reply-To: cdp@intac.com (comp.protocols.tcp-ip.domains FAQ comments) +Keywords: BIND,DOMAIN,DNS +X-Posting-Frequency: posted during the first week of each month +Date: Thu, 11 Feb 1999 20:18:01 GMT +NNTP-Posting-Host: chipmunk.iconnet.net +NNTP-Posting-Date: Thu, 11 Feb 1999 15:18:01 EDT +Xref: senator-bedfellow.mit.edu comp.protocols.tcp-ip.domains:22750 comp.answers:35016 news.answers:151035 comp.protocols.dns.bind:6289 + +Posted-By: auto-faq 3.3 beta (Perl 5.004) +Archive-name: internet/tcp-ip/domains-faq/part1 + +Note that this posting has been split into two parts because of its size. + +$Id: FAQ.1of2,v 8.5 2000/07/11 04:23:13 vixie Exp $ + +A new version of this document appears monthly. If this copy is more +than a month old it may be out of date. + +This FAQ is edited and maintained by Chris Peckham, . The +most recently posted version may be found for anonymous ftp from + +rtfm.mit.edu : /pub/usenet/news.answers/internet/tcp-ip/domains-faq + +It is also available in HTML from http://www.intac.com/~cdp/cptd-faq/. + +If you can contribute any answers for items in the TODO section, please do +so by sending e-mail to ! If you know of any items that +are not included and you feel that they should be, send the relevant +information to . + +=============================================================================== + +Index + + Section 1. TO DO / UPDATES + Q1.1 Contributions needed + Q1.2 UPDATES / Changes since last posting + + Section 2. INTRODUCTION / MISCELLANEOUS + Q2.1 What is this newsgroup ? + Q2.2 More information + Q2.3 What is BIND ? + Q2.4 What is the difference between BIND and DNS ? + Q2.5 Where is the latest version of BIND located ? + Q2.6 How can I find the path taken between two systems/domains ? + Q2.7 How do you find the hostname given the TCP-IP address ? + Q2.8 How do I register a domain ? + Q2.9 How can I change the IP address of our server ? + Q2.10 Issues when changing your domain name + Q2.11 How memory and CPU does DNS use ? + Q2.12 Other things to consider when planning your servers + Q2.13 Reverse domains (IN-ADDR.ARPA) and their delegation + Q2.14 How do I get my address assigned from the NIC ? + Q2.15 Is there a block of private IP addresses I can use? + Q2.16 Does BIND cache negative answers (failed DNS lookups) ? + Q2.17 What does an NS record really do ? + Q2.18 DNS ports + Q2.19 What is the cache file + Q2.20 Obtaining the latest cache file + Q2.21 Selecting a nameserver/root cache + Q2.22 Domain names and legal issues + Q2.23 Iterative and Recursive lookups + Q2.24 Dynamic DNS + Q2.25 What version of bind is running on a server ? + Q2.26 BIND and Y2K + + Section 3. UTILITIES + Q3.1 Utilities to administer DNS zone files + Q3.2 DIG - Domain Internet Groper + Q3.3 DNS packet analyzer + Q3.4 host + Q3.5 How can I use DNS information in my program? + Q3.6 A source of information relating to DNS + + Section 4. DEFINITIONS + Q4.1 TCP/IP Host Naming Conventions + Q4.2 What are slaves and forwarders ? + Q4.3 When is a server authoritative? + Q4.4 My server does not consider itself authoritative ! + Q4.5 NS records don't configure servers as authoritative ? + Q4.6 underscore in host-/domainnames + Q4.7 How do I turn the "_" check off ? + Q4.8 What is lame delegation ? + Q4.9 How can I see if the server is "lame" ? + Q4.10 What does opt-class field in a zone file do? + Q4.11 Top level domains + Q4.12 US Domain + Q4.13 Classes of networks + Q4.14 What is CIDR ? + Q4.15 What is the rule for glue ? + Q4.16 What is a stub record/directive ? + + Section 5. CONFIGURATION + Q5.1 Upgrading from 4.9.x to 8.x + Q5.2 Changing a Secondary server to a Primary server ? + Q5.3 Moving a Primary server to another server + Q5.4 How do I subnet a Class B Address ? + Q5.5 Subnetted domain name service + Q5.6 Recommended format/style of DNS files + Q5.7 DNS on a system not connected to the Internet + Q5.8 Multiple Domain configuration + Q5.9 wildcard MX records + Q5.10 How do you identify a wildcard MX record ? + Q5.11 Why are fully qualified domain names recommended ? + Q5.12 Distributing load using named + Q5.13 Round robin IS NOT load balancing + Q5.14 Order of returned records + Q5.15 resolv.conf + Q5.16 How do I delegate authority for sub-domains ? + Q5.17 DNS instead of NIS on a Sun OS 4.1.x system + Q5.18 Patches to add functionality to BIND + Q5.19 How to serve multiple domains from one server + Q5.20 hostname and domain name the same + Q5.21 Restricting zone transfers + Q5.22 DNS in firewalled and private networks + Q5.23 Modifying the Behavior of DNS with ndots + Q5.24 Different DNS answers for same RR + + Section 6. PROBLEMS + Q6.1 No address for root server + Q6.2 Error - No Root Nameservers for Class XX + Q6.3 Bind 4.9.x and MX querying? + Q6.4 Do I need to define an A record for localhost ? + Q6.5 MX records, CNAMES and A records for MX targets + Q6.6 Can an NS record point to a CNAME ? + Q6.7 Nameserver forgets own A record + Q6.8 General problems (core dumps !) + Q6.9 malloc and DECstations + Q6.10 Can't resolve names without a "." + Q6.11 Why does swapping kill BIND ? + Q6.12 Resource limits warning in system + Q6.13 ERROR:ns_forw: query...learnt + Q6.14 ERROR:zone has trailing dot + Q6.15 ERROR:Zone declared more then once + Q6.16 ERROR:response from unexpected source + Q6.17 ERROR:record too short from [zone name] + Q6.18 ERROR:sysquery: findns error (3) + Q6.19 ERROR:Err/TO getting serial# for XXX + Q6.20 ERROR:zonename IN NS points to a CNAME + Q6.21 ERROR:Masters for secondary zone [XX] unreachable + Q6.22 ERROR:secondary zone [XX] expired + Q6.23 ERROR:bad response to SOA query from [address] + Q6.24 ERROR:premature EOF, fetching [zone] + Q6.25 ERROR:Zone [XX] SOA serial# rcvd from [Y] is < ours + Q6.26 ERROR:connect(IP/address) for zone [XX] failed + Q6.27 ERROR:sysquery: no addrs found for NS + Q6.28 ERROR:zone [name] rejected due to errors + + Section 7. ACKNOWLEDGEMENTS + Q7.1 How is this FAQ generated ? + Q7.2 What formats are available ? + Q7.3 Contributors + +=============================================================================== + +Section 1. TO DO / UPDATES + + Q1.1 Contributions needed + Q1.2 UPDATES / Changes since last posting + +----------------------------------------------------------------------------- + +Question 1.1. Contributions needed + +Date: Mon Jan 18 22:57:01 EST 1999 + +* Additional information on the new TLDs +* Expand on Q: How to serve multiple domains from one server +* Q: DNS ports - need to expand/correct some issues + +----------------------------------------------------------------------------- + +Question 1.2. UPDATES / Changes since last posting + +Date: Thu Feb 11 14:36:02 EST 1999 + +* DNS in firewalled and private networks - Updated with comment about hint + file +* host - Updated NT info +* How do I register a domain ? - JP NIC +* BIND and Y2K + +=============================================================================== + +Section 2. INTRODUCTION / MISCELLANEOUS + + Q2.1 What is this newsgroup ? + Q2.2 More information + Q2.3 What is BIND ? + Q2.4 What is the difference between BIND and DNS ? + Q2.5 Where is the latest version of BIND located ? + Q2.6 How can I find the path taken between two systems/domains ? + Q2.7 How do you find the hostname given the TCP-IP address ? + Q2.8 How do I register a domain ? + Q2.9 How can I change the IP address of our server ? + Q2.10 Issues when changing your domain name + Q2.11 How memory and CPU does DNS use ? + Q2.12 Other things to consider when planning your servers + Q2.13 Reverse domains (IN-ADDR.ARPA) and their delegation + Q2.14 How do I get my address assigned from the NIC ? + Q2.15 Is there a block of private IP addresses I can use? + Q2.16 Does BIND cache negative answers (failed DNS lookups) ? + Q2.17 What does an NS record really do ? + Q2.18 DNS ports + Q2.19 What is the cache file + Q2.20 Obtaining the latest cache file + Q2.21 Selecting a nameserver/root cache + Q2.22 Domain names and legal issues + Q2.23 Iterative and Recursive lookups + Q2.24 Dynamic DNS + Q2.25 What version of bind is running on a server ? + Q2.26 BIND and Y2K + +----------------------------------------------------------------------------- + +Question 2.1. What is this newsgroup ? + +Date: Thu Dec 1 11:08:28 EST 1994 + +comp.protocols.tcp-ip.domains is the usenet newsgroup for discussion on +issues relating to the Domain Name System (DNS). + +This newsgroup is not for issues directly relating to IP routing and +addressing. Issues of that nature should be directed towards +comp.protocols.tcp-ip. + +----------------------------------------------------------------------------- + +Question 2.2. More information + +Date: Fri Dec 6 00:41:03 EST 1996 + +You can find more information concerning DNS in the following places: + +* The BOG (BIND Operations Guide) - in the BIND distribution +* The FAQ included with BIND 4.9.5 in doc/misc/FAQ +* DNS and BIND by Albitz and Liu (an O'Reilly & Associates Nutshell + handbook) +* A number of RFCs (920, 974, 1032, 1034, 1101, 1123, 1178, 1183, 1348, + 1535, 1536, 1537, 1591, 1706, 1712, 1713, 1912, 1918) +* The DNS Resources Directory (DNSRD) http://www.dns.net/dnsrd/ +* If you are having troubles relating to sendmail and DNS, you may wish to + refer to the USEnet newsgroup comp.mail.sendmail and/or the FAQ for that + newsgroup which may be found for anonymous ftp at rtfm.mit.edu : + /pub/usenet/news.answers/mail/sendmail-faq +* Information concerning some frequently asked questions relating to the + Internet (i.e., what is the InterNIC, what is an RFC, what is the IETF, + etc) may be found for anonymous ftp from ds.internic.net : /fyi/fyi4.txt + A version may also be obtained with the URL + gopher://ds.internic.net/00/fyi/fyi4.txt. +* Information on performing an initial installation of BIND may be found + using the DNS Resources Directory at + http://www.dns.net/dnsrd/docs/basic.txt +* Three other USEnet newsgroups: + + * comp.protocols.dns.bind + * comp.protocols.dns.ops + * comp.protocols.dns.std + +----------------------------------------------------------------------------- + +Question 2.3. What is BIND ? + +Date: Tue Sep 10 23:15:58 EDT 1996 + +From the BOG Introduction - + +The Berkeley Internet Name Domain (BIND) implements an Internet name +server for the BSD operating system. The BIND consists of a server (or +``daemon'') and a resolver library. A name server is a network +service that enables clients to name resources or objects and share this +information with other objects in the network. This in effect is a +distributed data base system for objects in a computer network. BIND +is fully integrated into BSD (4.3 and later releases) network programs +for use in storing and retrieving host names and address. The system +administrator can configure the system to use BIND as a replacement to +the older host table lookup of information in the network hosts file +/etc/hosts. The default configuration for BSD uses BIND. + +----------------------------------------------------------------------------- + +Question 2.4. What is the difference between BIND and DNS ? + +Date: Tue Sep 10 23:15:58 EDT 1996 + +(text provided by Andras Salamon) DNS is the Domain Name System, a set of +protocols for a distributed database that was originally designed to +replace /etc/hosts files. DNS is most commonly used by applications to +translate domain names of hosts to IP addresses. A client of the DNS is +called a resolver; resolvers are typically located in the application +layer of the networking software of each TCP/IP capable machine. Users +typically do not interact directly with the resolver. Resolvers query the +DNS by directing queries at name servers that contain parts of the +distributed database that is accessed by using the DNS protocols. In +common usage, `the DNS' usually refers just to the data in the database. + +BIND (Berkeley Internet Name Domain) is an implementation of DNS, both +server and client. Development of BIND is funded by the Internet Software +Consortium and is coordinated by Paul Vixie. BIND has been ported to +Windows NT and VMS, but is most often found on Unix. BIND source code is +freely available and very complex; most of the development on the DNS +protocols is based on this code; and most Unix vendors ship BIND-derived +DNS implementations. As a result, the BIND name server is the most widely +used name server on the Internet. In common usage, `BIND' usually refers +to the name server that is part of the BIND distribution, and sometimes to +name servers in general (whether BIND-derived or not). + +----------------------------------------------------------------------------- + +Question 2.5. Where is the latest version of BIND located ? + +Date: Mon Sep 14 22:46:00 EDT 1998 + +This information may be found at http://www.vix.com/isc/bind/. + +Presently, there are two 'production level' versions of BIND. They are +versions 4 and 8. + +Version 4 is the last "traditional" BIND -- the one everybody on the +Internet runs, except a few hundred sites running... + +Version 8 has been called "BIND-ng" (Next Generation). Many new features +are found in version 8. + +BIND-8.1 has the following features: + +* DNS Dynamic Updates (RFC 2136) +* DNS Change Notification (RFC 1996) +* Completely new configuration syntax +* Flexible, categorized logging system +* IP-address-based access control for queries, zone transfers, and updates + that may be specified on a zone-by-zone basis +* More efficient zone transfers +* Improved performance for servers with thousands of zones +* The server no longer forks for outbound zone transfers +* Many bug fixes. + +Bind version 8.1.2 may be found at the following location: + +* Source ftp.isc.org : /isc/bind/src/8.1.2/bind-8.1.2-src.tar.gz +* Documentation ftp.isc.org : /isc/bind/src/8.1.2/bind-8.1.2-doc.tar.gz +* Contributed packages ftp.isc.org : + /isc/bind/src/8.1.2/bind-8.1.2-contrib.tar.gz + +At this time, BIND version 4.9.7 may be found for anonymous ftp from + +ftp.isc.org : /isc/bind/src/4.9.7/bind-4.9.7-REL.tar.gz + +Other sites that officially mirror the BIND distribution are + +* bind.fit.qut.edu.au : /pub/bind +* ftp.funet.fi : /pub/unix/tcpip/dns/bind +* ftp.univ-lyon1.fr : /pub/mirrors/unix/bind +* ftp.oleane.net : /pub/mirrors/unix/bind +* ftp.ucr.ac.cr : /pub/Unix/dns/bind +* ftp.luth.se : /pub/unix/dns/bind/beta + +You may need GNU zip, Larry Wall's patch program (if there are any patch +files), and a C compiler to get BIND running from the above mentioned +source. + +GNU zip is available for anonymous ftp from + +prep.ai.mit.edu : /pub/gnu/gzip-1.2.4.tar + +patch is available for anonymous ftp from + +prep.ai.mit.edu : /pub/gnu/patch-2.1.tar.gz + +A version of BIND for Windows NT is available for anonymous ftp from + +ftp.isc.org : /isc/bind/contrib/ntbind/ntdns497relbin.zip + +and + +ftp.isc.org : /isc/bind/contrib/ntbind/ntbind497rel.zip + +If you contact access@drcoffsite.com, he will send you information +regarding a Windows NT/WIN95 bind port of 4.9.6 release. + +A Freeware version of Bind for NT is available at http://www.software.com. + +----------------------------------------------------------------------------- + +Question 2.6. How can I find the path taken between two systems/domains ? + +Date: Wed Jan 14 12:07:03 EST 1998 + +On a Unix system, use traceroute. If it is not available to you, you may +obtain the source source for 'traceroute', compile it and install it on +your system. + +One version of this program with additional functionality may be found for +anonymous ftp from + +ftp.nikhef.nl : /pub/network/traceroute.tar.Z + +Another version may be found for anonymous ftp from + +ftp.psc.edu : /pub/net_tools/traceroute.tar + +NT/Windows 95 users may use the command TRACERT.EXE, which is installed +with the TCP/IP protocol support. There is a Winsock utility called +WS_PING by John Junod that provides ping, traceroute, and nslookup +functionality. + +There are several shareware TCP/IP utilities that provide ping, +traceroute, and DNS lookup functionality for a Macintosh: Mac TCP Watcher +and IP Net Monitor are two of them. + +----------------------------------------------------------------------------- + +Question 2.7. How do you find the hostname given the TCP-IP address ? + + Mon Jun 15 21:32:57 EDT 1998 + +For an address a.b.c.d you can always do: + + % nslookup + > set q=ptr + > d.c.b.a.in-addr.arpa. + +Most newer version of nslookup (since 4.8.3) will recognize an address, so +you can just say: + + % nslookup a.b.c.d + +DiG will work like this also: + + % dig -x a.b.c.d + +dig is included in the bind distribution. host from the bind distribution +may also be used. + +On a Macintosh, some shareware utilities may be used. IP Net Monitor has +a very nice NS Lookup feature, producing DiG-like output; Mac TCP Watcher +just has a simple name-to-address and address-to-name translator. + +----------------------------------------------------------------------------- + +Question 2.8. How do I register a domain ? + +Date: Thu Feb 11 14:51:50 EST 1999 + +Procedures for registering a domain name depend on the top level domain +(TLD) to which the desired domain name will belong, i.e. the rightmost +suffix of the desired domain name. See the answer to "Top level domains" +question in the DEFINITIONS SECTION of this FAQ. + +Although domain registration may be performed by a direct contact with the +appropriate domain registration authorities (domain name registrars), the +easiest way to do it is to talk to your Internet Service Providers. They +can submit a domain registration request on your behalf, as well as to set +up secondary DNS for your domain (or both DNS servers, if you need a +domain name for Web hosting and/or mail delivery purposes only). + +In the case where the registration is done by the organization itself, it +still makes the whole process much easier if the ISP is approached for +secondary (see RFC 2182) servers _before_ the InterNIC is approached +for registration. + +In any case, you will need at least two domain name servers when you +register your domain. Many ISP's are willing to provide primary and/or +secondary name service for their customers. If you want to register a +domain name ending with .COM, .NET, .ORG, you'll want to take a look to +the InterNIC: + +* http://www.internic.net/ -> Registration Services +* internic.net : /templates/domain-template.txt +* gopher://rs.internic.net/ + +Please note that the InterNIC charges a fee for domain names in the "COM", +"ORG", and "NET". More information may be found from the Internic at + +http://rs.internic.net/domain-info/fee-policy.html. + +Note that InterNIC doesn't allocate and assign IP numbers any more. Please +refer to the answer to "How do I get my address assigned from the NIC?" in +this section. + +Registration of domain names ending with country code suffixes (ISO 3166 - +.FR, .CH, .SE etc.) is being done by the national domain name registrars +(NICs). If you want to obtain such a domain, please refer to the following +links: + +Additional domain/whois information may be found: + +* http://rs.internic.net/help/other-reg.html +* http://www.iana.org/ +* http://www.ripe.net/centr/tld.html +* http://www.UNINETT.NO/navn/domreg.html +* http://www.nic.fr/Guides/AutresNics/ +* http://www.arin.net +* whois.apnic.net +* whois.nic.ad.jp (with /e at the end of query for English) +* sipb.mit.edu : /pub/whois/whois-servers.list +* http://www.geektools.com/whois.html + +Many times, registration of a domain name can be initiated by sending +e-mail to the zone contact. You can obtain the contact in the SOA record +for the country, or in a whois server: + + $ nslookup -type=SOA fr. + origin = ns1.nic.fr + mail addr = nic.nic.fr + ... + +The mail address to contact in this case is 'nic@nic.fr' (you must +substitute an '@' for the first dot in the mail addr field). + +An alternate method to obtain the e-mail address of the national NIC is +the 'whois' server at InterNIC. + +You may be requested to make your request to another email address or +using a certain information template/application. You may be requested to +make your request to another email address or using a certain information +template/application. Please remember that every TLD registrar has its own +registration policies and procedures. + +----------------------------------------------------------------------------- + +Question 2.9. How can I change the IP address of our server ? + +Date: Wed Jan 14 12:09:09 EST 1998 + +(From Mark Andrews) Before the move. + +* Ensure you are running a modern nameserver. BIND 4.9.6-P1 or 8.1.1 are + good choices. +* Inform all your secondaries that you are going to change. Have them + install both the current and new addresses in their named.boot's. +* Drop the ttl of the A's associated with the nameserver to something + small (5 min is usually good). +* Drop the refresh and retry times of the zone containing the forward + records for the server. +* Configure the new reverse zone before the move and make sure it is + operational. +* On the day of the move add the new A record(s) for the server. Don't + forget to have these added to parent domains. You will look like you are + multihomed with one interface dead. + +Move the machine after gracefully terminating any other services it is +offering. Then, + +* Fixup the A's, ttl, refresh and retry counters. (If you are running an + all server EDIT out all references to the old addresses in the cache + files). +* Inform all the secondaries the move is complete. +* Inform the parents of all zones you are primary of the new NS/A pairs + for the relevant zones. If you're changing the address of a server + registered with the InterNIC, you also need to submit a Modify Host form + to the InterNIC, so they will update the glue records on the root + servers. It can take the InterNIC a few days to process this form, and + the old glue records have 2-day TTL's, so this transition may be + problematic. +* Inform all the administrators of zones you are secondarying that the + machine has moved. +* For good measure update the serial no for all zones you are primary for. + This will flush out old A's. + +----------------------------------------------------------------------------- + +Question 2.10. Issues when changing your domain name + +Date: Sun Nov 27 23:32:41 EST 1994 + +If you are changing your domain name from abc.foobar.com to foobar.net, +the forward zones are easy and there are a number of ways to do it. One +way is the following: + +Have a single db file for the 2 domains, and have a single machine be the +primary server for both abc.foobar.com and foobar.net. + +To resolve the host foo in both domains, use a single zone file which +merely uses this for the host: + +foo IN A 1.2.3.4 + +Use a "@" wherever the domain would be used ie for the SOA: + +@ IN SOA (... + +Then use this pair of lines in your named.boot: + +primary abc.foobar.com db.foobar +primary foobar.net db.foobar + +The reverse zones should either contain PTRs to both names, or to +whichever name you believe to be canonical currently. + +----------------------------------------------------------------------------- + +Question 2.11. How memory and CPU does DNS use ? + +Date: Fri Dec 6 01:07:56 EST 1996 + +It can use quite a bit ! The main thing that BIND needs is memory. It +uses very little CPU or network bandwidth. The main considerations to +keep in mind when planning are: + +* How many zones do you have and how large are they ? +* How many clients do you expect to serve and how active are they ? + +As an example, here is a snapshot of memory usage from CSIRO Division of +Mathematics and Statistics, Australia + + Named takes several days to stabilize its memory usage. + + Our main server stabalises at ~10Mb. It takes about 3 days to + reach this size from 6 M at startup. This is under Sun OS 4.1.3U1. + +As another example, here is the configuration of ns.uu.net (from late +1994): + + ns.uu.net only does nameservice. It is running a version of BIND + 4.9.3 on a Sun Classic with 96 MB of RAM, 220 MB of swap (remember + that Sun OS will reserve swap for each fork, even if it is not needed) + running Sun OS 4.1.3_U1. + + Joseph Malcolm, of Alternet, states that named generally hovers at + 5-10% of the CPU, except after a reload, when it eats it all. + +----------------------------------------------------------------------------- + +Question 2.12. Other things to consider when planning your servers + +Date: Mon Jan 2 14:24:51 EST 1995 + +When making the plans to set up your servers, you may want to also +consider the following issues: + + A) Server O/S limitations/capacities (which tend to be widely + divergent from vendor to vendor) + B) Client resolver behavior (even more widely divergent) + C) Expected query response time + D) Redundancy + E) Desired speed of change propagation + F) Network bandwidth availability + G) Number of zones/subdomain-levels desired + H) Richness of data stored (redundant MX records? HINFO records?) + I) Ease of administration desired + J) Network topology (impacts reverse-zone volume) + + Assuming a best-possible case for the factors above, particularly (A), (B), + (C), (F), (G) & (H), it would be possible to run a 1000-node domain + using a single lowly 25 or 40 MHz 386 PC with a fairly modest amount of RAM + by today's standards, e.g. 4 or 8 Meg. However, this configuration would + be slow, unreliable, and would provide no functionality beyond your basic + address-to-name and name-to-address mappings. + + Beyond that baseline case, depending on what factors listed above, + you may want look at other strategies, such splitting up the DNS + traffic among several machines strategically located, possibly larger ones, + and/or subdividing your domain itself. There are many options, tradeoffs, + and DNS architectural paradigms from which to choose. + +----------------------------------------------------------------------------- + +Question 2.13. Reverse domains (IN-ADDR.ARPA) and their delegation + +Date: Mon Jun 15 23:28:47 EDT 1998 + +(The following section was contributed by Berislav Todorovic.) + +Reverse domains (subdomains of the IN-ADDR.ARPA domain) are being used by +the domain name service to perform reverse name mapping - from IP +addresses to host names. Reverse domains are more closely related to IP +address space usage than to the "forward" domain names used. For example, +a host using IP address 10.91.8.6 will have its "reverse" name: +6.8.91.10.IN-ADDR.ARPA, which must be entered in the DNS, by a PTR record: + +6.8.91.10.in-addr.arpa. IN PTR myserver.mydomain.com. + +In spite of the fact that IP address space is not longer divided into +classes (A, B, C, D, E - see the answer to "What is CIDR?" in the +DEFINITIONS section), the reverse host/domain names are organized on IP +address byte boundaries. Thus, the reverse host name +6.8.91.10.IN-ADDR.ARPA may belong to one of the following reverse domains, +depending on the address space allocated/assigned to you and your DNS +configuration: + +(1) 8.91.10.in-addr.arpa -> + assigned one or more "C class" networks (IP >= /24) +(2) 91.10.in-addr.arpa -> + assigned a whole "B class" 10.91/16 (IP = /16) +(3) ISP dependent -> + assigned < "C class" - e.g. 10.91.8/26 (IP < /24) + +No matter what is your case (1, 2 or 3) - the reverse domain name must be +properly delegated - registered in the IN-ADDR.ARPA zone. Otherwise, +translation IP -> host name will fail, which may cause troubles when using +some Internet services and accessing some public sites. + +To register your reverse domain, talk to your Internet service provider, +to ensure proper DNS configuration, according to your network topology and +address space assigned. They will point you to a further instance, if +necessary. Generally speaking, while forward domain name registration is a +matter of domain name registrars (InterNIC, national NICs), reverse domain +name delegation is being done by the authorities, assigning IP address +space - Internet service providers and regional Internet registries (see +the answer to "How do I get my address assigned from the NIC?" in this +section). + +Important notes: + +(1) If you're assigned a block or one or more "Class C" networks, you'll +have to maintain a separate reverse domain zone file for each "Class C" +from the block. For example, if you're assigned 10.91.8/22, you'll have to +configure a separate zone file for 4 domains: + +8.91.10.in-addr.arpa +9.91.10.in-addr.arpa +10.91.10.in-addr.arpa +11.91.10.in-addr.arpa + +and to delegate them further in the DNS (according to the advice from your +ISP). + +(2) If you're assigned a whole "B class" (say, 10.91/16), you're in charge +for the whole 91.10.IN-ADDR.ARPA zone. See the answer to "How do I subnet +a Class B Address?" in the CONFIGURATION section. + +(3) If you're assigned only a portion of a "C class" (say, 10.91.8.0/26) +see the answer to "Subnetted domain name service" question in the +CONFIGURATION section. + +For more information on reverse domain delegations see: + +* http://www.arin.net/templates/inaddrtemplate.txt +* http://www.ripe.net/docs/ripe-159.html +* ftp.apnic.net : /apnic/docs/in-addr-request + +----------------------------------------------------------------------------- + +Question 2.14. How do I get my address assigned from the NIC ? + +Date: Mon Jun 15 22:48:24 EDT 1998 + +IP address space assignment to end users is no longer being performed by +regional Internet registries (InterNIC, ARIN, RIPE NCC, APNIC). If you +need IP address space, you should make a request to your Internet service +provider. If you already have address space and need more IP numbers, +make a request to your ISP again and you may be given more numbers +(different ISPs have different allocation requirements and procedures). +If you are a smaller ISP - talk to your upstream ISP to obtain necessary +numbers for your customers. If you change the ISP in the future, you MAY +have to renumber your network. See RFC 2050 and RFC 2071 for more +information on this issue. + +Currently, address space is being distributed in a hierarchical manner: +ISPs assign addresses to their end customers. The regional Internet +registries allocate blocks of addresses (usually sized between /19 (32 "C +class") and /16 (a "B class")) to the ISPs. Finally - IANA (Internet +Assigned Number Authority) allocates necessary address space (/8 ("A +class") sized blocks) to the regional registries, as the need for address +space arises. This hierarchical process ensures more efficient routing on +the backbones (less traffic caused by routing information updates, better +memory utilization in backbone routers etc.) as well as more rational +address usage. + +If you are an ISP, planning to connect yourself to more than one ISP (i.e. +becoming multi-homed) and/or expecting to have a lot of customers, you'll +have to obtain ISP independent address space from a regional Internet +registry. Depending on your geographical locations, you can obtain such +address blocks (/19 and larger blocks) from: + +* RIPE NCC (http://www.ripe.net/) -> Europe, North Africa and Middle East +* ARIN (http://www.arin.net/) -> North and South America, Central Africa +* APNIC (http://www.apnic.net/) -> Asian and Pacific region + +While the regional registries do not sell address space, they do charge +for their services (allocation of address space, reverse domain +delegations etc.) + +----------------------------------------------------------------------------- + +Question 2.15. Is there a block of private IP addresses I can use? + +Date: Sun May 5 23:02:49 EDT 1996 + +Yes there is. Please refer to RFC 1918: + + 1918 Address Allocation for Private Internets. Y. Rekhter, B. + Moskowitz, D. Karrenberg, G. de Groot, & E. Lear. February 1996. + (Format: TXT=22270 bytes) + +RFC 1918 documents the allocation of the following addresses for use by +``private internets'': + + 10.0.0.0 - 10.255.255.255 + 172.16.0.0 - 172.31.255.255 + 192.168.0.0 - 192.168.255.255 + +----------------------------------------------------------------------------- + +Question 2.16. Does BIND cache negative answers (failed DNS lookups) ? + +Date: Mon Jan 2 13:55:50 EST 1995 + +Yes, BIND 4.9.3 and more recent versions will cache negative answers. + +----------------------------------------------------------------------------- + +Question 2.17. What does an NS record really do ? + +Date: Wed Jan 14 12:28:46 EST 1998 + +The NS records in your zone data file pointing to the zone's name servers +(as opposed to the servers of delegated subdomains) don't do much. +They're essentially unused, though they are returned in the authority +section of reply packets from your name servers. + +However, the NS records in the zone file of the parent domain are used to +find the right servers to query for the zone in question. These records +are more important than the records in the zone itself. + +However, if the parent domain server is a secondary or stub server for the +child domain, it will "hoist" the NS records from the child into the +parent domain. This frequently happens with reverse domains, since the +ISP operates primary reverse DNS for its CIDR block and also often runs +secondary DNS for many customers' reverse domains. + +Caching servers will often replace the NS records learned from the parent +server with the authoritative list that the child server sends in its +authority section. If the authoritative list is missing the secondary +servers, those caching servers won't be able to look up in this domain if +the primary goes down. + +After all of this, it is important that your NS records be correct ! + +----------------------------------------------------------------------------- + +Question 2.18. DNS ports + +Date: Wed Jan 14 12:31:39 EST 1998 + +The following table shows what TCP/UDP ports bind before 8.x DNS uses to +send and receive queries: + + Prot Src Dst Use + udp 53 53 Queries between servers (eg, recursive queries) + Replies to above + tcp 53 53 Queries with long replies between servers, zone + transfers Replies to above + udp >1023 53 Client queries (sendmail, nslookup, etc ...) + udp 53 >1023 Replies to above + tcp >1023 53 Client queries with long replies + tcp 53 >1023 Replies to above + + Note: >1023 is for non-priv ports on Un*x clients. On other client + types, the limit may be more or less. + +BIND 8.x no longer uses port 53 as the source port for recursive queries. +By defalt it uses a random port >1023, although you can configure a +specific port (53 if you want). + +Another point to keep in mind when designing filters for DNS is that a DNS +server uses port 53 both as the source and destination for its queries. +So, a client queries an initial server from an unreserved port number to +UDP port 53. If the server needs to query another server to get the +required info, it sends a UDP query to that server with both source and +destination ports set to 53. The response is then sent with the same +src=53 dest=53 to the first server which then responds to the original +client from port 53 to the original source port number. + +The point of all this is that putting in filters to only allow UDP between +a high port and port 53 will not work correctly, you must also allow the +port 53 to port 53 UDP to get through. + +Also, ALL versions of BIND use TCP for queries in some cases. The +original query is tried using UDP. If the response is longer than the +allocated buffer, the resolver will retry the query using a TCP +connection. If you block access to TCP port 53 as suggested above, you +may find that some things don't work. + +Newer version of BIND allow you to configure a list of IP addresses from +which to allow zone transfers. This mechanism can be used to prevent +people from outside downloading your entire namespace. + +----------------------------------------------------------------------------- + +Question 2.19. What is the cache file + +Date: Fri Dec 6 01:15:22 EST 1996 + +From the "Name Server Operations Guide" + + 6.3. Cache Initialization + + 6.3.1. root.cache + + The name server needs to know the servers that + are the authoritative name servers for the root + domain of the network. To do this we have to prime + the name server's cache with the addresses of these + higher authorities. The location of this file is + specified in the boot file. ... + +----------------------------------------------------------------------------- + +Question 2.20. Obtaining the latest cache file + +Date: Fri Dec 6 01:15:22 EST 1996 + +If you have a version of dig running, you may obtain the information with +the command + + dig @a.root-servers.net. . ns + +A perl script to handle some possible problems when using this method +from behind a firewall and that can also be used to periodically obtain +the latest cache file was posted to comp.protocols.tcp-ip.domains during +early October, 1996. It was posted with the subject "Keeping db.cache +current". It is available at +http://www.intac.com/~cdp/cptd-faq/current_db_cache.txt. + +The latest cache file may also be obtained from the InterNIC via ftp or +gopher: + + ; This file is made available by InterNIC registration services + ; under anonymous FTP as + ; file /domain/named.root + ; on server FTP.RS.INTERNIC.NET + ; -OR- under Gopher at RS.INTERNIC.NET + ; under menu InterNIC Registration Services (NSI) + ; submenu InterNIC Registration Archives + ; file named.root + +----------------------------------------------------------------------------- + +Question 2.21. Selecting a nameserver/root cache + +Date: Mon Aug 5 22:54:11 EDT 1996 + +Exactly how is the a root server selected from the root cache? Does the +resolver attempt to pick the closest host or is it random or is it via +sortlist-type workings? If the root server selected is not available (for +whatever reason), will the the query fail instead of attempting another +root server in the list ? + +Every recursive BIND name server (that is, one which is willing to go out +and find something for you if you ask it something it doesn't know) will +remember the measured round trip time to each server it sends queries to. +If it has a choice of several servers for some domain (like "." for +example) it will use the one whose measured RTT is lowest. + +Since the measured RTT of all NS RRs starts at zero (0), every one gets +tried one time. Once all have responded, all RTT's will be nonzero, and +the "fastest server" will get all queries henceforth, until it slows down +for some reason. + +To promote dispersion and good record keeping, BIND will penalize the RTT +by a little bit each time a server is reused, and it will penalize the RTT +a _lot_ if it ever has to retransmit a query. For a server to stay "#1", +it has to keep on answering quickly and consistently. + +Note that this is something BIND does that the DNS Specification does not +mention at all. So other servers, those not based on BIND, might behave +very differently. + +----------------------------------------------------------------------------- + +Question 2.22. Domain names and legal issues + +Date: Mon Jun 15 22:15:32 EDT 1998 + +A domain name may be someone's trademark and the use of a trademark +without its owner's permission may be a trademark violation. This may +lead to a legal dispute. RFC 1591 allows registration authorities to +play a neutral role in domain name disputes, stating that: + + In case of a dispute between domain name registrants as to the + rights to a particular name, the registration authority shall have + no role or responsibility other than to provide the contact + information to both parties. + +The InterNIC's current domain dispute policy (effective February 25, 1998) +is located at: + +http://www.internic.net/domain-info/internic-domain-6.html + +Other domain registrars have similar domain dispute policies. + +The following information was submitted by Carl Oppedahl + : + +If the jealous party happens to have a trademark registration, it is quite +likely that the domain name owner will lose the domain name, even if they +aren't infringing the trademark. This presents a substantial risk of loss +of a domain name on only 30 days' notice. Anyone who is the manager of an +Internet-connected site should be aware of this risk and should plan for +it. + +See "How do I protect myself from loss of my domain name?" at +http://www.patents.com/weblaw.sht#domloss. + +For an example of an ISP's battle to keep its domain name, see +http://www.patents.com/nsi.sht. + +A compendium of information on the subject may be found at +http://www.law.georgetown.edu/lc/internic/domain1.html. + +----------------------------------------------------------------------------- + +Question 2.23. Iterative and Recursive lookups + +Date: Wed Jul 9 22:05:32 EDT 1997 + +Q: What is the difference between iterative and recursive lookups ? How +do you configure them and when would you specify one over the other ? + +A: (from an answer written by Barry Margolin) In an iterative lookup, the +server tells the client "I don't know the answer, try asking ". In a recursive lookup, the server asks one of the other +servers on your behalf, and then relays the answer back to you. + +Recursive servers are usually used by stub resolvers (the name lookup +software on end systems). They're configured to ask a specific set of +servers, and expect those servers to return an answer rather than a +referral. By configuring the servers with recursion, they will cache +answers so that if two clients try to look up the same thing it won't have +to ask the remote server twice, thus speeding things up. + +Servers that aren't intended for use by stub resolvers (e.g. the root +servers, authoritative servers for domains). Disabling recursion reduces +the load on them. + +In BIND 4.x, you disable recursion with "options no-recursion" in the +named.boot file. + +----------------------------------------------------------------------------- + +Question 2.24. Dynamic DNS + +Mon Jan 18 20:31:58 EST 1999 + +Q: Bind 8 includes some support for Dynamic DNS as specified in RFC 2136. +It does not currently include the authentication mechanism that is +described in RFC 2137, meaning that any update requests received from +allowed hosts will be honored. + +Could someone give me a working example of what syntax nsupdate expects ? +Is it possible to write an update routine which directs it's update to a +particular server, ignoring what the DNS servers are the serving NS's? + +A: You might check out Michael Fuhr's Net::DNS Perl module, which you can +use to put together dynamic update requests. See +http://www.fuhr.net/~mfuhr/perldns/Update.html for additional information. +Michael posted a sample script to show how to use Net::DNS: + + #!/usr/local/bin/perl -w + use Net::DNS; + $res = new Net::DNS::Resolver; + $res->nameservers("some-nameserver.foo.com"); + $update = new Net::DNS::Update("foo.com"); + $update->push("update", rr_del("old-host.foo.com")); + $update->push("update", rr_add("new-host.foo.com A 10.1.2.3")); + $ans = $res->send($update); + print $ans ? $ans->header->rcode : $res->errorstring, "\n"; + +Additional information for Dynamic DNS updates may be found at +http://simmons.starkville.ms.us/tips/081797/. + +----------------------------------------------------------------------------- + +Question 2.25. What version of bind is running on a server ? + +Date: Mon Mar 9 22:15:11 EST 1998 + +On 4.9+ servers, you may obtain the version of bind running with the +following command: + +dig @server.to.query txt chaos version.bind. + +and optionally pipe that into 'grep VERSION'. Please note that this will +not work on an older nameserver. + +----------------------------------------------------------------------------- + +Question 2.26. BIND and Y2K + +Date: Thu Feb 11 14:58:04 EST 1999 + +Is the "Y2K" problem an issue for bind ? + +You will find the Internet Software Consortium's comment on the "Y2K" +issue at http://www.isc.org/y2k.html. + +=============================================================================== + +Section 3. UTILITIES + + Q3.1 Utilities to administer DNS zone files + Q3.2 DIG - Domain Internet Groper + Q3.3 DNS packet analyzer + Q3.4 host + Q3.5 How can I use DNS information in my program? + Q3.6 A source of information relating to DNS + +----------------------------------------------------------------------------- + +Question 3.1. Utilities to administer DNS zone files + +Date: Tue Jan 7 00:22:31 EST 1997 + +There are a few utilities available to ease the administration of zone +files in the DNS. + +Two common ones are h2n and makezones. Both are perl scripts. h2n is +used to convert host tables into zone data files. It is available for +anonymous ftp from + +ftp.uu.net : /published/oreilly/nutshell/dnsbind/dns.tar.Z + +makezones works from a single file that looks like a forward zone file, +with some additional syntax for special cases. It is included in the +current BIND distribution. The newest version is always available for +anonymous ftp from + +ftp.cus.cam.ac.uk : /pub/software/programs/DNS/makezones + +bpp is a m4 macro package for pre-processing the master files bind uses to +define zones. Information on this package may be found at +http://www.meme.com/soft. + +More information on various DNS related utilities may be found using the +DNS Resources Directory + +http://www.dns.net/dnsrd/. + +----------------------------------------------------------------------------- + +Question 3.2. DIG - Domain Internet Groper + +Date: Thu Dec 1 11:09:11 EST 1994 + +The latest and greatest, official, accept-no-substitutes version of the +Domain Internet Groper (DiG) is the one that comes with BIND. Get the +latest kit. + +----------------------------------------------------------------------------- + +Question 3.3. DNS packet analyzer + +Date: Mon Jun 15 21:42:11 EDT 1998 + +There is a free ethernet analyzer called Ethload available for PC's +running DOS. The latest filename is ETHLD200.ZIP. It understands lots of +protocols including TCP/UDP. It'll look inside there and display +DNS/BOOTP/ICMP packets etc. (Ed. note: something nice for someone to add +to tcpdump ;^) ). Depending on the ethernet controller it's given it'll +perform slightly differently. It handles NDIS/Novell/Packet drivers. It +works best with Novell's promiscuous mode drivers. The current home page +for Ethload is http://www.ping.be/ethload. + +----------------------------------------------------------------------------- + +Question 3.4. host + +Date: Thu Feb 11 14:43:39 EST 1999 + +A section from the host man page: + + host looks for information about Internet hosts and domain + names. It gets this information from a set of intercon- + nected servers that are spread across the world. The infor- + mation is stored in the form of "resource records" belonging + to hierarchically organized "zones". + + By default, the program simply converts between host names + and Internet addresses. However, with the -t, -a and -v + options, it can be used to find all of the information about + domain names that is maintained by the domain nameserver + system. The information printed consists of various fields + of the associated resource records that were retrieved. + + The arguments can be either host names (domain names) or + numeric Internet addresses. + +'host' is compatible with both BIND 4.9 and BIND 4.8 + +'host' may be found in contrib/host in the BIND distribution. The latest +version always available for anonymous ftp from + +ftp.nikhef.nl : /pub/network/host.tar.Z + +It may also be found for anonymous ftp from + +ftp.uu.net : /networking/ip/dns/host.tar.Z + +Programs with some of the functionality of host for NT may be found at +http://www.tucows.com under "Network Tools, DNS Lookup Utilities". + +----------------------------------------------------------------------------- + +Question 3.5. How can I use DNS information in my program? + +Date: Fri Feb 10 15:25:11 EST 1995 + +It depends on precisely what you want to do: + +* Consider whether you need to write a program at all. It may well be + easier to write a shell program (e.g. using awk or perl) to parse the + output of dig, host or nslookup. +* If all you need is names and addresses, there will probably be system + routines 'gethostbyname' and 'gethostbyaddr' to provide this + information. +* If you need more details, then there are system routines (res_query and + res_search) to assist with making and sending DNS queries. However, + these do not include a routine to parse the resulting answer (although + routines to assist in this task are provided). There is a separate + library available that will take a DNS response and unpick it into its + constituent parts, returning a C structure that can be used by the + program. The source for this library is available for anonymous ftp at + + hpux.csc.liv.ac.uk : /hpux/Networking/Admin/resparse-1.2 + +----------------------------------------------------------------------------- + +Question 3.6. A source of information relating to DNS + +Mon Jan 18 20:35:49 EST 1999 + +You may find utilities and tools to help you manage your zone files +(including WWW front-ends) in the "tools" section of the DNS resources +directory: + +http://www.dns.net/dnsrd/tools.html + +Two that come to mind are MIT's WebDNS and the University of Utah tools. + +There are also a number of commercial IP management tools available. Data +Communications had an article on the subject in Sept/Oct of 1996. The +tools mentioned in the article and a few others may be found at the +following sites: + +* IP Address management, http://www.accugraph.com +* IP-Track, http://www.on.com +* NetID, http://www.isotro.com +* QIP, http://www.quadritek.com +* UName-It, http://www.esm.com +* dnsboss, http://www.dnsboss.com + +=============================================================================== + +Section 4. DEFINITIONS + + Q4.1 TCP/IP Host Naming Conventions + Q4.2 What are slaves and forwarders ? + Q4.3 When is a server authoritative? + Q4.4 My server does not consider itself authoritative ! + Q4.5 NS records don't configure servers as authoritative ? + Q4.6 underscore in host-/domainnames + Q4.7 How do I turn the "_" check off ? + Q4.8 What is lame delegation ? + Q4.9 How can I see if the server is "lame" ? + Q4.10 What does opt-class field in a zone file do? + Q4.11 Top level domains + Q4.12 US Domain + Q4.13 Classes of networks + Q4.14 What is CIDR ? + Q4.15 What is the rule for glue ? + Q4.16 What is a stub record/directive ? + +----------------------------------------------------------------------------- + +Question 4.1. TCP/IP Host Naming Conventions + +Date: Mon Aug 5 22:49:46 EDT 1996 + +One guide that may be used when naming hosts is RFC 1178, "Choosing a Name +for Your Computer", which is available via anonymous FTP from + +ftp.internic.net : /rfc/rfc1178.txt + +RFCs (Request For Comments) are specifications and guidelines for how many +aspects of TCP/IP and the Internet (should) work. Most RFCs are fairly +technical documents, and some have semantics that are hotly contested in +the newsgroups. But a few, like RFC 1178, are actually good to read for +someone who's just starting along a TCP/IP path. + +----------------------------------------------------------------------------- + +Question 4.2. What are slaves and forwarders ? + +Date: Mon Jan 18 22:14:30 EST 1999 + +Parts of this section were contributed by Albert E. Whale. + +"forwarders" is a list of NS records that are _prepended_ to a list of NS +records to query if the data is not available locally. This allows a rich +cache of records to be built up at a centralized location. This is good +for sites that have sporadic or very slow connections to the Internet. +(demand dial-up, for example) It's also just a good idea for very large +distributed sites to increase the chance that you don't have to go off to +the Internet to get an IP address. (sometimes for addresses across the +street!) + +If you have a "forwarders" line, you will only consult the root servers if +you get no response from the forwarder. If you get a response, and it +says there's no such host, you'll return that answer to the client -- you +won't consult the root. + +The "forwarders" statement is found in the /etc/named.boot file which is +read each time DNS is started. The command format is as follows: + +forwarders [, .... ] +The "forwarders" line specifies the IP Address(es) of DNS servers that +accept queries from other servers. + +The "forwarders" command is used to cause a large site wide cache to be +created on a master and reduce traffic over the network to other servers. +It can also be used to allow DNS servers to answer Internet name queries +which do not have direct access to the Internet. + +The forwarders command is used in conjunction with the traditional DNS +configuration which requires that a NS entry be found in the cache file. +The DNS server can support the forwarders command if the server is able to +resolve entries that are not part of the local server's cache. + +"slave" modifies this to say to replace the list of NS records with the +forwarders entry, instead of prepending to it. This is for firewalled +environments, where the nameserver can't directly get out to the Internet +at all. + +"slave" is meaningless (and invalid, in late-model BINDs) without +"forwarders". "forwarders" is an entry in named.boot, and therefore +applies only to the nameserver (not to resolvers). + +The "slave" command is usually found immediately following the forwarders +command in the boot file. It is normally used on machines that are +running DNS but do not have direct access to the Internet. By using the +"forwarders" and "slave" commands the server can contact another DNS +server which can answer DNS queries. The "slave" option may also be used +behind a firewall where there may not be a network path available to +directly contact nameservers listed in the cache. + +Additional information on slave servers may be found in the BOG (BIND +Operations Guide http://www.isc.org/bind.html) section 6.1.8 (Slave +Servers). + +----------------------------------------------------------------------------- + +Question 4.3. When is a server authoritative? + +Date: Mon Jan 2 13:15:13 EST 1995 + +In the case of BIND: + +* The server contains current data in files for the zone in question (Data + must be current for secondaries, as defined in the SOA) +* The server is told that it is authoritative for the zone, by a 'primary' + or 'secondary' keyword in /etc/named.boot. +* The server does an error-free load of the zone. + +----------------------------------------------------------------------------- + +Question 4.4. My server does not consider itself authoritative ! + +Date: Mon Jan 2 13:15:13 EST 1995 + +The question was: + + What if I have set up a DNS where there is an SOA record for + the domain, but the server still does not consider itself + authoritative. (when using nslookup and set server=the correct machine.) + It seems that something is not matching up somewhere. I suspect + that this is because the service provider has not given us control + over the IP numbers in our own domain, and so while the machine listed + has an A record for an address, there is no corresponding PTR record. + +With the answer: + + That's possible too, but is unrelated to the first question. + You need to be delegated a zone before outside people will start + talking to your server. However, a server can still be authoritative + for a zone even though it hasn't been delegated authority (it's just + that only the people who use that as their server will see the data). + + A server may consider itself non-authoritative even though it's a + primary if there is a syntax error in the zone (see the list in the + previous question). + +----------------------------------------------------------------------------- + +Question 4.5. NS records don't configure servers as authoritative ? + +Date: Fri Dec 6 16:13:34 EST 1996 + +Nope, delegation is a separate issue from authoritativeness. You can +still be authoritative, but not delegated. (you can also be delegated, +but not authoritative -- that's a "lame delegation") + +----------------------------------------------------------------------------- + +Question 4.6. underscore in host-/domainnames + +Date: Sat Aug 9 20:30:37 EDT 1997 + +The question is "Are underscores are allowed in host- or domainnames" ? + RFC 1033 allows them. + RFC 1035 doesn't. + RFC 1123 doesn't. + dnswalk complains about them. + + +Which RFC is the final authority these days? + +Actually RFC 1035 deals with names of machines or names of mail domains. +i.e "_" is not permitted in a hostname or on the RHS of the "@" in +local@domain. + +Underscore is permitted where ever the domain is NOT one of these types +of addresses. + +In general the DNS mostly contains hostnames and mail domainnames. This +will change as new resource record types for authenticating DNS queries +start to appear. + +The latest version of 'host' checks for illegal characters in A/MX record +names and the NS/MX target names. + +After saying all of that, remember that RFC 1123 is a Required Internet +Standard (per RFC 1720), and RFC 1033 isn't. Even RFC 1035 isn't a +required standard. Therefore, RFC 1123 wins, no contest. + +From RFC 1123, Section 2.1 + + 2.1 Host Names and Numbers + + The syntax of a legal Internet host name was specified in RFC-952 + [DNS:4]. One aspect of host name syntax is hereby changed: the + restriction on the first character is relaxed to allow either a + letter or a digit. Host software MUST support this more liberal + syntax. + + And described by Dave Barr in RFC1912: + + Allowable characters in a label for a host name are only ASCII + letters, digits, and the `-' character. Labels may not be all + numbers, but may have a leading digit (e.g., 3com.com). Labels must + end and begin only with a letter or digit. See [RFC 1035] and [RFC + 1123]. (Labels were initially restricted in [RFC 1035] to start with + a letter, and some older hosts still reportedly have problems with + the relaxation in [RFC 1123].) Note there are some Internet + hostnames which violate this rule (411.org, 1776.com). + + +Finally, one more piece of information (From Paul Vixie): + + RFC 1034 says only that domain names have characters in them, though it + says so with enough fancy and indirection that it's hard to tell exactly. + + Generally, for second level domains (i.e., something you would get from + InterNIC or from the US Domain Registrar and probably other ISO 3166 + country code TLDs), RFC 952 is thought to apply. RFC 952 was about host + names rather than domain names, but the rules seemed good enough. + + ::= + + ::= *["."] + ::= [*[]] + +There has been a recent update on this subject which may be found in + +ftp.internic.net : /internet-drafts/draft-andrews-dns-hostnames-03.txt. + +An RFC Internet standards track protocol on the subject "Clarifications to +the DNS Specification" may be found in RFC 2181. This updates RFC 1034, +RFC 1035, and RFC 1123. + +----------------------------------------------------------------------------- + +Question 4.7. How do I turn the "_" check off ? + +Date: Mon Nov 10 22:54:54 EST 1997 + +In the 4.9.5-REL and greater, you may turn this feature off with the +option "check-names" in the named boot file. This option is documented +in the named manual page. The syntax is: + + check-names primary warn + +----------------------------------------------------------------------------- + +Question 4.8. What is lame delegation ? + +Date: Tue Mar 11 21:51:21 EST 1997 + +Two things are required for a lame delegation: + +* A nameserver X is delegated as authoritative for a zone. +* Nameserver X is not performing nameservice for that zone. + +Try to think of a lame delegation as a long-term condition, brought about +by a misconfiguration somewhere. Bryan Beecher's 1992 LISA paper on lame +delegations is good to read on this. The problem really lies in +misconfigured nameservers, not "lameness" brought about by transient +outages. The latter is common on the Internet and hard to avoid, while +the former is correctable. + +In order to be performing nameservice for a zone, it must have (presumed +correct) data for that zone, and it must be answering authoritatively to +resolver queries for that zone. (The AA bit is set in the flags section) + +The "classic" lame delegation case is when nameserver X is delegated as +authoritative for domain Y, yet when you ask X about Y, it returns +non-authoritative data. + +Here's an example that shows what happens most often (using dig, dnswalk, +and doc to find). + +Let's say the domain bogus.com gets registered at the NIC and they have +listed 2 primary name servers, both from their *upstream* provider: + + bogus.com IN NS ns.bogus.com + bogus.com IN NS upstream.com + bogus.com IN NS upstream1.com + +So the root servers have this info. But when the admins at bogus.com +actually set up their zone files they put something like: + + bogus.com IN NS upstream.com + bogus.com IN NS upstream1.com + +So your name server may have the nameserver info cached (which it may have +gotten from the root). The root says "go ask ns.bogus.com" since they are +authoritative + +This is usually from stuff being registered at the NIC (either nic.ddn.mil +or rs.internic.net), and then updated later, but the folks who make the +updates later never let the folks at the NIC know about it. + +----------------------------------------------------------------------------- + +Question 4.9. How can I see if the server is "lame" ? + +Date: Mon Sep 14 22:09:35 EDT 1998 + +Go to the authoritative servers one level up, and ask them who they think +is authoritative, and then go ask each one of those delegees if they think +that they themselves are authoritative. If any responds "no", then you +know who the lame delegation is, and who is delegating lamely to them. +You can then send off a message to the administrators of the level above. + +The 'lamers' script from Byran Beecher really takes care of all this for +you. It parses the lame delegation notices from BIND's syslog and +summarizes them for you. It may be found in the contrib section of the +latest BIND distribution. The latest version is included in the BIND +distribution. + +If you want to actively check for lame delegations, you can use 'doc' and +'dnswalk'. You can check things manually with 'dig'. + +The InterNIC recently announced a new lame delegation that will be in +effect on 01 October, 1996. Here is a summary: + +* After receipt/processing of a name registration template, and at random + intervals thereafter, the InterNIC will perform a DNS query via UDP + Port 53 on domain names for an SOA response for the name being + registered. +* If the query of the domain name returns a non-authoritative response + from all the listed name servers, the query will be repeated four times + over the next 30 days at random intervals approximately 7 days apart, + with notification to all listed whois and nameserver contacts of the + possible pending deletion. If at least one server answers correctly, + but one or more are lame, FYI notifications will be sent to all contacts + and checking will be discontinued. Additionally, e-mail notices will be + provided to the contact for the name servers holding the delegation to + alert them to the "lame" condition. Notifications will state explicitly + the consequences of not correcting the "lame" condition and will be + assigned a descriptive subject as follows: + + Subject: Lame Delegation Notice: DOMAIN_NAME + + The notification will include a timestamp for when the query was + performed. +* If, following 30 days, the name servers still provide no SOA response, + the name will be placed in a "hold" status and the DNS information will + no longer be propagated. The administrative contact will be notified by + postal mail and all whois contacts will be notified by e-mail, with + instructions for taking corrective action. +* Following 60 days in a "hold" status, the name will be deleted and made + available for re-registration. Notification of the final deletion will + be sent to the name server and domain name contacts listed in the NIC + database. + +----------------------------------------------------------------------------- + +Question 4.10. What does opt-class field in a zone file do? + +Date: Thu Dec 1 11:10:39 EST 1994 + +This field is the address class. From the BOG - + + ...is the address class; currently, only one class + is supported: IN for internet addresses and other + internet information. Limited support is included for + the HS class, which is for MIT/Athena ``Hesiod'' + information. + +----------------------------------------------------------------------------- + +Question 4.11. Top level domains + +Date: Mon Jun 15 22:25:57 EDT 1998 + +RFC 1591 defines the term "Top Level Domain" (TLD) as: + + + 2. The Top Level Structure of the Domain Names + + In the Domain Name System (DNS) naming of computers there is a + hierarchy of names. The root of system is unnamed. There are a set + of what are called "top-level domain names" (TLDs). These are the + generic TLDs (EDU, COM, NET, ORG, GOV, MIL, and INT), and the two + letter country codes from ISO-3166. It is extremely unlikely that + any other TLDs will be created. + +The unnamed root-level domain (usually denoted as ".") is currently being +maintained by the Internet Assigned Number Authority (IANA). Beside that, +IANA is currently in charge for some other vital functions on the Internet +today, including global distribution of address space, autonomous system +numbers and all other similar numerical constants, necessary for proper +TCP/IP protocol stack operation (e.g. port numbers, protocol identifiers +and so on). According to the recent proposals of the US Government, better +known as "Green Paper": + +http://www.ntia.doc.gov/ntiahome/domainname/domainname130.htm + +IANA will gradually transfer its current functions to a new non-profit +international organization, which won't be influenced exclusively by the +US Government. This transfer will occur upon the final version of the +"Green Paper" has been issued. + +Currently, the root zone contains five categories of top level domains: + + +(1) World wide gTLDs - maintained by the InterNIC: + - COM - Intended for commercial entities - companies, corporations etc. + - NET - Intended for Internet service providers and similar entities. + - ORG - Intended for other organizations, which don't fit to the above. + +(2) Special status gTLDs + - EDU - Restricted to 4 year colleges and universities only. + - INT - Intended for international treaties and infrastructural databases. + +(3) US restricted gTLDs + - GOV - Intended for US Government offices and agencies. + - MIL - Intended for the US military. + +(4) ISO 3166 country code TLDs (ccTLDs) - FR, CH, SE etc. + +(5) Reverse TLD - IN-ADDR.ARPA. + +Generic TLDs COM, NET, ORG and EDU are currently being maintained by the +InterNIC. IANA maintains INT and IN-ADDR.ARPA. The US Government and US +Army maintain their TLDs independently. + +The application form for the EDU, COM, NET, ORG, and GOV domains may be +found for anonymous ftp from: + +internic.net : /templates/domain-template.txt + +The country code domains (ISO 3166 based - example, FR, NL, KR, US) are +each organized by an administrator for that country. These administrators +may further delegate the management of portions of the naming tree. These +administrators are performing a public service on behalf of the Internet +community. The ISO-3166 country codes may be found for anonymous ftp +from: + +* ftp.isi.edu : /in-notes/iana/assignments/country-codes +* ftp.ripe.net : /iso3166-codes + +More information about particular country code TLDs may be found at: + +* http://www.iana.org/ +* http://www.UNINETT.NO/navn/domreg.html +* http://www.ripe.net/centr/tld.html +* http://www.nic.fr/Guides/AutresNics/ +* sipb.mit.edu : /pub/whois/whois-servers.list + +Contrary to the initial plans, stated in the RFC 1591, not to include +more TLDs in the near future, some other forums don't share that opinion. + +The International Ad Hoc Committee (IAHC) ({http://www.iahc.org/) was was +selected by the IAB, IANA, ITU, INTA, WIPO, and ISOC to study and +recommend changes to the existing Domain Name System (DNS). The IAHC +recommended the following regarding TLD's on February 4, 1997: + + In order to cope with the great and growing demand for Internet + addresses in the generic top level domains, the generic Top Level + Domain (gTLD) MoU calls for the establishment of seven new gTLDs in + addition to the existing three. These will be .FIRM, .STORE, .WEB, + .ARTS, .REC, .NOM and .INFO. In addition, the MoU provides for the + setting up of an initial 28 new registrars around the world four + from each of seven world regions. More registrars will be added as + operational and administrative issues are worked out. Registrars + will compete on a global basis, and users will be able shop around + for the registrar which offers them the best arrangement and price. + Users will also be able to change registrar at any time while + retaining the same domain address, thus ensuring global portability. + +The full text of the recommendation may be found at: + +http://www.iahc.org/draft-iahc-recommend-00.html. + +Beside IAHC, several other forums have been created, by people willing to +change the current addressing structure in the global network. Some of +them may be found at: + +* http://www.alternic.net/ +* http://www.eu.org/ +* http://www.webtld.com/ + +You may participate in one of the discussions on iTLD proposals at + +* To sign up: http://www.newdom.com/lists +* Old postings: http://www.newdom.com/archive + +----------------------------------------------------------------------------- + +Question 4.12. US Domain + +Date: Mon Jun 15 22:25:57 EDT 1998 + +Information on the US domain registration services may be found at +http://www.isi.edu/in-notes/usdnr/. + +The application form for the US domain may be found: + +* for anonymous ftp from internic.net : /templates/us-domain-template.txt +* http://www.isi.edu/us-domain/ + +A WWW interface to a whois server for the US domain may be found at +http://www.isi.edu/in-notes/usdnr/rwhois.html. This whois server may be +used with the command + % whois -h nii-server.isi.edu k12.ks.us + OR + % whois k12.ks.us@nii-server.isi.edu + (depending on your version of whois). + + +----------------------------------------------------------------------------- + +Question 4.13. Classes of networks + +Date: Sun Feb 9 22:36:21 EST 1997 + +The usage of 'classes of networks' (class A, B, C) are historical and have +been replaced by CIDR blocks on the Internet. That being said... + +An Internet Protocol (IP) address is 32 bit in length, divided into two +or three parts (the network address, the subnet address (if present), and +the host address. The subnet addresses are only present if the network +has been divided into subnetworks. The length of the network, subnet, and +host field are all variable. + +There are five different network classes. The leftmost bits indicate the +class of the network. + + # of # of + bits in bits in + network host +Class field field Internet Protocol address in binary Ranges +============================================================================ + A 7 24 0NNNNNNN.HHHHHHHH.HHHHHHHH.HHHHHHHH 1-127.x.x.x + B 14 16 10NNNNNN.NNNNNNNN.HHHHHHHH.HHHHHHHH 128-191.x.x.x + C 21 8 110NNNNN.NNNNNNNN.NNNNNNNN.HHHHHHHH 192-223.x.x.x + D NOTE 1 1110xxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx 224-239.x.x.x + E NOTE 2 11110xxx.xxxxxxxx.xxxxxxxx.xxxxxxxx 240-247.x.x.x + + where N represents part of the network address and H represents part of + the host address. When the subnet address is defined, the needed bits + are assigned from the host address space. + + NOTE 1: Reserved for multicast groups - RFC 1112 + NOTE 2: Reserved for future use + + 127.0.0.1 is reserved for local loopback. + +----------------------------------------------------------------------------- + +Question 4.14. What is CIDR ? + +Date: Tue Nov 5 23:47:29 EST 1996 + +CIDR is "Classless Inter-Domain Routing (CIDR). From RFC 1517: + + ...Classless Inter-Domain Routing (CIDR) attempts to deal with + these problems by defining a mechanism to slow the growth of + routing tables and reduce the need to allocate new IP network + numbers. + +Much more information may be obtained in RFCs 1467, 1517, 1518, 1520; +with primary reference 1519. + +Also please see the CIDR FAQ at + +* http://www.ibm.net.il/~hank/cidr.html +* http://www.rain.net/faqs/cidr.faq.html +* http://www.lab.unisource.ch/services/internet/direct/cidr.html + +----------------------------------------------------------------------------- + +Question 4.15. What is the rule for glue ? + +Date: Mon Sep 14 22:04:42 EDT 1998 + +A glue record is an A record for a name that appears on the right-hand +side of a NS record. So, if you have this: + + + sub.foobar.com. IN NS dns.sub.foobar.com. + dns.sub.foobar.com. IN A 1.2.3.4 + +then the second record is a glue record (for the NS record above it). + +You need glue records when -- and only when -- you are delegating +authority to a nameserver that "lives" in the domain you are delegating +*and* you aren't a secondary server for that domain. + +In other words, in the example above, you need to add an A record for +dns.sub.foobar.com since it "lives" in the domain it serves. This boot +strapping information is necessary: How are you supposed to find out the +IP address of the nameserver for domain FOO if the nameserver for FOO +"lives" in FOO? + +If you have this NS record: + + sub.foobar.com. IN NS dns.xyz123.com. + +you do NOT need a glue record, and, in fact, adding one is a very bad +idea. If you add one, and then the folks at xyz123.com change the +address, then you will be passing out incorrect data. + +Also, unless you actually have a machine called something.IN-ADDR.ARPA, +you will never have any glue records present in any of your "reverse" +files. + +There is also a sort of implicit glue record that can be useful (or +confusing :^) ). If the parent server (abc.foobar.com domain in example +above) is a secondary server for the child, then the A record will be +fetched from the child server when the zone transfer is done. The glue is +still there but it's a little different, it's in the ip address in the +named.boot line instead of explicitly in the data. In this case you can +leave out the explicit glue A record and leave the manually configured +"glue" in just the one place in the named.boot file. + +RFC 1537 says it quite nicely: + + 2. Glue records + + Quite often, people put unnecessary glue (A) records in their + zone files. Even worse is that I've even seen *wrong* glue records + for an external host in a primary zone file! Glue records need only + be in a zone file if the server host is within the zone and there + is no A record for that host elsewhere in the zone file. + + Old BIND versions ("native" 4.8.3 and older versions) showed the + problem that wrong glue records could enter secondary servers in + a zone transfer. + +In response to a question on glue records, Mark Andrews stated the +following: + + BIND's current position is somewhere between the overly restrictive + position given above and the general allow all glue position that + prevailed in 4.8.x. + + BIND's current break point is below the *parent* zone, i.e. it + allows glue records from sibling zones of the zone being + delegated. + + The following applies for glue + + Below child: always required + Below parent: often required + Elsewhere: seldom required + + The main reason for resticting glue is not that it in not + required but that it is impossible to track down *bad* glue if + you allow glue that falls into "elsewhere". Ask UUNET or any + other large provider the problems that BIND 4.8.x general glue + rules caused. If you want to examine a true data virus you need + only look at the A records for ns.uu.net. + + The "below parent" and "below child" both allow you to find bad + glue records. Below the parent has a bigger search space to that + of below the child but is still managable. + + It is believed that the elsewhere cases are sufficiently rare + that they can be ignored in practice and if detected can be worked + around by creating be creating A records for the nameservers + that fall into one of the other two cases. This requires + resolvers to correctly lookup missing glue and requery when they + have this glue. BIND does *not* do this correctly at present. +----------------------------------------------------------------------------- + +Question 4.16. What is a stub record/directive ? + +Date: Mon Nov 10 22:45:33 EST 1997 + +Q: What is the difference, or advantages, of using a stub record versus +using an NS record and a glue record in the zone file? + +Cricket Liu responds, + + "Stub" is a directive, not a record (well, it's a directive in BIND 4; +in BIND 8, it's an option to the "zone" statement). The stub directive +configures your name server to do a zone transfer just as a secondary +master name server would, but to use just the NS records. It's a +convenient way for a parent name server to keep track of the servers +for subzones. + +and Barry Margolin adds, + + Using stub records ensures that the NS records in the parent will be +consistent with the NS records in the child. If you have to enter NS +records manually, you run the possibility that the child will change his +servers without telling you. Then you'll give out incorrect delegation +information, possibly resulting in the infamous "lame delegation". + + +The remainder of the FAQ is in the next part (Part 2 of 2). + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/misc/FAQ.1of2 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/misc/FAQ.2of2 =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/misc/FAQ.2of2 (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/misc/FAQ.2of2 (revision 109985) @@ -0,0 +1,2071 @@ +Path: senator-bedfellow.mit.edu!bloom-beacon.mit.edu!news.kodak.com!news-nysernet-16.sprintlink.net!news-in-east1.sprintlink.net!news.sprintlink.net!newshub.northeast.verio.net!news.idt.net!newsin.iconnet.net!IConNet!not-for-mail +From: cdp2582@hertz.njit.edu (Chris Peckham) +Newsgroups: comp.protocols.tcp-ip.domains,comp.answers,news.answers,comp.protocols.dns.bind +Subject: comp.protocols.tcp-ip.domains Frequently Asked Questions (FAQ) (Part 2 of 2) +Supersedes: +Followup-To: comp.protocols.tcp-ip.domains +Organization: NJIT.EDU - New Jersey Institute of Technology, Newark, NJ, USA +Lines: 2050 +Sender: cdp@chipmunk.iconnet.net +Approved: news-answers-request@MIT.EDU +Distribution: world +Expires: Wednesday, 20 Jan 99 11:47:26 EDT +Message-ID: +References: +Reply-To: domain-faq@pfmc.net (comp.protocols.tcp-ip.domains FAQ comments) +Keywords: BIND,DOMAIN,DNS +X-Posting-Frequency: posted during the first week of each month +Date: Wed, 16 Dec 1998 16:47:32 GMT +NNTP-Posting-Host: chipmunk.iconnet.net +NNTP-Posting-Date: Wed, 16 Dec 1998 11:47:32 EDT +Xref: senator-bedfellow.mit.edu comp.protocols.tcp-ip.domains:22180 comp.answers:34269 news.answers:146737 comp.protocols.dns.bind:6040 + +Posted-By: auto-faq 3.3 beta (Perl 5.004) +Archive-name: internet/tcp-ip/domains-faq/part2 + +(Continued from Part 1, where you'll find the introduction and +table of contents.) + + +=============================================================================== + +Section 5. CONFIGURATION + + Q5.1 Upgrading from 4.9.x to 8.x + Q5.2 Changing a Secondary server to a Primary server ? + Q5.3 Moving a Primary server to another server + Q5.4 How do I subnet a Class B Address ? + Q5.5 Subnetted domain name service + Q5.6 Recommended format/style of DNS files + Q5.7 DNS on a system not connected to the Internet + Q5.8 Multiple Domain configuration + Q5.9 wildcard MX records + Q5.10 How do you identify a wildcard MX record ? + Q5.11 Why are fully qualified domain names recommended ? + Q5.12 Distributing load using named + Q5.13 Round robin IS NOT load balancing + Q5.14 Order of returned records + Q5.15 resolv.conf + Q5.16 How do I delegate authority for sub-domains ? + Q5.17 DNS instead of NIS on a Sun OS 4.1.x system + Q5.18 Patches to add functionality to BIND + Q5.19 How to serve multiple domains from one server + Q5.20 hostname and domain name the same + Q5.21 Restricting zone transfers + Q5.22 DNS in firewalled and private networks + Q5.23 Different DNS answers for same RR + +----------------------------------------------------------------------------- + +Question 5.1. Upgrading from 4.9.x to 8.x + +Date: Wed Jul 9 22:00:07 EDT 1997 + +Q: Help ! How do I use the Completely new configuration syntax in BIND 8 +? I've attempted to upgrade bind from 4.9.5 to 8.1, but unfortunately it +didn't seem to like the same config/zone files.. is this normal or should +8.1 be able to read the same files as 4.9.5 did? + +A: If you then look in doc/html/config.html, you will find directions on +how to convert a 4.9.x .boot file to 8.x .conf file, as well as directions +on how to utilize all of the new features of the 8.x .conf file format. + +----------------------------------------------------------------------------- + +Question 5.2. Changing a Secondary server to a Primary server ? + +Date: Fri Jul 5 23:54:35 EDT 1996 + +For 4.8.3, it's prudent to kill and restart following any changes to +named.boot. + +In BIND 4.9.3, you only have to kill and restart named if you change a +primary zone to a secondary or v-v, or if you delete a zone and remain +authoritative for its parent. Every other case should be taken care of by +a HUP. (Ed. note: 4.9.3b9 may still require you to kill and restart the +server due to some bugs in the HUP code). + +You will also need to update the server information on the root servers. +You can do this by filing a new domain registration form to inform +InterNIC of the change. They will then update the root server's SOA +records. This process usually takes 10-12 business days after they +receive the request. + +----------------------------------------------------------------------------- + +Question 5.3. Moving a Primary server to another server + +Date: Fri Jul 5 23:54:35 EDT 1996 + +The usual solution is to move the primary to ns.newserver.com, and have +ns.oldserver.com be configured as a secondary server until the change to +the root servers takes place after the request has been made to the +InterNIC. + +If you are moving to a different ISP which will change your IP's, the +recommend setting for the SOA that would minimize problems for your name +servers using the old settings can be done as follows: + +Gradually lower the TTL value in your SOA (that's the last one of the five +numbers) to always be equal to the time left until you change over. +(assuming that none of your resource records have individual TTL's set, if +so, do likewise with them.) So, the day before, lower to 43200 seconds +(12 hours). Then lower every few hours to be the time remaining until +the change-over. So, an hour before the change, you may just want to +lower it all the way to 60 seconds or so. That way no one can cache +information past the change-over. + +After the change, start gradually incrementing the TTL value, because +you'll probably be making changes to work out problems. Once everything +stabilizes, move the TTL up to whatever your normal values are. + +To minimize name servers from using the "old settings", you can do the +same thing with the "refresh" interval in the SOA (the second number of +the SOA). That will tell the secondaries to refresh every X seconds. +Lower that value as you approach the changeover date. You probably don't +want to go much below an hour or you'll start the primary thrashing as all +the secondaries perpetually refresh. + +Also see the answer to the "How can I change the IP address of our server +?" in the INTRODUCTION section. + +----------------------------------------------------------------------------- + +Question 5.4. How do I subnet a Class B Address ? + +Date: Mon Jun 15 23:21:39 EDT 1998 + +That you need to subnet at all is something of a misconception. You can +also think of a class B network as giving you 65,534 individual hosts, and +such a network will work. You can also configure your class B as 16,384 +networks of 2 hosts each. That's obviously not very practical, but it +needs to be made clear that you are not constrained by the size of an +octet (remember that many older devices would not work in a network +configured in this manner). + +So, the question is: why do you need to subnet? One reason is that it is +easier to manage a subnetted network, and in fact, you can delegate the +responsibility for address space management to local administrators on the +various subnets. Also, IP based problems will end up localized rather +than affecting your entire network. + +If your network is a large backbone with numerous segments individually +branching off the backbone, that too suggests subnetting. + +Subnetting can also be used to improve routing conditions. + +You may wish to partition your network to disallow certain protocols on +certain segments of your net. You can, for example, restrict IP or IPX to +certain segments only by adding a router routing high level protocols, +and across the router you may have to subnet. + +Finally, as far as how many subnets you need depends on the answer to the +above question. As far as subnet masks are concerned, the mask can be +anything from 255.0.0.0 to 255.255.255.252. You'll probably be looking at +9 or 10 bits for the subnet (last octet 128 or 192 respectively). RFC +1219 discusses the issue of subnetting very well and leaves the network +administrator with a large amount of flexibility for future growth. + +(The following section was contributed by Berislav Todorovic.) + +A user or an ISP, having a whole /16 sized IP block (former "Class B") +network assigned/allocated, has the responsibility of maintaining the +reverse domain for the whole network. That policy is currently applied by +all regional Internet registries (RIPE NCC, ARIN, APNIC). In other words, +if you're assigned a whole "B class" (say, 10.91/16), you're in charge for +the whole 91.10.IN-ADDR.ARPA zone. This zone may be organized using two +methods, according to the network topology being in use. + +The first, "brute force" method is to place all PTR records directly into +a single zone file. Example: + + $origin 91.10.in-addr.arpa + @ IN SOA (usual stuff) + IN NS ns1.mydomain.com. + IN NS ns2.mydomain.com. + + 1.1 IN PTR one-1.mydomain.com. ; ---> 10.91.1.1 + 2.1 IN PTR one-2.mydomain.com. ; ---> 10.91.1.2 + ... + 254.1 IN PTR one-254.mydomain.com. ; ---> 10.91.1.254 + 1.2 IN PTR two-1.mydomain.com. ; ---> 10.91.2.1 + +While this approach may look simple in the networks with a central +management authority (say, campus networks), maintaining such a zone file +becomes more and more difficult in the more complex environment. Thus, +this becomes a bad method. Furthermore, if you're an ISP, it is more +likely that a /16 network will be subnetted and its subnets be assigned to +your customers. + +Therefore, another "smarter" approach is to delegate portions of the +reverse domain 91.10.IN-ADDR.ARPA to the end users of the subnets of +10.91/16. There would only be NS records in the zone file, while PTR +record insertion would be the responsibility of the end users. For +example, if you assign: + + * 10.91.0.0/22 (10.91.0.0 - 10.91.3.255) to Customer-A.COM + * 10.91.4.0/23 (10.91.4.0 - 10.91.5.255) to Customer-B.COM + * 10.91.7.0/24 (10.91.7.0 - 10.91.7.255) to Customer-C.COM + +then each customer will maintain zone files for the reverse domains of +their own networks (say, Customer C will maintain the zone +7.91.10.IN-ADDR.ARPA, customer B their 2 zones, Customer A their own 4 +zones). In this constellation, the zone file for reverse domain +91.10.IN-ADDR.ARPA will look like this: + + $origin 91.10.in-addr.arpa + @ IN SOA (usual stuff) + IN NS ns1.mydomain.com. + IN NS ns2.mydomain.com. + + ; --- Customer-A.COM + + + 0 IN NS ns.customer-A.com. + IN NS ns1.mydomain.com. + 1 IN NS ns.customer-A.com. + IN NS ns1.mydomain.com. + 2 IN NS ns.customer-A.com. + IN NS ns1.mydomain.com. + 3 IN NS ns.customer-A.com. + IN NS ns1.mydomain.com. + + ; --- Customer-B.COM + + 4 IN NS ns.customer-B.com. + IN NS ns1.mydomain.com. + 5 IN NS ns.customer-B.com. + IN NS ns1.mydomain.com. + + ; --- Customer-C.COM + + 7 IN NS ns.customer-C.com. + IN NS ns1.mydomain.com. + +The zone file of the Customer C reverse domain would look like this: + + $origin 7.91.10.in-addr.arpa + @ IN SOA (usual stuff) + IN NS ns.customer-C.com. + IN NS ns1.mydomain.com. + + 1 IN PTR one.customer-C.com. + 2 IN PTR two.customer-C.com. + 3 IN PTR three.customer-C.com. + ... + +----------------------------------------------------------------------------- + +Question 5.5. Subnetted domain name service + +Date: Thu Jul 16 10:50:41 EDT 1998 + +If you are looking for some examples of handling subnetted class C +networks as separate DNS domains, see RFC 2317 for more information. + +Details follow- You need to delegate down to the fourth octet, so you will +have one domain per IP address ! Here is how you can subdelegate a +in-addr.arpa address for non-byte aligned subnet masks: + +Take as an example the net 192.1.1.x, and example subnet mask +255.255.255.240. + +We first define the domain for the class C net, + + $origin 1.1.192.in-addr.arpa + @ SOA (usual stuff) + @ ns some.nameserver + ns some.other.nameserver + ; delegate a subdomain + one ns one.nameserver + ns some.nameserver + ; delegate another + two ns two.nameserver + ns some.nameserver + ; CNAME pointers to subdomain one + 0 CNAME 0.one + 1 CNAME 1.one + ; through + 15 CNAME 15.one + ; CNAME pointers to subdomain two + 16 CNAME 16.two + 17 CNAME 17.two + 31 CNAME 31.two + ; CNAME as many as required. + +Now, in the delegated nameserver, one.nameserver + + $origin one.1.1.192.in-addr.arpa + @ SOA (usual stuff) + NS one.nameserver + NS some.nameserver ; secondary for us + 0 PTR onenet.one.domain + 1 PTR onehost.one.domain + ; through + 15 PTR lasthost.one.domain + +And similar for the two.1.1.192.in-addr.arpa delegated domain. + +There is additional documentation and a perl script that may be used for +this purpose available for anonymous ftp from: + +ftp.is.co.za : /networking/ip/dns/gencidrzone/gencidrzone + +----------------------------------------------------------------------------- + +Question 5.6. Recommended format/style of DNS files + +Date: Sun Nov 27 23:32:41 EST 1994 + +This answer is quoted from an article posted by Paul Vixie: + + I've gone back and forth on the question of whether the BOG should + include a section on this topic. I know what I myself prefer, but + I'm wary of ramming my own stylistic preferences down the throat of + every BOG reader. But since you ask :-)... + + Create /var/named. If your system is too old to have a /var, either + create one or use /usr/local/adm/named instead. Put your named.boot + in it, and make /etc/named.boot a symlink to it. If your system + doesn't have symlinks, you're S-O-L (but you knew that). In + named.boot, put a "directory" directive that specifies your actual + BIND working directory: + + directory /var/named + + All relative pathnames used in "primary", "secondary", and "cache" + directives will be evaluated relative to this directory. Create two + subdirectories, /var/named/pri and /var/named/sec. Whenever you add + a "primary" directive to your named.boot, use "pri/WHATEVER" as the + path name. And then put the primary zone file into "pri/WHATEVER". + Likewise when you add "secondary" directives, use "sec/WHATEVER" and + BIND (really named-xfer) will create the files in that + subdirectory. + + (Variations: (1) make a midlevel directory "zones" and put "pri" and + "sec" into it; (2) if you tend to pick up a lot of secondaries from + a few hosts, group them together in their own subdirectories -- + something like /var/named/zones/uucp if you're a UUCP Project name + server.) + + For your forward files, name them after the zone. dec.com becomes + "/var/named/zones/pri/dec.com". For your reverse files, name them + after the network number. 0.1.16.in-addr.arpa becomes + "/var/named/zones/pri/16.1.0". + + When creating or maintaining primary zone files, try to use the same + SOA values everywhere, except for the serial number which varies per + zone. Put a $ORIGIN directive at the top of the primary zone file, + not because its needed (it's not since the default origin is the + zone named in the "primary" directive) but because it make it easier + to remember what you're working on when you have a lot of primary + zones. Put some comments up there indicating contact information + for the real owner if you're proxying. Use RCS and put the "Id" + in a ";" comment near the top of the zone file. + + The SOA and other top level information should all be listed + together. But don't put IN on every line, it defaults nicely. For + example: + +============== +@ IN SOA gw.home.vix.com. postmaster.vix.com. ( + 1994082501 ; serial + 3600 ; refresh (1 hour) + 1800 ; retry (30 mins) + 604800 ; expire (7 days) + 3600 ) ; minimum (1 hour) + + NS gw.home.vix.com. + NS ns.uu.net. + NS uucp-gw-1.pa.dec.com. + NS uucp-gw-2.pa.dec.com. + + MX 10 gw.home.vix.com. + MX 20 uucp-gw-1.pa.dec.com. + MX 20 uucp-gw-1.pa.dec.com. +============== + + I don't necessarily recommend those SOA values. Not every zone is + as volatile as the example shown. I do recommend that serial number + format; it's in date format with a 2-digit per-day revision number. + This format will last us until 2147 A.D. at which point I expect a + better solution will have been found :-). (Note that it would last + until 4294 A.D. except that there are some old BINDs out there that + use a signed quantity for representing serial number internally; I + suppose that as long as none of these are still running after 2047 + A.D., that we can use the above serial number format until 4294 + A.D., at which point a better solution will HAVE to be found.) + + You'll note that I use a tab stop for "IN" even though I never again + specify it. This leaves room for names longer than 7 bytes without + messing up the columns. You might also note that I've put the MX + priority and destination in the same tab stop; this is because both + are part of the RRdata and both are very different from MX which is + an RRtype. Some folks seem to prefer to group "MX" and the priority + together in one tab stop. While this looks neat it's very confusing + to newcomers and for them it violates the law of least + astonishment. + + If you have a multi-level zone (one which contains names that have + dots in them), you can use additional $ORIGIN statements but I + recommend against it since there is no "back" operator. That is, + given the above example you can add: + +============= +$ORIGIN home +gw A 192.5.5.1 +============= + + The problem with this is that subsequent RR's had better be + somewhere under the "home.vix.com" name or else the $ORIGIN that + introduces them will have to use a fully qualified name. FQDN + $ORIGIN's aren't bad and I won't be mad if you use them. + Unqualified ones as shown above are real trouble. I usually stay + away from them and just put the whole name in: + +============= +gw.home A 192.5.5.1 +============= + + In your reverse zones, you're usually in some good luck because the + owner name is usually a single short token or sometimes two. + +============= +$ORIGIN 5.5.192.in-addr.arpa. +@ IN SOA ... + NS ... +1 PTR gw.home.vix.com. +========================================= +$ORIGIN 1.16.in-addr.arpa. +@ IN SOA ... + NS ... +2.0 PTR gatekeeper.dec.com. +============= + + It is usually pretty hard to keep your forward and reverse zones in + sync. You can avoid that whole problem by just using "h2n" (see + the ORA book, DNS and BIND, and its sample toolkit, included in the + BIND distribution or on ftp.uu.net (use the QUOTE SITE EXEC INDEX + command there to find this -- I never can remember where it's at). + "h2n" and many tools like it can just read your old /etc/hosts file + and churn it into DNS zone files. (May I recommend + contrib/decwrl/mkdb.pl from the BIND distribution?) However, if you + (like me) prefer to edit these things by hand, you need to follow + the simple convention of making all of your holes consistent. If + you use 192.5.5.1 and 192.5.5.3 but not (yet) 192.5.5.2, then in + your forward file you will have something like + +============= +... +gw.home A 192.5.5.1 +;avail A 192.5.5.2 +pc.home A 192.5.5.3 +============= + + and in your reverse file you will have something like + +============= +... +1 PTR gw.home.vix.com. +;2 PTR avail +3 PTR pc.home.vix.com. +============= + + This convention will allow you to keep your sanity and make fewer + errors. Any kind of automation (h2n, mkdb, or your own + perl/tcl/awk/python tools) will help you maintain a consistent + universe even if it's also a complex one. Editing by hand doesn't + have to be deadly but you MUST take care. + +----------------------------------------------------------------------------- + +Question 5.7. DNS on a system not connected to the Internet + +Date: Sun Nov 27 23:32:41 EST 1994 + +You need to create your own root domain name server until you connect to +the internet. Your roots need to delegate to mydomain.com and any +in-addr.arpa subdomains you might have, and that's about it. As soon as +you're connected, rip out the fake roots and use the real ones. + +It does not actually have to be another server pretending to be the root. +You can set up the name server so that it is primary for each domain above +you and leave them empty (i.e. you are foo.bar.com - claim to be primary +for bar.com and com) + +If you connect intermittently and want DNS to work when you are connected, +and "fail" when you are not, you can point the resolver at the name server +at the remote site and if the connection (SLIP/PPP) isn't up, the resolver +doesn't have a route to the remote server and since there's only one name +server in resolv.conf, the resolver quickly backs off the using +/etc/hosts. No problem. You could do the same with multiple name server +and a resolver that did configurable /etc/hosts fallback. + +----------------------------------------------------------------------------- + +Question 5.8. Multiple Domain configuration + +Date: Fri Dec 2 15:40:49 EST 1994 + +If you want to have multiple domain names pointing to the same +destination, such as: + + ftp ftp.biff.com connects user to -> ftp.biff.com + ftp ftp.fred.com connects user to -> ftp.biff.com + ftp ftp.bowser.com connects user to -> ftp.biff.com + +You may do this by using CNAMEs: + + ftp.bowser.com. IN CNAME ftp.biff.com. + +You can also do the same thing with multiple A records. + +----------------------------------------------------------------------------- + +Question 5.9. wildcard MX records + +Date: Sun Nov 27 23:32:41 EST 1994 + +Does BIND not understand wildcard MX records such as the following? + + *.foo.com MX 0 mail.foo.com. + +No. It just doesn't work. + +Explicit RR's at one level of specificity will, by design, "block" a +wildcard at a lesser level of specificity. I suspect that you have an RR +(an A RR, perhaps?) for "bar.foo.com" which is blocking the application of +your "*.foo.com" wildcard. The initial MX query is thus failing (NOERROR +but an answer count of 0), and the backup query finds the A RR for +"bar.foo.com" and uses it to deliver the mail directly (which is what you +DIDN'T want it to do). Adding an explicit MX RR for the host is therefore +the right way to handle this situation. + +See RFC 1034, Section 4.3.3 ("Wildcards") for more information on this +"blocking" behavior, along with an illustrative example. See also RFC 974 +for an explanation of standard mailer behavior in the face of an "empty" +response to one's MX query. + +Basically, what it boils down to is, there is no point in trying to use a +wildcard MX for a host which is otherwise listed in the DNS. + +It just doesn't work. + +----------------------------------------------------------------------------- + +Question 5.10. How do you identify a wildcard MX record ? + +Date: Thu Dec 1 11:10:39 EST 1994 + +You don't really need to "identify" a wildcard MX RR. The precedence for +u@dom is: + + exact match MX + exact match A + wildcard MX + +One way to implement this is to query for ("dom",IN,MX) and if the answer +name that comes back is "*." something, you know it's a wildcard, +therefore you know there is no exact match MX, and you therefore query for +("dom",IN,A) and if you get something, use it. if you don't, use the +previous wildcard response. + +RFC 974 explains this pretty well. + +----------------------------------------------------------------------------- + +Question 5.11. Why are fully qualified domain names recommended ? + +Date: Sun Nov 27 23:32:41 EST 1994 + +The documentation for BIND 4.9.2 says that the hostname should be set to +the full domain style name (i.e host.our.domain rather than host). What +advantages are there in this, and are there any adverse consequences if we +don't? + +Paul Vixie likes to do it :-) He lists a few reasons - + +* Sendmail can be configured to just use Dj$w rather than Dj$w.mumble + where "mumble" is something you have to edit in by hand. Granted, most + people use "mumble" elsewhere in their config files ("tack on local + domain", etc) but why should it be a requirement ? +* The real reason is that not doing it violates a very useful invariant: + gethostbyname(gethostname) == gethostbyaddr(primary_interface_address) + + + If you take an address and go "backwards" through the PTR's with it, + you'll get a FQDN, and if you push that back through the A RR's, you get + the same address. Or you should. Many multi-homed hosts violate this + uncaringly. + + If you take a non-FQDN hostname and push it "forwards" through the A + RR's, you get an address which, if you push it through the PTR's, comes + back as a FQDN which is not the same as the hostname you started with. + Consider the fact that, absent NIS/YP, there is no "domainname" command + analogous to the "hostname" command. (NIS/YP's doesn't count, of + course, since it's sometimes-but-only-rarely the same as the Internet + domain or subdomain above a given host's name.) The "domain" keyword in + resolv.conf doesn't specify the parent domain of the current host; it + specifies the default domain of queries initiated on the current host, + which can be a very different thing. (As of RFC 1535 and BIND 4.9.2's + compliance with it, most people use "search" in resolv.conf, which + overrides "domain", anyway.) + + What this means is that there is NO authoritative way to + programmatically discover your host's FQDN unless it is set in the + hostname, or unless every application is willing to grovel the "netstat + -in" tables, find what it hopes is the primary address, and do a PTR + query on it. + + FQDN /bin/hostnames are, intuitively or not, the simplest way to go. + +----------------------------------------------------------------------------- + +Question 5.12. Distributing load using named + +Date: Thu Jul 16 10:42:05 EDT 1998 + +When you attempt to distribute the load on a system using named, the first +response be cached, and then later queries use the cached value (This +would be for requests that come through the same server). Therefore, it +can be useful to use a lower TTL on records where this is important. You +can use values like 300 or 500 seconds. + +If your local caching server has ROUND_ROBIN, it does not matter what the +authoritative servers have -- every response from the cache is rotated. + +But if it doesn't, and the authoritative server site is depending on this +feature (or the old "shuffle-A") to do load balancing, then if one doesn't +use small TTLs, one could conceivably end up with a really nasty +situation, e.g., hundreds of workstations at a branch campus pounding on +the same front end at the authoritative server's site during class +registration. + +Not nice. + +Paul Vixie has an example of the ROUND_ROBIN code in action. Here is +something that he wrote regarding his example: + + I want users to be distributed evenly among those 3 hosts. + + Believe it or not :-), BIND offers an ugly way to do this. I offer + for your collective amusement the following snippet from the + ugly.vix.com zone file: + + hydra cname hydra1 + cname hydra2 + cname hydra3 + hydra1 a 10.1.0.1 + a 10.1.0.2 + a 10.1.0.3 + hydra2 a 10.2.0.1 + a 10.2.0.2 + a 10.2.0.3 + hydra3 a 10.3.0.1 + a 10.3.0.2 + a 10.3.0.3 + + Note that having multiple CNAME RR's at a given name is + meaningless according to the DNS RFCs but BIND doesn't mind (in + fact it doesn't even complain). If you call + gethostbyname("hydra.ugly.vix.com") (try it!) you will get + results like the following. Note that there are two round robin + rotations going on: one at ("hydra",CNAME) and one at each + ("hydra1",A) et al. I used a layer of CNAME's above the layer of + A's to keep the response size down. If you don't have nine + addresses you probably don't care and would just use a pile of + CNAME's pointing directly at real host names. + + {hydra.ugly.vix.com + name: hydra2.ugly.vix.com + aliases: hydra.ugly.vix.com + addresses: 10.2.0.2 10.2.0.3 10.2.0.1 + + {hydra.ugly.vix.com + name: hydra3.ugly.vix.com + aliases: hydra.ugly.vix.com + addresses: 10.3.0.2 10.3.0.3 10.3.0.1 + + {hydra.ugly.vix.com + name: hydra1.ugly.vix.com + aliases: hydra.ugly.vix.com + addresses: 10.1.0.2 10.1.0.3 10.1.0.1 + + {hydra.ugly.vix.com + name: hydra2.ugly.vix.com + aliases: hydra.ugly.vix.com + addresses: 10.2.0.3 10.2.0.1 10.2.0.2 + + {hydra.ugly.vix.com + name: hydra3.ugly.vix.com + aliases: hydra.ugly.vix.com + addresses: 10.3.0.3 10.3.0.1 10.3.0.2 + +Please note that this is not a recommended practice and will not work with +modern BIND unless you have the entry "multiple-cnames yes" in your +named.conf file. + +----------------------------------------------------------------------------- + +Question 5.13. Round robin IS NOT load balancing + +Date: Mon Mar 9 22:10:51 EST 1998 + +Round robin != load balancing. It's a very crude attempt at load +balancing, and a method that is possible without breaking DNS protocols. +If a host is down that is included in a round robin list, then +connections to that particular host will fail. In addition, true load +balancing should take into consideration the actual LOAD on the system. + +Information on one such technique, implemented by Roland J. Schemers III +at Stanford, may be found at +http://www-leland.stanford.edu/~schemers/docs/lbnamed/lbnamed.html. + +Additional information may be found in RFC 1794. MultiNet for OpenVMS +also includes this feature. + +----------------------------------------------------------------------------- + +Question 5.14. Order of returned records + +Date: Tue Apr 8 20:21:02 EDT 1997 + +Sorting, is the *resolver's* responsibility. RFC 1123: + + + 6.1.3.4 Multihomed Hosts + + When the host name-to-address function encounters a host + with multiple addresses, it SHOULD rank or sort the + addresses using knowledge of the immediately connected + network number(s) and any other applicable performance or + history information. + + DISCUSSION: + The different addresses of a multihomed host generally + imply different Internet paths, and some paths may be + preferable to others in performance, reliability, or + administrative restrictions. There is no general way + for the domain system to determine the best path. A + recommended approach is to base this decision on local + configuration information set by the system + administrator. + +In BIND 4.9.x's resolver code, the "sortlist" directive in resolv.conf +can be used to configure this. The directive may also be used in the +named.boot as well. + +----------------------------------------------------------------------------- + +Question 5.15. resolv.conf + +Date: Fri Feb 10 15:46:17 EST 1995 + +The question was asked one time, "Why should I use 'real' IP addresses in +/etc/resolv.conf and not 0.0.0.0 or 127.0.0.1" ? + +Paul Vixie writes on the issue of the contents of resolv.conf: + + It's historical. Some kernels can't unbind a UDP socket's source + address, and some resolver versions (notably not including BIND + 4.9.2 or 4.9.3's) try to do this. The result can be wide area + network traffic with 127.0.0.1 as the source address. Rather than + giving out a long and detailed map of version/vendor combinations of + kernels/BINDs that have/don't this problem, I just tell folks not to + use 127.0.0.1 at all. + + 0.0.0.0 is just an alias for the first interface address assigned + after a system boot, and if that interface is a up-and-down point to + point link (PPP, SLIP, whatever), there's no guarantee that you'll + be able to reach yourself via 0.0.0.0 during the entire lifetime of + any system instance. On most kernels you can finesse this by adding + static routes to 127.0.0.1 for each of your interface addresses, but + some kernels don't like that trick and rather than give a detailed + map of which ones work and which ones don't, I just globally + recommend against 0.0.0.0. + + If you know enough to know that 127.0.0.1 or 0.0.0.0 is safe on your + kernel and resolver, then feel free to use them. If you don't know + for sure that it is safe, don't use them. I never use them (except + on my laptop, whose hostname is "localhost" and whose 0.0.0.0 is + 127.0.0.1 since I ifconfig my lo0 before any other interface). The + operational advantage to using a real IP address rather than an + wormhole like 0.0.0.0 or 127.0.0.1, is that you can then "rdist" or + otherwise share identical copies of your resolv.conf on all the + systems on any given subnet, not all of which will be servers. + +The problem was with older versions of the resolver (4.8.X). If you +listed 127.0.0.1 as the first entry in resolv.conf, and for whatever +reason the local name server wasn't running and the resolver fell back to +the second name server listed, it would send queries to the name server +with the source IP address set to 127.0.0.1 (as it was set when the +resolver was trying to send to 127.0.0.1--you use the loopback address to +send to the loopback address). + +----------------------------------------------------------------------------- + +Question 5.16. How do I delegate authority for sub-domains ? + +Date: Mon Nov 10 22:57:54 EST 1997 + +When you start having a very big domain that can be broken into logical +and separate entities that can look after their own DNS information, you +will probably want to do this. Maintain a central area for the things +that everyone needs to see and delegate the authority for the other parts +of the organization so that they can manage themselves. + +Another essential piece of information is that every domain that exists +must have it NS records associated with it. These NS records denote the +name servers that are queried for information about that zone. For your +zone to be recognized by the outside world, the server responsible for the +zone above you must have created a NS record for your your new servers +(NOTE that the new servers DO NOT have to be in the new domain). For +example, putting the computer club onto the network and giving them +control over their own part of the domain space we have the following. + +The machine authorative for gu.uwa.edu.au is mackerel and the machine +authorative for ucc.gu.uwa.edu.au is marlin. + +in mackerel's data for gu.uwa.edu.au we have the following + + @ IN SOA ... + IN A 130.95.100.3 + IN MX mackerel.gu.uwa.edu.au. + IN MX uniwa.uwa.edu.au. + + marlin IN A 130.95.100.4 + + ucc IN NS marlin.gu.uwa.edu.au. + IN NS mackerel.gu.uwa.edu.au. + +Marlin is also given an IP in our domain as a convenience. If they blow +up their name serving there is less that can go wrong because people can +still see that machine which is a start. You could place "marlin.ucc" in +the first column and leave the machine totally inside the ucc domain as +well. + +The second NS line is because mackerel will be acting as secondary name +server for the ucc.gu domain. Do not include this line if you are not +authorative for the information included in the sub-domain. + +To delegate authority for PTR records, the same concepts apply. + + stub 10.168.192.in-addr.arpa db.192.168.10 + +may be added to your primary server's named.boot in recent versions of +bind. In other versions (and recent ones :-) ), the following lines may +be added to the db.192.168.10 zone file to perform the same function: + + xxx IN NS + xxx IN NS + xxx IN NS ; if needed +... + xxx IN NS ; if needed + +----------------------------------------------------------------------------- + +Question 5.17. DNS instead of NIS on a Sun OS 4.1.x system + +Date: Sat Dec 7 01:14:17 EST 1996 + +Comments relating to running bind 4.9.x on a Sun OS 4.1.x system and the +effect on sendmail, ftp, telnet and other TCP/IP services bypassing NIS +and directly using named is documented quite well in the +comp.sys.sun.admin FAQ in questions one and two. You can get them from: + +* ftp.ece.uc.edu : /pub/sun-faq/FAQs/sun-faq.general +* http://www.cis.ohio-state.edu/hypertext/faq/usenet/comp-sys-sun-faq + +as well as from rtfm.mit.edu in the usual place, etc. + +----------------------------------------------------------------------------- + +Question 5.18. Patches to add functionality to BIND + +Date: Wed Jan 14 11:57:20 EST 1998 + +There are others, but these are listed here: + +* When using the round robin DNS and assigning 3 IPs to a host (for + example), a process to guarantee that all 3 IPs are reachable may be + found at + http://www-leland.stanford.edu/~schemers/docs/lbnamed/lbnamed.html + +* Patches for 4.9.3-REL that will support the IPv6 AAAA record format may + be found at ftp.inria.fr : /network/ipv6/ + + This is built into more recent versions of BIND (after 4.9.5?) + +* A patch for 4.9.3-REL that will allow you to turn off forwarding of + information from my server may be found at ftp.vix.com : + /pub/bind/release/4.9.3/contrib/noforward.tar.gz + + Also look at + + ftp.is.co.za : /networking/ip/dns/bind/contrib/noforward.tar.gz + +* How do I tell a server to listen to a particular interface to listen and + respond to DNS queries on ? + + Mark Andrews has a patch that will tell a 4.9.4 server to listen to a + particular interface and respond to DNS queries. It may be found at an + unofficial location: http://www.ultra.net/~jzp/andrews.patch.txt + + This is built into BIND 8.1.1. + +* A patch to implement "selective forwarding" from Todd Aven at + http://www.dns.net/dnsrd/servers.html. + +----------------------------------------------------------------------------- + +Question 5.19. How to serve multiple domains from one server + +Date: Tue Nov 5 23:44:02 EST 1996 + +Most name server implementations allow information about multiple domains +to be kept on one server, and questions about those domains to be +answered by that one server. For instance, there are many large servers +on the Internet that each serve information about more than 1000 +different domains. + +To be completely accurate, a server contains information about zones, +which are parts of domains that are kept as a single unit. [Ed note: for +a definition of zones and domains, see Section 2: The Name Service in the +"Name Server Operations Guide" included with the BIND 4.9.5 distribution.] + +In the configuration of the name server, the additional zones need to be +specified. An important consideration is whether a particular server is +primary or secondary for any specific zone--a secondary server maintains +only a copy of the zone, periodically refreshing its copy from another, +specified, server. In BIND, to set up a server as a secondary server for +the x.y.z zone, to the configuration file /etc/named.boot add the line + + secondary x.y.z 10.0.0.1 db.x.y.z + +where 10.0.0.1 is the IP address of the server that the zone will be +copied from, and db.x.y.z is a local filename that will contain the copy +of the zone. + +If this is a question related to how to set up multiple IP numbers on one +system, which you do not need to do to act as a domain server for +multiple domains, see + +http://www.thesphere.com/%7Edlp/TwoServers/. + +----------------------------------------------------------------------------- + +Question 5.20. hostname and domain name the same + +Date: Wed Jul 9 21:47:36 EDT 1997 + +Q: I have a subdomain sub.foobar.com. I would like to name a host +sub.foobar.com. It should also be the mail relay for all hosts in +sub.foobar.com. How do I do this ? + +A: You would add an A record for sub.foobar.com, and multiple MX records +pointing to this host (sub.foobar.com). For example: + +sub.foobar.com. IN A 1.2.3.4 ; address of host +; +foo.sub.foobar.com. IN MX 10 sub.foobar.com. +bar.sub.foobar.com. IN MX 10 sub.foobar.com. + +The host, sub.foobar.com, may also need to be to configured to understand +that mail addressed to user@sub.foobar.com and possibly other sub.foobar.com +hosts should be treated as local. + +----------------------------------------------------------------------------- + +Question 5.21. Restricting zone transfers + +Date: Wed Jan 14 12:16:35 EST 1998 + +Q: How do I restrict my zone transfers to my secondaries or other trusted +hosts? + +A: Use the 'xfrnets' directive within the named.boot file or the +'secure_zone' TXT RR within a zone file. The BOG has more information on +both of these options. + +As an example within an 4.9.x named.boot file: + + xfernets 10.1.2.0&255.255.255.0 44.66.10.0&255.255.255.0 + + +Only Nameservers on these networks will be able to do zone transfers from +the server with this configuration. + +Please note that 'secure_zone' restricts all access to the containing +zone, as well as restricting zone transfers :-) . + +BIND 8.x supports restricting zone transfers on a per-zone basis in the +named.conf file, whereas BIND 4.9.x only supports xfrnets as a global +option. + +----------------------------------------------------------------------------- + +Question 5.22. DNS in firewalled and private networks + +Date: Mon Sep 14 22:15:16 EDT 1998 + +(The following section was contributed by Berislav Todorovic) + +When talking about private networks, we distinguish between two cases: + +* Networks consisting of firewall-separated private and public subnetworks + + * Same domain name used in private and public part of the network + * Different domain names used in the public and private subnetwork + +* Closed networks, not connected the Internet at all + +* The first case of the "Same domain name", we're talking about DNS + configuration, usually referred to as "split DNS". In this case, two + different DNS servers (or two separate DNS processes on the same + multi-homed machine) have to be configured. One of them ("private DNS") + will serve the internal network and will contain data about all hosts in + the private part of the network. The other one ("public DNS") will serve + Internet users and will contain only the most necessary RR's for + Internet users (like MX records for email exchange, A and CNAME records + for public Web servers, records for other publicly accessible hosts + etc.). Both of them will be configured as primary for the same corporate + domain (e.g. DOMAIN.COM). The public DNS will be delegated with the + appropriate NIC as authoritative for domain DOMAIN.COM. + + Private DNS - resolves names from DOMAIN.COM for hosts inside the + private network. If asked for a name outside DOMAIN.COM, they should + forward the request to the public DNS (forwarders line should be used in + the boot file). They should NEVER contact a root DNS on the Internet. + The boot file for the private DNS should, therefore, be: + + primary domain.com ZONE.domain.com + primary 1.10.in-addr.arpa REV.10.1 + forwarders 172.16.12.10 + slave + Public DNS - resolves names from DOMAIN.COM for hosts on the public part + of the network. If asked for a name outside DOMAIN.COM they should + contact root DNS servers or (optionally) forward the request to a + forwarder on the ISP network. Boot file for the public DNS should be of + the form: + + primary domain.com ZONE.domain.com + primary 12.16.172.in-addr.arpa REV.172.16.12 + ... (other domains) + Zone files for domain DOMAIN.COM on the public and private DNS should + be: + + ; --- Public DNS - zone file for DOMAIN.COM + + domain.com. IN SOA ns.domain.com. hostmaster.domain.com. ( ... ) + IN NS ns.domain.com. + IN NS ns.provider.net. + IN MX 10 mail.provider.net. + + ns IN A 172.16.12.10 + www IN A 172.16.12.12 + ftp IN A 172.16.12.13 + ... + + ; --- Private DNS - zone file for DOMAIN.COM + + domain.com. IN SOA ns1.domain.com. hostmaster.domain.com. ( ... ) + IN NS ns1.domain.com. + IN NS ns2.domain.com. + wks1-1 IN A 10.1.1.1 + wks1-2 IN A 10.1.1.2 + ... + + The second case of the "Same domain name", is simpler than the previous + case: in the internal network, a separate domain name might be used. + Recommended domain name syntax is "name.local" (e.g. DOMAIN.LOCAL). + Sample configuration: + + ; --- Private DNS - named.boot + + primary domain.local ZONE.domain.local + ... + forwarders 172.16.12.10 + slave + + ; --- Public DNS - named.boot + + primary domain.com ZONE.domain.com + ... + IMPLEMENTATION NOTES + + Location of the DNS service in both cases is irrelevant. Usually, they + are located on two different physical servers, each of them connected to + the appropriate part of the network (private, public). Certain savings + may be done if public DNS service is hosted on the ISP network - in that + case, the user will need only one (private) DNS server. + + Finally, both public and private DNS, in some cases, may be placed on + the servers in the private network, behind the firewall. With a Cisco + PIX, a statical public/private IP address mapping in this case would be + needed. Two servers for the same domain could be even placed on the + same physical server, with two different DNS processes running on + different IP interfaces. Note that BIND 8 is needed in the latter case. + +* If the network is not connected to the Internet at all, only private DNS + servers are needed. However, due to the lack of Internet connectivity, + internal servers will fail to contact the root DNS servers every time a + user types, by mistake, an address outside the corporate domain + DOMAIN.COM. Some older servers won't even work if they can't reach root + servers. To overcome this, it is most proper to create a so-called "fake + root zone" on one or more DNS servers in the corporation. That would + make all DNS servers within the corporation think there is only one or + two DNS servers in the world, all located on the corporation network. + Only domain names used within the corporation (DOMAIN.COM, appropriate + inverse domains etc.) should be entered in the fake root zone file. Note + that no cache line in the boot file of the "root" DNS makes sense. + Sample configuration: + + ; --- named.boot + + primary domain.com ZONE.domain.com + primary 1.10.in-addr.arpa REV.10.1 + priamry . ZONE.root + ... (other data; NOTE - do *NOT* place any "cache" line here !!!) + + ; --- ZONE.root - fake root zone file, containing only corporation domains + + . IN NS ns.domain.com. hostmaster.domain.com. ( ... ) + IN NS ns.domain.com. + IN NS ns2.domain.com. + + domain.com. IN NS ns.domain.com. + ns.domain.com. IN A 10.1.1.1 + domain.com. IN NS ns2.domain.com. + ns2.domain.com. IN A 10.1.1.2 + + 1.10.in-addr.arpa. IN NS ns.domain.com. + IN NS ns2.domain.com. + + Other zone files follow standard configuration. + +----------------------------------------------------------------------------- + +Question 5.23. Different DNS answers for same RR + +Date: Mon Sep 14 22:15:16 EDT 1998 + +(The following section was contributed by Berislav Todorovic) + +Many times there is a need for a DNS server to send different answers for +same RR's, depending on the IP address of the request sender. For example, +many coprporations wish to make their customers to use the "geographically +closest" Web server when accessing corporate Web pages. A corporation may +impose the following policy: if someone asked for the IP address of +WWW.DOMAIN.COM, they may want to: + +* Answer that the IP address is 172.16.2.3, if the request came from one + of the following IP networks: 172.1/16, 172.2/16 or 172.10/16. +* Answer that the IP address is 172.16.1.1, if the request came from the + IP address 172.16/16 or 172.17.128/18. +* By default, for all other requests send the answer that the IP address + is 172.16.2.3. + +The example above will need a DNS to send different A RR's, depending on +the source of queries. A similar approach may be imposed for MX's, CNAME's +etc. The question which arise here is: IS IT POSSIBLE? + +[Ed note: There are commercial products such as Cisco's Distributed +Director that also will address this issue] + +The simple answer to the question is: NOT DIRECTLY. This is true if +standard DNS software (e.g. BIND) is used on the DNS servers. However, +there are two workarounds which may solve this problem: + +* Using two DNS servers on different UDP ports + UDP redirector +* Using two DNS servers on different IP addresses + NAT on the router + +Solution 1: (tested on a Linux system and should work on other Unix boxes +as well). Software needed is: + +* BIND 8 +* udprelay - a package which redirects traffic to other UDP port + (sunsite.unc.edu: /pub/Linux/system/network/misc/udprelay-0.2.tar.Z ). + +Build and install udprelay and bring up two DNS servers on different UDP +ports, using different configuration files (i.e., bring one on 5300 and +the other one on 5400): + + // --- named.conf.5300 + options { + directory "/var/named" + listen-on port 5300 { any; }; + ... (other options) + }; + + zone "domain.com" { + type master; + file "domain.com.5300"; + }; + + // --- named.conf.5400 + + options { + directory "/var/named" + listen-on port 5400 { any; }; + ... (other options) + }; + + zone "domain.com" { + type master; + file "domain.com.5400"; + }; + + + ; domain.com.5300 + ... (SOA and other stuff) + + www IN A 172.16.2.3 + + ; --- domain.com.5400 + ... (SOA and other stuff) + + www IN A 172.16.1.1 + +As can be seen, there will be two separate zone files for DOMAIN.COM, +depending on which UDP port the server listens to. Each zone file can +contain different records. Now, when configure udprelay to forward UDP +traffic from port 53 to 5300 or 5400, depending on the remote IP address: + + relay 172.1.0.0 mask 255.255.0.0 * 53 172.16.1.1 5300 53 + relay 172.2.0.0 mask 255.255.0.0 * 53 172.16.1.1 5300 53 + relay 172.10.0.0 mask 255.255.0.0 * 53 172.16.1.1 5300 53 + relay 172.16.0.0 mask 255.255.0.0 * 53 172.16.1.1 5400 53 + relay 172.17.0.0 mask 255.255.0.0 * 53 172.16.1.1 5400 53 + relay * * 53 172.16.1.1 5400 53 +After starting udprelay, all traffic coming to port 53 will be redirected +to 5300 or 5400, depending on the source IP address. + +NOTE - This solution deals with the UDP part of DNS only. Zone xfers will +be able to be done from one DNS server only, since this solution doesn't +deal the TCP part of DNS. This is, thus, a partial solution but it works! + +Solution 2: Bring up two DNS servers on your network, using "private" IP +addresses (RFC 1918), say ns1.domain.com (10.1.1.1) and ns2.domain.com +(10.1.1.2). Both servers will have the same public address - 172.16.1.1, +which will be used to access the servers. Configure them to be both +primary for domain DOMAIN.COM. Let one of them (say, ns1) be the +"default" DNS, which will be used in most of the cases. Establish NAT on +the router, so it translates the public IP address 172.16.1.1 to 10.1.1.1 +and delegate your "default" DNS with the appropriate NIC, using its public +address 172.16.1.1. Once you're assured everything works, setup your +router to translate the public IP address 172.16.1.1 to either 10.1.1.1 or +10.1.1.2, depending on the requestor IP address. After that, depending on +the source IP address, the router will return one translation or the +latter, thus forwarding the remote side to the appropriate DNS server. + +=============================================================================== + +Section 6. PROBLEMS + + Q6.1 No address for root server + Q6.2 Error - No Root Nameservers for Class XX + Q6.3 Bind 4.9.x and MX querying? + Q6.4 Do I need to define an A record for localhost ? + Q6.5 MX records, CNAMES and A records for MX targets + Q6.6 Can an NS record point to a CNAME ? + Q6.7 Nameserver forgets own A record + Q6.8 General problems (core dumps !) + Q6.9 malloc and DECstations + Q6.10 Can't resolve names without a "." + Q6.11 Why does swapping kill BIND ? + Q6.12 Resource limits warning in system + Q6.13 ERROR:ns_forw: query...learnt + Q6.14 ERROR:zone has trailing dot + Q6.15 ERROR:Zone declared more then once + Q6.16 ERROR:response from unexpected source + Q6.17 ERROR:record too short from [zone name] + Q6.18 ERROR:sysquery: findns error (3) + Q6.19 ERROR:Err/TO getting serial# for XXX + Q6.20 ERROR:zonename IN NS points to a CNAME + Q6.21 ERROR:Masters for secondary zone [XX] unreachable + Q6.22 ERROR:secondary zone [XX] expired + Q6.23 ERROR:bad response to SOA query from [address] + Q6.24 ERROR:premature EOF, fetching [zone] + Q6.25 ERROR:Zone [XX] SOA serial# rcvd from [Y] is < ours + Q6.26 ERROR:connect(IP/address) for zone [XX] failed + Q6.27 ERROR:sysquery: no addrs found for NS + Q6.28 ERROR:zone [name] rejected due to errors + +----------------------------------------------------------------------------- + +Question 6.1. No address for root server + +Date: Wed Jan 14 12:15:54 EST 1998 + +Q: I've been getting the following messages lately from bind-4.9.2.. + ns_req: no address for root server + +We are behind a firewall and have the following for our named.cache file - + + ; list of servers + . 99999999 IN NS POBOX.FOOBAR.COM. + 99999999 IN NS FOOHOST.FOOBAR.COM. + foobar.com. 99999999 IN NS pobox.foobar.com. + +You can't do that. Your nameserver contacts POBOX.FOOBAR.COM, gets the +correct list of root servers from it, then tries again and fails because +of your firewall. + +You will need a 'forwarder' definition, to ensure that all requests are +forwarded to a host which can penetrate the firewall. And it is unwise to +put phony data into 'named.cache'. + +Q: We are getting logging information in the form: + +Apr 8 08:05:22 gute named[107]: sysquery: no addrs found for root NS + (A.ROOT-SERVERS.NET) +Apr 8 08:05:22 gute named[107]: sysquery: no addrs found for root NS + (B.ROOT-SERVERS.NET) +Apr 8 08:05:22 gute named[107]: sysquery: no addrs found for root NS + (C.ROOT-SERVERS.NET) +... + +We are running bind 4.9.5PL1 Our system IS NOT behind a firewall. Any ideas ? + +This was discussed on the mailing list in November of 1996. The short +answer was to ignore it as it was not a problem. That being said, you +should upgrade to a newer version at this time if you are running a +non-current version :-) + +----------------------------------------------------------------------------- + +Question 6.2. Error - No Root Nameservers for Class XX + +Date: Sun Nov 27 23:32:41 EST 1994 + +Q: I've received errors before about "No root nameservers for class XX" + but they've been because of network connectivity problems. + I believe that Class 1 is Internet Class data. + And I think I heard someone say that Class 4 is Hesiod?? + Does anyone know what the various Class numbers are? + +From RFC 1700: + + DOMAIN NAME SYSTEM PARAMETERS + The Internet Domain Naming System (DOMAIN) includes several + parameters. These are documented in [RFC1034] and [RFC1035]. The + CLASS parameter is listed here. The per CLASS parameters are + defined in separate RFCs as indicated. + + Domain System Parameters: + + Decimal Name References + -------- ---- ---------- + 0 Reserved [PM1] + 1 Internet (IN) [RFC1034,PM1] + 2 Unassigned [PM1] + 3 Chaos (CH) [PM1] + 4 Hesoid (HS) [PM1] + 5-65534 Unassigned [PM1] + 65535 Reserved [PM1] + +DNS information for RFC 1700 was taken from + +ftp.isi.edu : /in-notes/iana/assignments/dns-parameters + +Hesiod is class 4, and there are no official root nameservers for class 4, +so you can safely declare yourself one if you like. You might want to +put up a packet filter so that no one outside your network is capable of +making Hesiod queries of your machines, if you define yourself to be a +root nameserver for class 4. + +----------------------------------------------------------------------------- + +Question 6.3. Bind 4.9.x and MX querying? + +Date: Sun Nov 27 23:32:41 EST 1994 + +If you query a 4.9.x DNS server for MX records, a list of the MX records +as well as a list of the authorative nameservers is returned. This +happens because bind 4.9.2 returns the list of nameserver that are +authorative for a domain in the response packet, along with their IP +addresses in the additional section. + +----------------------------------------------------------------------------- + +Question 6.4. Do I need to define an A record for localhost ? + +Date: Sat Sep 9 00:36:01 EDT 1995 + +Somewhere deep in the BOG (BIND Operations Guide) that came with 4.9.3 +(section 5.4.3), it says that you define this yourself (if need be) in +the same zone files as your "real" IP addresses for your domain. Quoting +the BOG: + + + ... As implied by this PTR + record, there should be a ``localhost.my.dom.ain'' + A record (with address 127.0.0.1) in every domain + that contains hosts. ``localhost.'' will lose its + trailing dot when 1.0.0.127.in-addr.arpa is queried + for;... + +The sample files in the BIND distribution show you what needs to be done +(see the BOG). + +Some HP boxen (especially those running HP OpenView) will also need +"loopback" defined with this IP address. You may set it as a CNAME +record pointing to the "localhost." record. + +----------------------------------------------------------------------------- + +Question 6.5. MX records, CNAMES and A records for MX targets + +Date: Sun Nov 27 23:32:41 EST 1994 + +The O'Reilly "DNS and Bind" book warns against using non-canonical names +in MX records, however, this warning is given in the context of mail hubs +that MX to each other for backup purposes. How does this apply to mail +spokes. RFC 974 has a similar warning, but where is it specifically +prohibited to us an alias in an MX record ? + +Without the restrictions in the RFC, a MTA must request the A records for +every MX listed to determine if it is in the MX list then reduce the list. +This introduces many more lookups than would other wise be required. If +you are behind a 1200 bps link YOU DON'T WANT TO DO THIS. The addresses +associated with CNAMES are not passed as additional data so you will force +additional traffic to result even if you are running a caching server +locally. + +There is also the problem of how does the MTA find all of it's IP +addresses. This is not straight forward. You have to be able to do this is +you allow CNAMEs (or extra A's) as MX targets. + +The letter of the law is that an MX record should point to an A record. + +There is no "real" reason to use CNAMEs for MX targets or separate As for +nameservers any more. CNAMEs for services other than mail should be used +because there is no specified method for locating the desired server yet. + +People don't care what the names of MX targets are. They're invisible to +the process anyway. If you have mail for "mary" redirected to "sue" is +totally irrelevant. Having CNAMEs as the targets of MX's just needlessly +complicates things, and is more work for the resolver. + +Having separate A's for nameservers like "ns.your.domain" is pointless +too, since again nobody cares what the name of your nameserver is, since +that too is invisible to the process. If you move your nameserver from +"mary.your.domain" to "sue.your.domain" nobody need care except you and +your parent domain administrator (and the InterNIC). Even less so for +mail servers, since only you are affected. + +Q: Given the example - + + hello in cname realname + mailx in mx 0 hello + + Now, while reading the operating manual of bind it clearly states + that this is *not* valid. These two statements clearly contradict + each other. Is there some later RFC than 974 that overrides what is + said in there with respect to MX and CNAMEs? Anyone have the + reference handy? + +A: This isn't what the BOG says at all. See below. You can have a CNAME + that points to some other RR type; in fact, all CNAMEs have to point + to other names (Canonical ones, hence the C in CNAME). What you + can't have is an MX that points to a CNAME. MX RR's that point to + names which have only CNAME RR's will not work in many cases, and + RFC 974 intimates that it's a bad idea: + + Note that the algorithm to delete irrelevant RRs breaks if LOCAL has + a alias and the alias is listed in the MX records for REMOTE. (E.g. + REMOTE has an MX of ALIAS, where ALIAS has a CNAME of LOCAL). This + can be avoided if aliases are never used in the data section of MX + RRs. + + Here's the relevant BOG snippet: + + aliases {ttl addr-class CNAME Canonical name + ucbmonet IN CNAME monet + + The Canonical Name resource record, CNAME, speci- + fies an alias or nickname for the official, or + canonical, host name. This record should be the + only one associated with the alias name. All other + resource records should be associated with the + canonical name, not with the nickname. Any + resource records that include a domain name as + their value (e.g., NS or MX) must list the canoni- + cal name, not the nickname. + +----------------------------------------------------------------------------- + +Question 6.6. Can an NS record point to a CNAME ? + +Date: Wed Mar 1 11:14:10 EST 1995 + +Can I do this ? Is it legal ? + + + @ SOA (.........) + NS ns.host.this.domain. + NS second.host.another.domain. + ns CNAME third + third IN A xxx.xxx.xxx.xxx + +No. Only one RR type is allowed to refer, in its data field, to a CNAME, +and that's CNAME itself. So CNAMEs can refer to CNAMEs but NSs and MXs +cannot. + +BIND 4.9.3 (Beta11 and later) explicitly syslogs this case rather than +simply failing as pre-4.9 servers did. Here's a current example: + + Dec 7 00:52:18 gw named[17561]: "foobar.com IN NS" \ + points to a CNAME (foobar.foobar.com) + +Here is the reason why: + +Nameservers are not required to include CNAME records in the Additional +Info section returned after a query. It's partly an implementation +decision and partly a part of the spec. The algorithm described in RFC +1034 (pp24,25; info also in RFC 1035, section 3.3.11, p 18) says 'Put +whatever addresses are available into the additional section, using glue +RRs [if necessary]'. Since NS records are speced to contain only primary +names of hosts, not CNAMEs, then there's no reason for algorithm to +mention them. If, on the other hand, it's decided to allow CNAMEs in NS +records (and indeed in other records) then there's no reason that CNAME +records might not be included along with A records. The Additional Info +section is intended for any information that might be useful but which +isn't strictly the answer to the DNS query processed. It's an +implementation decision in as much as some servers used to follow CNAMEs +in NS references. + +----------------------------------------------------------------------------- + +Question 6.7. Nameserver forgets own A record + +Date: Fri Dec 2 16:17:31 EST 1994 + +Q: Lately, I've been having trouble with named 4.9.2 and 4.9.3. + Periodically, the nameserver will seem to "forget" its own A record, + although the other information stays intact. One theory I had was + that somehow a site that the nameserver was secondary for was + "corrupting" the A record somehow. + +A: This is invariably due to not removing ALL of the cached zones + when you moved to 4.9.X. Remove ALL cached zones and restart + your nameservers. + + You get "ignoreds" because the primaries for the relevant zones are + running old versions of BIND which pass out more glue than is + required. named-xfer trims off this extra glue. + +----------------------------------------------------------------------------- + +Question 6.8. General problems (core dumps !) + +Date: Sun Dec 4 22:21:22 EST 1994 + +Paul Vixie says: + + I'm always interested in hearing about cases where BIND dumps core. + However, I need a stack trace. Compile with -g and not -O (unless + you are using gcc and know what you are doing) and then when it + dumps core, get into dbx or gdb using the executable and the core + file and use "bt" to get a stack trace. Send it to me + along with specific circumstances leading to or + surrounding the crash (test data, tail of the debug log, tail of the + syslog... whatever matters) and ideally you should save your core + dump for a day or so in case I have questions you can answer via + gdb/dbx. + +----------------------------------------------------------------------------- + +Question 6.9. malloc and DECstations + +Date: Mon Jan 2 14:19:22 EST 1995 + +We have replaced malloc on our DECstations with a malloc that is more +compact in memory usage, and this helped the operation of bind a lot. The +source is now available for anonymous ftp from + +ftp.cs.wisc.edu : /pub/misc/malloc.tar.gz + +----------------------------------------------------------------------------- + +Question 6.10. Can't resolve names without a "." + +(Answer written by Mark Andrews) You are not using a RFC 1535 aware +resolver. Depending upon the age of your resolver you could try adding a +search directive to resolv.conf. + + e.g. + domain + search [ ...] + +If that doesn't work you can configure you server to serve the parent and +grandparent domains as this is the default search list. + +"domain langley.af.mil" has an implicit "search langley.af.mil af.mil mil" +in the old resolvers, and you are timing out trying to resolve the +address with one of these domains tacked on. + +When resolving internic.net the following will be tried in order. + + internic.net.langley.af.mil + internic.net.af.mil + internic.net.mil + internic.net. + +RFC 1535 aware resolvers try qualified address first. + + internic.net. + internic.net.langley.af.mil + internic.net.af.mil + internic.net.mil + +RFC 1535 documents the problems associated with the old search +algorithim, including security issues, and how to alleviate some of the +problems. + +----------------------------------------------------------------------------- + +Question 6.11. Why does swapping kill BIND ? + +Date: Thu Jul 4 23:20:20 EDT 1996 + +The question was: + + I've been diagnosing a problem with BIND 4.9.x (where x is usually 3BETA9 + or 3REL) for several months now. I finally tracked it down to swap space + utilization on the unix boxes. + + This happens under (at least) under Linux 1.2.9 & 1.2.13, SunOS 4.1.3U1, + 4.1.1, and Solaris 2.5. The symptom is that if these machines get into + swap at all bind quits resolving most, if not all queries. Mind you that + these machines are not "swapping hard", but rather we're talking about a + several hundred K TEMPORARY deficiency. I have noticed while digging + through various archives that there is some referral to "bind thrashing + itself to death". Is this what is happening ? + +And the answer is: + + Yes it is. Bind can't tolerate having even a few pages swapped out. + The time required to send responses climbs to several seconds/request, + and the request queue fills and overflows. + + It's possible to shrink memory consumption a lot by undefining STATS + and XSTATS, and recompiling. You could nuke DEBUG too, which will + cut the code size down some, but probably not the data size. If that + doesn't do the job then it sounds like you'll need to move DNS onto a + separate box. + + BIND tends to touch all of its resident pages all of the time with + normal activity... if you look at the RSS verses the total process + size, you will always see the RSS within, usually, 90% of the total + size of the process. This means that *any* paging of named-owned + pages will stall named. Thus, a machine running a heavily accessed + named process cannot afford to swap *at all*. + + (Paul Vixie continues on this subject): + I plan to try to get BIND to exhibit slightly better locality of + reference in some future release. Of course, I can only do this if + the query names also exhibit some kind of hot spots. If someone + queries all your names often, BIND will have to touch all of its VM + pool that often. (Right now, BIND touches everything pretty often + even if you're just hammering on some hot spots -- that's the part + I'd like to fix. Malloc isn't cooperating.) + +----------------------------------------------------------------------------- + +Question 6.12. Resource limits warning in system + +Date: Sun Feb 15 22:04:43 EST 1998 + +When bind-8.1.1 is started the following informational message appears in +the syslog... + + Feb 13 14:19:35 ns1named[1986]: + "cannot set resource limits on this system" + +What does this mean ? + +A: It means that BIND doesn't know how to implement the "coresize", +"datasize", "stacksize", or "files" process limits on your OS. + +If you're not using these options, you may ignore the message. + +----------------------------------------------------------------------------- + +Question 6.13. ERROR:ns_forw: query...learnt + +Date: Sun Feb 15 23:08:06 EST 1998 + +The following message appears in syslog: + + Jan 22 21:59:55 server1 named[21386]: ns_forw: query(testval) contains + our address (dns1.foobar.org:1.2.3.4) learnt (A=:NS=) + +what does it mean ? + +A: This means that when it was looking up the NS records for the domain +containing "testval" (i.e. the root domain), it found an NS record +pointing to dns1.foobar.org, and the A record for this is 1.2.3.4. +This is server1's own IP address, but it's not authoritative for the +root domain. The (A-:NS=) part of the message means that it didn't +learn these NS records from any other machine. + +You may have listed dns1.foobar.org in your root server cache +file, even though it's not configured as a root server. + + +\question 09jul:linuxq ERROR:recvfrom: Connection refused + +Date: Wed Jul 9 21:57:40 EDT 1997 + +DNS on my linux system is reporting the error + +\verbatim +Mar 26 12:11:20 idg named[45]: recvfrom: Connection refused + +When I start or restart the named program I get no errors. What could be +causing this ? + +A: Are you running the BETA9 version of bind 4.9.3 ? It is a bug that +does no harm and the error reporting was corrected in later releases. You +should upgrade to a newer version of bind. + +----------------------------------------------------------------------------- + +Question 6.14. ERROR:zone has trailing dot + +Date: Wed Jul 9 22:11:51 EDT 1997 + +If syslog reports "zone has trailing dot", the zone information contains a +trailing dot in the named.boot file where it does not belong. + + + example: + secondary domain.com. xxx.xxx.xxx.xxx S-domain.com + ^ +----------------------------------------------------------------------------- + +Question 6.15. ERROR:Zone declared more then once + +Date: Wed Jul 9 22:12:45 EDT 1997 + +If syslog reports "Zone declared more then once", + +A zone is specified multiple times in the named.boot file + + example: + secondary domain.com 198.247.225.251 S-domain.com + secondary zone.com 198.247.225.251 S-zone.com + primary domain.com P-domain.com + + domain.com is declared twice, once as primary, and once as secondary + +----------------------------------------------------------------------------- + +Question 6.16. ERROR:response from unexpected source + +Date: Wed Jul 9 22:12:45 EDT 1997 + +If syslog reports "response from unexpected source", BIND (pre 4.9.3) has +a bug if implimented on a multi homed server. This error indicates that +the response to a query came from an address other then the one sent to. +So, if ace gets a response from an unexpected source, ace will ignore the +response. + +----------------------------------------------------------------------------- + +Question 6.17. ERROR:record too short from [zone name] + +Date: Mon Jun 15 21:34:49 EDT 1998 + +If syslog report "record too short from [zone name]", The secondary server +is trying to pull a zone from the primary server. For some reason, the +primary sent an incomplete zone. This usually is a problem at the primary +server. + + To troubleshoot, try this: + + dig [zonename] axfr @[primary IP address] + + Often, this is caused by a line broken in the middle. + +When the primary server's "named.boot" file contains "xfrnets" entries +for other servers and the secondary is not listed, this error can occur. +Creating an "xfrnets" entry for the secondary will solve the error. + +----------------------------------------------------------------------------- + +Question 6.18. ERROR:sysquery: findns error (3) + +Date: Wed Jul 9 22:17:09 EDT 1997 + +If syslog reports "sysquery: findns error (3)" or +"qserial_query(zonename): sysquery FAILED", there is no ns record for the +zone. or the NS record is not defined correctly. + +----------------------------------------------------------------------------- + +Question 6.19. ERROR:Err/TO getting serial# for XXX + +Date: Wed Jul 9 22:18:41 EDT 1997 + +If syslog reports "Err/TO getting serial# for XXX", there could be a +number of possible errors: + + - An incorrect IP address in named.boot, + - A network reachibility problem, + - The primary is lame for the zone. + +An external check to see if you can retrieve the SOA is the best way to +work out which it is. + +----------------------------------------------------------------------------- + +Question 6.20. ERROR:zonename IN NS points to a CNAME + +Date: Wed Jul 9 22:20:29 EDT 1997 + +If syslog reports "zonename IN NS points to a CNAME" or "zonename IN MX +points to a CNAME", named is 'reminding' you that due to various RFCs, an +NS or MX record cannot point to a CNAME. + + EXAMPLE 1 + --------- + domain.com IN SOA (...stuff...) + IN NS ns.domain.com. + ns IN CNAME machine.domain.com. + machine IN A 1.2.3.4 + + The IN NS record points to ns, which is a CNAME for machine. This + is what results in the above error + + EXAMPLE 2 + --------- + domain.com IN SOA (...stuff...) + IN MX mail.domain.com. + mail IN CNAME machine.domain.com. + machine IN A 1.2.3.4 + + This would cause the MX variety of the error. + + The fix is point MX and NS records to a machine that is defined explicitly + by an IN A record. + +----------------------------------------------------------------------------- + +Question 6.21. ERROR:Masters for secondary zone [XX] unreachable + +Date: Wed Jul 9 22:24:27 EDT 1997 + +If syslog reports "Masters for secondary zone [XX] unreachable", the +initial attempts to load a zone failed, and the name server is still +trying. If this occurs multiple times, a problem exists, likely on the +primary server. This is a fairly generic error, and could indicate a vast +number of problems. It might be that named is not running on the primary +server, or they do not have the correct zone file. If this keeps up long +enough a zone might expire. + +----------------------------------------------------------------------------- + +Question 6.22. ERROR:secondary zone [XX] expired + +Date: Wed Jul 9 22:25:53 EDT 1997 + +If syslog reports "secondary zone [XX] expired", there has been a +expiration of a secondary zone on this server. + +An expired zone is one in which a transfer hasn't successfully been +completed in the amount of time specified before a zone expires. + +This problem could be anything which prevents a zone transfer: The primary +server is down, named isn't running on the primary, named.boot has the +wrong IP address, etc. + +----------------------------------------------------------------------------- + +Question 6.23. ERROR:bad response to SOA query from [address] + +Date: Wed Jan 14 12:15:11 EST 1998 + +If syslog reports "bad response to SOA query from [address], zone [name]", +a syntax error may exist in the SOA record of the zone your server is +attempting to pull. + +It may also indicate that the primary server is lame, possibly due to a +syntax error somewhere in the zone file. + +----------------------------------------------------------------------------- + +Question 6.24. ERROR:premature EOF, fetching [zone] + +Date: Wed Jul 9 22:28:26 EDT 1997 + +If syslog reports "premature EOF, fetching [zone]", a syntax error exists +on the zone at the primary location, likely towards the End of File (EOF) +location. + +----------------------------------------------------------------------------- + +Question 6.25. ERROR:Zone [XX] SOA serial# rcvd from [Y] is < ours + +Date: Wed Jul 9 22:30:03 EDT 1997 + +If syslog reports "Zone [name] SOA serial# rcvd from [address] is < ours", +the zone transfer failed because the primary machine has a lower serial +number in the SOA record than the one on file on this server. + +----------------------------------------------------------------------------- + +Question 6.26. ERROR:connect(IP/address) for zone [XX] failed + +Date: Wed Jan 14 12:21:40 EST 1998 + +If syslog reports "connect(address) for zone [name] failed: No route to +host" or "connect(address) for zone [name] failed: Connection timed out", +it could be that there is no route to the specified host or a slow primary +system. Try a traceroute to the address specified to isolate the problem. +The problem may be a mistyped IP address in named.boot. + +A very slow primary machine or a connection may have been initialized, +then connectivity lost for some reason, etc. Try networking +troubleshooting tools like ping and traceroute, then try connecting to +port 53 using nslookup or dig. + +If syslog reports "connect(address) for zone [name] failed: Connection +refused", the destination address is not allowing the connection. Either +the destination is not running DNS (port 53), or possibly filtering the +connection from you. It is also possible that the named.boot is pointing +to the wrong address. + +----------------------------------------------------------------------------- + +Question 6.27. ERROR:sysquery: no addrs found for NS + +Date: Wed Jul 9 22:37:01 EDT 1997 + +If syslog reports "sysquery: no addrs found for NS" , the IN NS record may +be pointing to a host with no IN A record. + +----------------------------------------------------------------------------- + +Question 6.28. ERROR:zone [name] rejected due to errors + +Date: Wed Jul 9 22:37:51 EDT 1997 + +If syslog reports "primary zone [name] rejected due to errors", there will +likely be another more descriptive error along with this, like "zonefile: +line 17: database format error". That zone file should be investigated +for errors. + +=============================================================================== + +Section 7. ACKNOWLEDGEMENTS + + Q7.1 How is this FAQ generated ? + Q7.2 What formats are available ? + Q7.3 Contributors + +----------------------------------------------------------------------------- + +Question 7.1. How is this FAQ generated ? + +Date: Mon Jun 15 21:45:53 EDT 1998 + +This FAQ is maintained in BFNN (Bizzarre Format with No Name). This +allows me to create ASCII, HTML, and GNU info (postscript coming soon) +from one source file. + +The perl script "bfnnconv.pl" that is available with the linux FAQ is used +to generate the various output files from the BFNN source. This script is +available at + +txs-11.mit.edu : /pub/linux/docs/linux-faq/linux-faq.source.tar.gz + +----------------------------------------------------------------------------- + +Question 7.2. What formats are available ? + +Date: Fri Dec 6 16:51:31 EST 1996 + +You may obtain one of the following formats for this document: + +* ASCII: http://www.intac.com/~cdp/cptd-faq/cptd-faq.ascii +* BFNN: http://www.intac.com/~cdp/cptd-faq/cptd-faq.bfnn +* GNU info: http://www.intac.com/~cdp/cptd-faq/cptd-faq.info +* HTML: http://www.intac.com/~cdp/cptd-faq/index.html + +----------------------------------------------------------------------------- + +Question 7.3. Contributors + +Date: Thu Jul 16 10:45:57 EDT 1998 + +Many people have helped put this list together. Listed in e-mail address +alphabetical order, the following people have contributed to this FAQ: + +* (Berislav Todorovic) +* (Benoit.Grange) +* (Dave Shield) +* (Karl Auer) +* +* (Adam Goodfellow) +* (Andras Salamon) +* (Barry Margolin) +* (David Barr) +* (B.J. Herbison) +* (Ben Elliston) +* (Brad Knowles) +* (Christopher Davis) +* (Chris Peckham) +* (Cricket Liu) +* (Ian 'Vato' Dickinson [ID17]) +* (David Jagoda) +* (David Keegel) +* (Matthew Dillon) +* (David Parter) +* (Eric Wassenaar) +* (Tom Fitzgerald) +* (Frank Peters) +* (Glen A. Herrmannsfeldt) +* (Glenn Fleishman) +* (James Harvey) +* (Steve Hubert) +* (Ivan Leong) +* (Jim Pass) +* (John Hawkinson) +* (Joseph Malcolm) +* (Joe Provo) +* (J. Richard Sladkey) +* (Jon Drukman) +* (John Wells) +* (Karl O. Pinc) +* (Kevin Darcy) +* (Sean T. Lamont) +* (Michel Lavondes) +* (Mark Powell) +* (Mark Andrews) +* (Mathias Koerber) +* (Michael Fuhr) +* (Michael Hawk) +* (Mike O'Connor) +* (Nick Hilliard) +* (Carl Oppedahl) +* (Patrick J. Horgan) +* (Paul Wren) +* (Pierre Beyssac) +* (Philip Hazel) +* (Phil Trubey) +* (Raj Singh) +* (R. Bernstein) +* (Ruediger Volk) +* (Steve Edwards) +* (Michael Shields) +* (Stephen Sprunk) +* (Rob Tanner) +* (Paul A Vixie) +* (William Gianopoulos) +* (Bill Gray) +* (Christophe Wolfhugel) + +Thank you ! + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/misc/FAQ.2of2 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/misc/DynamicUpdate =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/misc/DynamicUpdate (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/misc/DynamicUpdate (revision 109985) @@ -0,0 +1,284 @@ + + + Description of Dynamic Update and T_UNSPEC Code + + + + + Added by Mike Schwartz + University of Washington Computer Science Department + 11/86 + schwartz@cs.washington.edu + + + + +I have incorporated 2 new features into BIND: + 1. Code to allow (unauthenticated) dynamic updates: surrounded by + #ifdef ALLOW_UPDATES + 2. Code to allow data of unspecified type: surrounded by + #ifdef ALLOW_T_UNSPEC + +Note that you can have one or the other or both (or neither) of these +modifications running, by appropriately modifying the makefiles. Also, +the external interface isn't changed (other than being extended), i.e., +a BIND server that allows dynamic updates and/or T_UNSPEC data can +still talk to a 'vanilla' server using the 'vanilla' operations. + +The description that follows is broken into 3 parts: a functional +description of the dynamic update facility, a functional description of +the T_UNSPEC facility, and a discussion of the implementation of +dynamic updates. The implementation description is mostly intended for +those who want to make future enhancements (especially the addition of +a good authentication mechanism). If you make enhancements, I would be +interested in hearing about them. + + + + + + 1. Dynamic Update Facility + +I added this code in conjunction with my research into naming in large +heterogeneous systems. For the purposes of this research, I ignored +security issues. In other words, no authentication/authorization +mechanism exists to control updates. Authentication will hopefully be +addressed at some future point (although probably not by me). In the +mean time, BIND Internet name servers (as opposed to "private" name +server networks operating with their own port numbers, as I use in my +research) should be compiled *without* -DALLOW_UPDATES, so that the +integrity of the Internet name database won't be compromised by this +code. + + +There are 5 different dynamic update interfaces: + UPDATEA - add a resource record + UPDATED - delete a specific resource record + UPDATEDA - delete all named resource records + UPDATEM - modify a specific resource record + UPDATEMA - modify all named resource records + +These all work through the normal resolver interface, i.e., these +interfaces are opcodes, and the data in the buffers passed to +res_mkquery must conform to what is expected for the particular +operation (see the #ifdef ALLOW_UPDATES extensions to nstest.c for +example usage). + +UPDATEM is logically equivalent to an UPDATED followed by an UPDATEA, +except that the updates occur atomically at the primary server (as +usual with Domain servers, secondaries may become temporarily +inconsistent). The difference between UPDATED and UPDATEDA is that the +latter allows you to delete all RRs associated with a name; similarly +for UPDATEM and UPDATEMA. The reason for the UPDATE{D,M}A interfaces +is two-fold: + + 1. Sometimes you want to delete/modify some data, but you know you'll + only have a single RR for that data; in such a case, it's more + convenient to delete/modify the RR by just giving the name; + otherwise, you would have to first look it up, and then + delete/modify it. + + 2. It is sometimes useful to be able to delete/modify multiple RRs + this way, since one can then perform the operation atomically. + Otherwise, one would have to delete/modify the RRs one-by-one. + +One additional point to note about UPDATEMA is that it will return a +success status if there were *zero* or more RRs associated with the given +name (and the RR add succeeds), whereas UPDATEM, UPDATED, and UPDATEDA +will return a success status if there were *one* or more RRs associated +with the given name. The reason for the difference is to handle the +(probably common) case where what you want to do is set a particular +name to contain a single RR, irrespective of whether or not it was +already set. + + + + + 2. T_UNSPEC Facility + +Type T_UNSPEC allows you to store data whose layout BIND doesn't +understand. Data of this type is not marshalled (i.e., converted +between host and network representation, as is done, for example, with +Internet addresses) by BIND, so it is up to the client to make sure +things work out ok w.r.t. heterogeneous data representations. The way +I use this type is to have the client marshal data, store it, retrieve +it, and demarshal it. This way I can store arbitrary data in BIND +without having to add new code for each specific type. + +T_UNSPEC data is dumped in an ASCII-encoded, checksummed format so +that, although it's not human-readable, it at least doesn't fill the +dump file with unprintable characters. + +Type T_UNSPEC is important for my research environment, where +potentially lots of people want to store data in the name service, and +each person's data looks different. Instead of having BIND understand +the format of each of their data types, the clients define marshaling +routines and pass buffers of marshalled data to BIND; BIND never tries +to demarshal the data...it just holds on to it, and gives it back to +the client when the client requests it, and the client must then +demarshal it. + +The Xerox Network System's name service (the Clearinghouse) works this +way. The reason 'vanilla' BIND understands the format of all the data +it holds is probably that BIND is tailored for a very specific +application, and wants to make sure the data it holds makes sense (and, +for some types, BIND needs to take additional action depending on the +data's semantics). For more general purpose name services (like the +Clearinghouse and my usage of BIND), this approach is less tractable. + +See the #ifdef ALLOW_T_UNSPEC extensions to nstest.c for example usage of +this type. + + + + + + + 3. Dynamic Update Implementation Description + +This section is divided into 3 subsections: General Discussion, +Miscellaneous Points, and Known Defects. + + + + + 3.1 General Discussion + +The basic scheme is this: When an update message arrives, a call is +made to InitDynUpdate, which first looks up the SOA record for the zone +the update affects. If this is the primary server for that zone, we do +the update and then update the zone serial number (so that secondaries +will refresh later). If this is a secondary server, we forward the +update to the primary, and if that's successful, we update our copy +afterwards. If it's neither, we refuse the update. (One might think +to try to propagate the update to an authoritative server; I figured +that updates will probably be most likely within an administrative +domain anyway; this could be changed if someone has strong feelings +about it). + +Note that this mechanism disallows updates when the primary is +down, preserving the Domain scheme's consistency requirements, +but making the primary a critical point for updates. This seemed +reasonable to me because + 1. Alternative schemes must deal with potentially complex + situations involving merging of inconsistent secondary + updates + 2. Updates are presumed to be rare relative to read accesses, + so this increased restrictiveness for updates over reads is + probably not critical + +I have placed comments through out the code, so it shouldn't be +too hard to see what I did. The majority of the processing is in +doupdate() and InitDynUpdate(). Also, I added a field to the zone +struct, to keep track of when zones get updated, so that only changed +zones get checkpointed. + + + + + + 3.2 Miscellaneous Points + +I use ns_maint to call zonedump() if the database changes, to +provide a checkpointing mechanism. I use the zone refresh times to +set up ns_maint interrupts if there are either secondaries or +primaries. Hence, if there is a secondary, this interrupt can cause +zoneref (as before), and if there is a primary, this interrupt can +cause doadump. I also checkpoint if needed before shutting down. + +You can force a server to checkpoint any changed zones by sending the +maint signal (SIGALRM) to the process. Otherwise it just checkpoints +during maint. interrupts, or when being shutdown (with SIGTERM). +Sending it the dump signal causes the database to be dumped into the +(single) dump file, but doesn't checkpoint (i.e., update the boot +files). Note that the boot files will be overwritten with checkpoint +files, so if you want to preserve the comments, you should keep copies +of the original boot files separate from the versions that are actually +used. + +I disallow T_SOA updates, for several reasons: + - T_SOA deletes at the primary wont be discovered by the secondaries + until they try to request them at maint time, which will cause + a failure + - the corresponding NS record would have to be deleted at the same + time (atomically) to avoid various problems + - T_SOA updates would have to be done in the right order, or else + the primary and secondaries will be out-of-sync for that zone. +My feeling is that changing the zone topology is a weighty enough thing +to do that it should involve changing the load file and reloading all +affected servers. + +There are alot of places where bind exits due to catastrophic failures +(mainly malloc failures). I don't try to dump the database in these +places because it's probably inconsistent anyway. It's probably better +to depend on the most recent dump. + + + + + + 3.2 Known Defects + +1. I put the following comment in nlookup (db_lookup.c): + + Note: at this point, if np->n_data is NULL, we could be in one + of two situations: Either we have come across a name for which + all the RRs have been (dynamically) deleted, or else we have + come across a name which has no RRs associated with it because + it is just a place holder (e.g., EDU). In the former case, we + would like to delete the namebuf, since it is no longer of use, + but in the latter case we need to hold on to it, so future + lookups that depend on it don't fail. The only way I can see + of doing this is to always leave the namebufs around (although + then the memory usage continues to grow whenever names are + added, and can never shrink back down completely when all their + associated RRs are deleted). + + Thus, there is a problem that the memory usage will keep growing for + the situation described. You might just choose to ignore this + problem (since I don't see any good way out), since things probably + wont grow fast anyway (how many names are created and then deleted + during a single server incarnation, after all?) + + The problem is that one can't delete old namebufs because one would + want to do it from db_update, but db_update calls nlookup to do the + actual work, and can't do it there, since we need to maintain place + holders. One could make db_update not call nlookup, so we know it's + ok to delete the namebuf (since we know the call is part of a delete + call); but then there is code with alot of overlapping functionality + in the 2 routines. + + This also causes another problem: If you create a name and then do + UPDATEDA, all it's RRs get deleted, but the name remains; then, if you + do a lookup on that name later, the name is found in the hash table, + but no RRs are found for it. It then forwards the query to itself (for + some reason), and then somehow decides there is no such domain, and then + returns (with the correct answer, but after going through extra work). + But the name remains, and each time it is looked up, we go through + these same steps. This should be fixed, but I don't have time right + now (and the right answer seems to come back anyway, so it's good + enough for now). + +2. There are 2 problems that crop up when you store data (other than + T_SOA and T_NS records) in the root: + a. Can't get primary to doaxfr RRs other than SOA and NS to + secondary. + b. Upon checkpoint (zonedump), this data sometimes comes out after other + data in the root, so that (since the SOA and NS records have null + names), they will get interpreted as being records under the + other names upon the next boot up. For example, if you have a + T_A record called ABC, the checkpoint may look like: + $ORIGIN . + ABC IN A 128.95.1.3 + 99999999 IN NS UW-BORNEO. + IN SOA UW-BORNEO. SCHWARTZ.CS.WASHINGTON.EDU. + ( 50 3600 300 3600000 3600 ) + Then when booting up the next time, the SOA and NS records get + interpreted as being called "ABC" rather than the null root + name. + +3. The secondary server caches the T_A RR for the primary, and hence when + it tries to ns_forw an update, it won't find the address of the primary + using nslookup unless that T_A RR is *also* stored in the main hashtable + (by putting it in a named.db file as well as the named.ca file). + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/misc/DynamicUpdate ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/misc/style.txt =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/misc/style.txt (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/misc/style.txt (revision 109985) @@ -0,0 +1,172 @@ +Path: vixie!vixie +From: vixie@vix.com (Paul A Vixie) +Newsgroups: comp.protocols.tcp-ip.domains +Subject: Re: Format of DNS files (style question) +Date: 28 Aug 94 03:17:08 +Organization: Vixie Enterprises +Lines: 159 +Distribution: inet +Message-ID: +References: <33onnr$i4u@zombie.ncsc.mil> +NNTP-Posting-Host: office.home.vix.com +In-reply-to: sjr@zombie.ncsc.mil's message of 27 Aug 1994 21:02:51 -0400 + +> (Style) Suggestions for how to layout DNS configuration files (both +> forward and reverse)? + +I've gone back and forth on the question of whether the BOG should include a +section on this topic. I know what I myself prefer, but I'm wary of ramming +my own stylistic preferences down the throat of every BOG reader. But since +you ask :-)... + +Create /var/named. If your system is too old to have a /var, either create +one or use /usr/local/adm/named instead. Put your named.boot in it, and make +/etc/named.boot a symlink to it. If your system doesn't have symlinks, you're +S-O-L (but you knew that). In named.boot, put a "directory" directive that +specifies your actual BIND working directory: + + directory /var/named + +All relative pathnames used in "primary", "secondary", and "cache" directives +will be evaluated relative to this directory. Create two subdirectories, +/var/named/pri and /var/named/sec. Whenever you add a "primary" directive +to your named.boot, use "pri/WHATEVER" as the path name. And then put the +primary zone file into "pri/WHATEVER". Likewise when you add "secondary" +directives, use "sec/WHATEVER" and BIND (really named-xfer) will create the +files in that subdirectory. + +(Variations: (1) make a midlevel directory "zones" and put "pri" and "sec" +into it; (2) if you tend to pick up a lot of secondaries from a few hosts, +group them together in their own subdirectories -- something like +/var/named/zones/uucp if you're a UUCP Project name server.) + +For your forward files, name them after the zone. dec.com becomes +"/var/named/zones/pri/dec.com". For your reverse files, name them after the +network number. 0.1.16.in-addr.arpa becomes "/var/named/zones/pri/16.1.0". + +When creating or maintaining primary zone files, try to use the same SOA +values everywhere, except for the serial number which varies per zone. Put +a $ORIGIN directive at the top of the primary zone file, not because it's +needed (it's not since the default origin is the zone named in the "primary" +directive) but because it make it easier to remember what you're working on +when you have a lot of primary zones. Put some comments up there indicating +contact information for the real owner if you're proxying. Use RCS and put +the "$Id: style.txt,v 8.1 1995/12/22 21:59:52 vixie Exp $" in a ";" comment near the top of the zone file. + +The SOA and other top level information should all be listed together. But +don't put IN on every line, it defaults nicely. For example: + +============== +@ IN SOA gw.home.vix.com. postmaster.vix.com. ( + 1994082501 ; serial + 3600 ; refresh (1 hour) + 1800 ; retry (30 mins) + 604800 ; expire (7 days) + 3600 ) ; minimum (1 hour) + + NS gw.home.vix.com. + NS ns.uu.net. + NS uucp-gw-1.pa.dec.com. + NS uucp-gw-2.pa.dec.com. + + MX 10 gw.home.vix.com. + MX 20 uucp-gw-1.pa.dec.com. + MX 20 uucp-gw-1.pa.dec.com. +============== + +I don't necessarily recommend those SOA values. Not every zone is as volatile +as the example shown. I do recommend that serial number format; it's in date +format with a 2-digit per-day revision number. This format will last us until +2147 A.D. at which point I expect a better solution will have been found :-). +(Note that it would last until 4294 A.D. except that there are some old BINDs +out there that use a signed quantity for representing serial number interally; +I suppose that as long as none of these are still running after 2047 A.D., +that we can use the above serial number format until 4294 A.D., at which point +a better solution will HAVE to be found.) + +You'll note that I use a tab stop for "IN" even though I never again specify +it. This leaves room for names longer than 7 bytes without messing up the +columns. You might also note that I've put the MX priority and destination +in the same tab stop; this is because both are part of the RRdata and both +are very different from MX which is an RRtype. Some folks seem to prefer to +group "MX" and the priority together in one tab stop. While this looks neat +it's very confusing to newcomers and for them it violates the law of least +astonishment. + +If you have a multi-level zone (one which contains names that have dots in +them), you can use additional $ORIGIN statements but I recommend against it +since there is no "back" operator. That is, given the above example you can +add: + +============= +$ORIGIN home +gw A 192.5.5.1 +============= + +The problem with this is that subsequent RR's had better be somewhere under +the "home.vix.com" name or else the $ORIGIN that introduces them will have +to use a fully qualified name. FQDN $ORIGIN's aren't bad and I won't be mad +if you use them. Unqualified ones as shown above are real trouble. I usually +stay away from them and just put the whole name in: + +============= +gw.home A 192.5.5.1 +============= + +In your reverse zones, you're usually in some good luck because the owner name +is usually a single short token or sometimes two. + +============= +$ORIGIN 5.5.192.in-addr.arpa. +@ IN SOA ... + NS ... +1 PTR gw.home.vix.com. +------------- +$ORIGIN 1.16.in-addr.arpa. +@ IN SOA ... + NS ... +2.0 PTR gatekeeper.dec.com. +============= + +It is usually pretty hard to keep your forward and reverse zones in synch. +You can avoid that whole problem by just using "h2n" (see the ORA book, DNS +and BIND, and its sample toolkit, included in the BIND distribution or on +ftp.uu.net (use the QUOTE SITE EXEC INDEX command there to find this -- I +never can remember where it's at). "h2n" and many tools like it can just +read your old /etc/hosts file and churn it into DNS zone files. (May I +recommend contrib/decwrl/mkdb.pl from the BIND distribution?) However, if +you (like me) prefer to edit these things by hand, you need to follow the +simple convention of making all of your holes consistent. If you use +192.5.5.1 and 192.5.5.3 but not (yet) 192.5.5.2, then in your forward file +you will have something like + +============= +... +gw.home A 192.5.5.1 +;avail A 192.5.5.2 +pc.home A 192.5.5.3 +============= + +and in your reverse file you will have something like + +============= +... +1 PTR gw.home.vix.com. +;2 PTR avail +3 PTR pc.home.vix.com. +============= + +This convention will allow you to keep your sanity and make fewer errors. +Any kind of automation (h2n, mkdb, or your own perl/tcl/awk/python tools) +will help you maintain a consistent universe even if it's also a complex +one. Editing by hand doesn't have to be deadly but you MUST take care. + +Anyone who wants to know how to maintain nonleaf zones, i.e., zones which +have few or no hosts in them but have hundreds or thousands of delegations, +should attend Usenix LISA in San Diego and be there for the SENDS talk. +Contact office@usenix.org for conference information. +-- +Paul Vixie +Redwood City, CA +decwrl!vixie!paul + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/misc/style.txt ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/html/logging.html =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/html/logging.html (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/html/logging.html (revision 109985) @@ -0,0 +1,373 @@ + + + + BIND logging Statement + + + +

BIND Configuration File Guide -- logging Statement

+ +
+ +

Syntax

+ +
+logging {
+  [ channel channel_name {
+    ( file path_name
+       [ versions ( number | unlimited ) ]
+       [ size size_spec ]
+     | syslog ( kern | user | mail | daemon | auth | syslog | lpr |
+                news | uucp | cron | authpriv | ftp |
+                local0 | local1 | local2 | local3 |
+                local4 | local5 | local6 | local7 )
+     | null );
+
+    [ severity ( critical | error | warning | notice |
+                 info  | debug [ level ] | dynamic ); ]
+    [ print-category yes_or_no; ]
+    [ print-severity yes_or_no; ]
+    [ print-time yes_or_no; ]
+  }; ]
+
+  [ category category_name {
+    channel_name; [ channel_name; ... ]
+  }; ]
+  ...
+};
+
+ +

Definition and Usage

+ +

The logging statement configures a wide variety of +logging options for the nameserver. Its channel phrase +associates output methods, format options and severity levels with +a name that can then be used with the category phrase to +select how various classes of messages are logged.

+ +

Only one logging statement is used to define as many +channels and categories as are wanted. If there are multiple logging +statements in a configuration, the first defined determines the logging, +and warnings are issued for the others. If there is no logging statement, +the logging configuration will be:

+ +
+    logging {
+        category default { default_syslog; default_debug; };
+        category panic { default_syslog; default_stderr; };
+        category packet { default_debug; };
+        category eventlib { default_debug; };
+    };
+
+ +The logging configuration is established as soon as the +logging statement is parsed. If you want to redirect +messages about processing of the entire configuration file, the +loggingstatement must appear first. Even if you do not +redirect configuration file parsing messages, we recommend +always putting the logging statement first so that this +rule need not be consciously recalled if you ever do want the +parser's messages relocated. + +

The channel phrase

+ +

All log output goes to one or more "channels"; you can make as many +of them as you want.

+ +

Every channel definition must include a clause that says whether +messages selected for the channel go to a file, to a particular syslog +facility, or are discarded. It can optionally also limit the message +severity level that will be accepted by the channel (default is +"info"), and whether to include a named-generated time +stamp, the category name and/or severity level (default is not to +include any).

+ +

The word null as the destination option for the +channel will cause all messages sent to it to be discarded; other +options for the channel are meaningless.

+ +

The file clause can include limitations both on how +large the file is allowed to become, and how many versions of the file +will be saved each time the file is opened. + +

The size option for files is simply a hard ceiling on +log growth. If the file ever exceeds the size, +named will just not write anything more to it until the +file is reopened; exceeding the size does not automatically trigger a +reopen. The default behavior is to not limit the size of the file.

+ +

If you use the version logfile option, +named will retain that many backup versions of the file +by renaming them when opening. For example, if you choose to keep 3 +old versions of the file "lamers.log" then just before it is opened +lamers.log.1 is renamed to lames.log.2, lamers.log.0 is renamed to +lamers.log.1, and lamers.log is renamed to lamers.log.0. No rolled +versions are kept by default; any existing log file is simply +appended. The unlimited keyword is synonymous with +99 in current BIND releases.

+ +

Example usage of the size and versions options: + +

+    channel an_example_level {
+        file "lamers.log" versions 3 size 20m;
+        print-time yes;
+        print-category yes;
+    };
+
+ +

The argument for the syslog clause is a syslog +facility as described in the syslog manual page. How +syslogd will handle messages sent to this facility is +described in the syslog.conf manual page. If you have a +system which uses a very old version of syslog that only +uses two arguments to the openlog() function, this +clause is silently ignored.

+ +

The severity clause works like syslog's +"priorities", except that they can also be used if you are writing +straight to a file rather than using syslog. Messages +which are not at least of the severity level given will not be +selected for the channel; messages of higher severity levels will be +accepted.

+ +

If you are using syslog, the +syslog.conf priorities will also determine what +eventually passes through. For example, defining a channel facility +and severity as daemon and debug but only +logging daemon.warning via syslog.conf will +cause messages of severity info and notice +to be dropped. If the situation were reversed, with +named writing messages of only warning or +higher, syslogd would print all messages it received +from the channel.

+ +

The server can supply extensive debugging information when it is in +debugging mode. If the server's global debug level is greater than +zero, debugging mode will be active. The global debug level is +set either by starting the named server with the "-d" +flag followed by a positive integer, or by sending the running server the +SIGUSR1 signal (for example, by using "ndc trace"). The global debug +level can be set to zero, and debugging mode turned off, by sending +the server the SIGUSR2 signal ("ndc notrace"). All debugging messages +in the server have a debug level, and higher debug levels give more +more detailed output. +Channels that specify a specific debug severity, e.g. + +

+    channel specific_debug_level {
+        file "foo";
+        severity debug 3;
+    };
+
+ +

will get debugging output of level 3 or less any time the +server is in debugging mode, regardless of the global debugging level. +Channels with dynamic severity use the server's global +level to determine what messages to print. + +

If print-time has been turned on, the date and +time will be logged. print-time may be specified for a +syslog channel, but is usually pointless since syslog also prints the +date and time. If print-category is requested, +then the category of the message will be logged as well. Finally, if +print-severity is on, the severity level of the +message will be logged. The print- options may be used +in any combination, and will always be printed in the following order: +time, category, severity. Here is an example where all three +print- options are on: + +

+    28-Apr-1997 15:05:32.863 default: notice: Ready to answer queries.
+
+ +

There are four predefined channels that are used for +default logging as follows. How they are used +used is described in the next section, The category phrase. + +

+    channel default_syslog {
+        syslog daemon;        # send to syslog's daemon facility
+        severity info;        # only send priority info and higher
+    };
+
+    channel default_debug {
+        file "named.run";     # write to named.run in the working directory
+                              # Note: stderr is used instead of "named.run"
+                              # if the server is started with the "-f" option.
+        severity dynamic;     # log at the server's current debug level
+    };
+
+    channel default_stderr {  # writes to stderr
+        file "<stderr>";      # this is illustrative only; there's currently
+                              # no way of specifying an internal file
+                              # descriptor in the configuration language.
+        severity info;        # only send priority info and higher
+    };
+
+    channel null {            
+        null;                 # toss anything sent to this channel
+    };
+
+ +

Once a channel is defined, it cannot be redefined. Thus you cannot +alter the built-in channels directly, but you can modify the default +logging by pointing categories at channels you have defined.

+ +

The category phrase

+ +

There are many categories, so you can send the logs you want to see +wherever you want, without seeing logs you don't want. If you don't specify +a list of channels for a category, log messages in that category will +be sent to the default category instead. If you don't specify +a default category, the following "default default" is used: + +

+    category default { default_syslog; default_debug; };
+
+ +

As an example, let's say you want to log security events to a file, +but you also want keep the default logging behavior. You'd specify the +following: + +

+    channel my_security_channel {
+        file "my_security_file";
+        severity info;
+    };
+    category security { my_security_channel; default_syslog; default_debug; };
+
+ +

To discard all messages in a category, specify the +null channel: + +

+    category lame-servers { null; };
+    category cname { null; };
+
+ +

The following +categories are available:

+ +
+
default +
+The catch-all. Many things still aren't classified into categories, +and they all end up here. Also, if you don't specify any channels for +a category, the default category is used instead. If you do not +define the default category, the following definition is used: +category default { default_syslog; default_debug; }; + +
config +
+High-level configuration file processing. + +
parser +
+Low-level configuration file processing. + +
queries +
+A short log message is generated for every query the server receives. + +
lame-servers +
+Messages like "Lame server on ..." + +
statistics +
+Statistics. + +
panic +
+If the server has to shut itself down due to an internal problem, it +will log the problem in this category as well as in the problem's native +category. If you do not define the panic category, the following definition +is used: category panic { default_syslog; default_stderr; }; + +
update +
+Dynamic updates. + +
update-security +
+Denied dynamic updates due to access controls. + +
ncache +
+Negative caching. + +
xfer-in +
+Zone transfers the server is receiving. + +
xfer-out +
+Zone transfers the server is sending. + +
db +
+All database operations. + +
eventlib +
+Debugging info from the event system. Only one channel may be specified for +this category, and it must be a file channel. If you do not define the +eventlib category, the following definition is used: category eventlib +{ default_debug; }; + +
packet +
+Dumps of packets received and sent. Only one channel may be specified for +this category, and it must be a file channel. If you do not define the +packet category, the following definition is used: category packet +{ default_debug; }; + +
notify +
+The NOTIFY protocol. + +
cname +
+Messages like "... points to a CNAME". + +
security +
+Approved/unapproved requests. + +
os +
+Operating system problems. + +
insist +
+Internal consistency check failures. + +
maintenance +
+Periodic maintenance events. + +
load +
+Zone loading messages. + +
response-checks +
+Messages arising from response checking, such as +"Malformed response ...", "wrong ans. name ...", +"unrelated additional info ...", "invalid RR type ...", and "bad referral ...". + +
+ +
+ +

[ BIND Config. File +| BIND Home +| ISC ]

+ +
+
+Last Updated: $Id: logging.html,v 1.14 2002/07/19 22:44:05 marka Exp $ +
+ + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/html/logging.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/html/options.html =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/html/options.html (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/html/options.html (revision 109985) @@ -0,0 +1,853 @@ + + + + BIND options Statement + + + +

BIND Configuration File Guide -- options Statement

+ +
+ +

Syntax

+ +
+options {
+  [ hostname hostname_string; ]
+  [ version version_string; ]
+  [ directory path_name; ]
+  [ named-xfer path_name; ]
+  [ dump-file path_name; ]
+  [ memstatistics-file path_name; ]
+  [ pid-file path_name; ]
+  [ statistics-file path_name; ]
+  [ auth-nxdomain yes_or_no; ]
+  [ deallocate-on-exit yes_or_no; ]
+  [ dialup yes_or_no; ]
+  [ fake-iquery yes_or_no; ]
+  [ fetch-glue yes_or_no; ]
+  [ has-old-clients yes_or_no; ]
+  [ host-statistics yes_or_no; ]
+  [ host-statistics-max number; ]
+  [ multiple-cnames yes_or_no; ]
+  [ notify ( yes_or_no | explicit ) <; ]
+  [ suppress-initial-notify yes_or_no; ]
+  [ recursion yes_or_no; ]
+  [ rfc2308-type1 yes_or_no; ]
+  [ use-id-pool yes_or_no; ]
+  [ treat-cr-as-space yes_or_no; ]
+  [ also-notify { ip_addr; [ ip_addr; ... ] }; ]
+  [ forward ( only | first ); ]
+  [ forwarders { [ in_addr ; [ in_addr ; ... ] ] }; ]
+  [ check-names ( master | slave | response ) ( warn | fail | ignore); ]
+  [ allow-query { address_match_list }; ]
+  [ allow-transfer { address_match_list }; ]
+  [ allow-recursion { address_match_list }; ]
+  [ blackhole { address_match_list }; ]
+  [ listen-on [ port ip_port ] { address_match_list }; ]
+  [ query-source [ address ( ip_addr | * ) ] [ port ( ip_port | * ) ] ; ]
+  [ lame-ttl number; ]
+  [ max-transfer-time-in number; ]
+  [ max-ncache-ttl number; ]
+  [ min-roots number; ]
+  [ serial-queries number; ]
+  [ transfer-format ( one-answer | many-answers ); ]
+  [ transfers-in  number; ]
+  [ transfers-out number; ]
+  [ transfers-per-ns number; ]
+  [ transfer-source ip_addr; ]
+  [ maintain-ixfr-base yes_or_no; ]
+  [ max-ixfr-log-size number; ]
+  [ coresize size_spec ; ]
+  [ datasize size_spec ; ]
+  [ files size_spec ; ]
+  [ stacksize size_spec ; ]
+  [ cleaning-interval number; ]
+  [ heartbeat-interval number; ]
+  [ interface-interval number; ]
+  [ statistics-interval number; ]
+  [ topology { address_match_list }; ]
+  [ sortlist { address_match_list }; ]
+  [ rrset-order { order_spec ; [ order_spec ; ... ] }; ]
+  [ preferred-glue ( A | AAAA ); ]
+};
+
+
+ +

Definition and Usage

+ +

The options statement sets up global options to be used by +BIND. This statement may appear at only once in a +configuration file; if more than one occurrence is found, the +first occurrence determines the actual options used, +and a warning will be generated. If there is no options statement, +an options block with each option set to its default will be used.

+ +

Server Information

+ +
+
hostname +
+This defaults to the hostname of the machine hosting the nameserver +as found by gethostname(). +Its prime purpose is to be able to identify which of a number of anycast +servers is actually answering your queries by sending a txt +query for hostname.bind in class chaos to the anycast +server and getting back a unique name. +Setting the hostname to a empty string ("") will disable processing of +the queries. + +
version +
+The version the server should report via the ndc command +or via a query of name version.bind in class chaos. +The default is the real version number of the server, but some server +operators prefer the string "surely you must be joking". +Changing the value of this string will not prevent people from identifying +what version you are running. +
+ +

Pathnames

+ +
+
directory +
+The working directory of the server. Any non-absolute +pathnames in the configuration file will be taken as relative to this +directory. The default location for most server output files +(e.g. "named.run") is this directory. If a directory is not +specified, the working directory defaults to ".", the directory from which the +server was started. The directory specified should be an absolute path. + +
named-xfer +
+The pathname to the named-xfer program that the server uses for +inbound zone transfers. If not specified, the default is +system dependent (e.g. "/usr/sbin/named-xfer"). + +
dump-file +
+The pathname of the file the server dumps the database to when it +receives SIGINT signal (ndc dumpdb). If not +specified, the default is "named_dump.db". + +
memstatistics-file +
+The pathname of the file the server writes memory usage statistics to, on exit, +if deallocate-on-exit is yes. If not +specified, the default is "named.memstats". + +
pid-file +
+The pathname of the file the server writes its process ID in. If not +specified, the default is operating system dependent, but is usually +"/var/run/named.pid" or "/etc/named.pid". The pid-file is used by +programs like "ndc" that want to send signals to the running +nameserver. + +
statistics-file +
+The pathname of the file the server appends statistics to when it +receives SIGILL signal (ndc stats). If not +specified, the default is "named.stats". +
+ +

Boolean Options

+ +
+
auth-nxdomain +
+If yes, the AA bit is always set on +NXDOMAIN responses, even if the server is not actually authoritative. +The default is no. Turning auth-nxdomain will +allow older clients that require AA to be set to accept +NXDOMAIN responses to work. + +
deallocate-on-exit +
+If yes, the server will painstakingly deallocate every object it +it allocated, when it exits, and then write a memory usage report to +the memstatistics-file. The default is no, because +it is faster to let the operating system clean up. +deallocate-on-exit is handy for detecting memory leaks. + +
dialup +
+If yes, the server treats all zones as if they are +doing zone transfers across a dial on demand dialup link, which can +be brought up by traffic originating from this server. This has +different effects according to zone type and concentrates the zone +maintenance so that it all happens in a short interval, once every +heartbeat-interval and hopefully during the one call. +It also suppresses some of the normal zone maintainance traffic. +The default is no. The dialup +option may also be specified in the zone statement, in which +case it overrides the options dialup statement. + +

+If the zone is a master zone, the server will send out +NOTIFY request to all the slaves. This will trigger the "zone up to +date checking" in the slave (providing it supports NOTIFY), allowing +the slave to verify the zone while the call us up. + +

+If the zone is a slave or stub zone, the server +will suppress the regular "zone up to date" queries and only perform +them when the heartbeat-interval expires. + +

fake-iquery +
+If yes, the server will simulate the obsolete DNS query type +IQUERY. The default is no. + +
fetch-glue +
+If yes (the default), the server will fetch "glue" resource +records it doesn't have when constructing the additional data section of +a response. fetch-glue no can be used in conjunction with +recursion no to prevent the server's cache from growing or +becoming corrupted (at the cost of requiring more work from the client). + +
has-old-clients +
+Setting the option to yes is equivalent to setting the following +options: auth-nxdomain yes; and rfc2308-type1 no;. +The use of has-old-clients with auth-nxdomain +and rfc2308-type1 is order dependent. + +
host-statistics +
+If yes, statistics are kept for every host that the +the nameserver interacts with. The default is no. Note: +turning on host-statistics can consume huge amounts of memory. + +
host-statistics-max +
+The maximum number of host records that will be kept. When this limit is +reached no new hosts will be added to the host statistics. If the set +to zero then there is no limit set. The default value is zero. + +
maintain-ixfr-base +
+If yes, a transaction log is kept for +Incremental Zone Transfer. The default is no. + +
multiple-cnames +
+If yes, multiple CNAME resource records will be +allowed for a domain name. The default is no. Allowing +multiple CNAME records is against standards and is not recommended. +Multiple CNAME support is available because previous versions of BIND +allowed multiple CNAME records, and these records have been used for load +balancing by a number of sites. + +
notify +
+If yes (the default), DNS NOTIFY messages are sent when a +zone the server is authoritative for changes. The use of NOTIFY +speeds convergence between the master and its slaves. Slave servers +that receive a NOTIFY message, and understand it, will contact the +master server for the zone to see if they need to do a zone transfer. If +they do, they will initiate it immediately. If explicit, +the NOTIFY messages will only be sent to the addresses in the +also-notify list. The notify +option may also be specified in the zone statement, in which +case it overrides the options notify statement. + +
suppress-initial-notify +
+If yes, suppress the initial notify messages when the server +first loads. The default is no. + +
recursion +
+If yes, and a DNS query requests recursion, the +server will attempt to do all the work required to answer the query. +If recursion is not on, the server will return a referral to the +client if it doesn't know the answer. The default is yes. +See also fetch-glue above. + +
rfc2308-type1 +
+If yes, the server will send NS records along with the SOA +record for negative answers from the cache. +You need to set this to no if you have an old BIND +server using you as a forwarder that does not understand negative answers +which contain both SOA and NS records or you have an old version of sendmail. +The correct fix is to upgrade the broken server or sendmail. +The default is no. + +
use-id-pool +
+If yes, the server will keep track of its own outstanding +query ID's to avoid duplication and increase randomness. This will result +in 128KB more memory being consumed by the server. +The default is no. + +
treat-cr-as-space +
+If yes, the server will treat '\r' characters the same way it +treats a ' ' or '\t'. This may be necessary when loading zone files on a +UNIX system that were generated on an NT or DOS machine. The default is no. + +
+ +

Also-Notify

+ +
also-notify +

+Defines a global list of IP addresses that also get sent NOTIFY messages +whenever a fresh copy of the zone is loaded. This helps to ensure that +copies of the zones will quickly converge on ``stealth'' servers. +If an also-notify list is given in a zone +statement, it will override the options also-notify statement. +When a zone notify statement is set to no, +the IP addresses in the global also-notify list will not get +sent NOTIFY messages for that zone. +The default is the empty list (no global notification list). + +

Forwarding

+ +

The forwarding facility can be used to create a large site-wide +cache on a few servers, reducing traffic over links to external +nameservers. It can also be used to allow queries by servers that do +not have direct access to the Internet, but wish to look up exterior +names anyway. Forwarding occurs only on those queries for which the +server is not authoritative and does not have the answer in its cache. + +

+
forward +
+This option is only meaningful if the forwarders list is +not empty. A value of first, the default, causes the +server to query the forwarders first, and if that doesn't answer the +question the server will then look for the answer itself. If +only is specified, the server will only query the +forwarders. + +
forwarders +
+Specifies the IP addresses to be used for forwarding. The default is the +empty list (no forwarding). +
+ +

Forwarding can also be configured on a per-zone basis, allowing for +the global forwarding options to be overridden in a variety of ways. +You can set particular zones to use different forwarders, or have +different forward only/first behavior, or to not forward +at all. See the zone statement +for more information. + +

Future versions of BIND 8 will provide a more powerful forwarding +system. The syntax described above will continue to be supported. + +

Name Checking

+ +

The server can check domain names based upon their expected client contexts. +For example, a domain name used as a hostname can be checked for compliance +with the RFCs defining valid hostnames. + +

Three checking methods are available: + +

+
ignore +
+No checking is done. + +
warn +
+Names are checked against their expected client contexts. Invalid names are +logged, but processing continues normally. + +
fail +
+Names are checked against their expected client contexts. Invalid names are +logged, and the offending data is rejected. +
+ +

The server can check names three areas: master zone files, slave +zone files, and in responses to queries the server has initiated. If +check-names response fail has been specified, and +answering the client's question would require sending an invalid name +to the client, the server will send a REFUSED response code to the +client. + +

The defaults are: + +

+    check-names master fail;
+    check-names slave warn;
+    check-names response ignore;
+
+ +

check-names may also be specified in the +zone +statement, in which case it overrides the options check-names +statement. When used in a zone statement, the area is not +specified (because it can be deduced from the zone type). + +

Access Control

+ +

Access to the server can be restricted based on the IP address of the +requesting system. See +address_match_list for details +on how to specify IP address lists. + +

+
allow-query +
+Specifies which hosts are allowed to ask ordinary questions. +allow-query may also be specified in the +zone statement, in which case it overrides the +options allow-query statement. If not specified, the default is +to allow queries from all hosts. + +
allow-transfer +
+Specifies which hosts are allowed to receive zone transfers from the +server. allow-transfer may also be specified in the +zone statement, in which case it overrides the +options allow-transfer statement. If not specified, the default +is to allow transfers from all hosts. + +
allow-recursion +
+Specifies which hosts are allowed to make recursive queries through this +server. If not specified, the default is to allow recursive queries from +all hosts. + +
blackhole +
+Specifies a list of addresses that the server will not accept queries from +or use to resolve a query. Queries from these addresses will not be +responded to. +
+ +

Interfaces

+ +

The interfaces and ports that the server will answer queries from may +be specified using the listen-on option. listen-on +takes an optional port, and an +address_match_list. The server will +listen on all interfaces allowed by the address match list. If a port is +not specified, port 53 will be used. + +

Multiple listen-on statements are allowed. For example, + +

+    listen-on { 5.6.7.8; };
+    listen-on port 1234 { !1.2.3.4; 1.2/16; };
+
+ +will enable the nameserver on port 53 for the IP address 5.6.7.8, and +on port 1234 of an address on the machine in net 1.2 that is not +1.2.3.4. + +

If no listen-on is specified, the server will listen on port +53 on all interfaces. + +

Query Address

+ +

If the server doesn't know the answer to a question, it will query +other nameservers. query-source specifies the address +and port used for such queries. If address is +* or is omitted, a wildcard IP address +(INADDR_ANY) will be used. If port is +* or is omitted, a random unprivileged port will be used. +The default is + +

+    query-source address * port *;
+
+ +

Note: query-source port applies only to UDP queries, +TCP queries always use a random unprivileged port. + +

Zone Transfers

+ +
+
max-transfer-time-in +
+Inbound zone transfers (named-xfer processes) running +longer than this many minutes will be terminated. The default is 120 +minutes (2 hours). + +
transfer-format +
+The server supports two zone transfer methods. +one-answer uses one DNS message per resource record +transferred. many-answers packs as many resource records +as possible into a message. many-answers is more +efficient, but is only known to be understood by BIND 8.1+ and patched +versions of BIND 4.9.5. The default is one-answer. +transfer-format may be +overridden on a per-server basis by using the server statement. + +
transfers-in +
+The maximum number of inbound zone transfers that can be running +concurrently. The default value is 10. Increasing +transfers-in may speed up the convergence of slave zones, +but it also may increase the load on the local system. + +
transfers-out +
+This option will be used in the future to limit the number of +concurrent outbound zone transfers. It is checked for syntax, but is +otherwise ignored. + +
transfers-per-ns +
+The maximum number of inbound zone transfers (named-xfer +processes) that can be concurrently transferring from a given remote +nameserver. The default value is 2. Increasing +transfers-per-ns may speed up the convergence of slave +zones, but it also may increase the load on the remote nameserver. +transfers-per-ns may be overridden on a per-server basis +by using the transfers phrase of the server +statement. + +
transfer-source +
+transfer-source determines which local address will be bound +to the TCP connection used to fetch all zones transferred inbound by the +server. If not set, it defaults to a system controlled value which will +usually be the address of the interface ``closest to'' the remote end. +This address must appear in the remote end's allow-transfer +option for the zone being transferred, if one is specified. This statement +sets the transfer-source for all zones, but can be overridden +on a per-zone basis by including a transfer-source statement +within the zone block in the configuration file. + +
serial-queries +
+Slave servers will periodically query master servers to find out if zone +serial numbers have changed. Each such query uses a minute amount of the +slave server's network bandwidth, but more importantly each query uses a +small amount of memory in the slave server while waiting for the +master server to respond. The serial-queries option sets the +maximum number of concurrent serial-number queries allowed to be outstanding +at any given time. The default is four (4). +Note: +If a server loads a large (tens or hundreds of thousands) number of slave +zones, this limit should be raised to the high hundreds or low +thousands -- otherwise the slave server may never actually become aware of +zone changes in the master servers. Beware, though, that setting this limit +arbitrarily high can spend a considerable amount of your slave server's +network, CPU, and memory resources. As with all tunable limits, this one +should be changed gently and monitored for its effects. +
+ +

Resource Limits

+ +

The server's usage of many system resources can be limited. Some +operating systems don't support some of the limits. On such systems, +a warning will be issued if the unsupported limit is used. Some +operating systems don't support limiting resources, and on these systems +a cannot set resource limits on this system message will +be logged. + +

Scaled values are allowed when specifying resource limits. For +example, 1G can be used instead of +1073741824 to specify a limit of one gigabyte. +unlimited requests unlimited use, or the maximum +available amount. default uses the limit that was in +force when the server was started. See +size_spec for more details. + +

+
coresize +
+The maximum size of a core dump. The default is default. + +
datasize +
+The maximum amount of data memory the server may use. The default is +default. + +
files +
+The maximum number of files the server may have open concurrently. +The default is unlimited. Note: on some operating +systems the server cannot set an unlimited value and cannot determine +the maximum number of open files the kernel can support. On such +systems, choosing unlimited will cause the server to use +the larger of the rlim_max for RLIMIT_NOFILE +and the value returned by sysconf(_SC_OPEN_MAX). If the +actual kernel limit is larger than this value, use limit +files to specify the limit explicitly. + +
max-ixfr-log-size +
+Limit the size of the transaction log kept for Incremental Zone Transfer. +Default 0 (unlimited). + +
stacksize +
+The maximum amount of stack memory the server may use. The default is +default. +
+ +

Periodic Task Intervals

+ +
+
cleaning-interval +
+The server will remove expired resource records from the cache every +cleaning-interval minutes. The default is 60 minutes. If set +to 0, no periodic cleaning will occur. + +
heartbeat-interval +
+The server will perform zone maintenance tasks for all zones marked +dialup yes whenever this interval expires. +The default is 60 minutes. Reasonable values are up to 1 day (1440 minutes). +If set to 0, no zone maintenance for these zones will occur. +
interface-interval +
+The server will scan the network interface list every +interface-interval minutes. The default is 60 minutes. +If set to 0, interface scanning will only occur when the configuration +file is loaded. After the scan, listeners will be started on any new +interfaces (provided they are allowed by the listen-on +configuration). Listeners on interfaces that have gone away will be +cleaned up. + +
statistics-interval +
+Nameserver statistics will be logged every statistics-interval +minutes. The default is 60. If set to 0, no statistics will be logged. +
+ +

Topology

+ +

All other things being equal, when the server chooses a nameserver +to query from a list of nameservers, it prefers the one that is +topologically closest to itself. The topology statement +takes an address_match_list +and interprets it in a special way. Each top-level list element is +assigned a distance. Non-negated elements get a distance based on +their position in the list, where the closer the match is to the start +of the list, the shorter the distance is between it and the server. A +negated match will be assigned the maximum distance from the server. +If there is no match, the address will get a distance which is further +than any non-negated list element, and closer than any negated +element. For example, + +

+    topology {
+        10/8;
+        !1.2.3/24;
+        { 1.2/16; 3/8; };
+    };
+
+ +

will prefer servers on network 10 the most, followed by hosts on +network 1.2.0.0 (netmask 255.255.0.0) and network 3, with the exception +of hosts on network 1.2.3 (netmask 255.255.255.0), which is preferred least +of all. + +

The default topology is + +

+    topology { localhost; localnets; };
+
+ +

Resource Record sorting

+ +

+When returning multiple RRs, +the nameserver will normally return them in +Round Robin, +i.e. after each request, the first RR is put to the end of the list. +As the order of RRs is not defined, this should not cause any problems. +

+

+The client resolver code should re-arrange the RRs as appropriate, +i.e. using any addresses on the local net in preference to other addresses. +However, not all resolvers can do this, or are not correctly configured. +

+

+When a client is using a local server, the sorting can be performed in the +server, based on the client's address. +This only requires configuring the nameservers, not all the clients. +

+

+The sortlist statement takes an address match list and interprets it even +more specially than the topology statement does. +

+

+Each top level statement in the sortlist must itself be an explicit +address match list with one or two elements. The first element +(which may be an IP address, an IP prefix, an ACL name or nested +address match list) of each top level list is checked against the +source address of the query until a match is found. +

+

+Once the source address of the query has been matched, if the top level +statement contains only one element, the actual primitive element that +matched the source address is used to select the address in the response +to move to the beginning of the response. If the statement is a list +of two elements, the second element is treated like the address +match list in a topology statement. Each top level element is assigned +a distance and the address in the response with the minimum distance is +moved to the beginning of the response. +

+

+In the following example, any queries received from any of the addresses +of the host itself will get responses preferring addresses on any of +the locally connected networks. Next most preferred are addresses on +the 192.168.1/24 network, and after that either the 192.168.2/24 or +192.168.3/24 network with no preference shown between these two networks. +Queries received from a host on the 192.168.1/24 network will prefer +other addresses on that network to the 192.168.2/24 and 192.168.3/24 +networks. Queries received from a host on the 192.168.4/24 or the +192.168.5/24 network will only prefer other addresses on their +directly connected networks. +

+sortlist {
+           { localhost;         // IF   the local host
+             { localnets;       // THEN first fit on the
+               192.168.1/24;    //      following nets
+               { 192,168.2/24; 192.168.3/24; }; }; };
+           { 192.168.1/24;      // IF   on class C 192.168.1
+             { 192.168.1/24;    // THEN use .1, or .2 or .3
+               { 192.168.2/24; 192.168.3/24; }; }; };
+           { 192.168.2/24;      // IF   on class C 192.168.2
+             { 192.168.2/24;    // THEN use .2, or .1 or .3
+               { 192.168.1/24; 192.168.3/24; }; }; };
+           { 192.168.3/24;      // IF   on class C 192.168.3
+             { 192.168.3/24;    // THEN use .3, or .1 or .2
+               { 192.168.1/24; 192.168.2/24; }; }; };
+           { { 192.168.4/24; 192.168.5/24; }; // if .4 or .5, prefer that net
+           };
+};
+
+The following example will give reasonable behaviour for the local host +and hosts on directly connected networks. It is similar to the behavior +of the address sort in BIND 4.9.x. Responses sent to queries from the +local host will favor any of the directly connected networks. Responses +sent to queries from any other hosts on a directly connected network will +prefer addresses on that same network. Responses to other queries will +not be sorted. +
+sortlist {
+            { localhost; localnets; };
+            { localnets; };
+};
+
+ +

+ + +

RRset Ordering

+ +

When multiple records are returned in an answer it may be useful to +configure the order the records are placed into the response. For example the +records for a zone might be configured to always be returned in the order they +are defined in the zone file. Or perhaps a random shuffle of the +records as they are returned is wanted. The rrset-order statement +permits configuration of the ordering made of the records in a multiple record +response. The default, if no ordering is defined, is a cyclic ordering (round +robin). + +

An order_spec is defined as follows: + +

+  [ class class_name ][ type type_name ][ name "FQDN" ] order ordering
+
+ +

If no class is specified, the default is ANY. If no +type is specified, the default is ANY. If no +name is specified, the default is "*". + +

The legal values for ordering are: + +

+
fixed +
Records are returned in the order they are defined in the zone file. + +
random +
Records are returned in some random order. + +
cyclic +
Records are returned in a round-robin order. + +
+ + +

For example: + +

+    rrset-order {
+	class IN type A name "rc.vix.com" order random;
+        order cyclic;
+    };
+
+ +

will cause any responses for type A records in class +IN that have "rc.vix.com" as a suffix, to always be returned in +random order. All other records are returned in cyclic order. + +

If multiple rrset-order statements appear, they are not +combined--the last one applies. + +

If no rrset-order statement is specified, a default one +of: + +

+    rrset-order { class ANY type ANY name "*" order cyclic ; };
+
+ +

is used. + +

Glue Ordering

+ +When running a root nameserver it is sometimes necessary to ensure that +other nameservers that are priming are successful. This requires +that glue A records for at least of the nameservers are returned in +the answer to a priming query. This can be achieved by setting +preferred-glue A; which will add A records before other types +in the additional section. + +

Tuning

+ +
+
lame-ttl +
+Sets the number of seconds to cache a lame server indication. +0 disables caching. Default is 600 (10 minutes). Maximum value is 1800 (30 minutes). +
max-ncache-ttl +
+To reduce network traffic and increase performance the server stores negative +answers. max-ncache-ttl is used to set a maximum retention time +for these answers in the server is seconds. The default max-ncache-ttl is +10800 seconds (3 hours). max-ncache-ttl cannot exceed the +maximum retention time for ordinary (positive) answers (7 days) and will be +silently truncated to 7 days if set to a value which is greater that 7 days. +
min-roots +
+The minimum number of root servers that is required for a +request for the root servers to be accepted. Default 2. +
+
+ +

[ BIND Config. File +| BIND Home +| ISC ]

+ +
+
+Last Updated: $Id: options.html,v 1.49 2002/09/09 00:19:17 marka Exp $ +
+ + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/html/options.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/html/server.html =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/html/server.html (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/html/server.html (revision 109985) @@ -0,0 +1,80 @@ + + + + BIND server Statement + + + +

BIND Configuration File Guide--server Statement

+ +
+ +

Syntax

+ +
+server ip_addr {
+  [ edns yes_or_no; ]
+  [ bogus yes_or_no; ]
+  [ support-ixfr yes_or_no; ]
+  [ transfers number; ]
+  [ transfer-format ( one-answer | many-answers ); ]
+  [ keys { key_id [key_id ... ] }; ]
+};
+
+ +
+ +

Definition and Usage

+ +

The server statement defines the characteristics to be +associated with a remote name server.

+ +

If you discover that a server does not support EDNS you can prevent +named making EDNS queries to it by specifying edns no;. +The default value of edns is yes. + +

If you discover that a server is giving out bad data, marking it as +bogus will prevent further queries to it. The default value of +bogus is no. Marking a server as bogus +will mark all other addresses for that server as bogus when +a match is made when looking up a server's address by name. + +

If the server supports IXFR you can tell named to attempt to perform a +IXFR style zone transfer by specifing support-ixfr yes. +The default value of support-ixfr is no. + +

The server supports two zone transfer methods. The first, +one-answer, uses one DNS message per resource record +transferred. many-answers packs as many resource records +as possible into a message. many-answers is more +efficient, but is only known to be understood by BIND 8.1 and patched +versions of BIND 4.9.5. You can specify which method to use for a +server with the transfer-format option. If +transfer-format is not specified, the transfer-format +specified by the options statement will be used. + +

The transfers will be used in a future release of the server +to limit the number of concurrent in-bound zone transfers from the specified +server. It is checked for syntax but is otherwise ignored. + +

The keys clause is used to identify a +key_id defined by the key statement, to be +used for transaction security when talking to the remote server. +The key statememnt must come before the server +statement that references it. When a request is sent to the remote server, +a request signature will be generated using the key specified here and +appended to the message. A request originating from the remote server is not +required to be signed by this key. + +


+ +

[ BIND Config. File +| BIND Home +| ISC ]

+ +
+
+Last Updated: $Id: server.html,v 1.13 2002/05/24 03:04:51 marka Exp $ +
+ + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/html/server.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/html/docdef.html =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/html/docdef.html (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/html/docdef.html (revision 109985) @@ -0,0 +1,118 @@ + + + + BIND Documentation Definitions + + + +

BIND Configuration File Guide--Documentation Definitions

+ +
+ +

Syntactic Miscellany

+ +

Described below are elements used throughout the BIND configuration +file documentation. Elements which are only associated with one +statement are described only in the section describing that statement. + +

+
acl_name +
+The name of an address match list, +as defined by the acl statement. + +
address_match_list +
+A list of one or more ip_address, ip_prefix +key_id or acl_name elements, as described in the +Address Match Lists section. + +
dotted-decimal +
+One or more integers valued 0 through 255 separated only by dots +("."), such as 123 or 45.67 or +89.123.45.67. + +
domain_name +
+A quoted string which will be used as a DNS name, for example +"my.test.domain". + +
path_name +
+A quoted string which will be used as a pathname, such as +"zones/master/my.test.domain". + +
ip_addr +
+An IP address with exactly four elements in +dotted-decimal notation. + +
ip_port +
+An IP port number. number is limited to 0 +through 65535, with values below 1024 typically restricted to +root-owned processes. In some cases an asterisk (``*'') character +can be used as a placeholder to select a random high-numbered port. + +
ip_prefix +
+An IP network specified in dotted-decimal form, followed by "/" +and then the number of bits in the netmask. E.g. 127/8 is +the network 127.0.0.0 with netmask 255.0.0.0. +1.2.3.0/24 is network 1.2.3.0 with netmask +255.255.255.0. + +
key_id +
+A string representing the name of a shared key, to be used for transaction +security. + +
number +
+A non-negative integer with an entire range limited by the range of a +C language signed integer (2,147,483,647 on a machine with 32 bit +integers). Its acceptable value might further be limited by the +context in which it is used. + +
size_spec +
+A number, the word unlimited, or the word +default. + +

The maximum value of size_spec is that of unsigned long +integers on the machine. unlimited requests unlimited use, or +the maximum available amount. default uses the limit that +was in force when the server was started.

+ +

A number can optionally be followed by a scaling factor: +K or k for kilobytes, M or +m for megabytes, and G or g for +gigabytes, which scale by 1024, 1024*1024, and 1024*1024*1024 +respectively. + +

Integer storage overflow is currently silently ignored during +conversion of scaled values, resulting in values less than intended, +possibly even negative. Using unlimited is the best way +to safely set a really large number.

+ +
yes_or_no +
+Either yes or no. The words +true and false are also accepted, as are the +numbers 1 and 0. + +
+ +
+ +

[ BIND Config. File +| BIND Home +| ISC ]

+ +
+
+Last Updated: $Id: docdef.html,v 1.9 2002/04/02 00:57:47 marka Exp $ +
+ + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/html/docdef.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/html/zone.html =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/html/zone.html (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/html/zone.html (revision 109985) @@ -0,0 +1,244 @@ + + + + BIND zone Statement + + + +

BIND Configuration File Guide--zone Statement

+ +
+ +

Syntax

+ +
+zone domain_name [ ( in | hs | hesiod | chaos ) ] { 
+  type master;
+  file path_name;
+  [ forward ( only | first ); ]
+  [ forwarders { [ ip_addr ; [ ip_addr ; ... ] ] }; ]
+  [ check-names ( warn | fail | ignore ); ]
+  [ allow-update { address_match_list }; ]
+  [ allow-query { address_match_list }; ]
+  [ allow-transfer { address_match_list }; ]
+  [ dialup yes_or_no; ]
+  [ notify (yes_or_no | explicit ); ]
+  [ also-notify { ip_addr; [ ip_addr; ... ] }; ]
+  [ ixfr-base  path_name; ]
+  [ pubkey number number number string; ]
+}; 
+
+zone domain_name [ ( in | hs | hesiod | chaos ) ] { 
+  type ( slave | stub );
+  [ file path_name; ]
+  [ ixfr-base  path_name; ]
+  masters [ port ip_port ] { ip_addr [key key_id]; [ ... ] };
+  [ forward ( only | first ); ]
+  [ forwarders { [ ip_addr ; [ ip_addr ; ... ] ] }; ]
+  [ check-names ( warn | fail | ignore ); ]
+  [ allow-update { address_match_list }; ]
+  [ allow-query { address_match_list }; ]
+  [ allow-transfer { address_match_list }; ]
+  [ transfer-source ip_addr; ]
+  [ dialup yes_or_no; ]
+  [ max-transfer-time-in number; ]
+  [ notify yes_or_no; ]
+  [ also-notify { ip_addr; [ ip_addr; ... ] }; ]
+  [ pubkey number number number string; ]
+};
+
+zone domain_name [ ( in | hs | hesiod | chaos ) ] { 
+  type forward;
+  [ forward ( only | first ); ]
+  [ forwarders { [ ip_addr ; [ ip_addr ; ... ] ] }; ]
+  [ check-names ( warn | fail | ignore ); ]
+};
+
+zone "." [ ( in | hs | hesiod | chaos ) ] { 
+  type hint;
+  file path_name;
+  [ check-names ( warn | fail | ignore ); ]
+};
+
+ +
+ +

Definition and Usage

+ +

Zone Types

+ +
+
master +
+The server has a master copy of the data for the zone and will be able +to provide authoritative answers for it. + + +
slave +
+A slave zone is a replica of a master zone. The +masters list specifies one or more IP addresses that the +slave contacts to update its copy of the zone. If a port +is specified then checks to see if the zone is current and zone transfers +will be done to the port given. If file +is specified, the replica will be written to this file whenever +the zone is changed, and reloaded from this file on a server restart. +Use of +file is recommended, since it often speeds server startup +and eliminates a needless waste of bandwidth. Note that for large numbers +(in the tens or hundreds of thousands) of zones per server, it is best to +use a two level naming scheme for zone file names. For example, a slave +server for the zone vix.com might place the zone contents into +a file called "vi/vix.com" where vi/ is just the +first two letters of the zone name. (Most operating systems behave very +slowly if you put 100K files into a single directory.) + +
stub +
+A stub zone is like a slave zone, except that it replicates +only the NS records of a master zone instead of the entire zone. + +
forward +
+A forward zone is used to +direct all queries in it to other servers. The specification of +options in such a zone will override any global options +declared in the options statement. + +

If either no forwarders statement is present in the +zone or an empty list for forwarders is given, no +forwarding will be done for the zone, cancelling the effects of any +forwarders in the options statement. +Thus if you want to use this +type of zone to change the behavior of the global forward +option, and not the servers used, you also need to respecify the +global forwarders. + +

hint +
+The initial set of root nameservers is specified using a +hint zone. When the server starts up, it uses the root hints +to find a root nameserver and get the most recent list of root nameservers. +
+ +

Note: previous releases of BIND used the term primary for a +master zone, secondary for a slave zone, and cache for +a hint zone.

+ +

Class

+ +

The zone's name may optionally be followed by a class. If a class +is not specified, class in (for "internet"), is assumed. +This is correct for the vast majority of cases. + +

The hesiod class is for an information service from MIT's +Project Athena. It is used to share information about various systems +databases, such as users, groups, printers and so on. More +information can be found at +MIT. +The keyword hs is a synonym for hesiod.

+ +

Another MIT development was CHAOSnet, a LAN protocol created in the +mid-1970s. It is still sometimes seen on LISP stations and other +hardware in the AI community, and zone data for it can be specified +with the +chaos class.

+ +

Options

+ +
+
check-names +
+See Name Checking. + +
allow-query +
+See the description of allow-query in the +Access Control section. Note that +this should in general be more restrictive than the similar global +option of the same name; otherwise, confusing and nonworthwhile delegations +will be returned. + +
allow-update +
+Specifies which hosts are allowed to submit Dynamic DNS updates to the +server. The default is to deny updates from all hosts. + +
allow-transfer +
+See the description of allow-transfer in +the Access Control section. + +
transfer-source +
+transfer-source determines which local address will be bound to +the TCP connection used to fetch this zone. If not set, it defaults to a +system controlled value which will usually be the address of the interface +``closest to'' the remote end. This address must appear in the remote end's +allow-transfer option for this zone if one is specified. + +
ixfr-base +
+ixfr-base +specifies the file name used for IXFR transaction log file. + +
max-transfer-time-in +
+See the description of max-transfer-time-in in +the Zone Transfers section. + +
dialup +
+See the description of dialup in +the Boolean Options section. + +
notify +
+See the description of notify in +the Boolean Options section. + +
also-notify +
+also-notify is only meaningful if notify is +active for this zone. The set of machines that will receive a DNS +NOTIFY message for this zone is made up of all the listed nameservers +for the zone (other than the primary master) plus any IP addresses +specified with also-notify. also-notify is not +meaningful for stub zones. The default is the empty list. + +
forward +
+forward is only meaningful if the zone has a +forwarders list. The only value causes the +lookup to fail after trying the forwarders and getting no +answer, while first would allow a normal lookup to be tried. + +
forwarders +
+The forwarders option in a zone is used to override the +list of global forwarders. If it is not specified in a zone of type +forward, no forwarding is done for the +zone; the global options are not used. + +
pubkey +
+A pubkey represents a public key for this zone. It is needed when this is the +top level authoritative zone served by this server and there is no chain of +trust to a trusted key. It is considered +secure, so that data that it signs will be considered secure. The DNSSEC +flags, protocol, and algorithm are specified, as well as a base-64 encoded +string representing the key. + +
+
+ +

[ BIND Config. File +| BIND Home +| ISC ]

+ +
+
+Last Updated: $Id: zone.html,v 1.26 2002/04/25 05:27:02 marka Exp $ +
+ + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/html/zone.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/html/controls.html =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/html/controls.html (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/html/controls.html (revision 109985) @@ -0,0 +1,75 @@ + + + + BIND controls Statement + + + +

BIND Configuration File Guide--controls Statement

+ +
+ +

Syntax

+ +
+controls {
+  [ inet ip_addr
+    port ip_port
+    allow { address_match_list; }; ]
+  [ unix path_name
+    perm number
+    owner number
+    group number; ]
+};
+
+ +
+ +

Definition and Usage

+ +

The controls statement declares control channels +to be used by system +administrators to affect the operation of the local name server. These +control channels are used by the ndc utility to send commands +to and retrieve non-DNS results from a name server.

+ +

A unix control channel is a FIFO in the file system, +and access to it is +controlled by normal file system permissions. +It is created by named with the specified file mode bits (see +the chmod(1) manual page), user and group owner. +Note that, unlike chmod, the mode bits specified for +perm will normally have a leading 0 so the number +is interpreted as octal. Also note that the user and group +ownership specified as owner and group +must be given as numbers, not names. +It is recommended that the +permissions be restricted to administrative personnel only, or else any +user on the system might be able to manage the local name server.

+ +

On Solaris and SunOS machines the permissions and ownerships are applied +to the containing directory. +This is done because these operating systems +do not honour the permission on the UNIX domain socket. + +

An inet control channel is a TCP/IP socket accessible +to the Internet, created at the specified ip_port on the +specified ip_addr. +Modern telnet clients are capable of speaking directly to these +sockets, and the control protocol is ARPAnet-style text. It is recommended +that 127.0.0.1 be the only ip_addr used, and this only if you +trust all non-privileged users on the local host to manage your name +server.

+ +
+ +

[ BIND Config. File +| BIND Home +| ISC ]

+ +
+
+Last Updated: $Id: controls.html,v 1.5 2001/02/01 04:27:11 marka Exp $ +
+ + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/html/controls.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/html/master.html =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/html/master.html (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/html/master.html (revision 109985) @@ -0,0 +1,166 @@ + + + + Master File Format + + + +

BIND Configuration Guide -- Master File Format

+ +
+ +

+The Master File Format was initially defined in +RFC 1035 +and has subsequently been extended. +

+While the Master File Format is class independent all records in a +Master File must be of the same class. + +

Master File Directives

+

$ORIGIN

+Syntax: $ORIGIN <domain-name> [<comment>] +

+$ORIGIN set the domain name that will be appended to any +unqualified records. +When a zone is first read in there is an implict $ORIGIN +<zone-name>. +The current $ORIGIN is appended to the domain specified in the +$ORIGIN argument if it is not absolute. + +

+$ORIGIN EXAMPLE.
+$ORIGIN MYZONE
+WWW	CNAME	MAIN-SERVER
+
+is equivlent to +
+WWW.MYZONE.EXAMPLE. CNAME MAIN-SERVER.MYZONE.EXAMPLE.
+
+ +

$INCLUDE

+Syntax: $INCLUDE <filename> [<origin>] [<comment>] +

+Read and process the file filename as if it was included into the file at this +point. If origin is specified the file is processed with $ORIGIN +set to that value otherwise the current $ORIGIN is used. +NOTE: The behaviour when <origin> is specified differs from that +described in +RFC 1035. +

+The origin and current domain revert to the values they were prior to the +$INCLUDE once the file has been read. +

$TTL

+Syntax: $TTL <default-ttl> [<comment>] +

+Set the default Time To Live (TTL) for subsequent records with undefined +TTL's. Valid TTL's are of the range 0-2147483647. +

+$TTL is defined in +RFC 2308. +

BIND Master File Extentions

+

$GENERATE

+Syntax: $GENERATE <range> <lhs> <type> <rhs> +[<comment>] +

+$GENERATE is used to create a series of resource records +that only differ from each other by an iterator. $GENERATE +can be used to easily generate the sets of records required to support +sub /24 reverse delegations described in +RFC 2317: Classless IN-ADDR.ARPA delegation. + +

+$ORIGIN 0.0.192.IN-ADDR.ARPA.
+$GENERATE 1-2 0 NS SERVER$.EXAMPLE.
+$GENERATE 1-127 $ CNAME $.0
+
+is equivalent to +
+0.0.0.192.IN-ADDR.ARPA NS SERVER1.EXAMPLE.
+0.0.0.192.IN-ADDR.ARPA NS SERVER2.EXAMPLE.
+1.0.0.192.IN-ADDR.ARPA CNAME 1.0.0.0.192.IN-ADDR.ARPA.
+2.0.0.192.IN-ADDR.ARPA CNAME 2.0.0.0.192.IN-ADDR.ARPA.
+...
+127.0.0.192.IN-ADDR.ARPA CNAME 127.0.0.0.192.IN-ADDR.ARPA.
+
+
+
range
+
+This can be one of two forms: +start-stop +or +start-stop/step. If the first form is +used then step is set to 1. All of start, stop and step must be positive. +
lhs
+
+Lhs describes the owner name of the resource records to be created. +Any single $ symbols within the LHS side are replaced by the iterator value. +To get a $ in the output use \$. If the lhs is not absolute +the current $ORIGIN is appended to the name, when appropriate. +You can also apply an offset to the iterator by using ${offset} where +offset is a decimal value to add to the iterator. +And you can also change the format of the iterator by using a printf +like string. The format is ${offset,width,radix} where offset is as before +(use 0 for no change), width is the minimum field width (always zero padded) +radix is one of d, o, x, or X to change the radix to decimal, octal, hex, or hex +with capital letters. +The default is ${0,1,d}. +For example: ${16,3} will add 16 to the iterator and be replaced by +a 3 digit decimal representation. ${0,2,x} will be replaced by a 2 digit +hex representation. To get a { character inserted into the text +immediately after the iterator, use $\{. +
type
+
+At present the only supported types are A, AAAA, PTR, CNAME and NS. +
rhs
+
+Rhs is the data. It is processed similarly to the lhs. +
+
+

Resource Records

+Syntax: {<domain>|@|<blank>} +[<ttl>] [<class>] <type> <rdata> +[<comment>] +

+All resource records have the same basic syntax. +

+
domain
+
+Specify the domain name for this record. If it is not absolute the +current $ORIGIN is appended. +
@
+
+Use the current $ORIGIN for the domain name for this record. +
blank
+
+Use the last specified domainname. +
ttl
+
+This specifies how long this record will be cached by caching servers. +The valid range is 0-2147483647. +
class
+
+Specify the class of this record. This is usually redundent as the +class of a zone is specfied in the configuration file prior to reading +the zone file. +
type
+
+Specify the type of this record. This describes the contents of the rdata +section. +
rdata
+
+This is the value of the resource record. +
+

Time Values: Alternate Specification format (BIND Enhancement)

+

+Many time values within the MASTER file may be specified in multiples +of weeks, days, hours, minutes and seconds rather than just seconds. +

+The format for this is #w#d#h#m#s. To specify 1 week you would +use 1w or two weeks and 1 hour 2w1h. +

+This format applies to TTL values, and SOA REFRESH, RETRY, EXPIRE and MINIMUM +values. +

+ + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/html/master.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/html/config.html =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/html/config.html (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/html/config.html (revision 109985) @@ -0,0 +1,97 @@ + + + + BIND Configuration File Guide + + + +

BIND Configuration File Guide

+ +
+ +

Overview

+ +

BIND 8 is much more configurable than previous releases of BIND. +There are entirely new areas of configuration, such as access control lists +and categorized logging. Many options that previously applied to all zones +can now be used selectively. These features, plus a consideration of future +configuration needs led to the creation of a new configuration file format. + +

The Configuration File

+ +

Example Configuration

+ +

Statements

+ +

A BIND 8 configuration consists of statements and comments. +Statements end with a semicolon. Many statements contain a block of +substatements, which are also terminated with a semicolon.

+ +

The following statements are supported: +

+
acl +
+defines a named IP address matching list, for access control and other uses + +
include +
+includes a file + +
key +
+specifies key information for use in authentication and authorization + +
logging +
+specifies what the server logs, and where the log messages are sent + +
options +
+controls global server configuration options and sets defaults for other +statements + +
controls +
+declares control channels to be used by the ndc utility + +
server +
+sets certain configuration options on a per-server basis + +
trusted-keys +
+defines DNSSEC keys that are preconfigured into the server and implicitly +trusted + +
zone +
+defines a zone +
+ +

The logging and options statements may only +occur once per configuration. + +

Comments

+ +The BIND 8 comment syntax allows for +comments to appear anywhere that whitespace may appear in a BIND +configuration file. To appeal to programmers of all kinds, they can +be written in C, C++, or shell/perl constructs. + +

Converting from BIND 4.9.x

+ +

BIND 4.9.x configuration files can be converted to the new format by +using src/bin/named/named-bootconf, a shell script that is part of +the BIND 8.2.x source kits. + +


+ +

[ BIND Home +| ISC ]

+ +
+
+Last Updated: $Id: config.html,v 1.11 2000/11/28 20:03:48 cyarnell Exp $ +
+ + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/html/config.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/html/address_list.html =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/html/address_list.html (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/html/address_list.html (revision 109985) @@ -0,0 +1,100 @@ + + + + BIND Address Match Lists + + + +

BIND Configuration File Guide--Address Match Lists

+ +
+ +

Syntax

+ +
+address_match_list    = address_match_element [ address_match_element ... ]
+
+address_match_element = [ "!" ] ( ip_address / ip_prefix / acl_name / "key" key_id / { address_match_list } ) ;
+
+ +
+ +

Definition and Usage

+ +

Address match lists are primarily used to determine access control for +various server operations. They are also used to define priorities +for querying other nameservers and to set the addresses on which +named will listen for queries. +The elements which constitute an address match list can be any +of the following:

+ +
    +
  • an IP address (in dotted-decimal notation),
  • + +
  • an IP prefix (in the '/'-notation),
  • + +
  • a key ID, as defined by the +key statement, or + +
  • the name of an address match list previously defined with +the acl statment, or
  • + +
  • another address_match_list
  • +
+ +

Elements can be negated with a leading exclamation mark ("!"), and +the match list names "any", "none", "localhost" and "localnets" are +predefined. More information on those names can be found in the +description of the acl statement. + +

The addition of the key +clause made the name of this syntactic element something of a +misnomer, since security keys can be used to validate access without +regard to a host or network address. Nonetheless, the term "address +match list" is still used throughout the documentation.

+ +

When a given IP address or prefix is compared to an address match +list, the list is traversed in order until an element matches. The +interpretation of a match depends on whether the list is being used +for access control, defining listen-on ports, or as a +topology, and whether the element was negated.

+ +

When used as an access control list, a non-negated match allows +access and a negated match denies access. If there is no match, +access is denied. The clauses allow-query, +allow-transfer, allow-update and +blackhole all use address match lists like this. +Similarly, the listen-on +option will cause the server to not accept queries on any of the +machine's addresses which do not match the list. + +

When used with the topology clause, a non-negated +match returns a distance based on its position on the list (the closer +the match is to the start of the list, the shorter the distance is +between it and the server). A negated match will be assigned the +maximum distance from the server. If there is no match, the address +will get a distance which is further than any non-negated list +element, and closer than any negated element.

+ +

Because of the first-match aspect of the algorithm, an element that +defines a subset of another element in the list should come before the +broader element, regardless of whether either is negated. For +example, in 1.2.3/24; ! 1.2.3.13; the 1.2.3.13 +element is completely useless, because the algorithm will match +any lookup for 1.2.3.13 to the 1.2.3/24 element. Using +! 1.2.3.13; 1.2.3/24 fixes that problem by +having 1.2.3.13 blocked by the negation but all other 1.2.3.* hosts +fall through. + +


+ +

[ BIND Config. File +| BIND Home +| ISC ]

+ +
+
+Last Updated: $Id: address_list.html,v 1.9 1999/12/03 02:20:42 gson Exp $ +
+ + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/html/address_list.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/html/index.html =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/html/index.html (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/html/index.html (revision 109985) @@ -0,0 +1,65 @@ + + + + BIND Version 8 Online Documentation + + + +

BIND Version 8 Online Documentation

+ +

BIND 8 Highlights

+ +
    +
  • DNS Dynamic Updates +(RFC 2136)
  • +
  • DNS Change Notification +(RFC 1996)
  • +
  • Completely new configuration syntax
  • +
  • Flexible, categorized logging system
  • +
  • IP-address-based access control for queries, zone transfers, and +updates that may be specified on a zone-by-zone basis
  • +
  • More efficient zone transfers
  • +
  • Improved performance for servers with thousands of zones
  • +
  • The server no longer forks for outbound zone transfers
  • +
  • Many bug fixes
  • +
+ +

Configuration File Guide

+ +

Master File Format

+ +

Kits

+ + +

Bug Reports and Comments

+

Send bug reports to +bind-bugs@isc.org. + +

DNS Related Newsgroups

+ + +

The Internet Software Consortium

+ +BIND is supported by the Internet Software Consortium, and +although it is free for use and redistribution and incorporation into +vendor products and export and anything else you can think of, it +costs money to produce. That money comes from ISPs, hardware and +software vendors, companies who make extensive use of the software, +and generally kind hearted folk such as yourself. + +
+
+Last Updated: $Id: index.html,v 1.6 1999/12/28 10:03:40 cyarnell Exp $ +
+ + + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/html/index.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/html/acl.html =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/html/acl.html (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/html/acl.html (revision 109985) @@ -0,0 +1,63 @@ + + + + BIND acl Statement + + + +

BIND Configuration File Guide--acl Statement

+ +
+ +

Syntax

+ +
+acl name {
+  address_match_list
+};
+
+ +
+ +

Definition and Usage

+ +

The acl statement creates a named address match list. +It gets its name from a primary use of address match lists: Access +Control Lists (ACLs).

+ +

Note that an address match list's name must be defined with +acl before it can be used elsewhere; no forward +references are allowed.

+ +The following ACLs are built-in: + +
+
any +
+Allows all hosts. + +
none +
+Denies all hosts. + +
localhost +
+Allows the IP addresses of all interfaces on the system. + +
localnets +
+Allows any host on a network for which the system has an interface. +
+ +
+ +

[ BIND Config. File +| BIND Home +| ISC ]

+ +
+
+Last Updated: $Id: acl.html,v 1.5 1999/09/15 20:28:00 cyarnell Exp $ +
+ + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/html/acl.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/html/comments.html =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/html/comments.html (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/html/comments.html (revision 109985) @@ -0,0 +1,84 @@ + + + + BIND Comment Syntax + + + +

BIND Configuration File Guide--Comment Syntax

+ +
+ +

Syntax

+ +
+/* This is a BIND comment as in C */
+
+// This is a BIND comment as in C++
+
+# This is a BIND comment as in common Unix shells and perl
+
+ +

Definition and Usage

+ +

Comments may appear anywhere that whitespace may appear in a BIND +configuration file.

+ +

C-style comments start with the two characters /* +(slash, star) and end with */ (star, slash). Because +they are completely delimited with these characters, they can be used +to comment only a portion of a line or to span multiple lines.

+ +

C-style comments cannot be nested. For example, the following is +not valid because the entire comment ends with the first +*/: + +

+/* This is the start of a comment.
+   This is still part of the comment.
+/* This is an incorrect attempt at nesting a comment. */
+   This is no longer in any comment. */
+
+ + +

C++-style comments start with the two characters // +(slash, slash) and continue to the end of the physical line. They +cannot be continued across multiple physical lines; to have one +logical comment span multiple lines, each line must use the +// pair. For example: + +

+// This is the start of a comment.  The next line
+// is a new comment, even though it is logically
+// part of the previous comment.
+
+ +

Shell-style (or perl-style, if you prefer) comments start with the +character # (hash or pound or number or octothorpe or +whatever) and continue to the end of the physical line, like C++ +comments.

For example: + +
+# This is the start of a comment.  The next line
+# is a new comment, even though it is logically
+# part of the previous comment.
+
+ +

WARNING: you cannot use the ; +(semicolon) character to start a comment such as you would in a zone +file. The semicolon indicates the end of a configuration statement, +so whatever follows it will be interpreted as the start of the next +statement.

+ +
+ +

[ BIND Config. File +| BIND Home +| ISC ]

+ +
+
+Last Updated: $Id: comments.html,v 1.5 1999/09/15 20:28:00 cyarnell Exp $ +
+ + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/html/comments.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/html/example.html =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/html/example.html (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/html/example.html (revision 109985) @@ -0,0 +1,65 @@ + + + + BIND Configuration File Guide -- Example Config File + + + +

BIND Configuration File Guide -- Example Config File

+ +
+ +
+
+/*
+ * A simple BIND 8 configuration
+ */
+
+logging {
+	category lame-servers { null; };
+	category cname { null; };
+};
+
+options {
+	directory "/var/named";
+};
+
+controls {
+	inet * port 52 allow { localnets; };		// a BAD idea
+	unix "/var/run/ndc" perm 0600 owner 0 group 0;	// the default
+};
+
+zone "isc.org" in {
+	type master;
+	file "master/isc.org";
+};
+
+zone "vix.com" in {
+	type slave;
+	file "slave/vix.com";
+	masters { 10.0.0.53; };
+};
+
+zone "." in {
+	type hint;
+	file "named.cache";
+};
+
+zone "0.0.127.in-addr.arpa" in {
+	type master;
+	notify no;
+	file "master/127.0.0";
+};
+
+ +
+ +

[ BIND Home +| ISC ]

+ +
+
+Last Updated: $Id: example.html,v 1.5 1999/09/15 20:28:01 cyarnell Exp $ +
+ + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/html/example.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/html/include.html =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/html/include.html (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/html/include.html (revision 109985) @@ -0,0 +1,57 @@ + + + + BIND include Statement + + + +

BIND Configuration File Guide--include Statement

+ +
+ +

Syntax

+ +
+include path_name;
+
+ +
+ +

Definition and Usage

+ +

The include statement inserts the specified file at +the point that the include statement is encountered. It +cannot be used within another statement, though, so a line such as +

+acl internal_hosts { include "internal_hosts.acl"; };
+
+is not allowed.

+ +

Use include to break the configuration up into +easily-managed chunks. For example: + +

+include "/etc/security/keys.bind";
+include "/etc/acls.bind";
+
+ +

could be used at the top of a BIND configuration file in order to +include any ACL or key information.

+ +

Be careful not to type +"#include", like you would in a C +program, because "#" is used to start a +comment.

+ +
+ +

[ BIND Config. File +| BIND Home +| ISC ]

+ +
+
+Last Updated: $Id: include.html,v 1.7 1999/09/15 20:28:01 cyarnell Exp $ +
+ + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/html/include.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/html/key.html =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/html/key.html (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/html/key.html (revision 109985) @@ -0,0 +1,57 @@ + + + + BIND key Statement + + + +

BIND Configuration File Guide--key Statement

+ +
+ +

Syntax

+ +
+key key_id {
+  algorithm algorithm_id;
+  secret secret_string;
+};
+
+ +
+ +

Definition and Usage

+ +

The key statement defines a key ID which can be used +in a server statement to +associate an authentication method with a particular name server. + +

A key ID must be created with the key +statement before it can be used in a server +definition or an address match list.

+ +

The algorithm_id is a string that specifies a +security/authentication algorithm. The only supported +algorithm is "hmac-md5". + +

secret_string is the secret to be used by the algorithm, +and is treated as a base-64 encoded string. This may be generated +using dnskeygen or another utility or created manually. + +

The key statement is intended for use in transaction +security. Unless included in a server +statement, it is not used to sign any requests. It is used to verify +requests matching the key_id and algorithm_id, +and sign replies to those requests. +


+ +

[ BIND Config. File +| BIND Home +| ISC ]

+ +
+
+Last Updated: $Id: key.html,v 1.10 1999/09/15 20:28:02 cyarnell Exp $ +
+ + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/html/key.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/doc/html/trusted-keys.html =================================================================== --- vendor/bind/8.3.4/contrib/bind/doc/html/trusted-keys.html (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/doc/html/trusted-keys.html (revision 109985) @@ -0,0 +1,58 @@ + + + + BIND trusted-keys Statement + + + +

BIND Configuration File Guide--trusted-keys Statement

+ +
+ +

Syntax

+ +
+trusted-keys { 
+  [ domain_name number number number string; ]
+};
+
+
+ +
+ +

Definition and Usage

+ +The trusted-keys +statement is for use with DNSSEC-style security, originally specified +in RFC 2065. DNSSEC is meant to +provide three distinct services: key distribution, data origin +authentication, and transaction and request authentication. A +complete description of DNSSEC and its use is beyond the scope of this +document, and readers interested in more information should start with + +RFC 2065 and then continue with the + +Internet Drafts.

+ +

Each trusted key is associated with a domain name. Its attributes are +the non-negative integral flags, protocol, and +algorithm, as well as a base-64 encoded string representing +the key.

+ +A trusted key is added when a public key for a non-authoritative zone is +known, but cannot be securely obtained through DNS. This occurs when +a signed zone is a child of an unsigned zone. Adding the trusted +key here allows data signed by that zone to be considered secure.

+ +
+ +

[ BIND Config. File +| BIND Home +| ISC ]

+ +
+
+Last Updated: $Id: trusted-keys.html,v 1.4 1999/09/15 20:28:02 cyarnell Exp $ +
+ + Property changes on: vendor/bind/8.3.4/contrib/bind/doc/html/trusted-keys.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/inet/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/inet/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/inet/Makefile (revision 109985) @@ -0,0 +1,97 @@ +# Copyright (c) 1996,1999 by Internet Software Consortium +# +# 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. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +# CONSORTIUM 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 +# SOFTWARE. + +# $Id: Makefile,v 8.23 2001/08/14 05:58:05 marka Exp $ + +# these are only appropriate for BSD 4.4 or derivatives, and are used in +# development. normal builds will be done in the top level directory and +# this Makefile will be invoked with a lot of overrides for the following: +SYSTYPE= freebsd +DESTDIR = +DESTLIB = /usr/local/lib +O=o +A=a +CC= cc +LD= ld +SHELL= /bin/sh +CDEBUG= -g -Wall +TOP= ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.${A} +LIBBINDR = ../${TOP}/lib/libbind_r.${A} +CFLAGS= ${CDEBUG} +CPPFLAGS= -I${PORTINCL} -I${INCL} +LD_LIBFLAGS= -x -r +AR= ar cru +RANLIB= ranlib +INSTALL= install +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin +THREADED= threaded + +SRCS= nsap_addr.c inet_addr.c inet_ntop.c inet_pton.c \ + inet_ntoa.c inet_neta.c inet_net_ntop.c inet_net_pton.c \ + inet_cidr_ntop.c inet_cidr_pton.c \ + inet_lnaof.c inet_makeaddr.c inet_netof.c inet_network.c \ + inet_data.c + +OBJS= nsap_addr.${O} inet_addr.${O} inet_ntop.${O} inet_pton.${O} \ + inet_ntoa.${O} inet_neta.${O} inet_net_ntop.${O} inet_net_pton.${O} \ + inet_cidr_ntop.${O} inet_cidr_pton.${O} \ + inet_lnaof.${O} inet_makeaddr.${O} inet_netof.${O} inet_network.${O} \ + inet_data.${O} + +all: ${LIBBIND} + +${LIBBIND}: ${OBJS} + ( cd ${THREADED} ; \ + ${AR} ${LIBBINDR} ${ARPREF} ${OBJS} ${ARSUFF} ; \ + ${RANLIB} ${LIBBINDR} ) + ${AR} ${LIBBIND} ${ARPREF} ${OBJS} ${ARSUFF} + ${RANLIB} ${LIBBIND} + +.c.${O}: + mkdir ${THREADED} 2> /dev/null || test -d ${THREADED} -a -w ${THREADED} + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} ${REENTRANT} -c $*.c \ + -o ${THREADED}/$*.${O} + -${LDS} ${LD} ${LD_LIBFLAGS} ${THREADED}/$*.${O} \ + -o ${THREADED}/$*.out && \ + ${LDS} mv ${THREADED}/$*.out ${THREADED}/$*.${O} + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c + -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} -o $*.out && \ + ${LDS} mv $*.out $*.${O} + +distclean: clean + +clean: FRC + rm -f .depend a.out core ${LIB} tags + rm -f *.${O} *.BAK *.CKP *~ + rm -f ${THREADED}/*.${O} + -if test -d ${THREADED} ; then rmdir ${THREADED}; else true; fi + + +depend: FRC + mkdep -I${INCL} -I${PORTINCL} ${CPPFLAGS} ${SRCS} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +install: + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Property changes on: vendor/bind/8.3.4/contrib/bind/lib/inet/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_addr.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/inet/inet_addr.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/inet/inet_addr.c (revision 109985) @@ -0,0 +1,206 @@ +/* + * Copyright (c) 1983, 1990, 1993 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; +static const char rcsid[] = "$Id: inet_addr.c,v 8.12 2001/05/29 05:48:18 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include + +#include +#include + +#include + +#include "port_after.h" + +/* + * Ascii internet address interpretation routine. + * The value returned is in network order. + */ +u_long +inet_addr(const char *cp) { + struct in_addr val; + + if (inet_aton(cp, &val)) + return (val.s_addr); + return (INADDR_NONE); +} + +/* + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + */ +int +inet_aton(const char *cp, struct in_addr *addr) { + u_long val; + int base, n; + char c; + u_int8_t parts[4]; + u_int8_t *pp = parts; + int digit; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, isdigit=decimal. + */ + if (!isdigit((unsigned char)c)) + return (0); + val = 0; base = 10; digit = 0; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') + base = 16, c = *++cp; + else { + base = 8; + digit = 1 ; + } + } + for (;;) { + if (isascii(c) && isdigit((unsigned char)c)) { + if (base == 8 && (c == '8' || c == '9')) + return (0); + val = (val * base) + (c - '0'); + c = *++cp; + digit = 1; + } else if (base == 16 && isascii(c) && + isxdigit((unsigned char)c)) { + val = (val << 4) | + (c + 10 - (islower((unsigned char)c) ? 'a' : 'A')); + c = *++cp; + digit = 1; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3 || val > 0xff) + return (0); + *pp++ = val; + c = *++cp; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && (!isascii(c) || !isspace((unsigned char)c))) + return (0); + /* + * Did we get a valid digit? + */ + if (!digit) + return (0); + /* + * Concoct the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + switch (n) { + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffff) + return (0); + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + if (addr != NULL) + addr->s_addr = htonl(val); + return (1); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_addr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_cidr_ntop.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/inet/inet_cidr_ntop.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/inet/inet_cidr_ntop.c (revision 109985) @@ -0,0 +1,259 @@ +/* + * Copyright (c) 1998,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_cidr_ntop.c,v 8.7 2001/09/28 05:19:36 marka Exp $"; +#endif + +#include "port_before.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +static char * inet_cidr_ntop_ipv4 __P((const u_char *src, int bits, + char *dst, size_t size)); +static char * inet_cidr_ntop_ipv6 __P((const u_char *src, int bits, + char *dst, size_t size)); + +/* + * char * + * inet_cidr_ntop(af, src, bits, dst, size) + * convert network address from network to presentation format. + * "src"'s size is determined from its "af". + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * 192.5.5.1/28 has a nonzero host part, which means it isn't a network + * as called for by inet_net_ntop() but it can be a host address with + * an included netmask. + * author: + * Paul Vixie (ISC), October 1998 + */ +char * +inet_cidr_ntop(int af, const void *src, int bits, char *dst, size_t size) { + switch (af) { + case AF_INET: + return (inet_cidr_ntop_ipv4(src, bits, dst, size)); + case AF_INET6: + return (inet_cidr_ntop_ipv6(src, bits, dst, size)); + default: + errno = EAFNOSUPPORT; + return (NULL); + } +} + +static int +decoct(const u_char *src, int bytes, char *dst, size_t size) { + char *odst = dst; + char *t; + int b; + + for (b = 1; b <= bytes; b++) { + if (size < sizeof "255.") + return (0); + t = dst; + dst += SPRINTF((dst, "%u", *src++)); + if (b != bytes) { + *dst++ = '.'; + *dst = '\0'; + } + size -= (size_t)(dst - t); + } + return (dst - odst); +} + +/* + * static char * + * inet_cidr_ntop_ipv4(src, bits, dst, size) + * convert IPv4 network address from network to presentation format. + * "src"'s size is determined from its "af". + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0b11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), October 1998 + */ +static char * +inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size) { + char *odst = dst; + size_t len = 4; + size_t b; + size_t bytes; + + if ((bits < -1) || (bits > 32)) { + errno = EINVAL; + return (NULL); + } + + /* Find number of significant bytes in address. */ + if (bits == -1) + len = 4; + else + for (len = 1, b = 1 ; b < 4; b++) + if (*(src + b)) + len = b + 1; + + /* Format whole octets plus nonzero trailing octets. */ + bytes = (((bits <= 0) ? 1 : bits) + 7) / 8; + if (len > bytes) + bytes = len; + b = decoct(src, bytes, dst, size); + if (b == 0) + goto emsgsize; + dst += b; + size -= b; + + if (bits != -1) { + /* Format CIDR /width. */ + if (size < sizeof "/32") + goto emsgsize; + dst += SPRINTF((dst, "/%u", bits)); + } + + return (odst); + + emsgsize: + errno = EMSGSIZE; + return (NULL); +} + +static char * +inet_cidr_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) { + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"]; + char *tp; + struct { int base, len; } best, cur; + u_int words[NS_IN6ADDRSZ / NS_INT16SZ]; + int i; + + if ((bits < -1) || (bits > 128)) { + errno = EINVAL; + return (NULL); + } + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < NS_IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + cur.base = -1; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && (best.len == 6 || + (best.len == 7 && words[7] != 0x0001) || + (best.len == 5 && words[5] == 0xffff))) { + int n; + + if (src[15] || bits == -1 || bits > 120) + n = 4; + else if (src[14] || bits > 112) + n = 3; + else + n = 2; + n = decoct(src+12, n, tp, sizeof tmp - (tp - tmp)); + if (n == 0) { + errno = EMSGSIZE; + return (NULL); + } + tp += strlen(tp); + break; + } + tp += SPRINTF((tp, "%x", words[i])); + } + + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == + (NS_IN6ADDRSZ / NS_INT16SZ)) + *tp++ = ':'; + *tp = '\0'; + + if (bits != -1) + tp += SPRINTF((tp, "/%u", bits)); + + /* + * Check for overflow, copy, and we're done. + */ + if ((size_t)(tp - tmp) > size) { + errno = EMSGSIZE; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_cidr_ntop.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_cidr_pton.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/inet/inet_cidr_pton.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/inet/inet_cidr_pton.c (revision 109985) @@ -0,0 +1,275 @@ +/* + * Copyright (c) 1998,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_cidr_pton.c,v 8.7 2001/09/28 04:21:28 marka Exp $"; +#endif + +#include "port_before.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +static int inet_cidr_pton_ipv4 __P((const char *src, u_char *dst, + int *bits, int ipv6)); +static int inet_cidr_pton_ipv6 __P((const char *src, u_char *dst, + int *bits)); + +static int getbits(const char *, int ipv6); + +/* + * int + * inet_cidr_pton(af, src, dst, *bits) + * convert network address from presentation to network format. + * accepts inet_pton()'s input for this "af" plus trailing "/CIDR". + * "dst" is assumed large enough for its "af". "bits" is set to the + * /CIDR prefix length, which can have defaults (like /32 for IPv4). + * return: + * -1 if an error occurred (inspect errno; ENOENT means bad format). + * 0 if successful conversion occurred. + * note: + * 192.5.5.1/28 has a nonzero host part, which means it isn't a network + * as called for by inet_net_pton() but it can be a host address with + * an included netmask. + * author: + * Paul Vixie (ISC), October 1998 + */ +int +inet_cidr_pton(int af, const char *src, void *dst, int *bits) { + switch (af) { + case AF_INET: + return (inet_cidr_pton_ipv4(src, dst, bits, 0)); + case AF_INET6: + return (inet_cidr_pton_ipv6(src, dst, bits)); + default: + errno = EAFNOSUPPORT; + return (-1); + } +} + +static const char digits[] = "0123456789"; + +static int +inet_cidr_pton_ipv4(const char *src, u_char *dst, int *pbits, int ipv6) { + const u_char *odst = dst; + int n, ch, tmp, bits; + size_t size = 4; + + /* Get the mantissa. */ + while (ch = *src++, (isascii(ch) && isdigit(ch))) { + tmp = 0; + do { + n = strchr(digits, ch) - digits; + INSIST(n >= 0 && n <= 9); + tmp *= 10; + tmp += n; + if (tmp > 255) + goto enoent; + } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch)); + if (size-- == 0) + goto emsgsize; + *dst++ = (u_char) tmp; + if (ch == '\0' || ch == '/') + break; + if (ch != '.') + goto enoent; + } + + /* Get the prefix length if any. */ + bits = -1; + if (ch == '/' && dst > odst) { + bits = getbits(src, ipv6); + if (bits == -2) + goto enoent; + } else if (ch != '\0') + goto enoent; + + /* Prefix length can default to /32 only if all four octets spec'd. */ + if (bits == -1) { + if (dst - odst == 4) + bits = ipv6 ? 128 : 32; + else + goto enoent; + } + + /* If nothing was written to the destination, we found no address. */ + if (dst == odst) + goto enoent; + + /* If prefix length overspecifies mantissa, life is bad. */ + if (((bits - (ipv6 ? 96 : 0)) / 8) > (dst - odst)) + goto enoent; + + /* Extend address to four octets. */ + while (size-- > 0) + *dst++ = 0; + + *pbits = bits; + return (0); + + enoent: + errno = ENOENT; + return (-1); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +static int +inet_cidr_pton_ipv6(const char *src, u_char *dst, int *pbits) { + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + u_int val; + int bits; + + memset((tp = tmp), '\0', NS_IN6ADDRSZ); + endp = tp + NS_IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + bits = -1; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } else if (*src == '\0') { + return (0); + } + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + inet_cidr_pton_ipv4(curtok, tp, &bits, 1) == 0) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + if (ch == '/') { + bits = getbits(src, 1); + if (bits == -2) + goto enoent; + break; + } + goto enoent; + } + if (saw_xdigit) { + if (tp + NS_INT16SZ > endp) + goto emsgsize; + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + if (tp == endp) + goto enoent; + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + + memcpy(dst, tmp, NS_IN6ADDRSZ); + + *pbits = bits; + return (0); + + enoent: + errno = ENOENT; + return (-1); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +int +getbits(const char *src, int ipv6) { + int bits = 0; + char *cp, ch; + + if (*src == '\0') /* syntax */ + return (-2); + do { + ch = *src++; + cp = strchr(digits, ch); + if (cp == NULL) /* syntax */ + return (-2); + bits *= 10; + bits += cp - digits; + if (bits == 0 && *src != '\0') /* no leading zeros */ + return (-2); + if (bits > (ipv6 ? 128 : 32)) /* range error */ + return (-2); + } while (*src != '\0'); + + return (bits); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_cidr_pton.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_data.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/inet/inet_data.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/inet/inet_data.c (revision 109985) @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1995-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: inet_data.c,v 1.2 2001/06/20 22:06:36 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +const struct in6_addr isc_in6addr_any = IN6ADDR_ANY_INIT; +const struct in6_addr isc_in6addr_loopback = IN6ADDR_LOOPBACK_INIT; Property changes on: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_data.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_net_ntop.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/inet/inet_net_ntop.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/inet/inet_net_ntop.c (revision 109985) @@ -0,0 +1,277 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.8 2001/09/27 15:08:36 marka Exp $"; +#endif + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +static char * inet_net_ntop_ipv4 __P((const u_char *src, int bits, + char *dst, size_t size)); +static char * inet_net_ntop_ipv6 __P((const u_char *src, int bits, + char *dst, size_t size)); + +/* + * char * + * inet_net_ntop(af, src, bits, dst, size) + * convert network number from network to presentation format. + * generates CIDR style result always. + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * author: + * Paul Vixie (ISC), July 1996 + */ +char * +inet_net_ntop(af, src, bits, dst, size) + int af; + const void *src; + int bits; + char *dst; + size_t size; +{ + switch (af) { + case AF_INET: + return (inet_net_ntop_ipv4(src, bits, dst, size)); + case AF_INET6: + return (inet_net_ntop_ipv6(src, bits, dst, size)); + default: + errno = EAFNOSUPPORT; + return (NULL); + } +} + +/* + * static char * + * inet_net_ntop_ipv4(src, bits, dst, size) + * convert IPv4 network number from network to presentation format. + * generates CIDR style result always. + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0b11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), July 1996 + */ +static char * +inet_net_ntop_ipv4(src, bits, dst, size) + const u_char *src; + int bits; + char *dst; + size_t size; +{ + char *odst = dst; + char *t; + u_int m; + int b; + + if (bits < 0 || bits > 32) { + errno = EINVAL; + return (NULL); + } + + if (bits == 0) { + if (size < sizeof "0") + goto emsgsize; + *dst++ = '0'; + size--; + *dst = '\0'; + } + + /* Format whole octets. */ + for (b = bits / 8; b > 0; b--) { + if (size <= sizeof "255.") + goto emsgsize; + t = dst; + dst += SPRINTF((dst, "%u", *src++)); + if (b > 1) { + *dst++ = '.'; + *dst = '\0'; + } + size -= (size_t)(dst - t); + } + + /* Format partial octet. */ + b = bits % 8; + if (b > 0) { + if (size <= sizeof ".255") + goto emsgsize; + t = dst; + if (dst != odst) + *dst++ = '.'; + m = ((1 << b) - 1) << (8 - b); + dst += SPRINTF((dst, "%u", *src & m)); + size -= (size_t)(dst - t); + } + + /* Format CIDR /width. */ + if (size <= sizeof "/32") + goto emsgsize; + dst += SPRINTF((dst, "/%u", bits)); + return (odst); + + emsgsize: + errno = EMSGSIZE; + return (NULL); +} + +/* + * static char * + * inet_net_ntop_ipv6(src, bits, fakebits, dst, size) + * convert IPv6 network number from network to presentation format. + * generates CIDR style result always. Picks the shortest representation + * unless the IP is really IPv4. + * always prints specified number of bits (bits). + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0x11110000 in its fourth octet. + * author: + * Vadim Kogan (UCB), June 2001 + * Original version (IPv4) by Paul Vixie (ISC), July 1996 + */ + +static char * +inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) { + u_int m; + int b; + int p; + int zero_s, zero_l, tmp_zero_s, tmp_zero_l; + int i; + int is_ipv4 = 0; + unsigned char inbuf[16]; + char outbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")]; + char *cp; + int words; + u_char *s; + + if (bits < 0 || bits > 128) { + errno = EINVAL; + return (NULL); + } + + cp = outbuf; + + if (bits == 0) { + *cp++ = ':'; + *cp++ = ':'; + *cp = '\0'; + } else { + /* Copy src to private buffer. Zero host part. */ + p = (bits + 7) / 8; + memcpy(inbuf, src, p); + memset(inbuf + p, 0, 16 - p); + b = bits % 8; + if (b != 0) { + m = ~0 << (8 - b); + inbuf[p-1] &= m; + } + + s = inbuf; + + /* how many words need to be displayed in output */ + words = (bits + 15) / 16; + if (words == 1) + words = 2; + + /* Find the longest substring of zero's */ + zero_s = zero_l = tmp_zero_s = tmp_zero_l = 0; + for (i = 0; i < (words * 2); i += 2) { + if ((s[i] | s[i+1]) == 0) { + if (tmp_zero_l == 0) + tmp_zero_s = i / 2; + tmp_zero_l++; + } else { + if (tmp_zero_l && zero_l < tmp_zero_l) { + zero_s = tmp_zero_s; + zero_l = tmp_zero_l; + tmp_zero_l = 0; + } + } + } + + if (tmp_zero_l && zero_l < tmp_zero_l) { + zero_s = tmp_zero_s; + zero_l = tmp_zero_l; + } + + if (zero_l != words && zero_s == 0 && ((zero_l == 6) || + ((zero_l == 5 && s[10] == 0xff && s[11] == 0xff) || + ((zero_l == 7 && s[14] != 0 && s[15] != 1))))) + is_ipv4 = 1; + + /* Format whole words. */ + for (p = 0; p < words; p++) { + if (zero_l != 0 && p >= zero_s && p < zero_s + zero_l) { + /* Time to skip some zeros */ + if (p == zero_s) + *cp++ = ':'; + if (p == words - 1) + *cp++ = ':'; + s++; + s++; + continue; + } + + if (is_ipv4 && p > 5 ) { + *cp++ = (p == 6) ? ':' : '.'; + cp += SPRINTF((cp, "%u", *s++)); + /* we can potentially drop the last octet */ + if (p != 7 || bits > 120) { + *cp++ = '.'; + cp += SPRINTF((cp, "%u", *s++)); + } + } else { + if (cp != outbuf) + *cp++ = ':'; + cp += SPRINTF((cp, "%x", *s * 256 + s[1])); + s += 2; + } + } + } + /* Format CIDR /width. */ + SPRINTF((cp, "/%u", bits)); + if (strlen(outbuf) + 1 > size) + goto emsgsize; + strcpy(dst, outbuf); + + return (dst); + +emsgsize: + errno = EMSGSIZE; + return (NULL); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_net_ntop.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_net_pton.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/inet/inet_net_pton.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/inet/inet_net_pton.c (revision 109985) @@ -0,0 +1,399 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_net_pton.c,v 1.13 2001/09/27 15:08:38 marka Exp $"; +#endif + +#include "port_before.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* + * static int + * inet_net_pton_ipv4(src, dst, size) + * convert IPv4 network number from presentation to network format. + * accepts hex octets, hex strings, decimal octets, and /CIDR. + * "size" is in bytes and describes "dst". + * return: + * number of bits, either imputed classfully or specified with /CIDR, + * or -1 if some failure occurred (check errno). ENOENT means it was + * not an IPv4 network specification. + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0b11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), June 1996 + */ +static int +inet_net_pton_ipv4( const char *src, u_char *dst, size_t size) { + static const char xdigits[] = "0123456789abcdef"; + static const char digits[] = "0123456789"; + int n, ch, tmp = 0, dirty, bits; + const u_char *odst = dst; + + ch = *src++; + if (ch == '0' && (src[0] == 'x' || src[0] == 'X') + && isascii((unsigned char)(src[1])) + && isxdigit((unsigned char)(src[1]))) { + /* Hexadecimal: Eat nybble string. */ + if (size <= 0) + goto emsgsize; + dirty = 0; + src++; /* skip x or X. */ + while ((ch = *src++) != '\0' && isascii(ch) && isxdigit(ch)) { + if (isupper(ch)) + ch = tolower(ch); + n = strchr(xdigits, ch) - xdigits; + INSIST(n >= 0 && n <= 15); + if (dirty == 0) + tmp = n; + else + tmp = (tmp << 4) | n; + if (++dirty == 2) { + if (size-- <= 0) + goto emsgsize; + *dst++ = (u_char) tmp; + dirty = 0; + } + } + if (dirty) { /* Odd trailing nybble? */ + if (size-- <= 0) + goto emsgsize; + *dst++ = (u_char) (tmp << 4); + } + } else if (isascii(ch) && isdigit(ch)) { + /* Decimal: eat dotted digit string. */ + for (;;) { + tmp = 0; + do { + n = strchr(digits, ch) - digits; + INSIST(n >= 0 && n <= 9); + tmp *= 10; + tmp += n; + if (tmp > 255) + goto enoent; + } while ((ch = *src++) != '\0' && + isascii(ch) && isdigit(ch)); + if (size-- <= 0) + goto emsgsize; + *dst++ = (u_char) tmp; + if (ch == '\0' || ch == '/') + break; + if (ch != '.') + goto enoent; + ch = *src++; + if (!isascii(ch) || !isdigit(ch)) + goto enoent; + } + } else + goto enoent; + + bits = -1; + if (ch == '/' && isascii((unsigned char)(src[0])) && + isdigit((unsigned char)(src[0])) && dst > odst) { + /* CIDR width specifier. Nothing can follow it. */ + ch = *src++; /* Skip over the /. */ + bits = 0; + do { + n = strchr(digits, ch) - digits; + INSIST(n >= 0 && n <= 9); + bits *= 10; + bits += n; + } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch)); + if (ch != '\0') + goto enoent; + if (bits > 32) + goto emsgsize; + } + + /* Firey death and destruction unless we prefetched EOS. */ + if (ch != '\0') + goto enoent; + + /* If nothing was written to the destination, we found no address. */ + if (dst == odst) + goto enoent; + /* If no CIDR spec was given, infer width from net class. */ + if (bits == -1) { + if (*odst >= 240) /* Class E */ + bits = 32; + else if (*odst >= 224) /* Class D */ + bits = 4; + else if (*odst >= 192) /* Class C */ + bits = 24; + else if (*odst >= 128) /* Class B */ + bits = 16; + else /* Class A */ + bits = 8; + /* If imputed mask is narrower than specified octets, widen. */ + if (bits >= 8 && bits < ((dst - odst) * 8)) + bits = (dst - odst) * 8; + } + /* Extend network to cover the actual mask. */ + while (bits > ((dst - odst) * 8)) { + if (size-- <= 0) + goto emsgsize; + *dst++ = '\0'; + } + return (bits); + + enoent: + errno = ENOENT; + return (-1); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +static int +getbits(const char *src, int *bitsp) { + static const char digits[] = "0123456789"; + int n; + int val; + char ch; + + val = 0; + n = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + pch = strchr(digits, ch); + if (pch != NULL) { + if (n++ != 0 && val == 0) /* no leading zeros */ + return (0); + val *= 10; + val += (pch - digits); + if (val > 128) /* range */ + return (0); + continue; + } + return (0); + } + if (n == 0) + return (0); + *bitsp = val; + return (1); +} + +static int +getv4(const char *src, u_char *dst, int *bitsp) { + static const char digits[] = "0123456789"; + u_char *odst = dst; + int n; + u_int val; + char ch; + + val = 0; + n = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + pch = strchr(digits, ch); + if (pch != NULL) { + if (n++ != 0 && val == 0) /* no leading zeros */ + return (0); + val *= 10; + val += (pch - digits); + if (val > 255) /* range */ + return (0); + continue; + } + if (ch == '.' || ch == '/') { + if (dst - odst > 3) /* too many octets? */ + return (0); + *dst++ = val; + if (ch == '/') + return (getbits(src, bitsp)); + val = 0; + n = 0; + continue; + } + return (0); + } + if (n == 0) + return (0); + if (dst - odst > 3) /* too many octets? */ + return (0); + *dst++ = val; + return (1); +} + +static int +inet_net_pton_ipv6(const char *src, u_char *dst, size_t size) { + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + u_int val; + int digits; + int bits; + size_t bytes; + int words; + int ipv4; + + memset((tp = tmp), '\0', NS_IN6ADDRSZ); + endp = tp + NS_IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + goto enoent; + curtok = src; + saw_xdigit = 0; + val = 0; + digits = 0; + bits = -1; + ipv4 = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (++digits > 4) + goto enoent; + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + goto enoent; + colonp = tp; + continue; + } else if (*src == '\0') + goto enoent; + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + saw_xdigit = 0; + digits = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + getv4(curtok, tp, &bits) > 0) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + ipv4 = 1; + break; /* '\0' was seen by inet_pton4(). */ + } + if (ch == '/' && getbits(src, &bits) > 0) + break; + goto enoent; + } + if (saw_xdigit) { + if (tp + NS_INT16SZ > endp) + goto enoent; + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + } + if (bits == -1) + bits = 128; + + words = (bits + 15) / 16; + if (words < 2) + words = 2; + if (ipv4) + words = 8; + endp = tmp + 2 * words; + + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + if (tp == endp) + goto enoent; + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + goto enoent; + + bytes = (bits + 7) / 8; + if (bytes > size) + goto emsgsize; + memcpy(dst, tmp, bytes); + return (bits); + + enoent: + errno = ENOENT; + return (-1); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +/* + * int + * inet_net_pton(af, src, dst, size) + * convert network number from presentation to network format. + * accepts hex octets, hex strings, decimal octets, and /CIDR. + * "size" is in bytes and describes "dst". + * return: + * number of bits, either imputed classfully or specified with /CIDR, + * or -1 if some failure occurred (check errno). ENOENT means it was + * not a valid network specification. + * author: + * Paul Vixie (ISC), June 1996 + */ +int +inet_net_pton(int af, const char *src, void *dst, size_t size) { + switch (af) { + case AF_INET: + return (inet_net_pton_ipv4(src, dst, size)); + case AF_INET6: + return (inet_net_pton_ipv6(src, dst, size)); + default: + errno = EAFNOSUPPORT; + return (-1); + } +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_net_pton.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_network.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/inet/inet_network.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/inet/inet_network.c (revision 109985) @@ -0,0 +1,104 @@ +/* + * Copyright (c) 1983, 1993 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_network.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include "port_after.h" + +/* + * Internet network address interpretation routine. + * The library routines call this routine to interpret + * network numbers. + */ +u_long +inet_network(cp) + register const char *cp; +{ + register u_long val, base, n, i; + register char c; + u_long parts[4], *pp = parts; + int digit; + +again: + val = 0; base = 10; digit = 0; + if (*cp == '0') + digit = 1, base = 8, cp++; + if (*cp == 'x' || *cp == 'X') + base = 16, cp++; + while ((c = *cp) != 0) { + if (isdigit((unsigned char)c)) { + if (base == 8 && (c == '8' || c == '9')) + return (INADDR_NONE); + val = (val * base) + (c - '0'); + cp++; + digit = 1; + continue; + } + if (base == 16 && isxdigit((unsigned char)c)) { + val = (val << 4) + + (c + 10 - (islower((unsigned char)c) ? 'a' : 'A')); + cp++; + digit = 1; + continue; + } + break; + } + if (!digit) + return (INADDR_NONE); + if (*cp == '.') { + if (pp >= parts + 4 || val > 0xff) + return (INADDR_NONE); + *pp++ = val, cp++; + goto again; + } + if (*cp && !isspace(*cp&0xff)) + return (INADDR_NONE); + *pp++ = val; + n = pp - parts; + if (n > 4) + return (INADDR_NONE); + for (val = 0, i = 0; i < n; i++) { + val <<= 8; + val |= parts[i] & 0xff; + } + return (val); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_network.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_ntop.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/inet/inet_ntop.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/inet/inet_ntop.c (revision 109985) @@ -0,0 +1,203 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_ntop.c,v 1.11 2001/09/27 15:12:57 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *inet_ntop4 __P((const u_char *src, char *dst, size_t size)); +static const char *inet_ntop6 __P((const u_char *src, char *dst, size_t size)); + +/* char * + * inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +inet_ntop(af, src, dst, size) + int af; + const void *src; + char *dst; + size_t size; +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); + case AF_INET6: + return (inet_ntop6(src, dst, size)); + default: + errno = EAFNOSUPPORT; + return (NULL); + } + /* NOTREACHED */ +} + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(src, dst, size) + const u_char *src; + char *dst; + size_t size; +{ + static const char fmt[] = "%u.%u.%u.%u"; + char tmp[sizeof "255.255.255.255"]; + + if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) >= size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} + +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop6(src, dst, size) + const u_char *src; + char *dst; + size_t size; +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; + struct { int base, len; } best, cur; + u_int words[NS_IN6ADDRSZ / NS_INT16SZ]; + int i; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < NS_IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + cur.base = -1; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && (best.len == 6 || + (best.len == 7 && words[7] != 0x0001) || + (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) + return (NULL); + tp += strlen(tp); + break; + } + tp += SPRINTF((tp, "%x", words[i])); + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == + (NS_IN6ADDRSZ / NS_INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((size_t)(tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_ntop.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_pton.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/inet/inet_pton.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/inet/inet_pton.c (revision 109985) @@ -0,0 +1,222 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_pton.c,v 1.8 2001/07/16 03:22:24 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "port_after.h" + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static int inet_pton4 __P((const char *src, u_char *dst)); +static int inet_pton6 __P((const char *src, u_char *dst)); + +/* int + * inet_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * author: + * Paul Vixie, 1996. + */ +int +inet_pton(af, src, dst) + int af; + const char *src; + void *dst; +{ + switch (af) { + case AF_INET: + return (inet_pton4(src, dst)); + case AF_INET6: + return (inet_pton6(src, dst)); + default: + errno = EAFNOSUPPORT; + return (-1); + } + /* NOTREACHED */ +} + +/* int + * inet_pton4(src, dst) + * like inet_aton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(src, dst) + const char *src; + u_char *dst; +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + u_char tmp[NS_INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr(digits, ch)) != NULL) { + u_int new = *tp * 10 + (pch - digits); + + if (saw_digit && *tp == 0) + return (0); + if (new > 255) + return (0); + *tp = new; + if (!saw_digit) { + if (++octets > 4) + return (0); + saw_digit = 1; + } + } else if (ch == '.' && saw_digit) { + if (octets == 4) + return (0); + *++tp = 0; + saw_digit = 0; + } else + return (0); + } + if (octets < 4) + return (0); + memcpy(dst, tmp, NS_INADDRSZ); + return (1); +} + +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton6(src, dst) + const char *src; + u_char *dst; +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + u_int val; + + memset((tp = tmp), '\0', NS_IN6ADDRSZ); + endp = tp + NS_IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } else if (*src == '\0') { + return (0); + } + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return (0); + } + if (saw_xdigit) { + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + if (tp == endp) + return (0); + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return (0); + memcpy(dst, tmp, NS_IN6ADDRSZ); + return (1); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_pton.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/inet/nsap_addr.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/inet/nsap_addr.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/inet/nsap_addr.c (revision 109985) @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAI! + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANT! + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 TH! + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nsap_addr.c,v 8.12 2001/05/28 07:37:46 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "port_after.h" + +static char +xtob(int c) { + return (c - (((c >= '0') && (c <= '9')) ? '0' : '7')); +} + +u_int +inet_nsap_addr(const char *ascii, u_char *binary, int maxlen) { + u_char c, nib; + u_int len = 0; + + if (ascii[0] != '0' || (ascii[1] != 'x' && ascii[1] != 'X')) + return (0); + ascii += 2; + + while ((c = *ascii++) != '\0' && len < (u_int)maxlen) { + if (c == '.' || c == '+' || c == '/') + continue; + if (!isascii(c)) + return (0); + if (islower(c)) + c = toupper(c); + if (isxdigit(c)) { + nib = xtob(c); + c = *ascii++; + if (c != '\0') { + c = toupper(c); + if (isxdigit(c)) { + *binary++ = (nib << 4) | xtob(c); + len++; + } else + return (0); + } + else + return (0); + } + else + return (0); + } + return (len); +} + +char * +inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii) { + int nib; + int i; + static char tmpbuf[2+255*3]; + char *start; + + if (ascii) + start = ascii; + else { + ascii = tmpbuf; + start = tmpbuf; + } + + *ascii++ = '0'; + *ascii++ = 'x'; + + if (binlen > 255) + binlen = 255; + + for (i = 0; i < binlen; i++) { + nib = *binary >> 4; + *ascii++ = nib + (nib < 10 ? '0' : '7'); + nib = *binary++ & 0x0f; + *ascii++ = nib + (nib < 10 ? '0' : '7'); + if (((i % 2) == 0 && (i + 1) < binlen)) + *ascii++ = '.'; + } + *ascii = '\0'; + return (start); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/inet/nsap_addr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_lnaof.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/inet/inet_lnaof.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/inet/inet_lnaof.c (revision 109985) @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1983, 1993 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_lnaof.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include + +#include "port_after.h" + +/* + * Return the local network address portion of an + * internet address; handles class a/b/c network + * number formats. + */ +u_long +inet_lnaof(in) + struct in_addr in; +{ + register u_long i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return ((i)&IN_CLASSA_HOST); + else if (IN_CLASSB(i)) + return ((i)&IN_CLASSB_HOST); + else + return ((i)&IN_CLASSC_HOST); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_lnaof.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_makeaddr.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/inet/inet_makeaddr.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/inet/inet_makeaddr.c (revision 109985) @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1983, 1993 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_makeaddr.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include + +#include "port_after.h" + +/* + * Formulate an Internet address from network + host. Used in + * building addresses stored in the ifnet structure. + */ +struct in_addr +inet_makeaddr(net, host) + u_long net, host; +{ + u_long addr; + + if (net < 128) + addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST); + else if (net < 65536) + addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST); + else if (net < 16777216L) + addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST); + else + addr = net | host; + addr = htonl(addr); + return (*(struct in_addr *)&addr); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_makeaddr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_neta.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/inet/inet_neta.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/inet/inet_neta.c (revision 109985) @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_neta.c,v 1.6 1999/01/08 19:23:45 vixie Exp $"; +#endif + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* + * char * + * inet_neta(src, dst, size) + * format a u_long network number into presentation format. + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * format of ``src'' is as for inet_network(). + * author: + * Paul Vixie (ISC), July 1996 + */ +char * +inet_neta(src, dst, size) + u_long src; + char *dst; + size_t size; +{ + char *odst = dst; + char *tp; + + while (src & 0xffffffff) { + u_char b = (src & 0xff000000) >> 24; + + src <<= 8; + if (b) { + if (size < sizeof "255.") + goto emsgsize; + tp = dst; + dst += SPRINTF((dst, "%u", b)); + if (src != 0L) { + *dst++ = '.'; + *dst = '\0'; + } + size -= (size_t)(dst - tp); + } + } + if (dst == odst) { + if (size < sizeof "0.0.0.0") + goto emsgsize; + strcpy(dst, "0.0.0.0"); + } + return (odst); + + emsgsize: + errno = EMSGSIZE; + return (NULL); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_neta.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_netof.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/inet/inet_netof.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/inet/inet_netof.c (revision 109985) @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1983, 1993 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_netof.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include + +#include "port_after.h" + +/* + * Return the network number from an internet + * address; handles class a/b/c network #'s. + */ +u_long +inet_netof(in) + struct in_addr in; +{ + register u_long i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); + else if (IN_CLASSB(i)) + return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); + else + return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_netof.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_ntoa.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/inet/inet_ntoa.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/inet/inet_ntoa.c (revision 109985) @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1983, 1993 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_ntoa.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: inet_ntoa.c,v 1.7 1999/05/14 18:16:55 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +/* + * Convert network-format internet address + * to base 256 d.d.d.d representation. + */ +/*const*/ char * +inet_ntoa(struct in_addr in) { + static char ret[18]; + + strcpy(ret, "[inet_ntoa error]"); + (void) inet_ntop(AF_INET, &in, ret, sizeof ret); + return (ret); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/inet/inet_ntoa.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_name.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_name.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_name.c (revision 109985) @@ -0,0 +1,947 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_name.c,v 8.18.4.1 2002/11/14 13:32:08 marka Exp $"; +#endif + +#include "port_before.h" + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +#define NS_TYPE_ELT 0x40 /* EDNS0 extended label type */ +#define DNS_LABELTYPE_BITSTRING 0x41 + +/* Data. */ + +static const char digits[] = "0123456789"; + +static const char digitvalue[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/ + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/ + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/ +}; + +/* Forward. */ + +static int special(int); +static int printable(int); +static int dn_find(const u_char *, const u_char *, + const u_char * const *, + const u_char * const *); +static int encode_bitsring(const char **, const char *, + char **, char **, const char *); +static int labellen(const u_char *); +static int decode_bitstring(const char **, char *, const char *); + +/* Public. */ + +/* + * ns_name_ntop(src, dst, dstsiz) + * Convert an encoded domain name to printable ascii as per RFC1035. + * return: + * Number of bytes written to buffer, or -1 (with errno set) + * notes: + * The root is returned as "." + * All other domains are returned in non absolute form + */ +int +ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) +{ + const u_char *cp; + char *dn, *eom; + u_char c; + u_int n; + int l; + + cp = src; + dn = dst; + eom = dst + dstsiz; + + while ((n = *cp++) != 0) { + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* Some kind of compression pointer. */ + errno = EMSGSIZE; + return (-1); + } + if (dn != dst) { + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '.'; + } + if ((l = labellen(cp - 1)) < 0) { + errno = EMSGSIZE; /* XXX */ + return(-1); + } + if (dn + l >= eom) { + errno = EMSGSIZE; + return (-1); + } + if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) { + int m; + + if (n != DNS_LABELTYPE_BITSTRING) { + /* XXX: labellen should reject this case */ + errno = EINVAL; + return(-1); + } + if ((m = decode_bitstring((const char **)&cp, dn, eom)) < 0) + { + errno = EMSGSIZE; + return(-1); + } + dn += m; + continue; + } + for ((void)NULL; l > 0; l--) { + c = *cp++; + if (special(c)) { + if (dn + 1 >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '\\'; + *dn++ = (char)c; + } else if (!printable(c)) { + if (dn + 3 >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '\\'; + *dn++ = digits[c / 100]; + *dn++ = digits[(c % 100) / 10]; + *dn++ = digits[c % 10]; + } else { + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = (char)c; + } + } + } + if (dn == dst) { + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '.'; + } + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '\0'; + return (dn - dst); +} + +/* + * ns_name_pton(src, dst, dstsiz) + * Convert a ascii string into an encoded domain name as per RFC1035. + * return: + * -1 if it fails + * 1 if string was fully qualified + * 0 is string was not fully qualified + * notes: + * Enforces label and domain length limits. + */ + +int +ns_name_pton(const char *src, u_char *dst, size_t dstsiz) +{ + u_char *label, *bp, *eom; + int c, n, escaped, e = 0; + char *cp; + + escaped = 0; + bp = dst; + eom = dst + dstsiz; + label = bp++; + + while ((c = *src++) != 0) { + if (escaped) { + if (c == '[') { /* start a bit string label */ + if ((cp = strchr(src, ']')) == NULL) { + errno = EINVAL; /* ??? */ + return(-1); + } + if ((e = encode_bitsring(&src, + cp + 2, + (char **)&label, + (char **)&bp, + (const char *)eom)) + != 0) { + errno = e; + return(-1); + } + escaped = 0; + label = bp++; + if ((c = *src++) == 0) + goto done; + else if (c != '.') { + errno = EINVAL; + return(-1); + } + continue; + } + else if ((cp = strchr(digits, c)) != NULL) { + n = (cp - digits) * 100; + if ((c = *src++) == 0 || + (cp = strchr(digits, c)) == NULL) { + errno = EMSGSIZE; + return (-1); + } + n += (cp - digits) * 10; + if ((c = *src++) == 0 || + (cp = strchr(digits, c)) == NULL) { + errno = EMSGSIZE; + return (-1); + } + n += (cp - digits); + if (n > 255) { + errno = EMSGSIZE; + return (-1); + } + c = n; + } + escaped = 0; + } else if (c == '\\') { + escaped = 1; + continue; + } else if (c == '.') { + c = (bp - label - 1); + if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ + errno = EMSGSIZE; + return (-1); + } + if (label >= eom) { + errno = EMSGSIZE; + return (-1); + } + *label = c; + /* Fully qualified ? */ + if (*src == '\0') { + if (c != 0) { + if (bp >= eom) { + errno = EMSGSIZE; + return (-1); + } + *bp++ = '\0'; + } + if ((bp - dst) > MAXCDNAME) { + errno = EMSGSIZE; + return (-1); + } + return (1); + } + if (c == 0 || *src == '.') { + errno = EMSGSIZE; + return (-1); + } + label = bp++; + continue; + } + if (bp >= eom) { + errno = EMSGSIZE; + return (-1); + } + *bp++ = (u_char)c; + } + c = (bp - label - 1); + if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ + errno = EMSGSIZE; + return (-1); + } + done: + if (label >= eom) { + errno = EMSGSIZE; + return (-1); + } + *label = c; + if (c != 0) { + if (bp >= eom) { + errno = EMSGSIZE; + return (-1); + } + *bp++ = 0; + } + if ((bp - dst) > MAXCDNAME) { /* src too big */ + errno = EMSGSIZE; + return (-1); + } + return (0); +} + +/* + * ns_name_ntol(src, dst, dstsiz) + * Convert a network strings labels into all lowercase. + * return: + * Number of bytes written to buffer, or -1 (with errno set) + * notes: + * Enforces label and domain length limits. + */ + +int +ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) +{ + const u_char *cp; + u_char *dn, *eom; + u_char c; + u_int n; + int l; + + cp = src; + dn = dst; + eom = dst + dstsiz; + + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + while ((n = *cp++) != 0) { + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* Some kind of compression pointer. */ + errno = EMSGSIZE; + return (-1); + } + *dn++ = n; + if ((l = labellen(cp - 1)) < 0) { + errno = EMSGSIZE; + return (-1); + } + if (dn + l >= eom) { + errno = EMSGSIZE; + return (-1); + } + for ((void)NULL; l > 0; l--) { + c = *cp++; + if (isupper(c)) + *dn++ = tolower(c); + else + *dn++ = c; + } + } + *dn++ = '\0'; + return (dn - dst); +} + +/* + * ns_name_unpack(msg, eom, src, dst, dstsiz) + * Unpack a domain name from a message, source may be compressed. + * return: + * -1 if it fails, or consumed octets if it succeeds. + */ +int +ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, + u_char *dst, size_t dstsiz) +{ + const u_char *srcp, *dstlim; + u_char *dstp; + int n, len, checked, l; + + len = -1; + checked = 0; + dstp = dst; + srcp = src; + dstlim = dst + dstsiz; + if (srcp < msg || srcp >= eom) { + errno = EMSGSIZE; + return (-1); + } + /* Fetch next label in domain name. */ + while ((n = *srcp++) != 0) { + /* Check for indirection. */ + switch (n & NS_CMPRSFLGS) { + case 0: + case NS_TYPE_ELT: + /* Limit checks. */ + if ((l = labellen(srcp - 1)) < 0) { + errno = EMSGSIZE; + return(-1); + } + if (dstp + l + 1 >= dstlim || srcp + l >= eom) { + errno = EMSGSIZE; + return (-1); + } + checked += l + 1; + *dstp++ = n; + memcpy(dstp, srcp, l); + dstp += l; + srcp += l; + break; + + case NS_CMPRSFLGS: + if (srcp >= eom) { + errno = EMSGSIZE; + return (-1); + } + if (len < 0) + len = srcp - src + 1; + srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); + if (srcp < msg || srcp >= eom) { /* Out of range. */ + errno = EMSGSIZE; + return (-1); + } + checked += 2; + /* + * Check for loops in the compressed name; + * if we've looked at the whole message, + * there must be a loop. + */ + if (checked >= eom - msg) { + errno = EMSGSIZE; + return (-1); + } + break; + + default: + errno = EMSGSIZE; + return (-1); /* flag error */ + } + } + *dstp = '\0'; + if (len < 0) + len = srcp - src; + return (len); +} + +/* + * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr) + * Pack domain name 'domain' into 'comp_dn'. + * return: + * Size of the compressed name, or -1. + * notes: + * 'dnptrs' is an array of pointers to previous compressed names. + * dnptrs[0] is a pointer to the beginning of the message. The array + * ends with NULL. + * 'lastdnptr' is a pointer to the end of the array pointed to + * by 'dnptrs'. + * Side effects: + * The list of pointers in dnptrs is updated for labels inserted into + * the message as we compress the name. If 'dnptr' is NULL, we don't + * try to compress names. If 'lastdnptr' is NULL, we don't update the + * list. + */ +int +ns_name_pack(const u_char *src, u_char *dst, int dstsiz, + const u_char **dnptrs, const u_char **lastdnptr) +{ + u_char *dstp; + const u_char **cpp, **lpp, *eob, *msg; + const u_char *srcp; + int n, l, first = 1; + + srcp = src; + dstp = dst; + eob = dstp + dstsiz; + lpp = cpp = NULL; + if (dnptrs != NULL) { + if ((msg = *dnptrs++) != NULL) { + for (cpp = dnptrs; *cpp != NULL; cpp++) + (void)NULL; + lpp = cpp; /* end of list to search */ + } + } else + msg = NULL; + + /* make sure the domain we are about to add is legal */ + l = 0; + do { + int l0; + + n = *srcp; + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + errno = EMSGSIZE; + return (-1); + } + if ((l0 = labellen(srcp)) < 0) { + errno = EINVAL; + return(-1); + } + l += l0 + 1; + if (l > MAXCDNAME) { + errno = EMSGSIZE; + return (-1); + } + srcp += l0 + 1; + } while (n != 0); + + /* from here on we need to reset compression pointer array on error */ + srcp = src; + do { + /* Look to see if we can use pointers. */ + n = *srcp; + if (n != 0 && msg != NULL) { + l = dn_find(srcp, msg, (const u_char * const *)dnptrs, + (const u_char * const *)lpp); + if (l >= 0) { + if (dstp + 1 >= eob) { + goto cleanup; + } + *dstp++ = (l >> 8) | NS_CMPRSFLGS; + *dstp++ = l % 256; + return (dstp - dst); + } + /* Not found, save it. */ + if (lastdnptr != NULL && cpp < lastdnptr - 1 && + (dstp - msg) < 0x4000 && first) { + *cpp++ = dstp; + *cpp = NULL; + first = 0; + } + } + /* copy label to buffer */ + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* Should not happen. */ + goto cleanup; + } + n = labellen(srcp); + if (dstp + 1 + n >= eob) { + goto cleanup; + } + memcpy(dstp, srcp, n + 1); + srcp += n + 1; + dstp += n + 1; + } while (n != 0); + + if (dstp > eob) { +cleanup: + if (msg != NULL) + *lpp = NULL; + errno = EMSGSIZE; + return (-1); + } + return (dstp - dst); +} + +/* + * ns_name_uncompress(msg, eom, src, dst, dstsiz) + * Expand compressed domain name to presentation format. + * return: + * Number of bytes read out of `src', or -1 (with errno set). + * note: + * Root domain returns as "." not "". + */ +int +ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src, + char *dst, size_t dstsiz) +{ + u_char tmp[NS_MAXCDNAME]; + int n; + + if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) + return (-1); + if (ns_name_ntop(tmp, dst, dstsiz) == -1) + return (-1); + return (n); +} + +/* + * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr) + * Compress a domain name into wire format, using compression pointers. + * return: + * Number of bytes consumed in `dst' or -1 (with errno set). + * notes: + * 'dnptrs' is an array of pointers to previous compressed names. + * dnptrs[0] is a pointer to the beginning of the message. + * The list ends with NULL. 'lastdnptr' is a pointer to the end of the + * array pointed to by 'dnptrs'. Side effect is to update the list of + * pointers for labels inserted into the message as we compress the name. + * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' + * is NULL, we don't update the list. + */ +int +ns_name_compress(const char *src, u_char *dst, size_t dstsiz, + const u_char **dnptrs, const u_char **lastdnptr) +{ + u_char tmp[NS_MAXCDNAME]; + + if (ns_name_pton(src, tmp, sizeof tmp) == -1) + return (-1); + return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr)); +} + +/* + * Reset dnptrs so that there are no active references to pointers at or + * after src. + */ +void +ns_name_rollback(const u_char *src, const u_char **dnptrs, + const u_char **lastdnptr) +{ + while (dnptrs < lastdnptr && *dnptrs != NULL) { + if (*dnptrs >= src) { + *dnptrs = NULL; + break; + } + dnptrs++; + } +} + +/* + * ns_name_skip(ptrptr, eom) + * Advance *ptrptr to skip over the compressed name it points at. + * return: + * 0 on success, -1 (with errno set) on failure. + */ +int +ns_name_skip(const u_char **ptrptr, const u_char *eom) +{ + const u_char *cp; + u_int n; + int l; + + cp = *ptrptr; + while (cp < eom && (n = *cp++) != 0) { + /* Check for indirection. */ + switch (n & NS_CMPRSFLGS) { + case 0: /* normal case, n == len */ + cp += n; + continue; + case NS_TYPE_ELT: /* EDNS0 extended label */ + if ((l = labellen(cp - 1)) < 0) { + errno = EMSGSIZE; /* XXX */ + return(-1); + } + cp += l; + continue; + case NS_CMPRSFLGS: /* indirection */ + cp++; + break; + default: /* illegal type */ + errno = EMSGSIZE; + return (-1); + } + break; + } + if (cp > eom) { + errno = EMSGSIZE; + return (-1); + } + *ptrptr = cp; + return (0); +} + +/* Private. */ + +/* + * special(ch) + * Thinking in noninternationalized USASCII (per the DNS spec), + * is this characted special ("in need of quoting") ? + * return: + * boolean. + */ +static int +special(int ch) { + switch (ch) { + case 0x22: /* '"' */ + case 0x2E: /* '.' */ + case 0x3B: /* ';' */ + case 0x5C: /* '\\' */ + case 0x28: /* '(' */ + case 0x29: /* ')' */ + /* Special modifiers in zone files. */ + case 0x40: /* '@' */ + case 0x24: /* '$' */ + return (1); + default: + return (0); + } +} + +/* + * printable(ch) + * Thinking in noninternationalized USASCII (per the DNS spec), + * is this character visible and not a space when printed ? + * return: + * boolean. + */ +static int +printable(int ch) { + return (ch > 0x20 && ch < 0x7f); +} + +/* + * Thinking in noninternationalized USASCII (per the DNS spec), + * convert this character to lower case if it's upper case. + */ +static int +mklower(int ch) { + if (ch >= 0x41 && ch <= 0x5A) + return (ch + 0x20); + return (ch); +} + +/* + * dn_find(domain, msg, dnptrs, lastdnptr) + * Search for the counted-label name in an array of compressed names. + * return: + * offset from msg if found, or -1. + * notes: + * dnptrs is the pointer to the first name on the list, + * not the pointer to the start of the message. + */ +static int +dn_find(const u_char *domain, const u_char *msg, + const u_char * const *dnptrs, + const u_char * const *lastdnptr) +{ + const u_char *dn, *cp, *sp; + const u_char * const *cpp; + u_int n; + + for (cpp = dnptrs; cpp < lastdnptr; cpp++) { + sp = *cpp; + /* + * terminate search on: + * root label + * compression pointer + * unusable offset + */ + while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 && + (sp - msg) < 0x4000) { + dn = domain; + cp = sp; + while ((n = *cp++) != 0) { + /* + * check for indirection + */ + switch (n & NS_CMPRSFLGS) { + case 0: /* normal case, n == len */ + n = labellen(cp - 1); /* XXX */ + + if (n != *dn++) + goto next; + + for ((void)NULL; n > 0; n--) + if (mklower(*dn++) != + mklower(*cp++)) + goto next; + /* Is next root for both ? */ + if (*dn == '\0' && *cp == '\0') + return (sp - msg); + if (*dn) + continue; + goto next; + case NS_CMPRSFLGS: /* indirection */ + cp = msg + (((n & 0x3f) << 8) | *cp); + break; + + default: /* illegal type */ + errno = EMSGSIZE; + return (-1); + } + } + next: ; + sp += *sp + 1; + } + } + errno = ENOENT; + return (-1); +} + +static int +decode_bitstring(const char **cpp, char *dn, const char *eom) +{ + const char *cp = *cpp; + char *beg = dn, tc; + int b, blen, plen; + + if ((blen = (*cp & 0xff)) == 0) + blen = 256; + plen = (blen + 3) / 4; + plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1); + if (dn + plen >= eom) + return(-1); + + cp++; + dn += SPRINTF((dn, "\\[x")); + for (b = blen; b > 7; b -= 8, cp++) + dn += SPRINTF((dn, "%02x", *cp & 0xff)); + if (b > 4) { + tc = *cp++; + dn += SPRINTF((dn, "%02x", tc & (0xff << (8 - b)))); + } else if (b > 0) { + tc = *cp++; + dn += SPRINTF((dn, "%1x", + ((tc >> 4) & 0x0f) & (0x0f << (4 - b)))); + } + dn += SPRINTF((dn, "/%d]", blen)); + + *cpp = cp; + return(dn - beg); +} + +static int +encode_bitsring(const char **bp, const char *end, char **labelp, + char ** dst, const char *eom) +{ + int afterslash = 0; + const char *cp = *bp; + char *tp, c; + const char *beg_blen; + char *end_blen = NULL; + int value = 0, count = 0, tbcount = 0, blen = 0; + + beg_blen = end_blen = NULL; + + /* a bitstring must contain at least 2 characters */ + if (end - cp < 2) + return(EINVAL); + + /* XXX: currently, only hex strings are supported */ + if (*cp++ != 'x') + return(EINVAL); + if (!isxdigit((*cp) & 0xff)) /* reject '\[x/BLEN]' */ + return(EINVAL); + + for (tp = *dst + 1; cp < end && tp < eom; cp++) { + switch((c = *cp)) { + case ']': /* end of the bitstring */ + if (afterslash) { + if (beg_blen == NULL) + return(EINVAL); + blen = (int)strtol(beg_blen, &end_blen, 10); + if (*end_blen != ']') + return(EINVAL); + } + if (count) + *tp++ = ((value << 4) & 0xff); + cp++; /* skip ']' */ + goto done; + case '/': + afterslash = 1; + break; + default: + if (afterslash) { + if (!isdigit(c&0xff)) + return(EINVAL); + if (beg_blen == NULL) { + + if (c == '0') { + /* blen never begings with 0 */ + return(EINVAL); + } + beg_blen = cp; + } + } else { + if (!isxdigit(c&0xff)) + return(EINVAL); + value <<= 4; + value += digitvalue[(int)c]; + count += 4; + tbcount += 4; + if (tbcount > 256) + return(EINVAL); + if (count == 8) { + *tp++ = value; + count = 0; + } + } + break; + } + } + done: + if (cp >= end || tp >= eom) + return(EMSGSIZE); + + /* + * bit length validation: + * If a is present, the number of digits in the + * MUST be just sufficient to contain the number of bits specified + * by the . If there are insignificant bits in a final + * hexadecimal or octal digit, they MUST be zero. + * RFC 2673, Section 3.2. + */ + if (blen > 0) { + int traillen; + + if (((blen + 3) & ~3) != tbcount) + return(EINVAL); + traillen = tbcount - blen; /* between 0 and 3 */ + if (((value << (8 - traillen)) & 0xff) != 0) + return(EINVAL); + } + else + blen = tbcount; + if (blen == 256) + blen = 0; + + /* encode the type and the significant bit fields */ + **labelp = DNS_LABELTYPE_BITSTRING; + **dst = blen; + + *bp = cp; + *dst = tp; + + return(0); +} + +static int +labellen(const u_char *lp) +{ + int bitlen; + u_char l = *lp; + + if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* should be avoided by the caller */ + return(-1); + } + + if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) { + if (l == DNS_LABELTYPE_BITSTRING) { + if ((bitlen = *(lp + 1)) == 0) + bitlen = 256; + return((bitlen + 7 ) / 8 + 1); + } + return(-1); /* unknwon ELT */ + } + return(l); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_name.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_samedomain.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_samedomain.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_samedomain.c (revision 109985) @@ -0,0 +1,206 @@ +/* + * Copyright (c) 1995,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_samedomain.c,v 8.9.6.2 2002/11/14 22:36:46 marka Exp $"; +#endif + +#include "port_before.h" + +#include +#include +#include +#include + +#include "port_after.h" + +/* + * int + * ns_samedomain(a, b) + * Check whether a name belongs to a domain. + * Inputs: + * a - the domain whose ancestory is being verified + * b - the potential ancestor we're checking against + * Return: + * boolean - is a at or below b? + * Notes: + * Trailing dots are first removed from name and domain. + * Always compare complete subdomains, not only whether the + * domain name is the trailing string of the given name. + * + * "host.foobar.top" lies in "foobar.top" and in "top" and in "" + * but NOT in "bar.top" + */ + +int +ns_samedomain(const char *a, const char *b) { + size_t la, lb; + int diff, i, escaped; + const char *cp; + + la = strlen(a); + lb = strlen(b); + + /* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */ + if (la != 0 && a[la - 1] == '.') { + escaped = 0; + /* Note this loop doesn't get executed if la==1. */ + for (i = la - 2; i >= 0; i--) + if (a[i] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else + break; + if (!escaped) + la--; + } + + /* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */ + if (lb != 0 && b[lb - 1] == '.') { + escaped = 0; + /* note this loop doesn't get executed if lb==1 */ + for (i = lb - 2; i >= 0; i--) + if (b[i] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else + break; + if (!escaped) + lb--; + } + + /* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */ + if (lb == 0) + return (1); + + /* 'b' longer than 'a' means 'a' can't be in 'b'. */ + if (lb > la) + return (0); + + /* 'a' and 'b' being equal at this point indicates sameness. */ + if (lb == la) + return (strncasecmp(a, b, lb) == 0); + + /* Ok, we know la > lb. */ + + diff = la - lb; + + /* + * If 'a' is only 1 character longer than 'b', then it can't be + * a subdomain of 'b' (because of the need for the '.' label + * separator). + */ + if (diff < 2) + return (0); + + /* + * If the character before the last 'lb' characters of 'b' + * isn't '.', then it can't be a match (this lets us avoid + * having "foobar.com" match "bar.com"). + */ + if (a[diff - 1] != '.') + return (0); + + /* + * We're not sure about that '.', however. It could be escaped + * and thus not a really a label separator. + */ + escaped = 0; + for (i = diff - 2; i >= 0; i--) + if (a[i] == '\\') + if (escaped) + escaped = 0; + else + escaped = 1; + else + break; + if (escaped) + return (0); + + /* Now compare aligned trailing substring. */ + cp = a + diff; + return (strncasecmp(cp, b, lb) == 0); +} + +/* + * int + * ns_subdomain(a, b) + * is "a" a subdomain of "b"? + */ +int +ns_subdomain(const char *a, const char *b) { + return (ns_samename(a, b) != 1 && ns_samedomain(a, b)); +} + +/* + * int + * ns_makecanon(src, dst, dstsize) + * make a canonical copy of domain name "src" + * notes: + * foo -> foo. + * foo. -> foo. + * foo.. -> foo. + * foo\. -> foo\.. + * foo\\. -> foo\\. + */ + +int +ns_makecanon(const char *src, char *dst, size_t dstsize) { + size_t n = strlen(src); + + if (n + sizeof "." > dstsize) { + errno = EMSGSIZE; + return (-1); + } + strcpy(dst, src); + while (n > 0 && dst[n - 1] == '.') /* Ends in "." */ + if (n > 1 && dst[n - 2] == '\\' && /* Ends in "\." */ + (n < 2 || dst[n - 3] != '\\')) /* But not "\\." */ + break; + else + dst[--n] = '\0'; + dst[n++] = '.'; + dst[n] = '\0'; + return (0); +} + +/* + * int + * ns_samename(a, b) + * determine whether domain name "a" is the same as domain name "b" + * return: + * -1 on error + * 0 if names differ + * 1 if names are the same + */ + +int +ns_samename(const char *a, const char *b) { + char ta[NS_MAXDNAME], tb[NS_MAXDNAME]; + + if (ns_makecanon(a, ta, sizeof ta) < 0 || + ns_makecanon(b, tb, sizeof tb) < 0) + return (-1); + if (strcasecmp(ta, tb) == 0) + return (1); + else + return (0); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_samedomain.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_sign.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_sign.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_sign.c (revision 109985) @@ -0,0 +1,369 @@ +/* + * Copyright (c) 1999 by Internet Software Consortium, Inc. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_sign.c,v 8.11 2002/04/30 03:43:55 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "port_after.h" + +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eob) { \ + errno = EMSGSIZE; \ + return(NS_TSIG_ERROR_NO_SPACE); \ + } \ + } while (0) + +/* ns_sign + * Parameters: + * msg message to be sent + * msglen input - length of message + * output - length of signed message + * msgsize length of buffer containing message + * error value to put in the error field + * key tsig key used for signing + * querysig (response), the signature in the query + * querysiglen (response), the length of the signature in the query + * sig a buffer to hold the generated signature + * siglen input - length of signature buffer + * output - length of signature + * + * Errors: + * - bad input data (-1) + * - bad key / sign failed (-BADKEY) + * - not enough space (NS_TSIG_ERROR_NO_SPACE) + */ +int +ns_sign(u_char *msg, int *msglen, int msgsize, int error, void *k, + const u_char *querysig, int querysiglen, u_char *sig, int *siglen, + time_t in_timesigned) +{ + return(ns_sign2(msg, msglen, msgsize, error, k, + querysig, querysiglen, sig, siglen, + in_timesigned, NULL, NULL)); +} + +int +ns_sign2(u_char *msg, int *msglen, int msgsize, int error, void *k, + const u_char *querysig, int querysiglen, u_char *sig, int *siglen, + time_t in_timesigned, u_char **dnptrs, u_char **lastdnptr) +{ + HEADER *hp = (HEADER *)msg; + DST_KEY *key = (DST_KEY *)k; + u_char *cp = msg + *msglen, *eob = msg + msgsize; + u_char *lenp; + u_char *name, *alg; + int n; + time_t timesigned; + + dst_init(); + if (msg == NULL || msglen == NULL || sig == NULL || siglen == NULL) + return (-1); + + /* Name. */ + if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) + n = dn_comp(key->dk_key_name, cp, eob - cp, dnptrs, lastdnptr); + else + n = dn_comp("", cp, eob - cp, NULL, NULL); + if (n < 0) + return (NS_TSIG_ERROR_NO_SPACE); + name = cp; + cp += n; + + /* Type, class, ttl, length (not filled in yet). */ + BOUNDS_CHECK(cp, INT16SZ + INT16SZ + INT32SZ + INT16SZ); + PUTSHORT(ns_t_tsig, cp); + PUTSHORT(ns_c_any, cp); + PUTLONG(0, cp); /* TTL */ + lenp = cp; + cp += 2; + + /* Alg. */ + if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) { + if (key->dk_alg != KEY_HMAC_MD5) + return (-ns_r_badkey); + n = dn_comp(NS_TSIG_ALG_HMAC_MD5, cp, eob - cp, NULL, NULL); + } + else + n = dn_comp("", cp, eob - cp, NULL, NULL); + if (n < 0) + return (NS_TSIG_ERROR_NO_SPACE); + alg = cp; + cp += n; + + /* Time. */ + BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); + PUTSHORT(0, cp); + timesigned = time(NULL); + if (error != ns_r_badtime) + PUTLONG(timesigned, cp); + else + PUTLONG(in_timesigned, cp); + PUTSHORT(NS_TSIG_FUDGE, cp); + + /* Compute the signature. */ + if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) { + void *ctx; + u_char buf[MAXDNAME], *cp2; + int n; + + dst_sign_data(SIG_MODE_INIT, key, &ctx, NULL, 0, NULL, 0); + + /* Digest the query signature, if this is a response. */ + if (querysiglen > 0 && querysig != NULL) { + u_int16_t len_n = htons(querysiglen); + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, + (u_char *)&len_n, INT16SZ, NULL, 0); + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, + querysig, querysiglen, NULL, 0); + } + + /* Digest the message. */ + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, msg, *msglen, + NULL, 0); + + /* Digest the key name. */ + n = ns_name_ntol(name, buf, sizeof(buf)); + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); + + /* Digest the class and TTL. */ + cp2 = buf; + PUTSHORT(ns_c_any, cp2); + PUTLONG(0, cp2); + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, cp2-buf, + NULL, 0); + + /* Digest the algorithm. */ + n = ns_name_ntol(alg, buf, sizeof(buf)); + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); + + /* Digest the time signed, fudge, error, and other data */ + cp2 = buf; + PUTSHORT(0, cp2); /* Top 16 bits of time */ + if (error != ns_r_badtime) + PUTLONG(timesigned, cp2); + else + PUTLONG(in_timesigned, cp2); + PUTSHORT(NS_TSIG_FUDGE, cp2); + PUTSHORT(error, cp2); /* Error */ + if (error != ns_r_badtime) + PUTSHORT(0, cp2); /* Other data length */ + else { + PUTSHORT(INT16SZ+INT32SZ, cp2); /* Other data length */ + PUTSHORT(0, cp2); /* Top 16 bits of time */ + PUTLONG(timesigned, cp2); + } + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, cp2-buf, + NULL, 0); + + n = dst_sign_data(SIG_MODE_FINAL, key, &ctx, NULL, 0, + sig, *siglen); + if (n < 0) + return (-ns_r_badkey); + *siglen = n; + } else + *siglen = 0; + + /* Add the signature. */ + BOUNDS_CHECK(cp, INT16SZ + (*siglen)); + PUTSHORT(*siglen, cp); + memcpy(cp, sig, *siglen); + cp += (*siglen); + + /* The original message ID & error. */ + BOUNDS_CHECK(cp, INT16SZ + INT16SZ); + PUTSHORT(ntohs(hp->id), cp); /* already in network order */ + PUTSHORT(error, cp); + + /* Other data. */ + BOUNDS_CHECK(cp, INT16SZ); + if (error != ns_r_badtime) + PUTSHORT(0, cp); /* Other data length */ + else { + PUTSHORT(INT16SZ+INT32SZ, cp); /* Other data length */ + BOUNDS_CHECK(cp, INT32SZ+INT16SZ); + PUTSHORT(0, cp); /* Top 16 bits of time */ + PUTLONG(timesigned, cp); + } + + /* Go back and fill in the length. */ + PUTSHORT(cp - lenp - INT16SZ, lenp); + + hp->arcount = htons(ntohs(hp->arcount) + 1); + *msglen = (cp - msg); + return (0); +} + +int +ns_sign_tcp_init(void *k, const u_char *querysig, int querysiglen, + ns_tcp_tsig_state *state) +{ + dst_init(); + if (state == NULL || k == NULL || querysig == NULL || querysiglen < 0) + return (-1); + state->counter = -1; + state->key = k; + if (state->key->dk_alg != KEY_HMAC_MD5) + return (-ns_r_badkey); + if (querysiglen > (int)sizeof(state->sig)) + return (-1); + memcpy(state->sig, querysig, querysiglen); + state->siglen = querysiglen; + return (0); +} + +int +ns_sign_tcp(u_char *msg, int *msglen, int msgsize, int error, + ns_tcp_tsig_state *state, int done) +{ + return (ns_sign_tcp2(msg, msglen, msgsize, error, state, + done, NULL, NULL)); +} + +int +ns_sign_tcp2(u_char *msg, int *msglen, int msgsize, int error, + ns_tcp_tsig_state *state, int done, + u_char **dnptrs, u_char **lastdnptr) +{ + u_char *cp, *eob, *lenp; + u_char buf[MAXDNAME], *cp2; + HEADER *hp = (HEADER *)msg; + time_t timesigned; + int n; + + if (msg == NULL || msglen == NULL || state == NULL) + return (-1); + + state->counter++; + if (state->counter == 0) + return (ns_sign2(msg, msglen, msgsize, error, state->key, + state->sig, state->siglen, + state->sig, &state->siglen, 0, + dnptrs, lastdnptr)); + + if (state->siglen > 0) { + u_int16_t siglen_n = htons(state->siglen); + dst_sign_data(SIG_MODE_INIT, state->key, &state->ctx, + NULL, 0, NULL, 0); + dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, + (u_char *)&siglen_n, INT16SZ, NULL, 0); + dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, + state->sig, state->siglen, NULL, 0); + state->siglen = 0; + } + + dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, msg, *msglen, + NULL, 0); + + if (done == 0 && (state->counter % 100 != 0)) + return (0); + + cp = msg + *msglen; + eob = msg + msgsize; + + /* Name. */ + n = dn_comp(state->key->dk_key_name, cp, eob - cp, dnptrs, lastdnptr); + if (n < 0) + return (NS_TSIG_ERROR_NO_SPACE); + cp += n; + + /* Type, class, ttl, length (not filled in yet). */ + BOUNDS_CHECK(cp, INT16SZ + INT16SZ + INT32SZ + INT16SZ); + PUTSHORT(ns_t_tsig, cp); + PUTSHORT(ns_c_any, cp); + PUTLONG(0, cp); /* TTL */ + lenp = cp; + cp += 2; + + /* Alg. */ + n = dn_comp(NS_TSIG_ALG_HMAC_MD5, cp, eob - cp, NULL, NULL); + if (n < 0) + return (NS_TSIG_ERROR_NO_SPACE); + cp += n; + + /* Time. */ + BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); + PUTSHORT(0, cp); + timesigned = time(NULL); + PUTLONG(timesigned, cp); + PUTSHORT(NS_TSIG_FUDGE, cp); + + /* + * Compute the signature. + */ + + /* Digest the time signed and fudge. */ + cp2 = buf; + PUTSHORT(0, cp2); /* Top 16 bits of time */ + PUTLONG(timesigned, cp2); + PUTSHORT(NS_TSIG_FUDGE, cp2); + + dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, + buf, cp2 - buf, NULL, 0); + + n = dst_sign_data(SIG_MODE_FINAL, state->key, &state->ctx, NULL, 0, + state->sig, sizeof(state->sig)); + if (n < 0) + return (-ns_r_badkey); + state->siglen = n; + + /* Add the signature. */ + BOUNDS_CHECK(cp, INT16SZ + state->siglen); + PUTSHORT(state->siglen, cp); + memcpy(cp, state->sig, state->siglen); + cp += state->siglen; + + /* The original message ID & error. */ + BOUNDS_CHECK(cp, INT16SZ + INT16SZ); + PUTSHORT(ntohs(hp->id), cp); /* already in network order */ + PUTSHORT(error, cp); + + /* Other data. */ + BOUNDS_CHECK(cp, INT16SZ); + PUTSHORT(0, cp); + + /* Go back and fill in the length. */ + PUTSHORT(cp - lenp - INT16SZ, lenp); + + hp->arcount = htons(ntohs(hp->arcount) + 1); + *msglen = (cp - msg); + return (0); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_sign.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/nameser/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/nameser/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/nameser/Makefile (revision 109985) @@ -0,0 +1,92 @@ +# +# Copyright (c) 1996,1999 by Internet Software Consortium +# +# 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. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +# CONSORTIUM 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 +# SOFTWARE. +# + +# $Id: Makefile,v 8.22 2001/08/14 05:58:09 marka Exp $ + +# these are only appropriate for BSD 4.4 or derivatives, and are used in +# development. normal builds will be done in the top level directory and +# this Makefile will be invoked with a lot of overrides for the following: +SYSTYPE= freebsd +DESTDIR = +DESTLIB = /usr/local/lib +O=o +A=a +CC= cc +LD= ld +SHELL= /bin/sh +CDEBUG= -g -Wall +TOP= ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.${A} +LIBBINDR = ../${TOP}/lib/libbind_r.${A} +CFLAGS= ${CDEBUG} +CPPFLAGS= -I${PORTINCL} -I${INCL} +LD_LIBFLAGS= -x -r +AR= ar cru +RANLIB= ranlib +INSTALL= install +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin +THREADED= threaded + +SRCS= ns_parse.c ns_print.c ns_netint.c ns_ttl.c ns_name.c \ + ns_sign.c ns_verify.c ns_date.c ns_samedomain.c + +OBJS= ns_parse.${O} ns_print.${O} ns_netint.${O} ns_ttl.${O} ns_name.${O} \ + ns_sign.${O} ns_verify.${O} ns_date.${O} ns_samedomain.${O} + +all: ${LIBBIND} + +${LIBBIND}: ${OBJS} + ( cd ${THREADED} ; \ + ${AR} ${LIBBINDR} ${ARPREF} ${OBJS} ${ARSUFF} ; \ + ${RANLIB} ${LIBBINDR} ) + ${AR} ${LIBBIND} ${ARPREF} ${OBJS} ${ARSUFF} + ${RANLIB} ${LIBBIND} + +.c.${O}: + mkdir ${THREADED} 2> /dev/null || test -d ${THREADED} -a -w ${THREADED} + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} ${REENTRANT} -c $*.c \ + -o ${THREADED}/$*.${O} + -${LDS} ${LD} ${LD_LIBFLAGS} ${THREADED}/$*.${O} \ + -o ${THREADED}/$*.out && \ + ${LDS} mv ${THREADED}/$*.out ${THREADED}/$*.${O} + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c + -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} -o $*.out && \ + ${LDS} mv $*.out $*.${O} + +distclean: clean + +clean: FRC + rm -f .depend a.out core ${LIB} tags + rm -f *.${O} *.BAK *.CKP *~ + rm -f ${THREADED}/*.${O} + -if test -d ${THREADED} ; then rmdir ${THREADED}; else true; fi + +depend: FRC + mkdep -I${INCL} -I${PORTINCL} ${CPPFLAGS} ${SRCS} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +install: + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Property changes on: vendor/bind/8.3.4/contrib/bind/lib/nameser/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_date.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_date.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_date.c (revision 109985) @@ -0,0 +1,128 @@ +/* + * Copyright (c) 1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_date.c,v 1.3 2001/05/29 05:49:34 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include + +#include +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Forward. */ + +static int datepart(const char *, int, int, int, int *); + +/* Public. */ + +/* Convert a date in ASCII into the number of seconds since + 1 January 1970 (GMT assumed). Format is yyyymmddhhmmss, all + digits required, no spaces allowed. */ + +u_int32_t +ns_datetosecs(const char *cp, int *errp) { + struct tm time; + u_int32_t result; + int mdays, i; + static const int days_per_month[12] = + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + if (strlen(cp) != 14) { + *errp = 1; + return (0); + } + *errp = 0; + + memset(&time, 0, sizeof time); + time.tm_year = datepart(cp + 0, 4, 1990, 9999, errp) - 1900; + time.tm_mon = datepart(cp + 4, 2, 01, 12, errp) - 1; + time.tm_mday = datepart(cp + 6, 2, 01, 31, errp); + time.tm_hour = datepart(cp + 8, 2, 00, 23, errp); + time.tm_min = datepart(cp + 10, 2, 00, 59, errp); + time.tm_sec = datepart(cp + 12, 2, 00, 59, errp); + if (*errp) /* Any parse errors? */ + return (0); + + /* + * OK, now because timegm() is not available in all environments, + * we will do it by hand. Roll up sleeves, curse the gods, begin! + */ + +#define SECS_PER_DAY ((u_int32_t)24*60*60) +#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) + + result = time.tm_sec; /* Seconds */ + result += time.tm_min * 60; /* Minutes */ + result += time.tm_hour * (60*60); /* Hours */ + result += (time.tm_mday - 1) * SECS_PER_DAY; /* Days */ + + /* Months are trickier. Look without leaping, then leap */ + mdays = 0; + for (i = 0; i < time.tm_mon; i++) + mdays += days_per_month[i]; + result += mdays * SECS_PER_DAY; /* Months */ + if (time.tm_mon > 1 && isleap(1900+time.tm_year)) + result += SECS_PER_DAY; /* Add leapday for this year */ + + /* First figure years without leapdays, then add them in. */ + /* The loop is slow, FIXME, but simple and accurate. */ + result += (time.tm_year - 70) * (SECS_PER_DAY*365); /* Years */ + for (i = 70; i < time.tm_year; i++) + if (isleap(1900+i)) + result += SECS_PER_DAY; /* Add leapday for prev year */ + + return (result); +} + +/* Private. */ + +/* + * Parse part of a date. Set error flag if any error. + * Don't reset the flag if there is no error. + */ +static int +datepart(const char *buf, int size, int min, int max, int *errp) { + int result = 0; + int i; + + for (i = 0; i < size; i++) { + if (!isdigit((unsigned char)(buf[i]))) + *errp = 1; + result = (result * 10) + buf[i] - '0'; + } + if (result < min) + *errp = 1; + if (result > max) + *errp = 1; + return (result); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_date.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_parse.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_parse.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_parse.c (revision 109985) @@ -0,0 +1,202 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_parse.c,v 8.17 2001/06/20 02:50:49 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include + +#include +#include + +#include +#include +#include + +#include "port_after.h" + +/* Forward. */ + +static void setsection(ns_msg *msg, ns_sect sect); + +/* Macros. */ + +#define RETERR(err) do { errno = (err); return (-1); } while (0) + +/* Public. */ + +/* These need to be in the same order as the nres.h:ns_flag enum. */ +struct _ns_flagdata _ns_flagdata[16] = { + { 0x8000, 15 }, /* qr. */ + { 0x7800, 11 }, /* opcode. */ + { 0x0400, 10 }, /* aa. */ + { 0x0200, 9 }, /* tc. */ + { 0x0100, 8 }, /* rd. */ + { 0x0080, 7 }, /* ra. */ + { 0x0040, 6 }, /* z. */ + { 0x0020, 5 }, /* ad. */ + { 0x0010, 4 }, /* cd. */ + { 0x000f, 0 }, /* rcode. */ + { 0x0000, 0 }, /* expansion (1/6). */ + { 0x0000, 0 }, /* expansion (2/6). */ + { 0x0000, 0 }, /* expansion (3/6). */ + { 0x0000, 0 }, /* expansion (4/6). */ + { 0x0000, 0 }, /* expansion (5/6). */ + { 0x0000, 0 }, /* expansion (6/6). */ +}; + +int ns_msg_getflag(ns_msg handle, int flag) { + return(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift); +} + +int +ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) { + const u_char *optr = ptr; + + for ((void)NULL; count > 0; count--) { + int b, rdlength; + + b = dn_skipname(ptr, eom); + if (b < 0) + RETERR(EMSGSIZE); + ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/; + if (section != ns_s_qd) { + if (ptr + NS_INT32SZ + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + ptr += NS_INT32SZ/*TTL*/; + NS_GET16(rdlength, ptr); + ptr += rdlength/*RData*/; + } + } + if (ptr > eom) + RETERR(EMSGSIZE); + return (ptr - optr); +} + +int +ns_initparse(const u_char *msg, int msglen, ns_msg *handle) { + const u_char *eom = msg + msglen; + int i; + + memset(handle, 0x5e, sizeof *handle); + handle->_msg = msg; + handle->_eom = eom; + if (msg + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + NS_GET16(handle->_id, msg); + if (msg + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + NS_GET16(handle->_flags, msg); + for (i = 0; i < ns_s_max; i++) { + if (msg + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + NS_GET16(handle->_counts[i], msg); + } + for (i = 0; i < ns_s_max; i++) + if (handle->_counts[i] == 0) + handle->_sections[i] = NULL; + else { + int b = ns_skiprr(msg, eom, (ns_sect)i, + handle->_counts[i]); + + if (b < 0) + return (-1); + handle->_sections[i] = msg; + msg += b; + } + if (msg != eom) + RETERR(EMSGSIZE); + setsection(handle, ns_s_max); + return (0); +} + +int +ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) { + int b; + + /* Make section right. */ + if (section >= ns_s_max) + RETERR(ENODEV); + if (section != handle->_sect) + setsection(handle, section); + + /* Make rrnum right. */ + if (rrnum == -1) + rrnum = handle->_rrnum; + if (rrnum < 0 || rrnum >= handle->_counts[(int)section]) + RETERR(ENODEV); + if (rrnum < handle->_rrnum) + setsection(handle, section); + if (rrnum > handle->_rrnum) { + b = ns_skiprr(handle->_msg_ptr, handle->_eom, section, + rrnum - handle->_rrnum); + + if (b < 0) + return (-1); + handle->_msg_ptr += b; + handle->_rrnum = rrnum; + } + + /* Do the parse. */ + b = dn_expand(handle->_msg, handle->_eom, + handle->_msg_ptr, rr->name, NS_MAXDNAME); + if (b < 0) + return (-1); + handle->_msg_ptr += b; + if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom) + RETERR(EMSGSIZE); + NS_GET16(rr->type, handle->_msg_ptr); + NS_GET16(rr->rr_class, handle->_msg_ptr); + if (section == ns_s_qd) { + rr->ttl = 0; + rr->rdlength = 0; + rr->rdata = NULL; + } else { + if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom) + RETERR(EMSGSIZE); + NS_GET32(rr->ttl, handle->_msg_ptr); + NS_GET16(rr->rdlength, handle->_msg_ptr); + if (handle->_msg_ptr + rr->rdlength > handle->_eom) + RETERR(EMSGSIZE); + rr->rdata = handle->_msg_ptr; + handle->_msg_ptr += rr->rdlength; + } + if (++handle->_rrnum > handle->_counts[(int)section]) + setsection(handle, (ns_sect)((int)section + 1)); + + /* All done. */ + return (0); +} + +/* Private. */ + +static void +setsection(ns_msg *msg, ns_sect sect) { + msg->_sect = sect; + if (sect == ns_s_max) { + msg->_rrnum = -1; + msg->_msg_ptr = NULL; + } else { + msg->_rrnum = 0; + msg->_msg_ptr = msg->_sections[(int)sect]; + } +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_parse.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_print.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_print.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_print.c (revision 109985) @@ -0,0 +1,901 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_print.c,v 8.24 2001/06/18 06:40:45 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Forward. */ + +static size_t prune_origin(const char *name, const char *origin); +static int charstr(const u_char *rdata, const u_char *edata, + char **buf, size_t *buflen); +static int addname(const u_char *msg, size_t msglen, + const u_char **p, const char *origin, + char **buf, size_t *buflen); +static void addlen(size_t len, char **buf, size_t *buflen); +static int addstr(const char *src, size_t len, + char **buf, size_t *buflen); +static int addtab(size_t len, size_t target, int spaced, + char **buf, size_t *buflen); + +/* Proto. */ + +u_int16_t dst_s_dns_key_id(const u_char *, const int); + +/* Macros. */ + +#define T(x) \ + do { \ + if ((x) < 0) \ + return (-1); \ + } while (0) + +/* Public. */ + +/* + * int + * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen) + * Convert an RR to presentation format. + * return: + * Number of characters written to buf, or -1 (check errno). + */ +int +ns_sprintrr(const ns_msg *handle, const ns_rr *rr, + const char *name_ctx, const char *origin, + char *buf, size_t buflen) +{ + int n; + + n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle), + ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr), + ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr), + name_ctx, origin, buf, buflen); + return (n); +} + +/* + * int + * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen, + * name_ctx, origin, buf, buflen) + * Convert the fields of an RR into presentation format. + * return: + * Number of characters written to buf, or -1 (check errno). + */ +int +ns_sprintrrf(const u_char *msg, size_t msglen, + const char *name, ns_class class, ns_type type, + u_long ttl, const u_char *rdata, size_t rdlen, + const char *name_ctx, const char *origin, + char *buf, size_t buflen) +{ + const char *obuf = buf; + const u_char *edata = rdata + rdlen; + int spaced = 0; + + const char *comment; + char tmp[100]; + int len, x; + + /* + * Owner. + */ + if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) { + T(addstr("\t\t\t", 3, &buf, &buflen)); + } else { + len = prune_origin(name, origin); + if (*name == '\0') { + goto root; + } else if (len == 0) { + T(addstr("@\t\t\t", 4, &buf, &buflen)); + } else { + T(addstr(name, len, &buf, &buflen)); + /* Origin not used or not root, and no trailing dot? */ + if (((origin == NULL || origin[0] == '\0') || + (origin[0] != '.' && origin[1] != '\0' && + name[len] == '\0')) && name[len - 1] != '.') { + root: + T(addstr(".", 1, &buf, &buflen)); + len++; + } + T(spaced = addtab(len, 24, spaced, &buf, &buflen)); + } + } + + /* + * TTL, Class, Type. + */ + T(x = ns_format_ttl(ttl, buf, buflen)); + addlen(x, &buf, &buflen); + len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type))); + T(addstr(tmp, len, &buf, &buflen)); + if (rdlen == 0) + return (buf - obuf); + T(spaced = addtab(x + len, 16, spaced, &buf, &buflen)); + + /* + * RData. + */ + switch (type) { + case ns_t_a: + if (rdlen != NS_INADDRSZ) + goto formerr; + (void) inet_ntop(AF_INET, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + break; + + case ns_t_cname: + case ns_t_mb: + case ns_t_mg: + case ns_t_mr: + case ns_t_ns: + case ns_t_ptr: + case ns_t_dname: + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + + case ns_t_hinfo: + case ns_t_isdn: + /* First word. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + + /* Second word, optional in ISDN records. */ + if (type == ns_t_isdn && rdata == edata) + break; + + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + break; + + case ns_t_soa: { + u_long t; + + /* Server name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Administrator name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" (\n", 3, &buf, &buflen)); + spaced = 0; + + if ((edata - rdata) != 5*NS_INT32SZ) + goto formerr; + + /* Serial number. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + len = SPRINTF((tmp, "%lu", t)); + T(addstr(tmp, len, &buf, &buflen)); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; serial\n", 9, &buf, &buflen)); + spaced = 0; + + /* Refresh interval. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; refresh\n", 10, &buf, &buflen)); + spaced = 0; + + /* Retry interval. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; retry\n", 8, &buf, &buflen)); + spaced = 0; + + /* Expiry. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; expiry\n", 9, &buf, &buflen)); + spaced = 0; + + /* Minimum TTL. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(addstr(" )", 2, &buf, &buflen)); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; minimum\n", 10, &buf, &buflen)); + + break; + } + + case ns_t_mx: + case ns_t_afsdb: + case ns_t_rt: { + u_int t; + + if (rdlen < NS_INT16SZ) + goto formerr; + + /* Priority. */ + t = ns_get16(rdata); + rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", t)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Target. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + } + + case ns_t_px: { + u_int t; + + if (rdlen < NS_INT16SZ) + goto formerr; + + /* Priority. */ + t = ns_get16(rdata); + rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", t)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Name1. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Name2. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + } + + case ns_t_x25: + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + break; + + case ns_t_txt: + while (rdata < edata) { + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + if (rdata < edata) + T(addstr(" ", 1, &buf, &buflen)); + } + break; + + case ns_t_nsap: { + char t[2+255*3]; + + (void) inet_nsap_ntoa(rdlen, rdata, t); + T(addstr(t, strlen(t), &buf, &buflen)); + break; + } + + case ns_t_aaaa: + if (rdlen != NS_IN6ADDRSZ) + goto formerr; + (void) inet_ntop(AF_INET6, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + break; + + case ns_t_loc: { + char t[255]; + + /* XXX protocol format checking? */ + (void) loc_ntoa(rdata, t); + T(addstr(t, strlen(t), &buf, &buflen)); + break; + } + + case ns_t_naptr: { + u_int order, preference; + char t[50]; + + if (rdlen < 2*NS_INT16SZ) + goto formerr; + + /* Order, Precedence. */ + order = ns_get16(rdata); rdata += NS_INT16SZ; + preference = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((t, "%u %u ", order, preference)); + T(addstr(t, len, &buf, &buflen)); + + /* Flags. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Service. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Regexp. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len < 0) + return (-1); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Server. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + } + + case ns_t_srv: { + u_int priority, weight, port; + char t[50]; + + if (rdlen < NS_INT16SZ*3) + goto formerr; + + /* Priority, Weight, Port. */ + priority = ns_get16(rdata); rdata += NS_INT16SZ; + weight = ns_get16(rdata); rdata += NS_INT16SZ; + port = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((t, "%u %u %u ", priority, weight, port)); + T(addstr(t, len, &buf, &buflen)); + + /* Server. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + } + + case ns_t_minfo: + case ns_t_rp: + /* Name1. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Name2. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + + case ns_t_wks: { + int n, lcnt; + + if (rdlen < NS_INT32SZ + 1) + goto formerr; + + /* Address. */ + (void) inet_ntop(AF_INET, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + rdata += NS_INADDRSZ; + + /* Protocol. */ + len = SPRINTF((tmp, " %u ( ", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + rdata += NS_INT8SZ; + + /* Bit map. */ + n = 0; + lcnt = 0; + while (rdata < edata) { + u_int c = *rdata++; + do { + if (c & 0200) { + if (lcnt == 0) { + T(addstr("\n\t\t\t\t", 5, + &buf, &buflen)); + lcnt = 10; + spaced = 0; + } + len = SPRINTF((tmp, "%d ", n)); + T(addstr(tmp, len, &buf, &buflen)); + lcnt--; + } + c <<= 1; + } while (++n & 07); + } + T(addstr(")", 1, &buf, &buflen)); + + break; + } + + case ns_t_key: { + char base64_key[NS_MD5RSA_MAX_BASE64]; + u_int keyflags, protocol, algorithm, key_id; + const char *leader; + int n; + + if (rdlen < NS_INT16SZ + NS_INT8SZ + NS_INT8SZ) + goto formerr; + + /* Key flags, Protocol, Algorithm. */ + key_id = dst_s_dns_key_id(rdata, edata-rdata); + keyflags = ns_get16(rdata); rdata += NS_INT16SZ; + protocol = *rdata++; + algorithm = *rdata++; + len = SPRINTF((tmp, "0x%04x %u %u", + keyflags, protocol, algorithm)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Public key data. */ + len = b64_ntop(rdata, edata - rdata, + base64_key, sizeof base64_key); + if (len < 0) + goto formerr; + if (len > 15) { + T(addstr(" (", 2, &buf, &buflen)); + leader = "\n\t\t"; + spaced = 0; + } else + leader = " "; + for (n = 0; n < len; n += 48) { + T(addstr(leader, strlen(leader), &buf, &buflen)); + T(addstr(base64_key + n, MIN(len - n, 48), + &buf, &buflen)); + } + if (len > 15) + T(addstr(" )", 2, &buf, &buflen)); + n = SPRINTF((tmp, " ; key_tag= %u", key_id)); + T(addstr(tmp, n, &buf, &buflen)); + + break; + } + + case ns_t_sig: { + char base64_key[NS_MD5RSA_MAX_BASE64]; + u_int type, algorithm, labels, footprint; + const char *leader; + u_long t; + int n; + + if (rdlen < 22) + goto formerr; + + /* Type covered, Algorithm, Label count, Original TTL. */ + type = ns_get16(rdata); rdata += NS_INT16SZ; + algorithm = *rdata++; + labels = *rdata++; + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s %d %d %lu ", + p_type(type), algorithm, labels, t)); + T(addstr(tmp, len, &buf, &buflen)); + if (labels > (u_int)dn_count_labels(name)) + goto formerr; + + /* Signature expiry. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Time signed. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Signature Footprint. */ + footprint = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", footprint)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Signer's name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + /* Signature. */ + len = b64_ntop(rdata, edata - rdata, + base64_key, sizeof base64_key); + if (len > 15) { + T(addstr(" (", 2, &buf, &buflen)); + leader = "\n\t\t"; + spaced = 0; + } else + leader = " "; + if (len < 0) + goto formerr; + for (n = 0; n < len; n += 48) { + T(addstr(leader, strlen(leader), &buf, &buflen)); + T(addstr(base64_key + n, MIN(len - n, 48), + &buf, &buflen)); + } + if (len > 15) + T(addstr(" )", 2, &buf, &buflen)); + break; + } + + case ns_t_nxt: { + int n, c; + + /* Next domain name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + /* Type bit map. */ + n = edata - rdata; + for (c = 0; c < n*8; c++) + if (NS_NXT_BIT_ISSET(c, rdata)) { + len = SPRINTF((tmp, " %s", p_type(c))); + T(addstr(tmp, len, &buf, &buflen)); + } + break; + } + + case ns_t_cert: { + u_int c_type, key_tag, alg; + int n; + unsigned int siz; + char base64_cert[8192], tmp[40]; + const char *leader; + + c_type = ns_get16(rdata); rdata += NS_INT16SZ; + key_tag = ns_get16(rdata); rdata += NS_INT16SZ; + alg = (u_int) *rdata++; + + len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg)); + T(addstr(tmp, len, &buf, &buflen)); + siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ + if (siz > sizeof(base64_cert) * 3/4) { + const char *str = "record too long to print"; + T(addstr(str, strlen(str), &buf, &buflen)); + } + else { + len = b64_ntop(rdata, edata-rdata, base64_cert, siz); + + if (len < 0) + goto formerr; + else if (len > 15) { + T(addstr(" (", 2, &buf, &buflen)); + leader = "\n\t\t"; + spaced = 0; + } + else + leader = " "; + + for (n = 0; n < len; n += 48) { + T(addstr(leader, strlen(leader), + &buf, &buflen)); + T(addstr(base64_cert + n, MIN(len - n, 48), + &buf, &buflen)); + } + if (len > 15) + T(addstr(" )", 2, &buf, &buflen)); + } + break; + } + + case ns_t_tkey: { + /* KJD - need to complete this */ + u_long t; + int mode, err, keysize; + + /* Algorithm name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Inception. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Experation. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Mode , Error, Key Size. */ + /* Priority, Weight, Port. */ + mode = ns_get16(rdata); rdata += NS_INT16SZ; + err = ns_get16(rdata); rdata += NS_INT16SZ; + keysize = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize)); + T(addstr(tmp, len, &buf, &buflen)); + + /* needs to dump key, print otherdata length & other data */ + break; + } + case ns_t_tsig: { + /* BEW - need to complete this */ + int n; + + T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + rdata += 8; /* time */ + n = ns_get16(rdata); rdata += INT16SZ; + rdata += n; /* sig */ + n = ns_get16(rdata); rdata += INT16SZ; /* original id */ + sprintf(buf, "%d", ns_get16(rdata)); + rdata += INT16SZ; + addlen(strlen(buf), &buf, &buflen); + break; + } + + case ns_t_a6: { + struct in6_addr a; + int pbyte, pbit; + + /* prefix length */ + if (rdlen == 0) goto formerr; + len = SPRINTF((tmp, "%d ", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + pbit = *rdata; + if (pbit > 128) goto formerr; + pbyte = (pbit & ~7) / 8; + rdata++; + + /* address suffix: provided only when prefix len != 128 */ + if (pbit < 128) { + if (rdata + pbyte >= edata) goto formerr; + memset(&a, 0, sizeof(a)); + memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte); + (void) inet_ntop(AF_INET6, &a, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + rdata += sizeof(a) - pbyte; + } + + /* prefix name: provided only when prefix len > 0 */ + if (pbit == 0) + break; + if (rdata >= edata) goto formerr; + T(addstr(" ", 1, &buf, &buflen)); + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + } + + case ns_t_opt: { + len = SPRINTF((tmp, "%u bytes", class)); + T(addstr(tmp, len, &buf, &buflen)); + break; + } + + default: + comment = "unknown RR type"; + goto hexify; + } + return (buf - obuf); + formerr: + comment = "RR format error"; + hexify: { + int n, m; + char *p; + + len = SPRINTF((tmp, "\\# %u (\t; %s", edata - rdata, comment)); + T(addstr(tmp, len, &buf, &buflen)); + while (rdata < edata) { + p = tmp; + p += SPRINTF((p, "\n\t")); + spaced = 0; + n = MIN(16, edata - rdata); + for (m = 0; m < n; m++) + p += SPRINTF((p, "%02x ", rdata[m])); + T(addstr(tmp, p - tmp, &buf, &buflen)); + if (n < 16) { + T(addstr(")", 1, &buf, &buflen)); + T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen)); + } + p = tmp; + p += SPRINTF((p, "; ")); + for (m = 0; m < n; m++) + *p++ = (isascii(rdata[m]) && isprint(rdata[m])) + ? rdata[m] + : '.'; + T(addstr(tmp, p - tmp, &buf, &buflen)); + rdata += n; + } + return (buf - obuf); + } +} + +/* Private. */ + +/* + * size_t + * prune_origin(name, origin) + * Find out if the name is at or under the current origin. + * return: + * Number of characters in name before start of origin, + * or length of name if origin does not match. + * notes: + * This function should share code with samedomain(). + */ +static size_t +prune_origin(const char *name, const char *origin) { + const char *oname = name; + + while (*name != '\0') { + if (origin != NULL && ns_samename(name, origin) == 1) + return (name - oname - (name > oname)); + while (*name != '\0') { + if (*name == '\\') { + name++; + /* XXX need to handle \nnn form. */ + if (*name == '\0') + break; + } else if (*name == '.') { + name++; + break; + } + name++; + } + } + return (name - oname); +} + +/* + * int + * charstr(rdata, edata, buf, buflen) + * Format a into the presentation buffer. + * return: + * Number of rdata octets consumed + * 0 for protocol format error + * -1 for output buffer error + * side effects: + * buffer is advanced on success. + */ +static int +charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) { + const u_char *odata = rdata; + size_t save_buflen = *buflen; + char *save_buf = *buf; + + if (addstr("\"", 1, buf, buflen) < 0) + goto enospc; + if (rdata < edata) { + int n = *rdata; + + if (rdata + 1 + n <= edata) { + rdata++; + while (n-- > 0) { + if (strchr("\n\"\\", *rdata) != NULL) + if (addstr("\\", 1, buf, buflen) < 0) + goto enospc; + if (addstr((const char *)rdata, 1, + buf, buflen) < 0) + goto enospc; + rdata++; + } + } + } + if (addstr("\"", 1, buf, buflen) < 0) + goto enospc; + return (rdata - odata); + enospc: + errno = ENOSPC; + *buf = save_buf; + *buflen = save_buflen; + return (-1); +} + +static int +addname(const u_char *msg, size_t msglen, + const u_char **pp, const char *origin, + char **buf, size_t *buflen) +{ + size_t newlen, save_buflen = *buflen; + char *save_buf = *buf; + int n; + + n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen); + if (n < 0) + goto enospc; /* Guess. */ + newlen = prune_origin(*buf, origin); + if (**buf == '\0') { + goto root; + } else if (newlen == 0) { + /* Use "@" instead of name. */ + if (newlen + 2 > *buflen) + goto enospc; /* No room for "@\0". */ + (*buf)[newlen++] = '@'; + (*buf)[newlen] = '\0'; + } else { + if (((origin == NULL || origin[0] == '\0') || + (origin[0] != '.' && origin[1] != '\0' && + (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') { + /* No trailing dot. */ + root: + if (newlen + 2 > *buflen) + goto enospc; /* No room for ".\0". */ + (*buf)[newlen++] = '.'; + (*buf)[newlen] = '\0'; + } + } + *pp += n; + addlen(newlen, buf, buflen); + **buf = '\0'; + return (newlen); + enospc: + errno = ENOSPC; + *buf = save_buf; + *buflen = save_buflen; + return (-1); +} + +static void +addlen(size_t len, char **buf, size_t *buflen) { + INSIST(len <= *buflen); + *buf += len; + *buflen -= len; +} + +static int +addstr(const char *src, size_t len, char **buf, size_t *buflen) { + if (len >= *buflen) { + errno = ENOSPC; + return (-1); + } + memcpy(*buf, src, len); + addlen(len, buf, buflen); + **buf = '\0'; + return (0); +} + +static int +addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { + size_t save_buflen = *buflen; + char *save_buf = *buf; + int t; + + if (spaced || len >= target - 1) { + T(addstr(" ", 2, buf, buflen)); + spaced = 1; + } else { + for (t = (target - len - 1) / 8; t >= 0; t--) + if (addstr("\t", 1, buf, buflen) < 0) { + *buflen = save_buflen; + *buf = save_buf; + return (-1); + } + spaced = 0; + } + return (spaced); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_print.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_verify.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_verify.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_verify.c (revision 109985) @@ -0,0 +1,480 @@ +/* + * Copyright (c) 1999 by Internet Software Consortium, Inc. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_verify.c,v 8.14 2001/05/29 05:49:40 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "port_after.h" + +/* Private. */ + +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eom) { \ + return (NS_TSIG_ERROR_FORMERR); \ + } \ + } while (0) + +/* Public. */ + +u_char * +ns_find_tsig(u_char *msg, u_char *eom) { + HEADER *hp = (HEADER *)msg; + int n, type; + u_char *cp = msg, *start; + + if (msg == NULL || eom == NULL || msg > eom) + return (NULL); + + if (cp + HFIXEDSZ >= eom) + return (NULL); + + if (hp->arcount == 0) + return (NULL); + + cp += HFIXEDSZ; + + n = ns_skiprr(cp, eom, ns_s_qd, ntohs(hp->qdcount)); + if (n < 0) + return (NULL); + cp += n; + + n = ns_skiprr(cp, eom, ns_s_an, ntohs(hp->ancount)); + if (n < 0) + return (NULL); + cp += n; + + n = ns_skiprr(cp, eom, ns_s_ns, ntohs(hp->nscount)); + if (n < 0) + return (NULL); + cp += n; + + n = ns_skiprr(cp, eom, ns_s_ar, ntohs(hp->arcount) - 1); + if (n < 0) + return (NULL); + cp += n; + + start = cp; + n = dn_skipname(cp, eom); + if (n < 0) + return (NULL); + cp += n; + if (cp + INT16SZ >= eom) + return (NULL); + + GETSHORT(type, cp); + if (type != ns_t_tsig) + return (NULL); + return (start); +} + +/* ns_verify + * Parameters: + * statp res stuff + * msg received message + * msglen length of message + * key tsig key used for verifying. + * querysig (response), the signature in the query + * querysiglen (response), the length of the signature in the query + * sig (query), a buffer to hold the signature + * siglen (query), input - length of signature buffer + * output - length of signature + * + * Errors: + * - bad input (-1) + * - invalid dns message (NS_TSIG_ERROR_FORMERR) + * - TSIG is not present (NS_TSIG_ERROR_NO_TSIG) + * - key doesn't match (-ns_r_badkey) + * - TSIG verification fails with BADKEY (-ns_r_badkey) + * - TSIG verification fails with BADSIG (-ns_r_badsig) + * - TSIG verification fails with BADTIME (-ns_r_badtime) + * - TSIG verification succeeds, error set to BAKEY (ns_r_badkey) + * - TSIG verification succeeds, error set to BADSIG (ns_r_badsig) + * - TSIG verification succeeds, error set to BADTIME (ns_r_badtime) + */ +int +ns_verify(u_char *msg, int *msglen, void *k, + const u_char *querysig, int querysiglen, u_char *sig, int *siglen, + time_t *timesigned, int nostrip) +{ + HEADER *hp = (HEADER *)msg; + DST_KEY *key = (DST_KEY *)k; + u_char *cp = msg, *eom; + char name[MAXDNAME], alg[MAXDNAME]; + u_char *recstart, *rdatastart; + u_char *sigstart, *otherstart; + int n; + int error; + u_int16_t type, length; + u_int16_t fudge, sigfieldlen, id, otherfieldlen; + + dst_init(); + if (msg == NULL || msglen == NULL || *msglen < 0) + return (-1); + + eom = msg + *msglen; + + recstart = ns_find_tsig(msg, eom); + if (recstart == NULL) + return (NS_TSIG_ERROR_NO_TSIG); + + cp = recstart; + + /* Read the key name. */ + n = dn_expand(msg, eom, cp, name, MAXDNAME); + if (n < 0) + return (NS_TSIG_ERROR_FORMERR); + cp += n; + + /* Read the type. */ + BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ); + GETSHORT(type, cp); + if (type != ns_t_tsig) + return (NS_TSIG_ERROR_NO_TSIG); + + /* Skip the class and TTL, save the length. */ + cp += INT16SZ + INT32SZ; + GETSHORT(length, cp); + if (eom - cp != length) + return (NS_TSIG_ERROR_FORMERR); + + /* Read the algorithm name. */ + rdatastart = cp; + n = dn_expand(msg, eom, cp, alg, MAXDNAME); + if (n < 0) + return (NS_TSIG_ERROR_FORMERR); + if (ns_samename(alg, NS_TSIG_ALG_HMAC_MD5) != 1) + return (-ns_r_badkey); + cp += n; + + /* Read the time signed and fudge. */ + BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); + cp += INT16SZ; + GETLONG((*timesigned), cp); + GETSHORT(fudge, cp); + + /* Read the signature. */ + BOUNDS_CHECK(cp, INT16SZ); + GETSHORT(sigfieldlen, cp); + BOUNDS_CHECK(cp, sigfieldlen); + sigstart = cp; + cp += sigfieldlen; + + /* Read the original id and error. */ + BOUNDS_CHECK(cp, 2*INT16SZ); + GETSHORT(id, cp); + GETSHORT(error, cp); + + /* Parse the other data. */ + BOUNDS_CHECK(cp, INT16SZ); + GETSHORT(otherfieldlen, cp); + BOUNDS_CHECK(cp, otherfieldlen); + otherstart = cp; + cp += otherfieldlen; + + if (cp != eom) + return (NS_TSIG_ERROR_FORMERR); + + /* Verify that the key used is OK. */ + if (key != NULL) { + if (key->dk_alg != KEY_HMAC_MD5) + return (-ns_r_badkey); + if (error != ns_r_badsig && error != ns_r_badkey) { + if (ns_samename(key->dk_key_name, name) != 1) + return (-ns_r_badkey); + } + } + + hp->arcount = htons(ntohs(hp->arcount) - 1); + + /* + * Do the verification. + */ + + if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) { + void *ctx; + u_char buf[MAXDNAME]; + u_char buf2[MAXDNAME]; + + /* Digest the query signature, if this is a response. */ + dst_verify_data(SIG_MODE_INIT, key, &ctx, NULL, 0, NULL, 0); + if (querysiglen > 0 && querysig != NULL) { + u_int16_t len_n = htons(querysiglen); + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + (u_char *)&len_n, INT16SZ, NULL, 0); + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + querysig, querysiglen, NULL, 0); + } + + /* Digest the message. */ + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, msg, recstart - msg, + NULL, 0); + + /* Digest the key name. */ + n = ns_name_pton(name, buf2, sizeof(buf2)); + if (n < 0) + return (-1); + n = ns_name_ntol(buf2, buf, sizeof(buf)); + if (n < 0) + return (-1); + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); + + /* Digest the class and TTL. */ + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + recstart + dn_skipname(recstart, eom) + INT16SZ, + INT16SZ + INT32SZ, NULL, 0); + + /* Digest the algorithm. */ + n = ns_name_pton(alg, buf2, sizeof(buf2)); + if (n < 0) + return (-1); + n = ns_name_ntol(buf2, buf, sizeof(buf)); + if (n < 0) + return (-1); + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); + + /* Digest the time signed and fudge. */ + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + rdatastart + dn_skipname(rdatastart, eom), + INT16SZ + INT32SZ + INT16SZ, NULL, 0); + + /* Digest the error and other data. */ + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + otherstart - INT16SZ - INT16SZ, + otherfieldlen + INT16SZ + INT16SZ, NULL, 0); + + n = dst_verify_data(SIG_MODE_FINAL, key, &ctx, NULL, 0, + sigstart, sigfieldlen); + + if (n < 0) + return (-ns_r_badsig); + + if (sig != NULL && siglen != NULL) { + if (*siglen < sigfieldlen) + return (NS_TSIG_ERROR_NO_SPACE); + memcpy(sig, sigstart, sigfieldlen); + *siglen = sigfieldlen; + } + } else { + if (sigfieldlen > 0) + return (NS_TSIG_ERROR_FORMERR); + if (sig != NULL && siglen != NULL) + *siglen = 0; + } + + /* Reset the counter, since we still need to check for badtime. */ + hp->arcount = htons(ntohs(hp->arcount) + 1); + + /* Verify the time. */ + if (abs((*timesigned) - time(NULL)) > fudge) + return (-ns_r_badtime); + + if (nostrip == 0) { + *msglen = recstart - msg; + hp->arcount = htons(ntohs(hp->arcount) - 1); + } + + if (error != NOERROR) + return (error); + + return (0); +} + +int +ns_verify_tcp_init(void *k, const u_char *querysig, int querysiglen, + ns_tcp_tsig_state *state) +{ + dst_init(); + if (state == NULL || k == NULL || querysig == NULL || querysiglen < 0) + return (-1); + state->counter = -1; + state->key = k; + if (state->key->dk_alg != KEY_HMAC_MD5) + return (-ns_r_badkey); + if (querysiglen > (int)sizeof(state->sig)) + return (-1); + memcpy(state->sig, querysig, querysiglen); + state->siglen = querysiglen; + return (0); +} + +int +ns_verify_tcp(u_char *msg, int *msglen, ns_tcp_tsig_state *state, + int required) +{ + HEADER *hp = (HEADER *)msg; + u_char *recstart, *rdatastart, *sigstart; + unsigned int sigfieldlen, otherfieldlen; + u_char *cp, *eom = msg + *msglen, *cp2; + char name[MAXDNAME], alg[MAXDNAME]; + u_char buf[MAXDNAME]; + int n, type, length, fudge, id, error; + time_t timesigned; + + if (msg == NULL || msglen == NULL || state == NULL) + return (-1); + + state->counter++; + if (state->counter == 0) + return (ns_verify(msg, msglen, state->key, + state->sig, state->siglen, + state->sig, &state->siglen, ×igned, 0)); + + if (state->siglen > 0) { + u_int16_t siglen_n = htons(state->siglen); + + dst_verify_data(SIG_MODE_INIT, state->key, &state->ctx, + NULL, 0, NULL, 0); + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + (u_char *)&siglen_n, INT16SZ, NULL, 0); + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + state->sig, state->siglen, NULL, 0); + state->siglen = 0; + } + + cp = recstart = ns_find_tsig(msg, eom); + + if (recstart == NULL) { + if (required) + return (NS_TSIG_ERROR_NO_TSIG); + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + msg, *msglen, NULL, 0); + return (0); + } + + hp->arcount = htons(ntohs(hp->arcount) - 1); + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + msg, recstart - msg, NULL, 0); + + /* Read the key name. */ + n = dn_expand(msg, eom, cp, name, MAXDNAME); + if (n < 0) + return (NS_TSIG_ERROR_FORMERR); + cp += n; + + /* Read the type. */ + BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ); + GETSHORT(type, cp); + if (type != ns_t_tsig) + return (NS_TSIG_ERROR_NO_TSIG); + + /* Skip the class and TTL, save the length. */ + cp += INT16SZ + INT32SZ; + GETSHORT(length, cp); + if (eom - cp != length) + return (NS_TSIG_ERROR_FORMERR); + + /* Read the algorithm name. */ + rdatastart = cp; + n = dn_expand(msg, eom, cp, alg, MAXDNAME); + if (n < 0) + return (NS_TSIG_ERROR_FORMERR); + if (ns_samename(alg, NS_TSIG_ALG_HMAC_MD5) != 1) + return (-ns_r_badkey); + cp += n; + + /* Verify that the key used is OK. */ + if ((ns_samename(state->key->dk_key_name, name) != 1 || + state->key->dk_alg != KEY_HMAC_MD5)) + return (-ns_r_badkey); + + /* Read the time signed and fudge. */ + BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); + cp += INT16SZ; + GETLONG(timesigned, cp); + GETSHORT(fudge, cp); + + /* Read the signature. */ + BOUNDS_CHECK(cp, INT16SZ); + GETSHORT(sigfieldlen, cp); + BOUNDS_CHECK(cp, sigfieldlen); + sigstart = cp; + cp += sigfieldlen; + + /* Read the original id and error. */ + BOUNDS_CHECK(cp, 2*INT16SZ); + GETSHORT(id, cp); + GETSHORT(error, cp); + + /* Parse the other data. */ + BOUNDS_CHECK(cp, INT16SZ); + GETSHORT(otherfieldlen, cp); + BOUNDS_CHECK(cp, otherfieldlen); + cp += otherfieldlen; + + if (cp != eom) + return (NS_TSIG_ERROR_FORMERR); + + /* + * Do the verification. + */ + + /* Digest the time signed and fudge. */ + cp2 = buf; + PUTSHORT(0, cp2); /* Top 16 bits of time. */ + PUTLONG(timesigned, cp2); + PUTSHORT(NS_TSIG_FUDGE, cp2); + + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + buf, cp2 - buf, NULL, 0); + + n = dst_verify_data(SIG_MODE_FINAL, state->key, &state->ctx, NULL, 0, + sigstart, sigfieldlen); + if (n < 0) + return (-ns_r_badsig); + + if (sigfieldlen > sizeof(state->sig)) + return (NS_TSIG_ERROR_NO_SPACE); + + memcpy(state->sig, sigstart, sigfieldlen); + state->siglen = sigfieldlen; + + /* Verify the time. */ + if (abs(timesigned - time(NULL)) > fudge) + return (-ns_r_badtime); + + *msglen = recstart - msg; + + if (error != NOERROR) + return (error); + + return (0); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_verify.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_netint.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_netint.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_netint.c (revision 109985) @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_netint.c,v 8.4 1999/10/13 16:39:35 vixie Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include + +#include "port_after.h" + +/* Public. */ + +u_int +ns_get16(const u_char *src) { + u_int dst; + + NS_GET16(dst, src); + return (dst); +} + +u_long +ns_get32(const u_char *src) { + u_long dst; + + NS_GET32(dst, src); + return (dst); +} + +void +ns_put16(u_int src, u_char *dst) { + NS_PUT16(src, dst); +} + +void +ns_put32(u_long src, u_char *dst) { + NS_PUT32(src, dst); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_netint.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_ttl.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_ttl.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_ttl.c (revision 109985) @@ -0,0 +1,159 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_ttl.c,v 8.8 1999/10/13 16:39:36 vixie Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Forward. */ + +static int fmt1(int t, char s, char **buf, size_t *buflen); + +/* Macros. */ + +#define T(x) if ((x) < 0) return (-1); else (void)NULL + +/* Public. */ + +int +ns_format_ttl(u_long src, char *dst, size_t dstlen) { + char *odst = dst; + int secs, mins, hours, days, weeks, x; + char *p; + + secs = src % 60; src /= 60; + mins = src % 60; src /= 60; + hours = src % 24; src /= 24; + days = src % 7; src /= 7; + weeks = src; src = 0; + + x = 0; + if (weeks) { + T(fmt1(weeks, 'W', &dst, &dstlen)); + x++; + } + if (days) { + T(fmt1(days, 'D', &dst, &dstlen)); + x++; + } + if (hours) { + T(fmt1(hours, 'H', &dst, &dstlen)); + x++; + } + if (mins) { + T(fmt1(mins, 'M', &dst, &dstlen)); + x++; + } + if (secs || !(weeks || days || hours || mins)) { + T(fmt1(secs, 'S', &dst, &dstlen)); + x++; + } + + if (x > 1) { + int ch; + + for (p = odst; (ch = *p) != '\0'; p++) + if (isascii(ch) && isupper(ch)) + *p = tolower(ch); + } + + return (dst - odst); +} + +int +ns_parse_ttl(const char *src, u_long *dst) { + u_long ttl, tmp; + int ch, digits, dirty; + + ttl = 0; + tmp = 0; + digits = 0; + dirty = 0; + while ((ch = *src++) != '\0') { + if (!isascii(ch) || !isprint(ch)) + goto einval; + if (isdigit(ch)) { + tmp *= 10; + tmp += (ch - '0'); + digits++; + continue; + } + if (digits == 0) + goto einval; + if (islower(ch)) + ch = toupper(ch); + switch (ch) { + case 'W': tmp *= 7; + case 'D': tmp *= 24; + case 'H': tmp *= 60; + case 'M': tmp *= 60; + case 'S': break; + default: goto einval; + } + ttl += tmp; + tmp = 0; + digits = 0; + dirty = 1; + } + if (digits > 0) { + if (dirty) + goto einval; + else + ttl += tmp; + } + *dst = ttl; + return (0); + + einval: + errno = EINVAL; + return (-1); +} + +/* Private. */ + +static int +fmt1(int t, char s, char **buf, size_t *buflen) { + char tmp[50]; + size_t len; + + len = SPRINTF((tmp, "%d%c", t, s)); + if (len + 1 > *buflen) + return (-1); + strcpy(*buf, tmp); + *buf += len; + *buflen -= len; + return (0); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/nameser/ns_ttl.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/dns_ho.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/dns_ho.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/dns_ho.c (revision 109985) @@ -0,0 +1,1654 @@ +/* + * Copyright (c) 1985, 1988, 1993 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* from gethostnamadr.c 8.1 (Berkeley) 6/4/93 */ +/* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_ho.c,v 1.39 2002/06/27 03:56:32 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "dns_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +/* Definitions. */ + +#define MAXALIASES 35 +#define MAXADDRS 35 + +#define MAXPACKET (1024*64) + +#define BOUNDS_CHECK(ptr, count) \ + if ((ptr) + (count) > eom) { \ + had_error++; \ + continue; \ + } else (void)0 + +typedef union { + HEADER hdr; + u_char buf[MAXPACKET]; +} querybuf; + +struct dns_res_target { + struct dns_res_target *next; + querybuf qbuf; /* query buffer */ + u_char *answer; /* buffer to put answer */ + int anslen; /* size of answer buffer */ + int qclass, qtype; /* class and type of query */ + int action; /* condition whether query is really issued */ + char qname[MAXDNAME +1]; /* domain name */ +#if 0 + int n; /* result length */ +#endif +}; +enum {RESTGT_DOALWAYS, RESTGT_AFTERFAILURE, RESTGT_IGNORE}; +enum {RESQRY_SUCCESS, RESQRY_FAIL}; + +struct pvt { + struct hostent host; + char * h_addr_ptrs[MAXADDRS + 1]; + char * host_aliases[MAXALIASES]; + char hostbuf[8*1024]; + u_char host_addr[16]; /* IPv4 or IPv6 */ + struct __res_state *res; + void (*free_res)(void *); +}; + +typedef union { + int32_t al; + char ac; +} align; + +static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; +static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; +/* Note: the IPv6 loopback address is in the "tunnel" space */ +static const u_char v6local[] = { 0,0, 0,1 }; /* last 4 bytes of IPv6 addr */ + +/* Forwards. */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); +static struct __res_state * ho_res_get(struct irs_ho *this); +static void ho_res_set(struct irs_ho *this, + struct __res_state *res, + void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +static void map_v4v6_hostent(struct hostent *hp, char **bp, + char *ep); +static void addrsort(res_state, char **, int); +static struct hostent * gethostans(struct irs_ho *this, + const u_char *ansbuf, int anslen, + const char *qname, int qtype, + int af, int size, + struct addrinfo **ret_aip, + const struct addrinfo *pai); +static int add_hostent(struct pvt *pvt, char *bp, char **hap, + struct addrinfo *ai); +static const u_char * ar_head(const u_char *, int, const u_char *, + const u_char *, struct pvt *, + int (*)(const char *)); +static struct addrinfo * a6_expand(const u_char *, const u_char *, int, + const u_char *, const u_char *, + const struct in6_addr *, int, + const struct addrinfo *, + struct pvt *, int (*)(const char *), int *); +static const char *dname_subst(const char *, const char *, const char *); +static int init(struct irs_ho *this); + +/* Exports. */ + +struct irs_ho * +irs_dns_ho(struct irs_acc *this) { + struct irs_ho *ho; + struct pvt *pvt; + + UNUSED(this); + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + + if (!(ho = memget(sizeof *ho))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->res_get = ho_res_get; + ho->res_set = ho_res_set; + ho->addrinfo = ho_addrinfo; + return (ho); +} + +/* Methods. */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + if (pvt) + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + + if (init(this) == -1) + return (NULL); + + if (pvt->res->options & RES_USE_INET6) { + hp = ho_byname2(this, name, AF_INET6); + if (hp) + return (hp); + } + return (ho_byname2(this, name, AF_INET)); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp = NULL; + int n, size; + char tmp[NS_MAXDNAME]; + const char *cp; + struct addrinfo ai; + struct dns_res_target *q, *q2, *p; + int querystate = RESQRY_FAIL; + + if (init(this) == -1) + return (NULL); + + q = memget(sizeof(*q)); + q2 = memget(sizeof(*q2)); + if (q == NULL || q2 == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = ENOMEM; + goto cleanup; + } + memset(q, 0, sizeof(q)); + memset(q2, 0, sizeof(q2)); + + switch (af) { + case AF_INET: + size = INADDRSZ; + q->qclass = C_IN; + q->qtype = T_A; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->action = RESTGT_DOALWAYS; + break; + case AF_INET6: + size = IN6ADDRSZ; + q->qclass = C_IN; + q->qtype = ns_t_a6; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->next = q2; +#ifdef RES_USE_A6 + if ((pvt->res->options & RES_USE_A6) == 0) + q->action = RESTGT_IGNORE; + else +#endif + q->action = RESTGT_DOALWAYS; + q2->qclass = C_IN; + q2->qtype = T_AAAA; + q2->answer = q2->qbuf.buf; + q2->anslen = sizeof(q2->qbuf); + q2->action = RESTGT_AFTERFAILURE; + break; + default: + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + hp = NULL; + goto cleanup; + } + + /* + * if there aren't any dots, it could be a user-level alias. + * this is also done in res_nquery() since we are not the only + * function that looks up host names. + */ + if (!strchr(name, '.') && (cp = res_hostalias(pvt->res, name, + tmp, sizeof tmp))) + name = cp; + + for (p = q; p; p = p->next) { + switch(p->action) { + case RESTGT_DOALWAYS: + break; + case RESTGT_AFTERFAILURE: + if (querystate == RESQRY_SUCCESS) + continue; + break; + case RESTGT_IGNORE: + continue; + } + + if ((n = res_nsearch(pvt->res, name, p->qclass, p->qtype, + p->answer, p->anslen)) < 0) { + querystate = RESQRY_FAIL; + continue; + } + + memset(&ai, 0, sizeof(ai)); + ai.ai_family = af; + if ((hp = gethostans(this, p->answer, n, name, p->qtype, + af, size, NULL, + (const struct addrinfo *)&ai)) != NULL) + goto cleanup; /* no more loop is necessary */ + + querystate = RESQRY_FAIL; + continue; + } + + cleanup: + if (q != NULL) + memput(q, sizeof(*q)); + if (q2 != NULL) + memput(q2, sizeof(*q2)); + return(hp); +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) +{ + struct pvt *pvt = (struct pvt *)this->private; + const u_char *uaddr = addr; + char *qp; + struct hostent *hp = NULL; + struct addrinfo ai; + struct dns_res_target *q, *q2, *p; + int n, size; + int querystate = RESQRY_FAIL; + + if (init(this) == -1) + return (NULL); + + q = memget(sizeof(*q)); + q2 = memget(sizeof(*q2)); + if (q == NULL || q2 == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = ENOMEM; + goto cleanup; + } + memset(q, 0, sizeof(q)); + memset(q2, 0, sizeof(q2)); + + if (af == AF_INET6 && len == IN6ADDRSZ && + (!memcmp(uaddr, mapped, sizeof mapped) || + (!memcmp(uaddr, tunnelled, sizeof tunnelled) && + memcmp(&uaddr[sizeof tunnelled], v6local, sizeof(v6local))))) { + /* Unmap. */ + addr = (const char *)addr + sizeof mapped; + uaddr += sizeof mapped; + af = AF_INET; + len = INADDRSZ; + } + switch (af) { + case AF_INET: + size = INADDRSZ; + q->qclass = C_IN; + q->qtype = T_PTR; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->action = RESTGT_DOALWAYS; + break; + case AF_INET6: + size = IN6ADDRSZ; + q->qclass = C_IN; + q->qtype = T_PTR; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->next = q2; + q->action = RESTGT_DOALWAYS; + q2->qclass = C_IN; + q2->qtype = T_PTR; + q2->answer = q2->qbuf.buf; + q2->anslen = sizeof(q2->qbuf); + if ((pvt->res->options & RES_NO_NIBBLE2) != 0) + q2->action = RESTGT_IGNORE; + else + q2->action = RESTGT_AFTERFAILURE; + break; + default: + errno = EAFNOSUPPORT; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + hp = NULL; + goto cleanup; + } + if (size > len) { + errno = EINVAL; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + hp = NULL; + goto cleanup; + } + switch (af) { + case AF_INET: + qp = q->qname; + (void) sprintf(qp, "%u.%u.%u.%u.in-addr.arpa", + (uaddr[3] & 0xff), + (uaddr[2] & 0xff), + (uaddr[1] & 0xff), + (uaddr[0] & 0xff)); + break; + case AF_INET6: + if (q->action != RESTGT_IGNORE) { + qp = q->qname; + for (n = IN6ADDRSZ - 1; n >= 0; n--) { + qp += SPRINTF((qp, "%x.%x.", + uaddr[n] & 0xf, + (uaddr[n] >> 4) & 0xf)); + } + strcpy(qp, res_get_nibblesuffix(pvt->res)); + } + if (q2->action != RESTGT_IGNORE) { + qp = q2->qname; + for (n = IN6ADDRSZ - 1; n >= 0; n--) { + qp += SPRINTF((qp, "%x.%x.", + uaddr[n] & 0xf, + (uaddr[n] >> 4) & 0xf)); + } + strcpy(qp, res_get_nibblesuffix2(pvt->res)); + } + break; + default: + abort(); + } + + for (p = q; p; p = p->next) { + switch(p->action) { + case RESTGT_DOALWAYS: + break; + case RESTGT_AFTERFAILURE: + if (querystate == RESQRY_SUCCESS) + continue; + break; + case RESTGT_IGNORE: + continue; + } + + if ((n = res_nquery(pvt->res, p->qname, p->qclass, p->qtype, + p->answer, p->anslen)) < 0) { + querystate = RESQRY_FAIL; + continue; + } + + memset(&ai, 0, sizeof(ai)); + ai.ai_family = af; + hp = gethostans(this, p->answer, n, p->qname, T_PTR, af, size, + NULL, (const struct addrinfo *)&ai); + if (!hp) { + querystate = RESQRY_FAIL; + continue; + } + + memcpy(pvt->host_addr, addr, len); + pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; + pvt->h_addr_ptrs[1] = NULL; + if (af == AF_INET && (pvt->res->options & RES_USE_INET6)) { + map_v4v6_address((char*)pvt->host_addr, + (char*)pvt->host_addr); + pvt->host.h_addrtype = AF_INET6; + pvt->host.h_length = IN6ADDRSZ; + } + + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + goto cleanup; /* no more loop is necessary. */ + } + hp = NULL; /* H_ERRNO was set by subroutines */ + + cleanup: + if (q != NULL) + memput(q, sizeof(*q)); + if (q2 != NULL) + memput(q2, sizeof(*q2)); + return(hp); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + + UNUSED(this); + + return (NULL); +} + +static void +ho_rewind(struct irs_ho *this) { + + UNUSED(this); + + /* NOOP */ +} + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +ho_res_get(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + ho_res_set(this, res, free); + } + + return (pvt->res); +} + +/* XXX */ +extern struct addrinfo *addr2addrinfo __P((const struct addrinfo *, + const char *)); + +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + int n; + char tmp[NS_MAXDNAME]; + const char *cp; + struct dns_res_target *q, *q2, *q3, *p; + struct addrinfo sentinel, *cur; + int querystate = RESQRY_FAIL; + + if (init(this) == -1) + return (NULL); + + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + q = memget(sizeof(*q)); + q2 = memget(sizeof(*q2)); + q3 = memget(sizeof(*q3)); + if (q == NULL || q2 == NULL || q3 == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = ENOMEM; + goto cleanup; + } + memset(q, 0, sizeof(q2)); + memset(q2, 0, sizeof(q2)); + memset(q3, 0, sizeof(q3)); + + switch (pai->ai_family) { + case AF_UNSPEC: + /* prefer IPv6 */ + q->qclass = C_IN; + q->qtype = ns_t_a6; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->next = q2; +#ifdef RES_USE_A6 + if ((pvt->res->options & RES_USE_A6) == 0) + q->action = RESTGT_IGNORE; + else +#endif + q->action = RESTGT_DOALWAYS; + q2->qclass = C_IN; + q2->qtype = T_AAAA; + q2->answer = q2->qbuf.buf; + q2->anslen = sizeof(q2->qbuf); + q2->next = q3; + /* try AAAA only when A6 query fails */ + q2->action = RESTGT_AFTERFAILURE; + q3->qclass = C_IN; + q3->qtype = T_A; + q3->answer = q3->qbuf.buf; + q3->anslen = sizeof(q3->qbuf); + q3->action = RESTGT_DOALWAYS; + break; + case AF_INET: + q->qclass = C_IN; + q->qtype = T_A; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->action = RESTGT_DOALWAYS; + break; + case AF_INET6: + q->qclass = C_IN; + q->qtype = ns_t_a6; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->next = q2; +#ifdef RES_USE_A6 + if ((pvt->res->options & RES_USE_A6) == 0) + q->action = RESTGT_IGNORE; + else +#endif + q->action = RESTGT_DOALWAYS; + q2->qclass = C_IN; + q2->qtype = T_AAAA; + q2->answer = q2->qbuf.buf; + q2->anslen = sizeof(q2->qbuf); + q2->action = RESTGT_AFTERFAILURE; + break; + default: + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /* better error? */ + goto cleanup; + } + + /* + * if there aren't any dots, it could be a user-level alias. + * this is also done in res_nquery() since we are not the only + * function that looks up host names. + */ + if (!strchr(name, '.') && (cp = res_hostalias(pvt->res, name, + tmp, sizeof tmp))) + name = cp; + + for (p = q; p; p = p->next) { + struct addrinfo *ai; + + switch(p->action) { + case RESTGT_DOALWAYS: + break; + case RESTGT_AFTERFAILURE: + if (querystate == RESQRY_SUCCESS) + continue; + break; + case RESTGT_IGNORE: + continue; + } + + if ((n = res_nsearch(pvt->res, name, p->qclass, p->qtype, + p->answer, p->anslen)) < 0) { + querystate = RESQRY_FAIL; + continue; + } + (void)gethostans(this, p->answer, n, name, p->qtype, + pai->ai_family, /* XXX: meaningless */ + 0, &ai, pai); + if (ai) { + querystate = RESQRY_SUCCESS; + cur->ai_next = ai; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + else + querystate = RESQRY_FAIL; + } + + cleanup: + if (q != NULL) + memput(q, sizeof(*q)); + if (q2 != NULL) + memput(q2, sizeof(*q2)); + if (q3 != NULL) + memput(q3, sizeof(*q3)); + return(sentinel.ai_next); +} + +static const u_char * +ar_head(cp, count, msg, eom, pvt, name_ok) + const u_char *cp, *msg, *eom; + int count; + struct pvt *pvt; + int (*name_ok)(const char *); +{ + int n; + char buf[1024]; /* XXX */ + + while (count-- > 0 && cp < eom) { + n = dn_expand(msg, eom, cp, buf, sizeof(buf)); + if (n < 0 || !maybe_ok(pvt->res, buf, name_ok)) + goto end; + cp += n; /* name */ + if (cp + 3 * INT16SZ + INT32SZ >= eom) + goto end; + cp += INT16SZ; /* type */ + cp += INT16SZ + INT32SZ; /* class, TTL */ + n = ns_get16(cp); + cp += n + INT16SZ; /* len */ + } + return(cp); + + end: + return(eom); /* XXX */ +} + +/* XXX: too many arguments */ +static struct addrinfo * +a6_expand(const u_char *ansbuf, const u_char *a6p, + int a6len, const u_char *arp, const u_char *eom, + const struct in6_addr *in6, int plen, const struct addrinfo *pai, + struct pvt *pvt, int (*name_ok)(const char *), int *errorp) +{ + struct in6_addr a; + int n, pbyte, plen1, pbyte1, error = 0; + const u_char *cp; + struct addrinfo sentinel, *cur; + char pname[1024], buf[1024]; /* XXX */ + + *errorp = NETDB_SUCCESS; + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + /* + * Validate A6 parameters. + */ + if (a6len == 0) { /* an A6 record must contain at least 1 byte. */ + error = NO_RECOVERY; + goto bad; + } + /* prefix length check. */ + if ((plen1 = *a6p) > 128) { + error = NO_RECOVERY; + goto bad; + } + if (plen1 > plen) { + /* + * New length must not be greater than old one. + * Ignore the record as specified in RFC 2874 + * Section 3.1.2. + */ + return(NULL); /* just ignore. */ + } + /* boundary check for new plen and prefix addr */ + pbyte1 = (plen1 & ~7) / 8; + if ((int)sizeof(struct in6_addr) - pbyte1 > a6len - 1) { + error = NO_RECOVERY; + goto bad; + } + + /* + * merge the new prefix portion. + * <--- plen(bits) ---> + * <--- pbyte ---><-b-> + * 000000000000000pppppxxxxxxxxxxx(= in6, 0: unknown, x: known, p: pad) + * PP++++++++(+ should be merged. P: padding, must be 0) + * <-- plen1--> + * <-pbyte1-> + * ^a6p+1 + * The result should be: + * 0000000000PP++++++++xxxxxxxxxxx(= a) + */ + pbyte = (plen & ~7) / 8; + a = *in6; + if (pbyte > pbyte1) { + /* N.B. the case of "pbyte1 == 128" is implicitly excluded. */ + int b = plen % 8; /* = the length of "pp..." above */ + u_char c_hi, c_lo; + + memcpy(&a.s6_addr[pbyte1], a6p + 1, pbyte - pbyte1); + if (b > 0) { + c_hi = a6p[pbyte - pbyte1 + 1]; + c_lo = in6->s6_addr[pbyte]; + a.s6_addr[pbyte] = + (c_hi & (0xff << (8 - b))) | + ((0x00ff >> b) & c_lo); + } + } + +#if 0 /* for debug */ + if ((pvt->res->options & RES_DEBUG) != 0) { + u_char ntopbuf[INET6_ADDRSTRLEN]; + + inet_ntop(AF_INET6, &a, ntopbuf, sizeof(ntopbuf)); + printf("a6_expand: %s\\%d\n", ntopbuf, plen1); + } +#endif + + if (plen1 == 0) { + /* Here is the end of A6 chain. make addrinfo, then return. */ + return(addr2addrinfo(pai, (const char *)&a)); + } + + /* + * Expand the new prefix name. Since the prefix name must not be + * compressed (RFC 2874 Section 3.1.1), we could use ns_name_ntop() + * here if it had a stricter boundary check. + */ + cp = a6p + 1 + (sizeof(*in6) - pbyte1); + n = dn_expand(ansbuf, eom, cp, pname, sizeof(pname)); + if (n < 0 || !maybe_ok(pvt->res, pname, name_ok)) { + error = NO_RECOVERY; + goto bad; + } + if (cp + n != a6p + a6len) { /* length mismatch */ + error = NO_RECOVERY; + goto bad; + } + + /* + * we need (more) additional section records, but no one is + * available, which possibly means a malformed answer. + */ + if (arp == NULL) { + error = NO_RECOVERY; /* we can't resolve the chain. */ + goto bad; + } + + /* + * Loop thru the rest of the buffer, searching for the next A6 record + * that has the same owner name as the prefix name. If found, then + * recursively call this function to expand the whole A6 chain. + */ + plen = plen1; + for (cp = arp; cp != NULL && cp < eom; cp += n) { + int class, type; + + n = dn_expand(ansbuf, eom, cp, buf, sizeof(buf)); + if (n < 0 || !maybe_ok(pvt->res, buf, name_ok)) { + error = NO_RECOVERY; + goto bad; + } + cp += n; /* name */ + if (cp + 3 * INT16SZ + INT32SZ > eom) { + error = NO_RECOVERY; + goto bad; + } + type = ns_get16(cp); + cp += INT16SZ; /* type */ + class = ns_get16(cp); + cp += INT16SZ + INT32SZ; /* class, TTL */ + n = ns_get16(cp); + cp += INT16SZ; /* len */ + if (cp + n > eom) { + error = NO_RECOVERY; + goto bad; + } + if (class != C_IN || type != ns_t_a6) { + /* we are only interested in A6 records. skip others */ + continue; + } + + if (ns_samename(buf, pname) != 1) { + continue; + } + + /* Proceed to the next record in the chain. */ + cur->ai_next = a6_expand(ansbuf, cp, n, cp + n, eom, + (const struct in6_addr *)&a, + plen, pai, pvt, name_ok, &error); + if (error != NETDB_SUCCESS) + goto bad; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + + return(sentinel.ai_next); + + bad: + *errorp = error; + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + return(NULL); +} + +static const char * +dname_subst(const char *qname0, const char *owner0, const char *target) { + char owner[MAXDNAME]; + static char qname[MAXDNAME]; + const char blabelhead[] = "\\[x"; /* we can assume hex strings */ + int qlen, olen; + int bufsiz = sizeof(qname); + + /* make local copies, which are canonicalized. */ + if (ns_makecanon(qname0, qname, sizeof(qname)) < 0 || + ns_makecanon(owner0, owner, sizeof(owner)) < 0) + return(NULL); + qlen = strlen(qname); + olen = strlen(owner); + /* from now on, do not refer to qname0 nor owner0. */ + + /* + * check if QNAME is a subdomain of OWNER. + * XXX: currently, we only handle the following two cases: + * (A) none of the labels are bitlabels, or + * (B) both of the head labels are bitlabels (and the following + * labels are NOT bitlabels). + * If we pass the check, then subtract the remaining part from QNAME. + * ex. (A) qname=www.foo.com,owner=foo.com => new qname=www. + * (B) qname=\[x3ffe0501/32].foo.com,owner=\[x3ffe/16].foo.com + * => new qname=\[x0501/16]. + */ + if (ns_samedomain(qname, owner)) { /* check (A) */ + /* at this point, qlen must not be smaller than olen */ + qname[qlen - olen] = 0; + bufsiz -= (qlen - olen); + } else { /* check (B) */ + char *parent0, *parent1; + /* the following 3 have enough size to store 1 bitlabel */ + u_char qlabel[64], olabel[64], newlabel[64]; + int qlabellen, olabellen; + + if (strncmp(qname, blabelhead, 3) != 0 || + strncmp(owner, blabelhead, 3) != 0) + return(NULL); + /* + * Both two begin with bitlabels. The succeeding parts + * must exact match. + */ + if ((parent0 = strchr(qname, '.')) == NULL || + (parent1 = strchr(owner, '.')) == NULL) + return(NULL); + + /* ns_samename allows names to begin with '.' */ + if (ns_samename(parent0, parent1) != 1) + return(NULL); + + /* cut the upper domain parts off. */ + *(parent0 + 1) = 0; + *(parent1 + 1) = 0; + /* convert the textual form into binary one. */ + if (ns_name_pton(qname, qlabel, sizeof(qlabel)) < 0 || + ns_name_pton(owner, olabel, sizeof(olabel)) < 0) + return(NULL); + if ((qlabellen = *(qlabel + 1)) == 0) + qlabellen = 256; + if ((olabellen = *(olabel + 1)) == 0) + olabellen = 256; + if (olabellen > qlabellen) + return(NULL); /* owner does not contain qname. */ + else { + int qplen = (qlabellen + 7) / 8; + int oplen = (olabellen + 7) / 8; + int sft = olabellen % 8; + int nllen, n; + u_char *qp, *op, *np; + + /* skip ELT and Count. */ + qp = qlabel + 2; + op = olabel + 2; + + /* check if olabel is a "subdomain" of qlabel. */ + if (memcmp(qp, op, oplen - 1) != 0) + return(NULL); + if (sft > 0) { + /* compare trailing bits (between 1 and 7) */ + if ((qp[qplen - 1] & (0xff << sft)) != + op[qplen - 1]) + return(NULL); + } + + /* OK, get remaining bits from qlabel. */ + np = newlabel; + if (olabellen == qlabellen) { + /* + * Two names (including bitlabels) are exactly + * same. Discard the whole names. + * XXX: ns_samename() above should exclude + * this case... + */ + qname[0] = 0; + goto maketarget; + } + *np++ = 0x41; /* XXX hardcoding */ + *np++ = nllen = (qlabellen - olabellen); + if (sft == 0) { + /* + * No alignment issue. can just use memcpy. + * Note that the "else" part below contains + * this case. We separate the two cases just + * for efficiency. + * We assume that ns_name_pton above ensures + * QP does not contain trailing garbages. + */ + memcpy(np, qp + oplen, qplen - oplen); + np += qplen - oplen; + *np = 0; + } else { + /* + * copy the lower (8-SFT) bits of QP to the + * upper (8-SFT) bits of NP, then copy the + * upper SFT bits of QP+1 to the lower SFT bits + * of NP, and so on... + * if QP is xxxyyyyy zzzwww..., then + * NP would be yyyyyzzz ... + * Again, we assume QP does not contain + * trailing garbages. + */ + qp += (oplen - 1); + while (nllen > 0) { + *np = (*qp << sft) & 0xff; + if ((nllen -= (8 - sft)) <= 0) + break; /* done */ + qp++; + *np |= ((*qp >> sft) & 0xff); + np++; + nllen -= sft; + } + *++np = 0; + } + + /* + * make a new bitlabel with the remaining bits. + * Note that there's no buffer boundary issue, since + * qlabel, olabel, and newlabel all have the same size. + * ns_name_ntop() must not return 0, since we have + * a non-empty bitlabel. + */ + if ((n = ns_name_ntop(newlabel, qname, sizeof(qname))) + <= 0) + return(NULL); + bufsiz -= n; + if (qname[n - 1] != '.') { /* XXX no trailing dot */ + qname[n - 1] = '.'; + qname[n] = 0; + bufsiz--; + } + + } + } + + maketarget: + /* + * Finally, append the remaining part (maybe empty) to the new target. + */ + if (bufsiz < (int)strlen(target)) /* bufsiz takes care of the \0. */ + return(NULL); + strcat(qname, target); + + return((const char *)qname); +} + +static void +ho_res_set(struct irs_ho *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +/* Private. */ + +static struct hostent * +gethostans(struct irs_ho *this, + const u_char *ansbuf, int anslen, const char *qname, int qtype, + int af, int size, /* meaningless for addrinfo cases */ + struct addrinfo **ret_aip, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + int type, class, ancount, qdcount, n, haveanswer, had_error; + int error = NETDB_SUCCESS, arcount; + int (*name_ok)(const char *); + const HEADER *hp; + const u_char *eom; + const u_char *eor; + const u_char *cp; + const char *tname; + const char *hname; + char *bp, *ep, **ap, **hap; + char tbuf[MAXDNAME+1]; + struct addrinfo sentinel, *cur, ai; + const u_char *arp = NULL; + + if (pai == NULL) abort(); + if (ret_aip != NULL) + *ret_aip = NULL; + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + tname = qname; + eom = ansbuf + anslen; + switch (qtype) { + case ns_t_a6: + case T_A: + case T_AAAA: + case T_ANY: /* use T_ANY only for T_A/T_AAAA lookup */ + name_ok = res_hnok; + break; + case T_PTR: + name_ok = res_dnok; + break; + default: + abort(); + } + + pvt->host.h_addrtype = af; + pvt->host.h_length = size; + hname = pvt->host.h_name = NULL; + + /* + * Find first satisfactory answer. + */ + if (ansbuf + HFIXEDSZ > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + hp = (const HEADER *)ansbuf; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + arcount = ntohs(hp->arcount); + bp = pvt->hostbuf; + ep = pvt->hostbuf + sizeof(pvt->hostbuf); + cp = ansbuf + HFIXEDSZ; + if (qdcount != 1) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + n = dn_expand(ansbuf, eom, cp, bp, ep - bp); + if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + cp += n + QFIXEDSZ; + if (cp > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + if (qtype == T_A || qtype == T_AAAA || + qtype == ns_t_a6 || qtype == T_ANY) { + /* res_nsend() has already verified that the query name is the + * same as the one we sent; this just gets the expanded name + * (i.e., with the succeeding search-domain tacked on). + */ + n = strlen(bp) + 1; /* for the \0 */ + if (n > MAXHOSTNAMELEN) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + pvt->host.h_name = bp; + hname = bp; + bp += n; + /* The qname can be abbreviated, but hname is now absolute. */ + qname = pvt->host.h_name; + } + ap = pvt->host_aliases; + *ap = NULL; + pvt->host.h_aliases = pvt->host_aliases; + hap = pvt->h_addr_ptrs; + *hap = NULL; + pvt->host.h_addr_list = pvt->h_addr_ptrs; + haveanswer = 0; + had_error = 0; + while (ancount-- > 0 && cp < eom && !had_error) { + n = dn_expand(ansbuf, eom, cp, bp, ep - bp); + if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) { + had_error++; + continue; + } + cp += n; /* name */ + BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); + type = ns_get16(cp); + cp += INT16SZ; /* type */ + class = ns_get16(cp); + cp += INT16SZ + INT32SZ; /* class, TTL */ + n = ns_get16(cp); + cp += INT16SZ; /* len */ + BOUNDS_CHECK(cp, n); + if (class != C_IN) { + cp += n; + continue; + } + eor = cp + n; + if ((qtype == T_A || qtype == T_AAAA || qtype == ns_t_a6 || + qtype == T_ANY) && type == T_CNAME) { + if (haveanswer) { + int level = LOG_CRIT; +#ifdef LOG_SECURITY + level |= LOG_SECURITY; +#endif + syslog(level, + "gethostans: possible attempt to exploit buffer overflow while looking up %s", + *qname ? qname : "."); + } + n = dn_expand(ansbuf, eor, cp, tbuf, sizeof tbuf); + if (n < 0 || !maybe_ok(pvt->res, tbuf, name_ok)) { + had_error++; + continue; + } + cp += n; + /* Store alias. */ + if (ap >= &pvt->host_aliases[MAXALIASES-1]) + continue; + *ap++ = bp; + n = strlen(bp) + 1; /* for the \0 */ + bp += n; + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > (ep - bp) || n > MAXHOSTNAMELEN) { + had_error++; + continue; + } + strcpy(bp, tbuf); + pvt->host.h_name = bp; + hname = bp; + bp += n; + continue; + } + if (type == ns_t_dname) { + const char *t0, *t; + + /* + * just replace the query target; do not update the + * alias list. (Or should we?) + */ + t0 = (qtype == T_PTR) ? tname : hname; + + n = dn_expand(ansbuf, eor, cp, tbuf, sizeof(tbuf)); + if (n < 0 || !maybe_dnok(pvt->res, tbuf)) { + had_error++; + continue; + } +#ifdef RES_USE_DNAME + if ((pvt ->res->options & RES_USE_DNAME) == 0) { + cp += n; + continue; + } +#endif + if ((t = dname_subst(t0, bp, tbuf)) == NULL) { + cp += n; + continue; + } +#if 0 /* for debug */ + if ((pvt->res->options & RES_DEBUG) != 0) { + printf("DNAME owner=%s, target=%s, next=%s\n", + bp, tbuf, t); + } +#endif + cp += n; + + n = strlen(t) + 1; /* for the \0 */ + if (n > (ep - bp)) { + had_error++; + continue; + } + strcpy(bp, t); + if (qtype == T_PTR) + tname = bp; + else + hname = bp; + bp += n; + + continue; + } + if (qtype == T_PTR && type == T_CNAME) { + n = dn_expand(ansbuf, eor, cp, tbuf, sizeof tbuf); + if (n < 0 || !maybe_dnok(pvt->res, tbuf)) { + had_error++; + continue; + } + cp += n; +#ifdef RES_USE_DNAME + if ((pvt->res->options & RES_USE_DNAME) != 0) +#endif + { + /* + * We may be able to check this regardless + * of the USE_DNAME bit, but we add the check + * for now since the DNAME support is + * experimental. + */ + if (ns_samename(tname, bp) != 1) + continue; + } + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > (ep - bp)) { + had_error++; + continue; + } + strcpy(bp, tbuf); + tname = bp; + bp += n; + continue; + } + if (qtype == T_ANY) { + if (!(type == T_A || type == T_AAAA || + type == ns_t_a6)) { + cp += n; + continue; + } + } else if (type != qtype) { + cp += n; + continue; + } + switch (type) { + case T_PTR: + if (ret_aip != NULL) { + /* addrinfo never needs T_PTR */ + cp += n; + continue; + } + if (ns_samename(tname, bp) != 1) { + cp += n; + continue; + } + n = dn_expand(ansbuf, eor, cp, bp, ep - bp); + if (n < 0 || !maybe_hnok(pvt->res, bp) || + n >= MAXHOSTNAMELEN) { + had_error++; + break; + } + cp += n; + if (!haveanswer) { + pvt->host.h_name = bp; + hname = bp; + } + else if (ap < &pvt->host_aliases[MAXALIASES-1]) + *ap++ = bp; + else + n = -1; + if (n != -1) { + n = strlen(bp) + 1; /* for the \0 */ + bp += n; + } + break; + case ns_t_a6: { + struct in6_addr in6; + struct addrinfo ai; + +#ifdef RES_USE_A6 + if ((pvt->res->options & RES_USE_A6) == 0) { + cp += n; + continue; + } +#endif + + if (ns_samename(hname, bp) != 1) { + cp += n; + continue; + } + + /* + * search for the top of the additional section. + * once found, keep it for the case where we have + * more than one A6 record. + * XXX: however, we may not need this part. + */ + if (arp == NULL && arcount > 0) { + int nscount = ntohs(hp->nscount); + + arp = ar_head(cp + n, nscount + ancount - 1, + ansbuf, eom, pvt, name_ok); + } + + /* recursively collect the whole A6 chain */ + ai = *pai; /* XXX: we can't override constant pai */ + ai.ai_family = AF_INET6; + memset(&in6, 0, sizeof(in6)); /* just for safety */ + cur->ai_next = a6_expand(ansbuf, cp, n, arp, eom, + &in6, 128, + (const struct addrinfo *)&ai, + pvt, name_ok, &error); + if (error != NETDB_SUCCESS) { +#ifdef DEBUG + /* in this case, cur->ai_next must be NULL. */ + if (cur->ai_next != NULL) + abort(); +#endif + had_error++; + continue; + } + + /* + * We don't bother even if cur->ai_next is NULL unless + * the expansion failed by a fatal error. The list + * can be NULL if the given A6 is incomplete, but we + * may have another complete A6 chain in this answer. + * See the last paragraph of RFC 2874 Section 3.1.4. + */ + if (cur->ai_next == NULL) { + cp += n; + continue; /* no error, no answer */ + } + goto convertinfo; + } /* FALLTHROUGH */ + case T_A: + case T_AAAA: + if (ns_samename(hname, bp) != 1) { + cp += n; + continue; + } + if (type == T_A && n != INADDRSZ) { + cp += n; + continue; + } + if (type == T_AAAA && n != IN6ADDRSZ) { + cp += n; + continue; + } + + /* make addrinfo. don't overwrite constant PAI */ + ai = *pai; + ai.ai_family = (type == T_AAAA) ? AF_INET6 : AF_INET; + cur->ai_next = addr2addrinfo( + (const struct addrinfo *)&ai, + (const char *)cp); + if (cur->ai_next == NULL) + had_error++; + + convertinfo: /* convert addrinfo into hostent form */ + if (!haveanswer) { + int nn; + + nn = strlen(bp) + 1; /* for the \0 */ + if (nn >= MAXHOSTNAMELEN) { + cp += n; + had_error++; + continue; + } + pvt->host.h_name = bp; + hname = bp; + bp += nn; + } + /* Ensure alignment. */ + bp = (char *)(((u_long)bp + (sizeof(align) - 1)) & + ~(sizeof(align) - 1)); + /* Avoid overflows. */ + if (bp + n >= &pvt->hostbuf[sizeof pvt->hostbuf]) { + had_error++; + continue; + } + if (ret_aip) { /* need addrinfo. keep it. */ + while (cur && cur->ai_next) + cur = cur->ai_next; + } else if (cur->ai_next) { /* need hostent */ + struct addrinfo *aip = cur->ai_next; + + for (aip = cur->ai_next; aip; + aip = aip->ai_next) { + int m; + + m = add_hostent(pvt, bp, hap, aip); + if (m < 0) { + had_error++; + break; + } + if (m == 0) + continue; + if (hap < &pvt->h_addr_ptrs[MAXADDRS-1]) + hap++; + + bp += m; + } + + freeaddrinfo(cur->ai_next); + cur->ai_next = NULL; + } + cp += n; + break; + default: + abort(); + } + if (!had_error) + haveanswer++; + } + if (haveanswer) { + if (ret_aip == NULL) { + *ap = NULL; + *hap = NULL; + + if (pvt->res->nsort && haveanswer > 1 && qtype == T_A) + addrsort(pvt->res, pvt->h_addr_ptrs, + haveanswer); + if (pvt->host.h_name == NULL) { + n = strlen(qname) + 1; /* for the \0 */ + if (n > (ep - bp) || n >= MAXHOSTNAMELEN) + goto no_recovery; + strcpy(bp, qname); + pvt->host.h_name = bp; + bp += n; + } + if (pvt->res->options & RES_USE_INET6) + map_v4v6_hostent(&pvt->host, &bp, ep); + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (&pvt->host); + } else { + if ((pai->ai_flags & AI_CANONNAME) != 0) { + if (pvt->host.h_name == NULL) { + sentinel.ai_next->ai_canonname = + strdup(qname); + } + else { + sentinel.ai_next->ai_canonname = + strdup(pvt->host.h_name); + } + } + *ret_aip = sentinel.ai_next; + return(NULL); + } + } + no_recovery: + if (sentinel.ai_next) { + /* this should be impossible, but check it for safety */ + freeaddrinfo(sentinel.ai_next); + } + if (error == NETDB_SUCCESS) + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + else + RES_SET_H_ERRNO(pvt->res, error); + return(NULL); +} + +static int +add_hostent(struct pvt *pvt, char *bp, char **hap, struct addrinfo *ai) +{ + int addrlen; + char *addrp; + const char **tap; + char *obp = bp; + + switch(ai->ai_addr->sa_family) { + case AF_INET6: + addrlen = IN6ADDRSZ; + addrp = (char *)&((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr; + break; + case AF_INET: + addrlen = INADDRSZ; + addrp = (char *)&((struct sockaddr_in *)ai->ai_addr)->sin_addr; + break; + default: + return(-1); /* abort? */ + } + + /* Ensure alignment. */ + bp = (char *)(((u_long)bp + (sizeof(align) - 1)) & + ~(sizeof(align) - 1)); + /* Avoid overflows. */ + if (bp + addrlen >= &pvt->hostbuf[sizeof pvt->hostbuf]) + return(-1); + if (hap >= &pvt->h_addr_ptrs[MAXADDRS-1]) + return(0); /* fail, but not treat it as an error. */ + + /* Suppress duplicates. */ + for (tap = (const char **)pvt->h_addr_ptrs; + *tap != NULL; + tap++) + if (memcmp(*tap, addrp, addrlen) == 0) + break; + if (*tap != NULL) + return (0); + + memcpy(*hap = bp, addrp, addrlen); + return((bp + addrlen) - obp); +} + +static void +map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep) { + char **ap; + + if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) + return; + hp->h_addrtype = AF_INET6; + hp->h_length = IN6ADDRSZ; + for (ap = hp->h_addr_list; *ap; ap++) { + int i = (u_long)*bpp % sizeof(align); + + if (i != 0) + i = sizeof(align) - i; + + if ((ep - *bpp) < (i + IN6ADDRSZ)) { + /* Out of memory. Truncate address list here. */ + *ap = NULL; + return; + } + *bpp += i; + map_v4v6_address(*ap, *bpp); + *ap = *bpp; + *bpp += IN6ADDRSZ; + } +} + +static void +addrsort(res_state statp, char **ap, int num) { + int i, j, needsort = 0, aval[MAXADDRS]; + char **p; + + p = ap; + for (i = 0; i < num; i++, p++) { + for (j = 0 ; (unsigned)j < statp->nsort; j++) + if (statp->sort_list[j].addr.s_addr == + (((struct in_addr *)(*p))->s_addr & + statp->sort_list[j].mask)) + break; + aval[i] = j; + if (needsort == 0 && i > 0 && j < aval[i-1]) + needsort = i; + } + if (!needsort) + return; + + while (needsort < num) { + for (j = needsort - 1; j >= 0; j--) { + if (aval[j] > aval[j+1]) { + char *hp; + + i = aval[j]; + aval[j] = aval[j+1]; + aval[j+1] = i; + + hp = ap[j]; + ap[j] = ap[j+1]; + ap[j+1] = hp; + + } else + break; + } + needsort++; + } +} + +static int +init(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !ho_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/dns_ho.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/dns_nw.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/dns_nw.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/dns_nw.c (revision 109985) @@ -0,0 +1,589 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_nw.c,v 1.23 2002/06/26 07:42:06 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "dns_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +/* Definitions. */ + +#define MAXALIASES 35 + +#define MAXPACKET (64*1024) + +struct pvt { + struct nwent net; + char * ali[MAXALIASES]; + char buf[BUFSIZ+1]; + struct __res_state * res; + void (*free_res)(void *); +}; + +typedef union { + long al; + char ac; +} align; + +enum by_what { by_addr, by_name }; + +/* Forwards. */ + +static void nw_close(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static struct nwent * nw_next(struct irs_nw *); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); +static struct __res_state * nw_res_get(struct irs_nw *this); +static void nw_res_set(struct irs_nw *this, + struct __res_state *res, + void (*free_res)(void *)); + +static struct nwent * get1101byaddr(struct irs_nw *, u_char *, int); +static struct nwent * get1101byname(struct irs_nw *, const char *); +static struct nwent * get1101answer(struct irs_nw *, + u_char *ansbuf, int anslen, + enum by_what by_what, + int af, const char *name, + const u_char *addr, int addrlen); +static struct nwent * get1101mask(struct irs_nw *this, struct nwent *); +static int make1101inaddr(const u_char *, int, char *, int); +static void normalize_name(char *name); +static int init(struct irs_nw *this); + +/* Exports. */ + +struct irs_nw * +irs_dns_nw(struct irs_acc *this) { + struct irs_nw *nw; + struct pvt *pvt; + + UNUSED(this); + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + nw->private = pvt; + nw->close = nw_close; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->next = nw_next; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + nw->res_get = nw_res_get; + nw->res_set = nw_res_set; + return (nw); +} + +/* Methods. */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + + if (init(this) == -1) + return (NULL); + + switch (af) { + case AF_INET: + return (get1101byname(this, name)); + default: + (void)NULL; + } + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + return (NULL); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + + if (init(this) == -1) + return (NULL); + + switch (af) { + case AF_INET: + return (get1101byaddr(this, net, len)); + default: + (void)NULL; + } + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + return (NULL); +} + +static struct nwent * +nw_next(struct irs_nw *this) { + + UNUSED(this); + + return (NULL); +} + +static void +nw_rewind(struct irs_nw *this) { + UNUSED(this); + /* NOOP */ +} + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +nw_res_get(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + nw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +nw_res_set(struct irs_nw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +/* Private. */ + +static struct nwent * +get1101byname(struct irs_nw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + u_char *ansbuf; + int anslen; + struct nwent *result; + + ansbuf = memget(MAXPACKET); + if (ansbuf == NULL) { + errno = ENOMEM; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + anslen = res_nsearch(pvt->res, name, C_IN, T_PTR, ansbuf, MAXPACKET); + if (anslen < 0) { + memput(ansbuf, MAXPACKET); + return (NULL); + } + result = get1101mask(this, get1101answer(this, ansbuf, anslen, by_name, + AF_INET, name, NULL, 0)); + memput(ansbuf, MAXPACKET); + return (result); +} + +static struct nwent * +get1101byaddr(struct irs_nw *this, u_char *net, int len) { + struct pvt *pvt = (struct pvt *)this->private; + char qbuf[sizeof "255.255.255.255.in-addr.arpa"]; + struct nwent *result; + u_char *ansbuf; + int anslen; + + if (len < 1 || len > 32) { + errno = EINVAL; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + if (make1101inaddr(net, len, qbuf, sizeof qbuf) < 0) + return (NULL); + ansbuf = memget(MAXPACKET); + if (ansbuf == NULL) { + errno = ENOMEM; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + anslen = res_nquery(pvt->res, qbuf, C_IN, T_PTR, ansbuf, MAXPACKET); + if (anslen < 0) { + memput(ansbuf, MAXPACKET); + return (NULL); + } + result = get1101mask(this, get1101answer(this, ansbuf, anslen, by_addr, + AF_INET, NULL, net, len)); + memput(ansbuf, MAXPACKET); + return (result); +} + +static struct nwent * +get1101answer(struct irs_nw *this, + u_char *ansbuf, int anslen, enum by_what by_what, + int af, const char *name, const u_char *addr, int addrlen) +{ + struct pvt *pvt = (struct pvt *)this->private; + int type, class, ancount, qdcount, haveanswer; + char *bp, *ep, **ap; + u_char *cp, *eom; + HEADER *hp; + + /* Initialize, and parse header. */ + eom = ansbuf + anslen; + if (ansbuf + HFIXEDSZ > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + hp = (HEADER *)ansbuf; + cp = ansbuf + HFIXEDSZ; + qdcount = ntohs(hp->qdcount); + while (qdcount-- > 0) { + int n = dn_skipname(cp, eom); + cp += n + QFIXEDSZ; + if (n < 0 || cp > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + } + ancount = ntohs(hp->ancount); + if (!ancount) { + if (hp->aa) + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + else + RES_SET_H_ERRNO(pvt->res, TRY_AGAIN); + return (NULL); + } + + /* Prepare a return structure. */ + bp = pvt->buf; + ep = pvt->buf + sizeof(pvt->buf); + pvt->net.n_name = NULL; + pvt->net.n_aliases = pvt->ali; + pvt->net.n_addrtype = af; + pvt->net.n_addr = NULL; + pvt->net.n_length = addrlen; + + /* Save input key if given. */ + switch (by_what) { + case by_name: + if (name != NULL) { + int n = strlen(name) + 1; + + if (n > (ep - bp)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + pvt->net.n_name = strcpy(bp, name); + bp += n; + } + break; + case by_addr: + if (addr != NULL && addrlen != 0) { + int n = addrlen / 8 + ((addrlen % 8) != 0); + + if (INADDRSZ > (ep - bp)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + memset(bp, 0, INADDRSZ); + memcpy(bp, addr, n); + pvt->net.n_addr = bp; + bp += INADDRSZ; + } + break; + default: + abort(); + } + + /* Parse the answer, collect aliases. */ + ap = pvt->ali; + haveanswer = 0; + while (--ancount >= 0 && cp < eom) { + int n = dn_expand(ansbuf, eom, cp, bp, ep - bp); + + cp += n; /* Owner */ + if (n < 0 || !maybe_dnok(pvt->res, bp) || + cp + 3 * INT16SZ + INT32SZ > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + GETSHORT(type, cp); /* Type */ + GETSHORT(class, cp); /* Class */ + cp += INT32SZ; /* TTL */ + GETSHORT(n, cp); /* RDLENGTH */ + if (class == C_IN && type == T_PTR) { + int nn; + + nn = dn_expand(ansbuf, eom, cp, bp, ep - bp); + if (nn < 0 || !maybe_hnok(pvt->res, bp) || nn != n) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + normalize_name(bp); + switch (by_what) { + case by_addr: { + if (pvt->net.n_name == NULL) + pvt->net.n_name = bp; + else if (ns_samename(pvt->net.n_name, bp) == 1) + break; + else + *ap++ = bp; + nn = strlen(bp) + 1; + bp += nn; + haveanswer++; + break; + } + case by_name: { + u_int b1, b2, b3, b4; + + if (pvt->net.n_addr != NULL || + sscanf(bp, "%u.%u.%u.%u.in-addr.arpa", + &b1, &b2, &b3, &b4) != 4) + break; + if ((ep - bp) < INADDRSZ) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + pvt->net.n_addr = bp; + *bp++ = b4; + *bp++ = b3; + *bp++ = b2; + *bp++ = b1; + pvt->net.n_length = INADDRSZ * 8; + haveanswer++; + } + } + } + cp += n; /* RDATA */ + } + if (!haveanswer) { + RES_SET_H_ERRNO(pvt->res, TRY_AGAIN); + return (NULL); + } + *ap = NULL; + + return (&pvt->net); +} + +static struct nwent * +get1101mask(struct irs_nw *this, struct nwent *nwent) { + struct pvt *pvt = (struct pvt *)this->private; + char qbuf[sizeof "255.255.255.255.in-addr.arpa"], owner[MAXDNAME]; + int anslen, type, class, ancount, qdcount; + u_char *ansbuf, *cp, *eom; + HEADER *hp; + + if (!nwent) + return (NULL); + if (make1101inaddr(nwent->n_addr, nwent->n_length, qbuf, sizeof qbuf) + < 0) { + /* "First, do no harm." */ + return (nwent); + } + + ansbuf = memget(MAXPACKET); + if (ansbuf == NULL) { + errno = ENOMEM; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + /* Query for the A RR that would hold this network's mask. */ + anslen = res_nquery(pvt->res, qbuf, C_IN, T_A, ansbuf, MAXPACKET); + if (anslen < HFIXEDSZ) { + memput(ansbuf, MAXPACKET); + return (nwent); + } + + /* Initialize, and parse header. */ + hp = (HEADER *)ansbuf; + cp = ansbuf + HFIXEDSZ; + eom = ansbuf + anslen; + qdcount = ntohs(hp->qdcount); + while (qdcount-- > 0) { + int n = dn_skipname(cp, eom); + cp += n + QFIXEDSZ; + if (n < 0 || cp > eom) { + memput(ansbuf, MAXPACKET); + return (nwent); + } + } + ancount = ntohs(hp->ancount); + + /* Parse the answer, collect aliases. */ + while (--ancount >= 0 && cp < eom) { + int n = dn_expand(ansbuf, eom, cp, owner, sizeof owner); + + if (n < 0 || !maybe_dnok(pvt->res, owner)) + break; + cp += n; /* Owner */ + if (cp + 3 * INT16SZ + INT32SZ > eom) + break; + GETSHORT(type, cp); /* Type */ + GETSHORT(class, cp); /* Class */ + cp += INT32SZ; /* TTL */ + GETSHORT(n, cp); /* RDLENGTH */ + if (cp + n > eom) + break; + if (n == INADDRSZ && class == C_IN && type == T_A && + ns_samename(qbuf, owner) == 1) { + /* This A RR indicates the actual netmask. */ + int nn, mm; + + nwent->n_length = 0; + for (nn = 0; nn < INADDRSZ; nn++) + for (mm = 7; mm >= 0; mm--) + if (cp[nn] & (1 << mm)) + nwent->n_length++; + else + break; + } + cp += n; /* RDATA */ + } + memput(ansbuf, MAXPACKET); + return (nwent); +} + +static int +make1101inaddr(const u_char *net, int bits, char *name, int size) { + int n, m; + + /* Zero fill any whole bytes left out of the prefix. */ + for (n = (32 - bits) / 8; n > 0; n--) { + if (size < (int)(sizeof "0.")) + goto emsgsize; + m = SPRINTF((name, "0.")); + name += m; + size -= m; + } + + /* Format the partial byte, if any, within the prefix. */ + if ((n = bits % 8) != 0) { + if (size < (int)(sizeof "255.")) + goto emsgsize; + m = SPRINTF((name, "%u.", + net[bits / 8] & ~((1 << (8 - n)) - 1))); + name += m; + size -= m; + } + + /* Format the whole bytes within the prefix. */ + for (n = bits / 8; n > 0; n--) { + if (size < (int)(sizeof "255.")) + goto emsgsize; + m = SPRINTF((name, "%u.", net[n - 1])); + name += m; + size -= m; + } + + /* Add the static text. */ + if (size < (int)(sizeof "in-addr.arpa")) + goto emsgsize; + (void) SPRINTF((name, "in-addr.arpa")); + return (0); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +static void +normalize_name(char *name) { + char *t; + + /* Make lower case. */ + for (t = name; *t; t++) + if (isascii((unsigned char)*t) && isupper((unsigned char)*t)) + *t = tolower(*t); + + /* Remove trailing dots. */ + while (t > name && t[-1] == '.') + *--t = '\0'; +} + +static int +init(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !nw_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/dns_nw.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/gethostent.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/gethostent.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/gethostent.c (revision 109985) @@ -0,0 +1,1042 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gethostent.c,v 1.32 2002/05/27 06:50:55 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "irs_data.h" + +/* Definitions */ + +struct pvt { + char * aliases[1]; + char * addrs[2]; + char addr[NS_IN6ADDRSZ]; + char name[NS_MAXDNAME + 1]; + struct hostent host; +}; + +/* Forward */ + +static struct net_data *init(void); +static void freepvt(struct net_data *); +static struct hostent *fakeaddr(const char *, int, struct net_data *); + + +/* Public */ + +struct hostent * +gethostbyname(const char *name) { + struct net_data *net_data = init(); + + return (gethostbyname_p(name, net_data)); +} + +struct hostent * +gethostbyname2(const char *name, int af) { + struct net_data *net_data = init(); + + return (gethostbyname2_p(name, af, net_data)); +} + +struct hostent * +gethostbyaddr(const char *addr, int len, int af) { + struct net_data *net_data = init(); + + return (gethostbyaddr_p(addr, len, af, net_data)); +} + +struct hostent * +gethostent() { + struct net_data *net_data = init(); + + return (gethostent_p(net_data)); +} + +void +sethostent(int stayopen) { + struct net_data *net_data = init(); + sethostent_p(stayopen, net_data); +} + + +void +endhostent() { + struct net_data *net_data = init(); + endhostent_p(net_data); +} + +/* Shared private. */ + +struct hostent * +gethostbyname_p(const char *name, struct net_data *net_data) { + struct hostent *hp; + + if (!net_data) + return (NULL); + + if (net_data->res->options & RES_USE_INET6) { + hp = gethostbyname2_p(name, AF_INET6, net_data); + if (hp) + return (hp); + } + return (gethostbyname2_p(name, AF_INET, net_data)); +} + +struct hostent * +gethostbyname2_p(const char *name, int af, struct net_data *net_data) { + struct irs_ho *ho; + char tmp[NS_MAXDNAME]; + struct hostent *hp; + const char *cp; + char **hap; + + if (!net_data || !(ho = net_data->ho)) + return (NULL); + if (net_data->ho_stayopen && net_data->ho_last && + net_data->ho_last->h_addrtype == af) { + if (ns_samename(name, net_data->ho_last->h_name) == 1) + return (net_data->ho_last); + for (hap = net_data->ho_last->h_aliases; hap && *hap; hap++) + if (ns_samename(name, *hap) == 1) + return (net_data->ho_last); + } + if (!strchr(name, '.') && (cp = res_hostalias(net_data->res, name, + tmp, sizeof tmp))) + name = cp; + if ((hp = fakeaddr(name, af, net_data)) != NULL) + return (hp); + net_data->ho_last = (*ho->byname2)(ho, name, af); + if (!net_data->ho_stayopen) + endhostent(); + return (net_data->ho_last); +} + +struct hostent * +gethostbyaddr_p(const char *addr, int len, int af, struct net_data *net_data) { + struct irs_ho *ho; + char **hap; + + if (!net_data || !(ho = net_data->ho)) + return (NULL); + if (net_data->ho_stayopen && net_data->ho_last && + net_data->ho_last->h_length == len) + for (hap = net_data->ho_last->h_addr_list; + hap && *hap; + hap++) + if (!memcmp(addr, *hap, len)) + return (net_data->ho_last); + net_data->ho_last = (*ho->byaddr)(ho, addr, len, af); + if (!net_data->ho_stayopen) + endhostent(); + return (net_data->ho_last); +} + + +struct hostent * +gethostent_p(struct net_data *net_data) { + struct irs_ho *ho; + struct hostent *hp; + + if (!net_data || !(ho = net_data->ho)) + return (NULL); + while ((hp = (*ho->next)(ho)) != NULL && + hp->h_addrtype == AF_INET6 && + (net_data->res->options & RES_USE_INET6) == 0) + continue; + net_data->ho_last = hp; + return (net_data->ho_last); +} + + +void +sethostent_p(int stayopen, struct net_data *net_data) { + struct irs_ho *ho; + + if (!net_data || !(ho = net_data->ho)) + return; + freepvt(net_data); + (*ho->rewind)(ho); + net_data->ho_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); +} + +void +endhostent_p(struct net_data *net_data) { + struct irs_ho *ho; + + if ((net_data != NULL) && ((ho = net_data->ho) != NULL)) + (*ho->minimize)(ho); +} + +#ifndef IN6_IS_ADDR_V4COMPAT +static const unsigned char in6addr_compat[12] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +#define IN6_IS_ADDR_V4COMPAT(x) (!memcmp((x)->s6_addr, in6addr_compat, 12) && \ + ((x)->s6_addr[12] != 0 || \ + (x)->s6_addr[13] != 0 || \ + (x)->s6_addr[14] != 0 || \ + ((x)->s6_addr[15] != 0 && \ + (x)->s6_addr[15] != 1))) +#endif +#ifndef IN6_IS_ADDR_V4MAPPED +#define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12)) +#endif + +static const unsigned char in6addr_mapped[12] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; + +static int scan_interfaces(int *, int *); +static struct hostent *copyandmerge(struct hostent *, struct hostent *, int, int *); + +/* + * Public functions + */ + +/* + * AI_V4MAPPED + AF_INET6 + * If no IPv6 address then a query for IPv4 and map returned values. + * + * AI_ALL + AI_V4MAPPED + AF_INET6 + * Return IPv6 and IPv4 mapped. + * + * AI_ADDRCONFIG + * Only return IPv6 / IPv4 address if there is an interface of that + * type active. + */ + +struct hostent * +getipnodebyname(const char *name, int af, int flags, int *error_num) { + int have_v4 = 1, have_v6 = 1; + struct in_addr in4; + struct in6_addr in6; + struct hostent he, *he1 = NULL, *he2 = NULL, *he3; + int v4 = 0, v6 = 0; + struct net_data *net_data = init(); + u_long options; + int tmp_err; + + if (net_data == NULL) { + *error_num = NO_RECOVERY; + return (NULL); + } + + /* If we care about active interfaces then check. */ + if ((flags & AI_ADDRCONFIG) != 0) + if (scan_interfaces(&have_v4, &have_v6) == -1) { + *error_num = NO_RECOVERY; + return (NULL); + } + + /* Check for literal address. */ + if ((v4 = inet_pton(AF_INET, name, &in4)) != 1) + v6 = inet_pton(AF_INET6, name, &in6); + + /* Impossible combination? */ + + if ((af == AF_INET6 && (flags & AI_V4MAPPED) == 0 && v4 == 1) || + (af == AF_INET && v6 == 1) || + (have_v4 == 0 && v4 == 1) || + (have_v6 == 0 && v6 == 1) || + (have_v4 == 0 && af == AF_INET) || + (have_v6 == 0 && af == AF_INET6)) { + *error_num = HOST_NOT_FOUND; + return (NULL); + } + + /* Literal address? */ + if (v4 == 1 || v6 == 1) { + char *addr_list[2]; + char *aliases[1]; + + DE_CONST(name, he.h_name); + he.h_addr_list = addr_list; + he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6; + he.h_addr_list[1] = NULL; + he.h_aliases = aliases; + he.h_aliases[0] = NULL; + he.h_length = (v4 == 1) ? INADDRSZ : IN6ADDRSZ; + he.h_addrtype = (v4 == 1) ? AF_INET : AF_INET6; + return (copyandmerge(&he, NULL, af, error_num)); + } + + options = net_data->res->options; + net_data->res->options &= ~RES_USE_INET6; + + tmp_err = NO_RECOVERY; + if (have_v6 && af == AF_INET6) { + he2 = gethostbyname2_p(name, AF_INET6, net_data); + if (he2 != NULL) { + he1 = copyandmerge(he2, NULL, af, error_num); + if (he1 == NULL) + return (NULL); + he2 = NULL; + } else { + tmp_err = net_data->res->res_h_errno; + } + } + + if (have_v4 && + ((af == AF_INET) || + (af == AF_INET6 && (flags & AI_V4MAPPED) != 0 && + (he1 == NULL || (flags & AI_ALL) != 0)))) { + he2 = gethostbyname2_p(name, AF_INET, net_data); + if (he1 == NULL && he2 == NULL) { + *error_num = net_data->res->res_h_errno; + return (NULL); + } + } else + *error_num = tmp_err; + + net_data->res->options = options; + + he3 = copyandmerge(he1, he2, af, error_num); + + if (he1 != NULL) + freehostent(he1); + return (he3); +} + +struct hostent * +getipnodebyaddr(const void *src, size_t len, int af, int *error_num) { + struct hostent *he1, *he2; + struct net_data *net_data = init(); + + /* Sanity Checks. */ + if (src == NULL) { + *error_num = NO_RECOVERY; + return (NULL); + } + + switch (af) { + case AF_INET: + if (len != INADDRSZ) { + *error_num = NO_RECOVERY; + return (NULL); + } + break; + case AF_INET6: + if (len != IN6ADDRSZ) { + *error_num = NO_RECOVERY; + return (NULL); + } + break; + default: + *error_num = NO_RECOVERY; + return (NULL); + } + + /* + * Lookup IPv4 and IPv4 mapped/compatible addresses + */ + if ((af == AF_INET6 && + IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)src)) || + (af == AF_INET6 && + IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src)) || + (af == AF_INET)) { + const char *cp = src; + + if (af == AF_INET6) + cp += 12; + he1 = gethostbyaddr_p(cp, 4, AF_INET, net_data); + if (he1 == NULL) { + *error_num = net_data->res->res_h_errno; + return (NULL); + } + he2 = copyandmerge(he1, NULL, af, error_num); + if (he2 == NULL) + return (NULL); + /* + * Restore original address if mapped/compatible. + */ + if (af == AF_INET6) + memcpy(he1->h_addr, src, len); + return (he2); + } + + /* + * Lookup IPv6 address. + */ + if (memcmp((const struct in6_addr *)src, &in6addr_any, 16) == 0) { + *error_num = HOST_NOT_FOUND; + return (NULL); + } + + he1 = gethostbyaddr_p(src, 16, AF_INET6, net_data); + if (he1 == NULL) { + *error_num = net_data->res->res_h_errno; + return (NULL); + } + return (copyandmerge(he1, NULL, af, error_num)); +} + +void +freehostent(struct hostent *he) { + char **cpp; + int names = 1; + int addresses = 1; + + memput(he->h_name, strlen(he->h_name) + 1); + + cpp = he->h_addr_list; + while (*cpp != NULL) { + memput(*cpp, (he->h_addrtype == AF_INET) ? + INADDRSZ : IN6ADDRSZ); + *cpp = NULL; + cpp++; + addresses++; + } + + cpp = he->h_aliases; + while (*cpp != NULL) { + memput(*cpp, strlen(*cpp) + 1); + cpp++; + names++; + } + + memput(he->h_aliases, sizeof(char *) * (names)); + memput(he->h_addr_list, sizeof(char *) * (addresses)); + memput(he, sizeof *he); +} + +/* + * Private + */ + +/* + * Scan the interface table and set have_v4 and have_v6 depending + * upon whether there are IPv4 and IPv6 interface addresses. + * + * Returns: + * 0 on success + * -1 on failure. + */ + +#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \ + !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF) + +#ifdef __hpux +#define lifc_len iflc_len +#define lifc_buf iflc_buf +#define lifc_req iflc_req +#define LIFCONF if_laddrconf +#else +#define SETFAMILYFLAGS +#define LIFCONF lifconf +#endif + +#ifdef __hpux +#define lifr_addr iflr_addr +#define lifr_name iflr_name +#define lifr_dstaddr iflr_dstaddr +#define lifr_flags iflr_flags +#define ss_family sa_family +#define LIFREQ if_laddrreq +#else +#define LIFREQ lifreq +#endif + +static int +scan_interfaces6(int *have_v4, int *have_v6) { + struct LIFCONF lifc; + struct LIFREQ lifreq; + struct in_addr in4; + struct in6_addr in6; + char *buf = NULL, *cp, *cplim; + static unsigned int bufsiz = 4095; + int s, cpsize, n; + + /* Set to zero. Used as loop terminators below. */ + *have_v4 = *have_v6 = 0; + + /* Get interface list from system. */ + if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) == -1) + goto err_ret; + + /* + * Grow buffer until large enough to contain all interface + * descriptions. + */ + for (;;) { + buf = memget(bufsiz); + if (buf == NULL) + goto err_ret; +#ifdef SETFAMILYFLAGS + lifc.lifc_family = AF_UNSPEC; /* request all families */ + lifc.lifc_flags = 0; +#endif + lifc.lifc_len = bufsiz; + lifc.lifc_buf = buf; + if ((n = ioctl(s, SIOCGLIFCONF, (char *)&lifc)) != -1) { + /* + * Some OS's just return what will fit rather + * than set EINVAL if the buffer is too small + * to fit all the interfaces in. If + * lifc.lifc_len is too near to the end of the + * buffer we will grow it just in case and + * retry. + */ + if (lifc.lifc_len + 2 * sizeof(lifreq) < bufsiz) + break; + } + if ((n == -1) && errno != EINVAL) + goto err_ret; + + if (bufsiz > 1000000) + goto err_ret; + + memput(buf, bufsiz); + bufsiz += 4096; + } + + /* Parse system's interface list. */ + cplim = buf + lifc.lifc_len; /* skip over if's with big ifr_addr's */ + for (cp = buf; + (*have_v4 == 0 || *have_v6 == 0) && cp < cplim; + cp += cpsize) { + memcpy(&lifreq, cp, sizeof lifreq); +#ifdef HAVE_SA_LEN +#ifdef FIX_ZERO_SA_LEN + if (lifreq.lifr_addr.sa_len == 0) + lifreq.lifr_addr.sa_len = 16; +#endif +#ifdef HAVE_MINIMUM_IFREQ + cpsize = sizeof lifreq; + if (lifreq.lifr_addr.sa_len > sizeof (struct sockaddr)) + cpsize += (int)lifreq.lifr_addr.sa_len - + (int)(sizeof (struct sockaddr)); +#else + cpsize = sizeof lifreq.lifr_name + lifreq.lifr_addr.sa_len; +#endif /* HAVE_MINIMUM_IFREQ */ +#elif defined SIOCGIFCONF_ADDR + cpsize = sizeof lifreq; +#else + cpsize = sizeof lifreq.lifr_name; + /* XXX maybe this should be a hard error? */ + if (ioctl(s, SIOCGLIFADDR, (char *)&lifreq) < 0) + continue; +#endif + switch (lifreq.lifr_addr.ss_family) { + case AF_INET: + if (*have_v4 == 0) { + memcpy(&in4, + &((struct sockaddr_in *) + &lifreq.lifr_addr)->sin_addr, + sizeof in4); + if (in4.s_addr == INADDR_ANY) + break; + n = ioctl(s, SIOCGLIFFLAGS, (char *)&lifreq); + if (n < 0) + break; + if ((lifreq.lifr_flags & IFF_UP) == 0) + break; + *have_v4 = 1; + } + break; + case AF_INET6: + if (*have_v6 == 0) { + memcpy(&in6, + &((struct sockaddr_in6 *) + &lifreq.lifr_addr)->sin6_addr, sizeof in6); + if (memcmp(&in6, &in6addr_any, sizeof in6) == 0) + break; + n = ioctl(s, SIOCGLIFFLAGS, (char *)&lifreq); + if (n < 0) + break; + if ((lifreq.lifr_flags & IFF_UP) == 0) + break; + *have_v6 = 1; + } + break; + } + } + if (buf != NULL) + memput(buf, bufsiz); + close(s); + /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */ + return (0); + err_ret: + if (buf != NULL) + memput(buf, bufsiz); + if (s != -1) + close(s); + /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */ + return (-1); +} + +#endif + +static int +scan_interfaces(int *have_v4, int *have_v6) { + struct ifconf ifc; + union { + char _pad[256]; /* leave space for IPv6 addresses */ + struct ifreq ifreq; + } u; + struct in_addr in4; + struct in6_addr in6; + char *buf = NULL, *cp, *cplim; + static unsigned int bufsiz = 4095; + int s, n; + size_t cpsize; + +#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \ + !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF) + /* + * Try to scan the interfaces using IPv6 ioctls(). + */ + if (!scan_interfaces6(have_v4, have_v6)) + return (0); +#endif + + /* Set to zero. Used as loop terminators below. */ + *have_v4 = *have_v6 = 0; + + /* Get interface list from system. */ + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) + goto err_ret; + + /* + * Grow buffer until large enough to contain all interface + * descriptions. + */ + for (;;) { + buf = memget(bufsiz); + if (buf == NULL) + goto err_ret; + ifc.ifc_len = bufsiz; + ifc.ifc_buf = buf; +#ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF + /* + * This is a fix for IRIX OS in which the call to ioctl with + * the flag SIOCGIFCONF may not return an entry for all the + * interfaces like most flavors of Unix. + */ + if (emul_ioctl(&ifc) >= 0) + break; +#else + if ((n = ioctl(s, SIOCGIFCONF, (char *)&ifc)) != -1) { + /* + * Some OS's just return what will fit rather + * than set EINVAL if the buffer is too small + * to fit all the interfaces in. If + * ifc.ifc_len is too near to the end of the + * buffer we will grow it just in case and + * retry. + */ + if (ifc.ifc_len + 2 * sizeof(u.ifreq) < bufsiz) + break; + } +#endif + if ((n == -1) && errno != EINVAL) + goto err_ret; + + if (bufsiz > 1000000) + goto err_ret; + + memput(buf, bufsiz); + bufsiz += 4096; + } + + /* Parse system's interface list. */ + cplim = buf + ifc.ifc_len; /* skip over if's with big ifr_addr's */ + for (cp = buf; + (*have_v4 == 0 || *have_v6 == 0) && cp < cplim; + cp += cpsize) { + memcpy(&u.ifreq, cp, sizeof u.ifreq); +#ifdef HAVE_SA_LEN +#ifdef FIX_ZERO_SA_LEN + if (u.ifreq.ifr_addr.sa_len == 0) + u.ifreq.ifr_addr.sa_len = 16; +#endif +#ifdef HAVE_MINIMUM_IFREQ + cpsize = sizeof u.ifreq; + if (u.ifreq.ifr_addr.sa_len > sizeof (struct sockaddr)) + cpsize += (int)u.ifreq.ifr_addr.sa_len - + (int)(sizeof (struct sockaddr)); +#else + cpsize = sizeof u.ifreq.ifr_name + u.ifreq.ifr_addr.sa_len; +#endif /* HAVE_MINIMUM_IFREQ */ + if (cpsize > sizeof u.ifreq && cpsize <= sizeof u) + memcpy(&u.ifreq, cp, cpsize); +#elif defined SIOCGIFCONF_ADDR + cpsize = sizeof u.ifreq; +#else + cpsize = sizeof u.ifreq.ifr_name; + /* XXX maybe this should be a hard error? */ + if (ioctl(s, SIOCGIFADDR, (char *)&u.ifreq) < 0) + continue; +#endif + switch (u.ifreq.ifr_addr.sa_family) { + case AF_INET: + if (*have_v4 == 0) { + memcpy(&in4, + &((struct sockaddr_in *) + &u.ifreq.ifr_addr)->sin_addr, + sizeof in4); + if (in4.s_addr == INADDR_ANY) + break; + n = ioctl(s, SIOCGIFFLAGS, (char *)&u.ifreq); + if (n < 0) + break; + if ((u.ifreq.ifr_flags & IFF_UP) == 0) + break; + *have_v4 = 1; + } + break; + case AF_INET6: + if (*have_v6 == 0) { + memcpy(&in6, + &((struct sockaddr_in6 *) + &u.ifreq.ifr_addr)->sin6_addr, + sizeof in6); + if (memcmp(&in6, &in6addr_any, sizeof in6) == 0) + break; + n = ioctl(s, SIOCGIFFLAGS, (char *)&u.ifreq); + if (n < 0) + break; + if ((u.ifreq.ifr_flags & IFF_UP) == 0) + break; + *have_v6 = 1; + } + break; + } + } + if (buf != NULL) + memput(buf, bufsiz); + close(s); + /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */ + return (0); + err_ret: + if (buf != NULL) + memput(buf, bufsiz); + if (s != -1) + close(s); + /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */ + return (-1); +} + +static struct hostent * +copyandmerge(struct hostent *he1, struct hostent *he2, int af, int *error_num) { + struct hostent *he = NULL; + int addresses = 1; /* NULL terminator */ + int names = 1; /* NULL terminator */ + int len = 0; + char **cpp, **npp; + + /* + * Work out array sizes; + */ + if (he1 != NULL) { + cpp = he1->h_addr_list; + while (*cpp != NULL) { + addresses++; + cpp++; + } + cpp = he1->h_aliases; + while (*cpp != NULL) { + names++; + cpp++; + } + } + + if (he2 != NULL) { + cpp = he2->h_addr_list; + while (*cpp != NULL) { + addresses++; + cpp++; + } + if (he1 == NULL) { + cpp = he2->h_aliases; + while (*cpp != NULL) { + names++; + cpp++; + } + } + } + + if (addresses == 1) { + *error_num = NO_ADDRESS; + return (NULL); + } + + he = memget(sizeof *he); + if (he == NULL) + goto no_recovery; + + he->h_addr_list = memget(sizeof(char *) * (addresses)); + if (he->h_addr_list == NULL) + goto cleanup0; + memset(he->h_addr_list, 0, sizeof(char *) * (addresses)); + + /* copy addresses */ + npp = he->h_addr_list; + if (he1 != NULL) { + cpp = he1->h_addr_list; + while (*cpp != NULL) { + *npp = memget((af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + if (*npp == NULL) + goto cleanup1; + /* convert to mapped if required */ + if (af == AF_INET6 && he1->h_addrtype == AF_INET) { + memcpy(*npp, in6addr_mapped, + sizeof in6addr_mapped); + memcpy(*npp + sizeof in6addr_mapped, *cpp, + INADDRSZ); + } else { + memcpy(*npp, *cpp, + (af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + } + cpp++; + npp++; + } + } + + if (he2 != NULL) { + cpp = he2->h_addr_list; + while (*cpp != NULL) { + *npp = memget((af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + if (*npp == NULL) + goto cleanup1; + /* convert to mapped if required */ + if (af == AF_INET6 && he2->h_addrtype == AF_INET) { + memcpy(*npp, in6addr_mapped, + sizeof in6addr_mapped); + memcpy(*npp + sizeof in6addr_mapped, *cpp, + INADDRSZ); + } else { + memcpy(*npp, *cpp, + (af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + } + cpp++; + npp++; + } + } + + he->h_aliases = memget(sizeof(char *) * (names)); + if (he->h_aliases == NULL) + goto cleanup1; + memset(he->h_aliases, 0, sizeof(char *) * (names)); + + /* copy aliases */ + npp = he->h_aliases; + cpp = (he1 != NULL) ? he1->h_aliases : he2->h_aliases; + while (*cpp != NULL) { + len = strlen (*cpp) + 1; + *npp = memget(len); + if (*npp == NULL) + goto cleanup2; + strcpy(*npp, *cpp); + npp++; + cpp++; + } + + /* copy hostname */ + he->h_name = memget(strlen((he1 != NULL) ? + he1->h_name : he2->h_name) + 1); + if (he->h_name == NULL) + goto cleanup2; + strcpy(he->h_name, (he1 != NULL) ? he1->h_name : he2->h_name); + + /* set address type and length */ + he->h_addrtype = af; + he->h_length = (af == AF_INET) ? INADDRSZ : IN6ADDRSZ; + return(he); + + cleanup2: + cpp = he->h_aliases; + while (*cpp != NULL) { + memput(*cpp, strlen(*cpp) + 1); + cpp++; + } + memput(he->h_aliases, sizeof(char *) * (names)); + + cleanup1: + cpp = he->h_addr_list; + while (*cpp != NULL) { + memput(*cpp, (af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + *cpp = NULL; + cpp++; + } + memput(he->h_addr_list, sizeof(char *) * (addresses)); + + cleanup0: + memput(he, sizeof *he); + + no_recovery: + *error_num = NO_RECOVERY; + return (NULL); +} + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->ho) { + net_data->ho = (*net_data->irs->ho_map)(net_data->irs); + if (!net_data->ho || !net_data->res) { + error: + errno = EIO; + if (net_data && net_data->res) + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + + (*net_data->ho->res_set)(net_data->ho, net_data->res, NULL); + } + + return (net_data); +} + +static void +freepvt(struct net_data *net_data) { + if (net_data->ho_data) { + free(net_data->ho_data); + net_data->ho_data = NULL; + } +} + +static struct hostent * +fakeaddr(const char *name, int af, struct net_data *net_data) { + struct pvt *pvt; + + freepvt(net_data); + net_data->ho_data = malloc(sizeof (struct pvt)); + if (!net_data->ho_data) { + errno = ENOMEM; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + pvt = net_data->ho_data; +#ifndef __bsdi__ + /* + * Unlike its forebear(inet_aton), our friendly inet_pton() is strict + * in its interpretation of its input, and it will only return "1" if + * the input string is a formally valid(and thus unambiguous with + * respect to host names) internet address specification for this AF. + * + * This means "telnet 0xdeadbeef" and "telnet 127.1" are dead now. + */ + if (inet_pton(af, name, pvt->addr) != 1) { +#else + /* BSDI XXX + * We put this back to inet_aton -- we really want the old behavior + * Long live 127.1... + */ + if ((af != AF_INET || + inet_aton(name, (struct in_addr *)pvt->addr) != 1) && + inet_pton(af, name, pvt->addr) != 1) { +#endif + RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); + return (NULL); + } + strncpy(pvt->name, name, NS_MAXDNAME); + pvt->name[NS_MAXDNAME] = '\0'; + if (af == AF_INET && (net_data->res->options & RES_USE_INET6) != 0) { + map_v4v6_address(pvt->addr, pvt->addr); + af = AF_INET6; + } + pvt->host.h_addrtype = af; + switch(af) { + case AF_INET: + pvt->host.h_length = NS_INADDRSZ; + break; + case AF_INET6: + pvt->host.h_length = NS_IN6ADDRSZ; + break; + default: + errno = EAFNOSUPPORT; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + pvt->host.h_name = pvt->name; + pvt->host.h_aliases = pvt->aliases; + pvt->aliases[0] = NULL; + pvt->addrs[0] = (char *)pvt->addr; + pvt->addrs[1] = NULL; + pvt->host.h_addr_list = pvt->addrs; + RES_SET_H_ERRNO(net_data->res, NETDB_SUCCESS); + return (&pvt->host); +} + +#ifdef grot /* for future use in gethostbyaddr(), for "SUNSECURITY" */ + struct hostent *rhp; + char **haddr; + u_long old_options; + char hname2[MAXDNAME+1]; + + if (af == AF_INET) { + /* + * turn off search as the name should be absolute, + * 'localhost' should be matched by defnames + */ + strncpy(hname2, hp->h_name, MAXDNAME); + hname2[MAXDNAME] = '\0'; + old_options = net_data->res->options; + net_data->res->options &= ~RES_DNSRCH; + net_data->res->options |= RES_DEFNAMES; + if (!(rhp = gethostbyname(hname2))) { + net_data->res->options = old_options; + RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); + return (NULL); + } + net_data->res->options = old_options; + for (haddr = rhp->h_addr_list; *haddr; haddr++) + if (!memcmp(*haddr, addr, INADDRSZ)) + break; + if (!*haddr) { + RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); + return (NULL); + } + } +#endif /* grot */ + +#endif /*__BIND_NOSTATIC*/ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/gethostent.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/getaddrinfo.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/getaddrinfo.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/getaddrinfo.c (revision 109985) @@ -0,0 +1,1218 @@ +/* $KAME: getaddrinfo.c,v 1.14 2001/01/06 09:41:15 jinmei Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 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. Neither the name of the project 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 PROJECT 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 PROJECT 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 + * SUCH DAMAGE. + */ + +/* + * Issues to be discussed: + * - Thread safe-ness must be checked. + * - Return values. There are nonstandard return values defined and used + * in the source code. This is because RFC2553 is silent about which error + * code must be returned for which situation. + * - IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2 + * says to use inet_aton() to convert IPv4 numeric to binary (allows + * classful form as a result). + * current code - disallow classful form for IPv4 (due to use of inet_pton). + * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is + * invalid. + * current code - SEGV on freeaddrinfo(NULL) + * Note: + * - We use getipnodebyname() just for thread-safeness. There's no intent + * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to + * getipnodebyname(). + * - The code filters out AFs that are not supported by the kernel, + * when globbing NULL hostname (to loopback, or wildcard). Is it the right + * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG + * in ai_flags? + * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague. + * (1) what should we do against numeric hostname (2) what should we do + * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready? + * non-loopback address configured? global address configured? + * - To avoid search order issue, we have a big amount of code duplicate + * from gethnamaddr.c and some other places. The issues that there's no + * lower layer function to lookup "IPv4 or IPv6" record. Calling + * gethostbyname2 from getaddrinfo will end up in wrong search order, as + * follows: + * - The code makes use of following calls when asked to resolver with + * ai_family = PF_UNSPEC: + * getipnodebyname(host, AF_INET6); + * getipnodebyname(host, AF_INET); + * This will result in the following queries if the node is configure to + * prefer /etc/hosts than DNS: + * lookup /etc/hosts for IPv6 address + * lookup DNS for IPv6 address + * lookup /etc/hosts for IPv4 address + * lookup DNS for IPv4 address + * which may not meet people's requirement. + * The right thing to happen is to have underlying layer which does + * PF_UNSPEC lookup (lookup both) and return chain of addrinfos. + * This would result in a bit of code duplicate with _dns_ghbyname() and + * friends. + */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "port_after.h" + +#include "irs_data.h" + +/* + * if we enable it, we will see duplicated addrinfo entries on reply if both + * AAAA and A6 records are found. disable it for default installation. + */ +#undef T_A6 + +#define SUCCESS 0 +#define ANY 0 +#define YES 1 +#define NO 0 + +static const char in_addrany[] = { 0, 0, 0, 0 }; +static const char in6_addrany[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +static const char in_loopback[] = { 127, 0, 0, 1 }; +static const char in6_loopback[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 +}; + +static const struct afd { + int a_af; + int a_addrlen; + int a_socklen; + int a_off; + const char *a_addrany; + const char *a_loopback; + int a_scoped; +} afdl [] = { + {PF_INET6, sizeof(struct in6_addr), + sizeof(struct sockaddr_in6), + offsetof(struct sockaddr_in6, sin6_addr), + in6_addrany, in6_loopback, 1}, + {PF_INET, sizeof(struct in_addr), + sizeof(struct sockaddr_in), + offsetof(struct sockaddr_in, sin_addr), + in_addrany, in_loopback, 0}, + {0, 0, 0, 0, NULL, NULL, 0}, +}; + +struct explore { + int e_af; + int e_socktype; + int e_protocol; + const char *e_protostr; + int e_wild; +#define WILD_AF(ex) ((ex)->e_wild & 0x01) +#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) +#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) +}; + +static const struct explore explore[] = { +#if 0 + { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 }, +#endif + { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, + { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, + { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 }, + { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, + { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, + { PF_INET, SOCK_RAW, ANY, NULL, 0x05 }, + { -1, 0, 0, NULL, 0 }, +}; + +#define PTON_MAX 16 + +static int str_isnumber __P((const char *)); +static int explore_fqdn __P((const struct addrinfo *, const char *, + const char *, struct addrinfo **)); +static int explore_copy __P((const struct addrinfo *, const struct addrinfo *, + struct addrinfo **)); +static int explore_null __P((const struct addrinfo *, + const char *, struct addrinfo **)); +static int explore_numeric __P((const struct addrinfo *, const char *, + const char *, struct addrinfo **)); +static int explore_numeric_scope __P((const struct addrinfo *, const char *, + const char *, struct addrinfo **)); +static int get_canonname __P((const struct addrinfo *, + struct addrinfo *, const char *)); +static struct addrinfo *get_ai __P((const struct addrinfo *, + const struct afd *, const char *)); +static struct addrinfo *copy_ai __P((const struct addrinfo *)); +static int get_portmatch __P((const struct addrinfo *, const char *)); +static int get_port __P((const struct addrinfo *, const char *, int)); +static const struct afd *find_afd __P((int)); +static int addrconfig __P((int)); +static int ip6_str2scopeid __P((char *, struct sockaddr_in6 *)); +static struct net_data *init __P((void)); + +struct addrinfo *hostent2addrinfo __P((struct hostent *, + const struct addrinfo *)); +struct addrinfo *addr2addrinfo __P((const struct addrinfo *, + const char *)); + +#if 0 +static const char *ai_errlist[] = { + "Success", + "Address family for hostname not supported", /* EAI_ADDRFAMILY */ + "Temporary failure in name resolution", /* EAI_AGAIN */ + "Invalid value for ai_flags", /* EAI_BADFLAGS */ + "Non-recoverable failure in name resolution", /* EAI_FAIL */ + "ai_family not supported", /* EAI_FAMILY */ + "Memory allocation failure", /* EAI_MEMORY */ + "No address associated with hostname", /* EAI_NODATA */ + "hostname nor servname provided, or not known", /* EAI_NONAME */ + "servname not supported for ai_socktype", /* EAI_SERVICE */ + "ai_socktype not supported", /* EAI_SOCKTYPE */ + "System error returned in errno", /* EAI_SYSTEM */ + "Invalid value for hints", /* EAI_BADHINTS */ + "Resolved protocol is unknown", /* EAI_PROTOCOL */ + "Unknown error", /* EAI_MAX */ +}; +#endif + +/* XXX macros that make external reference is BAD. */ + +#define GET_AI(ai, afd, addr) \ +do { \ + /* external reference: pai, error, and label free */ \ + (ai) = get_ai(pai, (afd), (addr)); \ + if ((ai) == NULL) { \ + error = EAI_MEMORY; \ + goto free; \ + } \ +} while (/*CONSTCOND*/0) + +#define GET_PORT(ai, serv) \ +do { \ + /* external reference: error and label free */ \ + error = get_port((ai), (serv), 0); \ + if (error != 0) \ + goto free; \ +} while (/*CONSTCOND*/0) + +#define GET_CANONNAME(ai, str) \ +do { \ + /* external reference: pai, error and label free */ \ + error = get_canonname(pai, (ai), (str)); \ + if (error != 0) \ + goto free; \ +} while (/*CONSTCOND*/0) + +#define ERR(err) \ +do { \ + /* external reference: error, and label bad */ \ + error = (err); \ + goto bad; \ + /*NOTREACHED*/ \ +} while (/*CONSTCOND*/0) + +#define MATCH_FAMILY(x, y, w) \ + ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC))) +#define MATCH(x, y, w) \ + ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY))) + +#if 0 /* bind8 has its own version */ +char * +gai_strerror(ecode) + int ecode; +{ + if (ecode < 0 || ecode > EAI_MAX) + ecode = EAI_MAX; + return ai_errlist[ecode]; +} +#endif + +void +freeaddrinfo(ai) + struct addrinfo *ai; +{ + struct addrinfo *next; + + do { + next = ai->ai_next; + if (ai->ai_canonname) + free(ai->ai_canonname); + /* no need to free(ai->ai_addr) */ + free(ai); + ai = next; + } while (ai); +} + +static int +str_isnumber(p) + const char *p; +{ + char *ep; + + if (*p == '\0') + return NO; + ep = NULL; + (void)strtoul(p, &ep, 10); + if (ep && *ep == '\0') + return YES; + else + return NO; +} + +int +getaddrinfo(hostname, servname, hints, res) + const char *hostname, *servname; + const struct addrinfo *hints; + struct addrinfo **res; +{ + struct addrinfo sentinel; + struct addrinfo *cur; + int error = 0; + struct addrinfo ai, ai0, *afai = NULL; + struct addrinfo *pai; + const struct explore *ex; + + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + pai = &ai; + pai->ai_flags = 0; + pai->ai_family = PF_UNSPEC; + pai->ai_socktype = ANY; + pai->ai_protocol = ANY; + pai->ai_addrlen = 0; + pai->ai_canonname = NULL; + pai->ai_addr = NULL; + pai->ai_next = NULL; + + if (hostname == NULL && servname == NULL) + return EAI_NONAME; + if (hints) { + /* error check for hints */ + if (hints->ai_addrlen || hints->ai_canonname || + hints->ai_addr || hints->ai_next) + ERR(EAI_BADHINTS); /* xxx */ + if (hints->ai_flags & ~AI_MASK) + ERR(EAI_BADFLAGS); + switch (hints->ai_family) { + case PF_UNSPEC: + case PF_INET: + case PF_INET6: + break; + default: + ERR(EAI_FAMILY); + } + memcpy(pai, hints, sizeof(*pai)); + + /* + * if both socktype/protocol are specified, check if they + * are meaningful combination. + */ + if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { + for (ex = explore; ex->e_af >= 0; ex++) { + if (pai->ai_family != ex->e_af) + continue; + if (ex->e_socktype == ANY) + continue; + if (ex->e_protocol == ANY) + continue; + if (pai->ai_socktype == ex->e_socktype && + pai->ai_protocol != ex->e_protocol) { + ERR(EAI_BADHINTS); + } + } + } + } + + /* + * post-2553: AI_ALL and AI_V4MAPPED are effective only against + * AF_INET6 query. They needs to be ignored if specified in other + * occassions. + */ + switch (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) { + case AI_V4MAPPED: + case AI_ALL | AI_V4MAPPED: + if (pai->ai_family != AF_INET6) + pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); + break; + case AI_ALL: +#if 1 + /* illegal */ + ERR(EAI_BADFLAGS); +#else + pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); + break; +#endif + } + + /* + * check for special cases. (1) numeric servname is disallowed if + * socktype/protocol are left unspecified. (2) servname is disallowed + * for raw and other inet{,6} sockets. + */ + if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) +#ifdef PF_INET6 + || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) +#endif + ) { + ai0 = *pai; /* backup *pai */ + + if (pai->ai_family == PF_UNSPEC) { +#ifdef PF_INET6 + pai->ai_family = PF_INET6; +#else + pai->ai_family = PF_INET; +#endif + } + error = get_portmatch(pai, servname); + if (error) + ERR(error); + + *pai = ai0; + } + + ai0 = *pai; + + /* NULL hostname, or numeric hostname */ + for (ex = explore; ex->e_af >= 0; ex++) { + *pai = ai0; + + if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) + continue; + if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) + continue; + if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) + continue; + + if (pai->ai_family == PF_UNSPEC) + pai->ai_family = ex->e_af; + if (pai->ai_socktype == ANY && ex->e_socktype != ANY) + pai->ai_socktype = ex->e_socktype; + if (pai->ai_protocol == ANY && ex->e_protocol != ANY) + pai->ai_protocol = ex->e_protocol; + + /* + * if the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + continue; + + if (hostname == NULL) { + /* + * filter out AFs that are not supported by the kernel + * XXX errno? + */ + if (!addrconfig(pai->ai_family)) + continue; + error = explore_null(pai, servname, &cur->ai_next); + } else + error = explore_numeric_scope(pai, hostname, servname, + &cur->ai_next); + + if (error) + goto free; + + while (cur && cur->ai_next) + cur = cur->ai_next; + } + + /* + * XXX + * If numreic representation of AF1 can be interpreted as FQDN + * representation of AF2, we need to think again about the code below. + */ + if (sentinel.ai_next) + goto good; + + if (pai->ai_flags & AI_NUMERICHOST) + ERR(EAI_NONAME); + if (hostname == NULL) + ERR(EAI_NONAME); + + /* + * hostname as alphabetical name. + * We'll make sure that + * - if returning addrinfo list is empty, return non-zero error + * value (already known one or EAI_NONAME). + * - otherwise, + * + if we haven't had any errors, return 0 (i.e. success). + * + if we've had an error, free the list and return the error. + * without any assumption on the behavior of explore_fqdn(). + */ + + /* first, try to query DNS for all possible address families. */ + *pai = ai0; + error = explore_fqdn(pai, hostname, servname, &afai); + if (error) { + if (afai != NULL) + freeaddrinfo(afai); + goto free; + } + if (afai == NULL) { + error = EAI_NONAME; /* we've had no errors. */ + goto free; + } + + /* + * we would like to prefer AF_INET6 than AF_INET, so we'll make an + * outer loop by AFs. + */ + for (ex = explore; ex->e_af >= 0; ex++) { + *pai = ai0; + + if (pai->ai_family == PF_UNSPEC) + pai->ai_family = ex->e_af; + + if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) + continue; + if (!MATCH(pai->ai_socktype, ex->e_socktype, + WILD_SOCKTYPE(ex))) { + continue; + } + if (!MATCH(pai->ai_protocol, ex->e_protocol, + WILD_PROTOCOL(ex))) { + continue; + } + +#ifdef AI_ADDRCONFIG + /* + * If AI_ADDRCONFIG is specified, check if we are + * expected to return the address family or not. + */ + if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && + !addrconfig(pai->ai_family)) + continue; +#endif + + if (pai->ai_family == PF_UNSPEC) + pai->ai_family = ex->e_af; + if (pai->ai_socktype == ANY && ex->e_socktype != ANY) + pai->ai_socktype = ex->e_socktype; + if (pai->ai_protocol == ANY && ex->e_protocol != ANY) + pai->ai_protocol = ex->e_protocol; + + /* + * if the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + continue; + + if ((error = explore_copy(pai, afai, &cur->ai_next)) != 0) { + freeaddrinfo(afai); + goto free; + } + + while (cur && cur->ai_next) + cur = cur->ai_next; + } + + freeaddrinfo(afai); /* afai must not be NULL at this point. */ + + /* we must not have got any errors. */ + if (error != 0) /* just for diagnosis */ + abort(); + + if (sentinel.ai_next) { +good: + *res = sentinel.ai_next; + return(SUCCESS); + } else { + /* + * All the process succeeded, but we've had an empty list. + * This can happen if the given hints do not match our + * candidates. + */ + error = EAI_NONAME; + } + +free: +bad: + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + *res = NULL; + return(error); +} + +/* + * FQDN hostname, DNS lookup + */ +static int +explore_fqdn(pai, hostname, servname, res) + const struct addrinfo *pai; + const char *hostname; + const char *servname; + struct addrinfo **res; +{ + struct addrinfo *result; + struct addrinfo *cur; + struct net_data *net_data = init(); + struct irs_ho *ho; + int error = 0; + char tmp[NS_MAXDNAME]; + const char *cp; + + result = NULL; + + /* + * if the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + return(0); + + if (!net_data || !(ho = net_data->ho)) + return(0); +#if 0 /* XXX (notyet) */ + if (net_data->ho_stayopen && net_data->ho_last && + net_data->ho_last->h_addrtype == af) { + if (ns_samename(name, net_data->ho_last->h_name) == 1) + return (net_data->ho_last); + for (hap = net_data->ho_last->h_aliases; hap && *hap; hap++) + if (ns_samename(name, *hap) == 1) + return (net_data->ho_last); + } +#endif + if (!strchr(hostname, '.') && + (cp = res_hostalias(net_data->res, hostname, + tmp, sizeof(tmp)))) + hostname = cp; + result = (*ho->addrinfo)(ho, hostname, pai); + if (!net_data->ho_stayopen) { + (*ho->minimize)(ho); + } + if (result == NULL) { + int e = h_errno; + + switch(e) { + case NETDB_INTERNAL: + error = EAI_SYSTEM; + break; + case TRY_AGAIN: + error = EAI_AGAIN; + break; + case NO_RECOVERY: + error = EAI_FAIL; + break; + case HOST_NOT_FOUND: + case NO_DATA: + error = EAI_NONAME; + break; + default: + case NETDB_SUCCESS: /* should be impossible... */ + error = EAI_NONAME; + break; + } + goto free; + } + + for (cur = result; cur; cur = cur->ai_next) { + GET_PORT(cur, servname); /* XXX: redundant lookups... */ + /* canonname should already be filled. */ + } + + *res = result; + + return(0); + +free: + if (result) + freeaddrinfo(result); + return error; +} + +static int +explore_copy(pai, src0, res) + const struct addrinfo *pai; /* seed */ + const struct addrinfo *src0; /* source */ + struct addrinfo **res; +{ + int error; + struct addrinfo sentinel, *cur; + const struct addrinfo *src; + + error = 0; + sentinel.ai_next = NULL; + cur = &sentinel; + + for (src = src0; src != NULL; src = src->ai_next) { + if (src->ai_family != pai->ai_family) + continue; + + cur->ai_next = copy_ai(src); + if (!cur->ai_next) { + error = EAI_MEMORY; + goto fail; + } + + cur->ai_next->ai_socktype = pai->ai_socktype; + cur->ai_next->ai_protocol = pai->ai_protocol; + cur = cur->ai_next; + } + + *res = sentinel.ai_next; + return 0; + +fail: + freeaddrinfo(sentinel.ai_next); + return error; +} + +/* + * hostname == NULL. + * passive socket -> anyaddr (0.0.0.0 or ::) + * non-passive socket -> localhost (127.0.0.1 or ::1) + */ +static int +explore_null(pai, servname, res) + const struct addrinfo *pai; + const char *servname; + struct addrinfo **res; +{ + const struct afd *afd; + struct addrinfo *cur; + struct addrinfo sentinel; + int error; + + *res = NULL; + sentinel.ai_next = NULL; + cur = &sentinel; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return 0; + + if (pai->ai_flags & AI_PASSIVE) { + GET_AI(cur->ai_next, afd, afd->a_addrany); + /* xxx meaningless? + * GET_CANONNAME(cur->ai_next, "anyaddr"); + */ + GET_PORT(cur->ai_next, servname); + } else { + GET_AI(cur->ai_next, afd, afd->a_loopback); + /* xxx meaningless? + * GET_CANONNAME(cur->ai_next, "localhost"); + */ + GET_PORT(cur->ai_next, servname); + } + cur = cur->ai_next; + + *res = sentinel.ai_next; + return 0; + +free: + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + return error; +} + +/* + * numeric hostname + */ +static int +explore_numeric(pai, hostname, servname, res) + const struct addrinfo *pai; + const char *hostname; + const char *servname; + struct addrinfo **res; +{ + const struct afd *afd; + struct addrinfo *cur; + struct addrinfo sentinel; + int error; + char pton[PTON_MAX]; + + *res = NULL; + sentinel.ai_next = NULL; + cur = &sentinel; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return 0; + + switch (afd->a_af) { +#if 0 /*X/Open spec*/ + case AF_INET: + if (inet_aton(hostname, (struct in_addr *)pton) == 1) { + if (pai->ai_family == afd->a_af || + pai->ai_family == PF_UNSPEC /*?*/) { + GET_AI(cur->ai_next, afd, pton); + GET_PORT(cur->ai_next, servname); + while (cur && cur->ai_next) + cur = cur->ai_next; + } else + ERR(EAI_FAMILY); /*xxx*/ + } + break; +#endif + default: + if (inet_pton(afd->a_af, hostname, pton) == 1) { + if (pai->ai_family == afd->a_af || + pai->ai_family == PF_UNSPEC /*?*/) { + GET_AI(cur->ai_next, afd, pton); + GET_PORT(cur->ai_next, servname); + while (cur && cur->ai_next) + cur = cur->ai_next; + } else + ERR(EAI_FAMILY); /*xxx*/ + } + break; + } + + *res = sentinel.ai_next; + return 0; + +free: +bad: + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + return error; +} + +/* + * numeric hostname with scope + */ +static int +explore_numeric_scope(pai, hostname, servname, res) + const struct addrinfo *pai; + const char *hostname; + const char *servname; + struct addrinfo **res; +{ +#ifndef SCOPE_DELIMITER + return explore_numeric(pai, hostname, servname, res); +#else + const struct afd *afd; + struct addrinfo *cur; + int error; + char *cp, *hostname2 = NULL, *scope, *addr; + struct sockaddr_in6 *sin6; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return 0; + + if (!afd->a_scoped) + return explore_numeric(pai, hostname, servname, res); + + cp = strchr(hostname, SCOPE_DELIMITER); + if (cp == NULL) + return explore_numeric(pai, hostname, servname, res); + + /* + * Handle special case of + */ + hostname2 = strdup(hostname); + if (hostname2 == NULL) + return EAI_MEMORY; + /* terminate at the delimiter */ + hostname2[cp - hostname] = '\0'; + addr = hostname2; + scope = cp + 1; + + error = explore_numeric(pai, addr, servname, res); + if (error == 0) { + int scopeid; + + for (cur = *res; cur; cur = cur->ai_next) { + if (cur->ai_family != AF_INET6) + continue; + sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr; + if ((scopeid = ip6_str2scopeid(scope, sin6)) == -1) { + free(hostname2); + return(EAI_NONAME); /* XXX: is return OK? */ + } +#ifdef HAVE_SIN6_SCOPE_ID + sin6->sin6_scope_id = scopeid; +#endif + } + } + + free(hostname2); + + return error; +#endif +} + +static int +get_canonname(pai, ai, str) + const struct addrinfo *pai; + struct addrinfo *ai; + const char *str; +{ + if ((pai->ai_flags & AI_CANONNAME) != 0) { + ai->ai_canonname = (char *)malloc(strlen(str) + 1); + if (ai->ai_canonname == NULL) + return EAI_MEMORY; + strcpy(ai->ai_canonname, str); + } + return 0; +} + +static struct addrinfo * +get_ai(pai, afd, addr) + const struct addrinfo *pai; + const struct afd *afd; + const char *addr; +{ + char *p; + struct addrinfo *ai; + + ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + + (afd->a_socklen)); + if (ai == NULL) + return NULL; + + memcpy(ai, pai, sizeof(struct addrinfo)); + ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); + memset(ai->ai_addr, 0, (size_t)afd->a_socklen); +#ifdef HAVE_SA_LEN + ai->ai_addr->sa_len = afd->a_socklen; +#endif + ai->ai_addrlen = afd->a_socklen; + ai->ai_addr->sa_family = ai->ai_family = afd->a_af; + p = (char *)(void *)(ai->ai_addr); + memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); + return ai; +} + +/* XXX need to malloc() the same way we do from other functions! */ +static struct addrinfo * +copy_ai(pai) + const struct addrinfo *pai; +{ + struct addrinfo *ai; + size_t l; + + l = sizeof(*ai) + pai->ai_addrlen; + if ((ai = (struct addrinfo *)malloc(l)) == NULL) + return NULL; + memset(ai, 0, l); + memcpy(ai, pai, sizeof(*ai)); + ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); + memcpy(ai->ai_addr, pai->ai_addr, pai->ai_addrlen); + + if (pai->ai_canonname) { + l = strlen(pai->ai_canonname) + 1; + if ((ai->ai_canonname = malloc(l)) == NULL) { + free(ai); + return NULL; + } +#ifdef HAVE_STRLCPY + strlcpy(ai->ai_canonname, pai->ai_canonname, l); +#else + strncpy(ai->ai_canonname, pai->ai_canonname, l); +#endif + } else { + /* just to make sure */ + ai->ai_canonname = NULL; + } + + ai->ai_next = NULL; + + return ai; +} + +static int +get_portmatch(const struct addrinfo *ai, const char *servname) { + + /* get_port does not touch first argument. when matchonly == 1. */ + /* LINTED const cast */ + return get_port((const struct addrinfo *)ai, servname, 1); +} + +static int +get_port(const struct addrinfo *ai, const char *servname, int matchonly) { + const char *proto; + struct servent *sp; + int port; + int allownumeric; + + if (servname == NULL) + return 0; + switch (ai->ai_family) { + case AF_INET: +#ifdef AF_INET6 + case AF_INET6: +#endif + break; + default: + return 0; + } + + switch (ai->ai_socktype) { + case SOCK_RAW: + return EAI_SERVICE; + case SOCK_DGRAM: + case SOCK_STREAM: + allownumeric = 1; + break; + case ANY: + allownumeric = 0; + break; + default: + return EAI_SOCKTYPE; + } + + if (str_isnumber(servname)) { + if (!allownumeric) + return EAI_SERVICE; + port = htons(atoi(servname)); + if (port < 0 || port > 65535) + return EAI_SERVICE; + } else { + switch (ai->ai_socktype) { + case SOCK_DGRAM: + proto = "udp"; + break; + case SOCK_STREAM: + proto = "tcp"; + break; + default: + proto = NULL; + break; + } + + if ((sp = getservbyname(servname, proto)) == NULL) + return EAI_SERVICE; + port = sp->s_port; + } + + if (!matchonly) { + switch (ai->ai_family) { + case AF_INET: + ((struct sockaddr_in *)(void *) + ai->ai_addr)->sin_port = port; + break; + case AF_INET6: + ((struct sockaddr_in6 *)(void *) + ai->ai_addr)->sin6_port = port; + break; + } + } + + return 0; +} + +static const struct afd * +find_afd(af) + int af; +{ + const struct afd *afd; + + if (af == PF_UNSPEC) + return NULL; + for (afd = afdl; afd->a_af; afd++) { + if (afd->a_af == af) + return afd; + } + return NULL; +} + +/* + * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend + * will take care of it. + * the semantics of AI_ADDRCONFIG is not defined well. we are not sure + * if the code is right or not. + */ +static int +addrconfig(af) + int af; +{ + int s; + + /* XXX errno */ + s = socket(af, SOCK_DGRAM, 0); + if (s < 0) { + if (errno != EMFILE) + return 0; + } else + close(s); + return 1; +} + +/* convert a string to a scope identifier. XXX: IPv6 specific */ +static int +ip6_str2scopeid(scope, sin6) + char *scope; + struct sockaddr_in6 *sin6; +{ + int scopeid; + struct in6_addr *a6 = &sin6->sin6_addr; + char *ep; + + /* empty scopeid portion is invalid */ + if (*scope == '\0') + return -1; + +#ifdef USE_IFNAMELINKID + if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) { + /* + * Using interface names as link indices can be allowed + * only when we can assume a one-to-one mappings between + * links and interfaces. See comments in getnameinfo.c. + */ + scopeid = if_nametoindex(scope); + if (scopeid == 0) + goto trynumeric; + return(scopeid); + } +#endif + + /* still unclear about literal, allow numeric only - placeholder */ + if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) + goto trynumeric; + if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) + goto trynumeric; + else + goto trynumeric; /* global */ + + /* try to convert to a numeric id as a last resort */ +trynumeric: + scopeid = (int)strtoul(scope, &ep, 10); + if (*ep == '\0') + return scopeid; + else + return -1; +} + +struct addrinfo * +hostent2addrinfo(hp, pai) + struct hostent *hp; + const struct addrinfo *pai; +{ + int i, af, error = 0; + char **aplist = NULL, *ap; + struct addrinfo sentinel, *cur; + const struct afd *afd; + + af = hp->h_addrtype; + if (pai->ai_family != AF_UNSPEC && af != pai->ai_family) + return(NULL); + + afd = find_afd(af); + if (afd == NULL) + return(NULL); + + aplist = hp->h_addr_list; + + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + for (i = 0; (ap = aplist[i]) != NULL; i++) { +#if 0 /* the trick seems too much */ + af = hp->h_addr_list; + if (af == AF_INET6 && + IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) { + af = AF_INET; + ap = ap + sizeof(struct in6_addr) + - sizeof(struct in_addr); + } + afd = find_afd(af); + if (afd == NULL) + continue; +#endif /* 0 */ + + GET_AI(cur->ai_next, afd, ap); + + /* GET_PORT(cur->ai_next, servname); */ + if ((pai->ai_flags & AI_CANONNAME) != 0) { + /* + * RFC2553 says that ai_canonname will be set only for + * the first element. we do it for all the elements, + * just for convenience. + */ + GET_CANONNAME(cur->ai_next, hp->h_name); + } + while (cur && cur->ai_next) /* no need to loop, actually. */ + cur = cur->ai_next; + continue; + + free: + if (cur->ai_next) + freeaddrinfo(cur->ai_next); + cur->ai_next = NULL; + /* continue, without tht pointer CUR advanced. */ + } + + return(sentinel.ai_next); +} + +struct addrinfo * +addr2addrinfo(pai, cp) + const struct addrinfo *pai; + const char *cp; +{ + const struct afd *afd; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return(NULL); + + return(get_ai(pai, afd, cp)); +} + +static struct net_data * +init() +{ + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->ho) { + net_data->ho = (*net_data->irs->ho_map)(net_data->irs); + if (!net_data->ho || !net_data->res) { +error: + errno = EIO; + if (net_data && net_data->res) + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + + (*net_data->ho->res_set)(net_data->ho, net_data->res, NULL); + } + + return (net_data); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/getaddrinfo.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/getnameinfo.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/getnameinfo.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/getnameinfo.c (revision 109985) @@ -0,0 +1,321 @@ +/* + * Issues to be discussed: + * - Thread safe-ness must be checked + */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 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 WIDE Project and + * its contributors. + * 4. Neither the name of the project 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 PROJECT 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 PROJECT 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 + * SUCH DAMAGE. + */ + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +/* + * Note that a_off will be dynamically adjusted so that to be consistent + * with the definition of sockaddr_in{,6}. + * The value presented below is just a guess. + */ +static struct afd { + int a_af; + int a_addrlen; + size_t a_socklen; + int a_off; +} afdl [] = { + /* first entry is linked last... */ + {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in), + offsetof(struct sockaddr_in, sin_addr)}, + {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6), + offsetof(struct sockaddr_in6, sin6_addr)}, + {0, 0, 0, 0}, +}; + +struct sockinet { +#ifdef HAVE_SA_LEN + u_char si_len; +#endif + u_char si_family; + u_short si_port; +}; + +static int ip6_parsenumeric __P((const struct sockaddr *, const char *, char *, + size_t, int)); +#ifdef HAVE_SIN6_SCOPE_ID +static int ip6_sa2str __P((const struct sockaddr_in6 *, char *, size_t, int)); +#endif + +int +getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) + const struct sockaddr *sa; + size_t salen; + char *host; + size_t hostlen; + char *serv; + size_t servlen; + int flags; +{ + struct afd *afd; + struct servent *sp; + struct hostent *hp; + u_short port; +#ifdef HAVE_SA_LEN + size_t len; +#endif + int family, i; + const char *addr; + char *p; + char numserv[512]; + char numaddr[512]; + const struct sockaddr_in6 *sin6; + + if (sa == NULL) + return EAI_FAIL; + +#ifdef HAVE_SA_LEN + len = sa->sa_len; + if (len != salen) return EAI_FAIL; +#endif + + family = sa->sa_family; + for (i = 0; afdl[i].a_af; i++) + if (afdl[i].a_af == family) { + afd = &afdl[i]; + goto found; + } + return EAI_FAMILY; + + found: + if (salen != afd->a_socklen) return EAI_FAIL; + + port = ((const struct sockinet *)sa)->si_port; /* network byte order */ + addr = (const char *)sa + afd->a_off; + + if (serv == NULL || servlen == 0) { + /* + * rfc2553bis says that serv == NULL or servlen == 0 means that + * the caller does not want the result. + */ + } else if (flags & NI_NUMERICSERV) { + sprintf(numserv, "%d", ntohs(port)); + if (strlen(numserv) > servlen) + return EAI_MEMORY; + strcpy(serv, numserv); + } else { + sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp"); + if (sp) { + if (strlen(sp->s_name) + 1 > servlen) + return EAI_MEMORY; + strcpy(serv, sp->s_name); + } else + return EAI_NONAME; + } + + switch (sa->sa_family) { + case AF_INET: + if (ntohl(*(const u_long *)addr) >> IN_CLASSA_NSHIFT == 0) + flags |= NI_NUMERICHOST; + break; + case AF_INET6: + sin6 = (const struct sockaddr_in6 *)sa; + switch (sin6->sin6_addr.s6_addr[0]) { + case 0x00: + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) + ; + else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) + ; + else + flags |= NI_NUMERICHOST; + break; + default: + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) + flags |= NI_NUMERICHOST; + else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) + flags |= NI_NUMERICHOST; + break; + } + break; + } + if (host == NULL || hostlen == 0) { + /* + * rfc2553bis says that host == NULL or hostlen == 0 means that + * the caller does not want the result. + */ + } else if (flags & NI_NUMERICHOST) { + goto numeric; + } else { + hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af); + + if (hp) { + if (flags & NI_NOFQDN) { + p = strchr(hp->h_name, '.'); + if (p) *p = '\0'; + } + if (strlen(hp->h_name) + 1 > hostlen) + return EAI_MEMORY; + strcpy(host, hp->h_name); + } else { + if (flags & NI_NAMEREQD) + return EAI_NONAME; + numeric: + switch(afd->a_af) { + case AF_INET6: + { + int error; + + if ((error = ip6_parsenumeric(sa, addr, host, + hostlen, + flags)) != 0) + return(error); + break; + } + + default: + if (inet_ntop(afd->a_af, addr, numaddr, + sizeof(numaddr)) == NULL) + return EAI_NONAME; + if (strlen(numaddr) + 1 > hostlen) + return EAI_MEMORY; + strcpy(host, numaddr); + } + } + } + return(0); +} + +static int +ip6_parsenumeric(const struct sockaddr *sa, const char *addr, char *host, + size_t hostlen, int flags) +{ + size_t numaddrlen; + char numaddr[512]; + +#ifndef HAVE_SIN6_SCOPE_ID + UNUSED(sa); + UNUSED(flags); +#endif + + if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) + == NULL) + return EAI_SYSTEM; + + numaddrlen = strlen(numaddr); + if (numaddrlen + 1 > hostlen) /* don't forget terminator */ + return EAI_MEMORY; + strcpy(host, numaddr); + +#ifdef HAVE_SIN6_SCOPE_ID + if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) { + char scopebuf[MAXHOSTNAMELEN]; /* XXX */ + int scopelen; + + /* ip6_sa2str never fails */ + scopelen = ip6_sa2str((const struct sockaddr_in6 *)sa, + scopebuf, sizeof(scopebuf), flags); + + if (scopelen + 1 + numaddrlen + 1 > hostlen) + return EAI_MEMORY; + + /* construct */ + memcpy(host + numaddrlen + 1, scopebuf, + scopelen); + host[numaddrlen] = SCOPE_DELIMITER; + host[numaddrlen + 1 + scopelen] = '\0'; + } +#endif + + return 0; +} + +#ifdef HAVE_SIN6_SCOPE_ID +/* ARGSUSED */ +static int +ip6_sa2str(const struct sockaddr_in6 *sa6, char *buf, + size_t bufsiz, int flags) +{ +#ifdef USE_IFNAMELINKID + unsigned int ifindex = (unsigned int)sa6->sin6_scope_id; + const struct in6_addr *a6 = &sa6->sin6_addr; +#endif + char tmp[64]; + +#ifdef NI_NUMERICSCOPE + if (flags & NI_NUMERICSCOPE) { + sprintf(tmp, "%u", sa6->sin6_scope_id); + if (bufsiz != 0) { + strncpy(buf, tmp, bufsiz - 1); + buf[bufsiz - 1] = '\0'; + } + return(strlen(tmp)); + } +#endif + +#ifdef USE_IFNAMELINKID + /* + * For a link-local address, convert the index to an interface + * name, assuming a one-to-one mapping between links and interfaces. + * Note, however, that this assumption is stronger than the + * specification of the scoped address architecture; the + * specficication says that more than one interfaces can belong to + * a single link. + */ + + /* if_indextoname() does not take buffer size. not a good api... */ + if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) && + bufsiz >= IF_NAMESIZE) { + char *p = if_indextoname(ifindex, buf); + if (p) { + return(strlen(p)); + } + } +#endif + + /* last resort */ + sprintf(tmp, "%u", sa6->sin6_scope_id); + if (bufsiz != 0) { + strncpy(buf, tmp, bufsiz - 1); + buf[bufsiz - 1] = '\0'; + } + return(strlen(tmp)); +} +#endif Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/getnameinfo.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/Makefile (revision 109985) @@ -0,0 +1,119 @@ +# Copyright (c) 1996,1999 by Internet Software Consortium +# +# 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. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +# CONSORTIUM 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 +# SOFTWARE. + +# $Id: Makefile,v 8.24 2001/08/14 05:58:07 marka Exp $ + +# these are only appropriate for BSD 4.4 or derivatives, and are used in +# development. normal builds will be done in the top level directory and +# this Makefile will be invoked with a lot of overrides for the following: +SYSTYPE= freebsd +DESTDIR = +DESTLIB = /usr/local/lib +O=o +A=a +CC= cc +LD= ld +SHELL= /bin/sh +CDEBUG= -g -Wall +TOP= ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.${A} +LIBBINDR = ../${TOP}/lib/libbind_r.${A} +CFLAGS= ${CDEBUG} +CPPFLAGS= -I${PORTINCL} -I${INCL} +# -D__BIND_NOSTATIC -Wimplicit +LD_LIBFLAGS= -x -r +AR= ar cru +RANLIB= ranlib +INSTALL= install +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin +THREADED= threaded + +SRCS= dns.c dns_gr.c dns_ho.c dns_nw.c dns_pr.c dns_pw.c \ + dns_sv.c gai_strerror.c gen.c gen_gr.c gen_ho.c \ + gen_ng.c gen_nw.c gen_pr.c gen_pw.c gen_sv.c \ + getaddrinfo.c getgrent.c getgrent_r.c gethostent.c \ + gethostent_r.c getnameinfo.c getnetent.c getnetent_r.c \ + getnetgrent.c getnetgrent_r.c getprotoent.c \ + getprotoent_r.c getpwent.c getpwent_r.c getservent.c \ + getservent_r.c hesiod.c irs_data.c \ + irp.c irp_gr.c irp_ho.c irp_ng.c irp_nw.c \ + irp_pr.c irp_pw.c irp_sv.c irpmarshall.c \ + lcl.c lcl_gr.c \ + lcl_ho.c lcl_ng.c lcl_nw.c lcl_pr.c lcl_pw.c \ + lcl_sv.c nis.c nis_gr.c nis_ho.c nis_ng.c nis_nw.c \ + nis_pr.c nis_pw.c nis_sv.c nul_ng.c util.c + +OBJS= dns.${O} dns_gr.${O} dns_ho.${O} dns_nw.${O} dns_pr.${O} dns_pw.${O} \ + dns_sv.${O} gai_strerror.${O} gen.${O} gen_gr.${O} gen_ho.${O} \ + gen_ng.${O} gen_nw.${O} gen_pr.${O} gen_pw.${O} gen_sv.${O} \ + getaddrinfo.${O} getgrent.${O} getgrent_r.${O} gethostent.${O} \ + gethostent_r.${O} getnameinfo.${O} getnetent.${O} getnetent_r.${O} \ + getnetgrent.${O} getnetgrent_r.${O} getprotoent.${O} \ + getprotoent_r.${O} getpwent.${O} getpwent_r.${O} getservent.${O} \ + getservent_r.${O} hesiod.${O} irs_data.${O} \ + irp.${O} irp_gr.${O} irp_ho.${O} irp_ng.${O} irp_nw.${O} \ + irp_pr.${O} irp_pw.${O} irp_sv.${O} irpmarshall.${O} \ + lcl.${O} lcl_gr.${O} \ + lcl_ho.${O} lcl_ng.${O} lcl_nw.${O} lcl_pr.${O} lcl_pw.${O} \ + lcl_sv.${O} nis.${O} nis_gr.${O} nis_ho.${O} nis_ng.${O} nis_nw.${O} \ + nis_pr.${O} nis_pw.${O} nis_sv.${O} nul_ng.${O} util.${O} + +all: ${LIBBIND} + +${LIBBIND}: ${OBJS} + -( cd ${THREADED} ; \ + ${AR} ${LIBBINDR} ${ARPREF} ${OBJS} ${ARSUFF} ; \ + ${RANLIB} ${LIBBINDR} ) + ${AR} ${LIBBIND} ${ARPREF} ${OBJS} ${ARSUFF} + ${RANLIB} ${LIBBIND} + +.c.${O}: + mkdir ${THREADED} 2> /dev/null || test -d ${THREADED} -a -w ${THREADED} + -(${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} ${REENTRANT} -c $*.c \ + -o ${THREADED}/$*.${O} ; \ + ${LDS} ${LD} ${LD_LIBFLAGS} ${THREADED}/$*.${O} \ + -o ${THREADED}/$*.out && \ + ${LDS} mv ${THREADED}/$*.out ${THREADED}/$*.${O}) + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c + -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} -o $*.out && \ + ${LDS} mv $*.out $*.${O} + +distclean: clean + +clean: FRC + rm -f .depend a.out core ${LIB} tags + rm -f *.${O} *.BAK *.CKP *~ + rm -f ${THREADED}/*.${O} + -if test -d ${THREADED} ; then rmdir ${THREADED}; else true; fi + +depend: FRC + mkdep -I${INCL} -I${PORTINCL} ${CPPFLAGS} ${SRCS} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +testirpd: testirpd.o ${LIBBIND} + ${CC} ${CDEBUG} ${LDFLAGS} -o testirpd testirpd.o ${LIBBIND} ${SYSLIBS} + + +install: + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/dns.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/dns.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/dns.c (revision 109985) @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns.c,v 1.16 2001/05/29 05:48:26 marka Exp $"; +#endif + +/* + * dns.c --- this is the top-level accessor function for the dns + */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* forward */ + +static void dns_close(struct irs_acc *); +static struct __res_state * dns_res_get(struct irs_acc *); +static void dns_res_set(struct irs_acc *, struct __res_state *, + void (*)(void *)); + +/* public */ + +struct irs_acc * +irs_dns_acc(const char *options) { + struct irs_acc *acc; + struct dns_p *dns; + + UNUSED(options); + + if (!(acc = memget(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(dns = memget(sizeof *dns))) { + errno = ENOMEM; + memput(acc, sizeof *acc); + return (NULL); + } + memset(dns, 0x5e, sizeof *dns); + dns->res = NULL; + dns->free_res = NULL; + if (hesiod_init(&dns->hes_ctx) < 0) { + /* + * We allow the dns accessor class to initialize + * despite hesiod failing to initialize correctly, + * since dns host queries don't depend on hesiod. + */ + dns->hes_ctx = NULL; + } + acc->private = dns; +#ifdef WANT_IRS_GR + acc->gr_map = irs_dns_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_dns_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_dns_sv; + acc->pr_map = irs_dns_pr; + acc->ho_map = irs_dns_ho; + acc->nw_map = irs_dns_nw; + acc->ng_map = irs_nul_ng; + acc->res_get = dns_res_get; + acc->res_set = dns_res_set; + acc->close = dns_close; + return (acc); +} + +/* methods */ +static struct __res_state * +dns_res_get(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + + if (dns->res == NULL) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) + return (NULL); + memset(dns->res, 0, sizeof *dns->res); + dns_res_set(this, res, free); + } + + if ((dns->res->options & RES_INIT) == 0 && + res_ninit(dns->res) < 0) + return (NULL); + + return (dns->res); +} + +static void +dns_res_set(struct irs_acc *this, struct __res_state *res, + void (*free_res)(void *)) { + struct dns_p *dns = (struct dns_p *)this->private; + + if (dns->res && dns->free_res) { + res_nclose(dns->res); + (*dns->free_res)(dns->res); + } + dns->res = res; + dns->free_res = free_res; +} + +static void +dns_close(struct irs_acc *this) { + struct dns_p *dns; + + dns = (struct dns_p *)this->private; + if (dns->res && dns->free_res) + (*dns->free_res)(dns->res); + if (dns->hes_ctx) + hesiod_end(dns->hes_ctx); + memput(dns, sizeof *dns); + memput(this, sizeof *this); +} + Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/dns.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/dns_gr.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/dns_gr.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/dns_gr.c (revision 109985) @@ -0,0 +1,293 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_gr.c,v 1.20 2001/05/29 05:48:27 marka Exp $"; +#endif + +/* + * dns_gr.c --- this file contains the functions for accessing + * group information from Hesiod. + */ + +#include "port_before.h" + +#ifndef WANT_IRS_GR +static int __bind_irs_gr_unneeded; +#else + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Types. */ + +struct pvt { + /* + * This is our private accessor data. It has a shared hesiod context. + */ + struct dns_p * dns; + /* + * Need space to store the entries read from the group file. + * The members list also needs space per member, and the + * strings making up the user names must be allocated + * somewhere. Rather than doing lots of small allocations, + * we keep one buffer and resize it as needed. + */ + struct group group; + size_t nmemb; /* Malloc'd max index of gr_mem[]. */ + char * membuf; + size_t membufsize; +}; + +/* Forward. */ + +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static void gr_close(struct irs_gr *); +static int gr_list(struct irs_gr *, const char *, + gid_t, gid_t *, int *); +static void gr_minimize(struct irs_gr *); +static struct __res_state * gr_res_get(struct irs_gr *); +static void gr_res_set(struct irs_gr *, + struct __res_state *, + void (*)(void *)); + +static struct group * get_hes_group(struct irs_gr *this, + const char *name, + const char *type); + +/* Public. */ + +struct irs_gr * +irs_dns_gr(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + struct irs_gr *gr; + struct pvt *pvt; + + if (!dns || !dns->hes_ctx) { + errno = ENODEV; + return (NULL); + } + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->dns = dns; + if (!(gr = memget(sizeof *gr))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x5e, sizeof *gr); + gr->private = pvt; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->close = gr_close; + gr->list = gr_list; + gr->minimize = gr_minimize; + gr->res_get = gr_res_get; + gr->res_set = gr_res_set; + return (gr); +} + +/* methods */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->group.gr_mem) + free(pvt->group.gr_mem); + if (pvt->membuf) + free(pvt->membuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct group * +gr_next(struct irs_gr *this) { + + UNUSED(this); + + return (NULL); +} + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + return (get_hes_group(this, name, "group")); +} + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + char name[32]; + + sprintf(name, "%ld", (long)gid); + return (get_hes_group(this, name, "gid")); +} + +static void +gr_rewind(struct irs_gr *this) { + + UNUSED(this); + + /* NOOP */ +} + +static int +gr_list(struct irs_gr *this, const char *name, + gid_t basegid, gid_t *groups, int *ngroups) +{ + UNUSED(this); + UNUSED(name); + UNUSED(basegid); + UNUSED(groups); + + *ngroups = 0; + /* There's some way to do this in Hesiod. */ + return (-1); +} + +static void +gr_minimize(struct irs_gr *this) { + + UNUSED(this); + /* NOOP */ +} + +/* Private. */ + +static struct group * +get_hes_group(struct irs_gr *this, const char *name, const char *type) { + struct pvt *pvt = (struct pvt *)this->private; + char **hes_list, *cp, **new; + size_t num_members = 0; + u_long t; + + hes_list = hesiod_resolve(pvt->dns->hes_ctx, name, type); + if (!hes_list) + return (NULL); + + /* + * Copy the returned hesiod string into storage space. + */ + if (pvt->membuf) + free(pvt->membuf); + pvt->membuf = strdup(*hes_list); + hesiod_free_list(pvt->dns->hes_ctx, hes_list); + + cp = pvt->membuf; + pvt->group.gr_name = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->group.gr_passwd = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + errno = -1; + t = strtoul(cp, NULL, 10); + if (errno == ERANGE) + goto cleanup; + pvt->group.gr_gid = (gid_t) t; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + cp++; + + /* + * Parse the members out. + */ + while (*cp) { + if (num_members+1 >= pvt->nmemb || pvt->group.gr_mem == NULL) { + pvt->nmemb += 10; + new = realloc(pvt->group.gr_mem, + pvt->nmemb * sizeof(char *)); + if (new == NULL) + goto cleanup; + pvt->group.gr_mem = new; + } + pvt->group.gr_mem[num_members++] = cp; + if (!(cp = strchr(cp, ','))) + break; + *cp++ = '\0'; + } + if (!pvt->group.gr_mem) { + pvt->group.gr_mem = malloc(sizeof(char*)); + if (!pvt->group.gr_mem) + goto cleanup; + } + pvt->group.gr_mem[num_members] = NULL; + + return (&pvt->group); + + cleanup: + if (pvt->group.gr_mem) { + free(pvt->group.gr_mem); + pvt->group.gr_mem = NULL; + } + if (pvt->membuf) { + free(pvt->membuf); + pvt->membuf = NULL; + } + return (NULL); +} + +static struct __res_state * +gr_res_get(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + return (__hesiod_res_get(dns->hes_ctx)); +} + +static void +gr_res_set(struct irs_gr *this, struct __res_state * res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + __hesiod_res_set(dns->hes_ctx, res, free_res); +} + +#endif /* WANT_IRS_GR */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/dns_gr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/dns_pr.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/dns_pr.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/dns_pr.c (revision 109985) @@ -0,0 +1,266 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_pr.c,v 1.15 2001/05/29 05:48:31 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Types. */ + +struct pvt { + struct dns_p * dns; + struct protoent proto; + char * prbuf; +}; + +/* Forward. */ + +static void pr_close(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static struct protoent * pr_next(struct irs_pr *); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); +static struct __res_state * pr_res_get(struct irs_pr *); +static void pr_res_set(struct irs_pr *, + struct __res_state *, + void (*)(void *)); + +static struct protoent * parse_hes_list(struct irs_pr *, char **); + +/* Public. */ + +struct irs_pr * +irs_dns_pr(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + struct pvt *pvt; + struct irs_pr *pr; + + if (!dns->hes_ctx) { + errno = ENODEV; + return (NULL); + } + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(pr = memget(sizeof *pr))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(pr, 0x5e, sizeof *pr); + pvt->dns = dns; + pr->private = pvt; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->next = pr_next; + pr->rewind = pr_rewind; + pr->close = pr_close; + pr->minimize = pr_minimize; + pr->res_get = pr_res_get; + pr->res_set = pr_res_set; + return (pr); +} + +/* Methods. */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->proto.p_aliases) + free(pvt->proto.p_aliases); + if (pvt->prbuf) + free(pvt->prbuf); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct protoent *proto; + char **hes_list; + + if (!(hes_list = hesiod_resolve(dns->hes_ctx, name, "protocol"))) + return (NULL); + + proto = parse_hes_list(this, hes_list); + hesiod_free_list(dns->hes_ctx, hes_list); + return (proto); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int num) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct protoent *proto; + char numstr[16]; + char **hes_list; + + sprintf(numstr, "%d", num); + if (!(hes_list = hesiod_resolve(dns->hes_ctx, numstr, "protonum"))) + return (NULL); + + proto = parse_hes_list(this, hes_list); + hesiod_free_list(dns->hes_ctx, hes_list); + return (proto); +} + +static struct protoent * +pr_next(struct irs_pr *this) { + UNUSED(this); + errno = ENODEV; + return (NULL); +} + +static void +pr_rewind(struct irs_pr *this) { + UNUSED(this); + /* NOOP */ +} + +static void +pr_minimize(struct irs_pr *this) { + UNUSED(this); + /* NOOP */ +} + +static struct __res_state * +pr_res_get(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + return (__hesiod_res_get(dns->hes_ctx)); +} + +static void +pr_res_set(struct irs_pr *this, struct __res_state * res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + __hesiod_res_set(dns->hes_ctx, res, free_res); +} + +/* Private. */ + +static struct protoent * +parse_hes_list(struct irs_pr *this, char **hes_list) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *cp, **cpp, **new; + int num = 0; + int max = 0; + + for (cpp = hes_list; *cpp; cpp++) { + cp = *cpp; + + /* Strip away comments, if any. */ + if ((p = strchr(cp, '#'))) + *p = 0; + + /* Skip blank lines. */ + p = cp; + while (*p && !isspace((unsigned char)*p)) + p++; + if (!*p) + continue; + + /* OK, we've got a live one. Let's parse it for real. */ + if (pvt->prbuf) + free(pvt->prbuf); + pvt->prbuf = strdup(cp); + + p = pvt->prbuf; + pvt->proto.p_name = p; + while (*p && !isspace((unsigned char)*p)) + p++; + if (!*p) + continue; + *p++ = '\0'; + + pvt->proto.p_proto = atoi(p); + while (*p && !isspace((unsigned char)*p)) + p++; + if (*p) + *p++ = '\0'; + + while (*p) { + if ((num + 1) >= max || !pvt->proto.p_aliases) { + max += 10; + new = realloc(pvt->proto.p_aliases, + max * sizeof(char *)); + if (!new) { + errno = ENOMEM; + goto cleanup; + } + pvt->proto.p_aliases = new; + } + pvt->proto.p_aliases[num++] = p; + while (*p && !isspace((unsigned char)*p)) + p++; + if (*p) + *p++ = '\0'; + } + if (!pvt->proto.p_aliases) + pvt->proto.p_aliases = malloc(sizeof(char *)); + if (!pvt->proto.p_aliases) + goto cleanup; + pvt->proto.p_aliases[num] = NULL; + return (&pvt->proto); + } + + cleanup: + if (pvt->proto.p_aliases) { + free(pvt->proto.p_aliases); + pvt->proto.p_aliases = NULL; + } + if (pvt->prbuf) { + free(pvt->prbuf); + pvt->prbuf = NULL; + } + return (NULL); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/dns_pr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/dns_pw.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/dns_pw.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/dns_pw.c (revision 109985) @@ -0,0 +1,231 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_pw.c,v 1.19 2001/05/29 05:48:32 marka Exp $"; +#endif + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_pw_unneeded; +#else + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Types. */ + +struct pvt { + struct dns_p * dns; + struct passwd passwd; + char * pwbuf; +}; + +/* Forward. */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static struct passwd * pw_next(struct irs_pw *); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); +static struct __res_state * pw_res_get(struct irs_pw *); +static void pw_res_set(struct irs_pw *, + struct __res_state *, + void (*)(void *)); + +static struct passwd * getpwcommon(struct irs_pw *, const char *, + const char *); + +/* Public. */ + +struct irs_pw * +irs_dns_pw(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + struct irs_pw *pw; + struct pvt *pvt; + + if (!dns || !dns->hes_ctx) { + errno = ENODEV; + return (NULL); + } + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->dns = dns; + if (!(pw = memget(sizeof *pw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(pw, 0x5e, sizeof *pw); + pw->private = pvt; + pw->close = pw_close; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->next = pw_next; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + pw->res_get = pw_res_get; + pw->res_set = pw_res_set; + return (pw); +} + +/* Methods. */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->pwbuf) + free(pvt->pwbuf); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct passwd * +pw_byname(struct irs_pw *this, const char *nam) { + return (getpwcommon(this, nam, "passwd")); +} + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + char uidstr[16]; + + sprintf(uidstr, "%lu", (u_long)uid); + return (getpwcommon(this, uidstr, "uid")); +} + +static struct passwd * +pw_next(struct irs_pw *this) { + UNUSED(this); + errno = ENODEV; + return (NULL); +} + +static void +pw_rewind(struct irs_pw *this) { + UNUSED(this); + /* NOOP */ +} + +static void +pw_minimize(struct irs_pw *this) { + UNUSED(this); + /* NOOP */ +} + +static struct __res_state * +pw_res_get(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + return (__hesiod_res_get(dns->hes_ctx)); +} + +static void +pw_res_set(struct irs_pw *this, struct __res_state * res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + __hesiod_res_set(dns->hes_ctx, res, free_res); +} + +/* Private. */ + +static struct passwd * +getpwcommon(struct irs_pw *this, const char *arg, const char *type) { + struct pvt *pvt = (struct pvt *)this->private; + char **hes_list, *cp; + + if (!(hes_list = hesiod_resolve(pvt->dns->hes_ctx, arg, type))) + return (NULL); + if (!*hes_list) { + hesiod_free_list(pvt->dns->hes_ctx, hes_list); + errno = ENOENT; + return (NULL); + } + + memset(&pvt->passwd, 0, sizeof pvt->passwd); + if (pvt->pwbuf) + free(pvt->pwbuf); + pvt->pwbuf = strdup(*hes_list); + hesiod_free_list(pvt->dns->hes_ctx, hes_list); + + cp = pvt->pwbuf; + pvt->passwd.pw_name = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_passwd = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_uid = atoi(cp); + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_gid = atoi(cp); + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_gecos = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_dir = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_shell = cp; + return (&pvt->passwd); + + cleanup: + free(pvt->pwbuf); + pvt->pwbuf = NULL; + return (NULL); +} + +#endif /* WANT_IRS_PW */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/dns_pw.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/dns_sv.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/dns_sv.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/dns_sv.c (revision 109985) @@ -0,0 +1,298 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_sv.c,v 1.20 2001/05/29 05:48:33 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Definitions */ + +struct pvt { + struct dns_p * dns; + struct servent serv; + char * svbuf; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward. */ + +static void sv_close(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, + const char *, const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static struct servent * sv_next(struct irs_sv *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); +#ifdef SV_RES_SETGET +static struct __res_state * sv_res_get(struct irs_sv *); +static void sv_res_set(struct irs_sv *, + struct __res_state *, + void (*)(void *)); +#endif + +static struct servent * parse_hes_list(struct irs_sv *, + char **, const char *); + +/* Public */ + +struct irs_sv * +irs_dns_sv(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + struct irs_sv *sv; + struct pvt *pvt; + + if (!dns || !dns->hes_ctx) { + errno = ENODEV; + return (NULL); + } + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->dns = dns; + if (!(sv = memget(sizeof *sv))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + sv->private = pvt; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->next = sv_next; + sv->rewind = sv_rewind; + sv->close = sv_close; + sv->minimize = sv_minimize; +#ifdef SV_RES_SETGET + sv->res_get = sv_res_get; + sv->res_set = sv_res_set; +#else + sv->res_get = NULL; /* sv_res_get; */ + sv->res_set = NULL; /* sv_res_set; */ +#endif + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->serv.s_aliases) + free(pvt->serv.s_aliases); + if (pvt->svbuf) + free(pvt->svbuf); + + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct servent *s; + char **hes_list; + + if (!(hes_list = hesiod_resolve(dns->hes_ctx, name, "service"))) + return (NULL); + + s = parse_hes_list(this, hes_list, proto); + hesiod_free_list(dns->hes_ctx, hes_list); + return (s); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct servent *s; + char portstr[16]; + char **hes_list; + + sprintf(portstr, "%d", ntohs(port)); + if (!(hes_list = hesiod_resolve(dns->hes_ctx, portstr, "port"))) + return (NULL); + + s = parse_hes_list(this, hes_list, proto); + hesiod_free_list(dns->hes_ctx, hes_list); + return (s); +} + +static struct servent * +sv_next(struct irs_sv *this) { + UNUSED(this); + errno = ENODEV; + return (NULL); +} + +static void +sv_rewind(struct irs_sv *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static struct servent * +parse_hes_list(struct irs_sv *this, char **hes_list, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *cp, **cpp, **new; + int proto_len; + int num = 0; + int max = 0; + + for (cpp = hes_list; *cpp; cpp++) { + cp = *cpp; + + /* Strip away comments, if any. */ + if ((p = strchr(cp, '#'))) + *p = 0; + + /* Check to make sure the protocol matches. */ + p = cp; + while (*p && !isspace((unsigned char)*p)) + p++; + if (!*p) + continue; + if (proto) { + proto_len = strlen(proto); + if (strncasecmp(++p, proto, proto_len) != 0) + continue; + if (p[proto_len] && !isspace(p[proto_len]&0xff)) + continue; + } + /* OK, we've got a live one. Let's parse it for real. */ + if (pvt->svbuf) + free(pvt->svbuf); + pvt->svbuf = strdup(cp); + + p = pvt->svbuf; + pvt->serv.s_name = p; + while (*p && !isspace(*p&0xff)) + p++; + if (!*p) + continue; + *p++ = '\0'; + + pvt->serv.s_proto = p; + while (*p && !isspace(*p&0xff)) + p++; + if (!*p) + continue; + *p++ = '\0'; + + pvt->serv.s_port = htons((u_short) atoi(p)); + while (*p && !isspace(*p&0xff)) + p++; + if (*p) + *p++ = '\0'; + + while (*p) { + if ((num + 1) >= max || !pvt->serv.s_aliases) { + max += 10; + new = realloc(pvt->serv.s_aliases, + max * sizeof(char *)); + if (!new) { + errno = ENOMEM; + goto cleanup; + } + pvt->serv.s_aliases = new; + } + pvt->serv.s_aliases[num++] = p; + while (*p && !isspace(*p&0xff)) + p++; + if (*p) + *p++ = '\0'; + } + if (!pvt->serv.s_aliases) + pvt->serv.s_aliases = malloc(sizeof(char *)); + if (!pvt->serv.s_aliases) + goto cleanup; + pvt->serv.s_aliases[num] = NULL; + return (&pvt->serv); + } + + cleanup: + if (pvt->serv.s_aliases) { + free(pvt->serv.s_aliases); + pvt->serv.s_aliases = NULL; + } + if (pvt->svbuf) { + free(pvt->svbuf); + pvt->svbuf = NULL; + } + return (NULL); +} + +static void +sv_minimize(struct irs_sv *this) { + UNUSED(this); + /* NOOP */ +} + +#ifdef SV_RES_SETGET +static struct __res_state * +sv_res_get(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + return (__hesiod_res_get(dns->hes_ctx)); +} + +static void +sv_res_set(struct irs_sv *this, struct __res_state * res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + __hesiod_res_set(dns->hes_ctx, res, free_res); +} +#endif Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/dns_sv.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/gai_strerror.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/gai_strerror.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/gai_strerror.c (revision 109985) @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2001 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#include +#include +#include + +#ifdef DO_PTHREADS +#include +#include +#endif + +static const char *gai_errlist[] = { + "no error", + "address family not supported for name",/* EAI_ADDRFAMILY */ + "temporary failure", /* EAI_AGAIN */ + "invalid flags", /* EAI_BADFLAGS */ + "permanent failure", /* EAI_FAIL */ + "address family not supported", /* EAI_FAMILY */ + "memory failure", /* EAI_MEMORY */ + "no address", /* EAI_NODATA */ + "unknown name or service", /* EAI_NONAME */ + "service not supported for socktype", /* EAI_SERVICE */ + "socktype not supported", /* EAI_SOCKTYPE */ + "system failure", /* EAI_SYSTEM */ + "bad hints", /* EAI_BADHINTS */ + "bad protocol", /* EAI_PROTOCOL */ + + "unknown error" /* Must be last. */ +}; + +static const int gai_nerr = (sizeof(gai_errlist)/sizeof(*gai_errlist)); + +#define EAI_BUFSIZE 128 + +const char * +gai_strerror(int ecode) { +#ifndef DO_PTHREADS + static char buf[EAI_BUFSIZE]; +#else /* DO_PTHREADS */ + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + static pthread_key_t key; + static int once = 0; + char *buf; +#endif + + if (ecode >= 0 && ecode < (gai_nerr - 1)) + return (gai_errlist[ecode]); + +#ifdef DO_PTHREADS + if (!once) { + pthread_mutex_lock(&lock); + if (!once++) + pthread_key_create(&key, free); + pthread_mutex_unlock(&lock); + } + + buf = pthread_getspecific(key); + if (buf == NULL) { + buf = malloc(EAI_BUFSIZE); + if (buf == NULL) + return ("unknown error"); + pthread_setspecific(key, buf); + } +#endif + /* + * XXX This really should be snprintf(buf, EAI_BUFSIZE, ...). + * It is safe until message catalogs are used. + */ + sprintf(buf, "%s: %d", gai_errlist[gai_nerr - 1], ecode); + return (buf); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/gai_strerror.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/gen.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/gen.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/gen.c (revision 109985) @@ -0,0 +1,430 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen.c,v 1.26 2001/05/29 05:48:35 marka Exp $"; +#endif + +/* + * this is the top level dispatcher + * + * The dispatcher is implemented as an accessor class; it is an + * accessor class that calls other accessor classes, as controlled by a + * configuration file. + * + * A big difference between this accessor class and others is that the + * map class initializers are NULL, and the map classes are already + * filled in with method functions that will do the right thing. + */ + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Definitions */ + +struct nameval { + const char * name; + int val; +}; + +static const struct nameval acc_names[irs_nacc+1] = { + { "local", irs_lcl }, + { "dns", irs_dns }, + { "nis", irs_nis }, + { "irp", irs_irp }, + { NULL, irs_nacc } +}; + +typedef struct irs_acc *(*accinit) __P((const char *options)); + +static const accinit accs[irs_nacc+1] = { + irs_lcl_acc, + irs_dns_acc, +#ifdef WANT_IRS_NIS + irs_nis_acc, +#else + NULL, +#endif + irs_irp_acc, + NULL +}; + +static const struct nameval map_names[irs_nmap+1] = { + { "group", irs_gr }, + { "passwd", irs_pw }, + { "services", irs_sv }, + { "protocols", irs_pr }, + { "hosts", irs_ho }, + { "networks", irs_nw }, + { "netgroup", irs_ng }, + { NULL, irs_nmap } +}; + +static const struct nameval option_names[] = { + { "merge", IRS_MERGE }, + { "continue", IRS_CONTINUE }, + { NULL, 0 } +}; + +/* Forward */ + +static void gen_close(struct irs_acc *); +static struct __res_state * gen_res_get(struct irs_acc *); +static void gen_res_set(struct irs_acc *, struct __res_state *, + void (*)(void *)); +static int find_name(const char *, const struct nameval nv[]); +static void init_map_rules(struct gen_p *, const char *conf_file); +static struct irs_rule *release_rule(struct irs_rule *); +static int add_rule(struct gen_p *, + enum irs_map_id, enum irs_acc_id, + const char *); + +/* Public */ + +struct irs_acc * +irs_gen_acc(const char *options, const char *conf_file) { + struct irs_acc *acc; + struct gen_p *irs; + + if (!(acc = memget(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(irs = memget(sizeof *irs))) { + errno = ENOMEM; + memput(acc, sizeof *acc); + return (NULL); + } + memset(irs, 0x5e, sizeof *irs); + irs->options = strdup(options); + irs->res = NULL; + irs->free_res = NULL; + memset(irs->accessors, 0, sizeof irs->accessors); + memset(irs->map_rules, 0, sizeof irs->map_rules); + init_map_rules(irs, conf_file); + acc->private = irs; +#ifdef WANT_IRS_GR + acc->gr_map = irs_gen_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_gen_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_gen_sv; + acc->pr_map = irs_gen_pr; + acc->ho_map = irs_gen_ho; + acc->nw_map = irs_gen_nw; + acc->ng_map = irs_gen_ng; + acc->res_get = gen_res_get; + acc->res_set = gen_res_set; + acc->close = gen_close; + return (acc); +} + +/* Methods */ + +static struct __res_state * +gen_res_get(struct irs_acc *this) { + struct gen_p *irs = (struct gen_p *)this->private; + + if (irs->res == NULL) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) + return (NULL); + memset(res, 0, sizeof *res); + gen_res_set(this, res, free); + } + + if (((irs->res->options & RES_INIT) == 0) && res_ninit(irs->res) < 0) + return (NULL); + + return (irs->res); +} + +static void +gen_res_set(struct irs_acc *this, struct __res_state *res, + void (*free_res)(void *)) { + struct gen_p *irs = (struct gen_p *)this->private; +#if 0 + struct irs_rule *rule; + struct irs_ho *ho; + struct irs_nw *nw; +#endif + + if (irs->res && irs->free_res) { + res_nclose(irs->res); + (*irs->free_res)(irs->res); + } + + irs->res = res; + irs->free_res = free_res; + +#if 0 + for (rule = irs->map_rules[irs_ho]; rule; rule = rule->next) { + ho = rule->inst->ho; + + (*ho->res_set)(ho, res, NULL); + } + for (rule = irs->map_rules[irs_nw]; rule; rule = rule->next) { + nw = rule->inst->nw; + + (*nw->res_set)(nw, res, NULL); + } +#endif +} + +static void +gen_close(struct irs_acc *this) { + struct gen_p *irs = (struct gen_p *)this->private; + int n; + + /* Search rules. */ + for (n = 0; n < irs_nmap; n++) + while (irs->map_rules[n] != NULL) + irs->map_rules[n] = release_rule(irs->map_rules[n]); + + /* Access methods. */ + for (n = 0; n < irs_nacc; n++) { + /* Map objects. */ + if (irs->accessors[n].gr != NULL) + (*irs->accessors[n].gr->close)(irs->accessors[n].gr); + if (irs->accessors[n].pw != NULL) + (*irs->accessors[n].pw->close)(irs->accessors[n].pw); + if (irs->accessors[n].sv != NULL) + (*irs->accessors[n].sv->close)(irs->accessors[n].sv); + if (irs->accessors[n].pr != NULL) + (*irs->accessors[n].pr->close)(irs->accessors[n].pr); + if (irs->accessors[n].ho != NULL) + (*irs->accessors[n].ho->close)(irs->accessors[n].ho); + if (irs->accessors[n].nw != NULL) + (*irs->accessors[n].nw->close)(irs->accessors[n].nw); + if (irs->accessors[n].ng != NULL) + (*irs->accessors[n].ng->close)(irs->accessors[n].ng); + /* Enclosing accessor. */ + if (irs->accessors[n].acc != NULL) + (*irs->accessors[n].acc->close)(irs->accessors[n].acc); + } + + /* The options string was strdup'd. */ + free((void*)irs->options); + + if (irs->res && irs->free_res) + (*irs->free_res)(irs->res); + + /* The private data container. */ + memput(irs, sizeof *irs); + + /* The object. */ + memput(this, sizeof *this); +} + +/* Private */ + +static int +find_name(const char *name, const struct nameval names[]) { + int n; + + for (n = 0; names[n].name != NULL; n++) + if (strcmp(name, names[n].name) == 0) + return (names[n].val); + return (-1); +} + +static struct irs_rule * +release_rule(struct irs_rule *rule) { + struct irs_rule *next = rule->next; + + memput(rule, sizeof *rule); + return (next); +} + +static int +add_rule(struct gen_p *irs, + enum irs_map_id map, enum irs_acc_id acc, + const char *options) +{ + struct irs_rule **rules, *last, *tmp, *new; + struct irs_inst *inst; + const char *cp; + int n; + +#ifndef WANT_IRS_GR + if (map == irs_gr) + return (-1); +#endif +#ifndef WANT_IRS_PW + if (map == irs_pw) + return (-1); +#endif +#ifndef WANT_IRS_NIS + if (acc == irs_nis) + return (-1); +#endif + new = memget(sizeof *new); + if (new == NULL) + return (-1); + memset(new, 0x5e, sizeof *new); + new->next = NULL; + + new->inst = &irs->accessors[acc]; + + new->flags = 0; + cp = options; + while (cp && *cp) { + char option[50], *next; + + next = strchr(cp, ','); + if (next) + n = next++ - cp; + else + n = strlen(cp); + if ((size_t)n > sizeof option - 1) + n = sizeof option - 1; + strncpy(option, cp, n); + option[n] = '\0'; + + n = find_name(option, option_names); + if (n >= 0) + new->flags |= n; + + cp = next; + } + + rules = &irs->map_rules[map]; + for (last = NULL, tmp = *rules; + tmp != NULL; + last = tmp, tmp = tmp->next) + (void)NULL; + if (last == NULL) + *rules = new; + else + last->next = new; + + /* Try to instantiate map accessors for this if necessary & approp. */ + inst = &irs->accessors[acc]; + if (inst->acc == NULL && accs[acc] != NULL) + inst->acc = (*accs[acc])(irs->options); + if (inst->acc != NULL) { + if (inst->gr == NULL && inst->acc->gr_map != NULL) + inst->gr = (*inst->acc->gr_map)(inst->acc); + if (inst->pw == NULL && inst->acc->pw_map != NULL) + inst->pw = (*inst->acc->pw_map)(inst->acc); + if (inst->sv == NULL && inst->acc->sv_map != NULL) + inst->sv = (*inst->acc->sv_map)(inst->acc); + if (inst->pr == NULL && inst->acc->pr_map != NULL) + inst->pr = (*inst->acc->pr_map)(inst->acc); + if (inst->ho == NULL && inst->acc->ho_map != NULL) + inst->ho = (*inst->acc->ho_map)(inst->acc); + if (inst->nw == NULL && inst->acc->nw_map != NULL) + inst->nw = (*inst->acc->nw_map)(inst->acc); + if (inst->ng == NULL && inst->acc->ng_map != NULL) + inst->ng = (*inst->acc->ng_map)(inst->acc); + } + + return (0); +} + +static void +default_map_rules(struct gen_p *irs) { + /* Install time honoured and proved BSD style rules as default. */ + add_rule(irs, irs_gr, irs_lcl, ""); + add_rule(irs, irs_pw, irs_lcl, ""); + add_rule(irs, irs_sv, irs_lcl, ""); + add_rule(irs, irs_pr, irs_lcl, ""); + add_rule(irs, irs_ho, irs_dns, "continue"); + add_rule(irs, irs_ho, irs_lcl, ""); + add_rule(irs, irs_nw, irs_dns, "continue"); + add_rule(irs, irs_nw, irs_lcl, ""); + add_rule(irs, irs_ng, irs_lcl, ""); +} + +static void +init_map_rules(struct gen_p *irs, const char *conf_file) { + char line[1024], pattern[40], mapname[20], accname[20], options[100]; + FILE *conf; + + if (conf_file == NULL) + conf_file = _PATH_IRS_CONF ; + + /* A conf file of "" means compiled in defaults. Irpd wants this */ + if (conf_file[0] == '\0' || (conf = fopen(conf_file, "r")) == NULL) { + default_map_rules(irs); + return; + } + (void) sprintf(pattern, "%%%ds %%%ds %%%ds\n", + sizeof mapname, sizeof accname, sizeof options); + while (fgets(line, sizeof line, conf)) { + enum irs_map_id map; + enum irs_acc_id acc; + char *tmp; + int n; + + for (tmp = line; + isascii((unsigned char)*tmp) && + isspace((unsigned char)*tmp); + tmp++) + (void)NULL; + if (*tmp == '#' || *tmp == '\n' || *tmp == '\0') + continue; + n = sscanf(tmp, pattern, mapname, accname, options); + if (n < 2) + continue; + if (n < 3) + options[0] = '\0'; + + n = find_name(mapname, map_names); + INSIST(n < irs_nmap); + if (n < 0) + continue; + map = (enum irs_map_id) n; + + n = find_name(accname, acc_names); + INSIST(n < irs_nacc); + if (n < 0) + continue; + acc = (enum irs_acc_id) n; + + add_rule(irs, map, acc, options); + } + fclose(conf); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/gen.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/gen_gr.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/gen_gr.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/gen_gr.c (revision 109985) @@ -0,0 +1,469 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_gr.c,v 1.25 2001/06/07 02:12:26 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_GR +static int __bind_irs_gr_unneeded; +#else + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Definitions */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct irs_gr * gr; + /* + * Need space to store the entries read from the group file. + * The members list also needs space per member, and the + * strings making up the user names must be allocated + * somewhere. Rather than doing lots of small allocations, + * we keep one buffer and resize it as needed. + */ + struct group group; + size_t nmemb; /* Malloc'd max index of gr_mem[]. */ + char * membuf; + size_t membufsize; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void gr_close(struct irs_gr *); +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static int gr_list(struct irs_gr *, const char *, + gid_t, gid_t *, int *); +static void gr_minimize(struct irs_gr *); +static struct __res_state * gr_res_get(struct irs_gr *); +static void gr_res_set(struct irs_gr *, + struct __res_state *, + void (*)(void *)); + +static void grmerge(struct irs_gr *gr, const struct group *src, + int preserve); + +static int countvec(char **vec); +static int isnew(char **old, char *new); +static int countnew(char **old, char **new); +static size_t sizenew(char **old, char **new); +static int newgid(int, gid_t *, gid_t); + +/* Public */ + +struct irs_gr * +irs_gen_gr(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_gr *gr; + struct pvt *pvt; + + if (!(gr = memget(sizeof *gr))) { + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x5e, sizeof *gr); + if (!(pvt = memget(sizeof *pvt))) { + memput(gr, sizeof *gr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_gr]; + pvt->rule = pvt->rules; + gr->private = pvt; + gr->close = gr_close; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->list = gr_list; + gr->minimize = gr_minimize; + gr->res_get = gr_res_get; + gr->res_set = gr_res_set; + return (gr); +} + +/* Methods. */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct group * +gr_next(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct group *rval; + struct irs_gr *gr; + + while (pvt->rule) { + gr = pvt->rule->inst->gr; + rval = (*gr->next)(gr); + if (rval) + return (rval); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + gr = pvt->rule->inst->gr; + (*gr->rewind)(gr); + } + } + return (NULL); +} + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct group *tval; + struct irs_gr *gr; + int dirty; + + dirty = 0; + for (rule = pvt->rules; rule; rule = rule->next) { + gr = rule->inst->gr; + tval = (*gr->byname)(gr, name); + if (tval) { + grmerge(this, tval, dirty++); + if (!(rule->flags & IRS_MERGE)) + break; + } else { + if (!(rule->flags & IRS_CONTINUE)) + break; + } + } + if (dirty) + return (&pvt->group); + return (NULL); +} + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct group *tval; + struct irs_gr *gr; + int dirty; + + dirty = 0; + for (rule = pvt->rules; rule; rule = rule->next) { + gr = rule->inst->gr; + tval = (*gr->bygid)(gr, gid); + if (tval) { + grmerge(this, tval, dirty++); + if (!(rule->flags & IRS_MERGE)) + break; + } else { + if (!(rule->flags & IRS_CONTINUE)) + break; + } + } + if (dirty) + return (&pvt->group); + return (NULL); +} + +static void +gr_rewind(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_gr *gr; + + pvt->rule = pvt->rules; + if (pvt->rule) { + gr = pvt->rule->inst->gr; + (*gr->rewind)(gr); + } +} + +static int +gr_list(struct irs_gr *this, const char *name, + gid_t basegid, gid_t *groups, int *ngroups) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct irs_gr *gr; + int t_ngroups, maxgroups; + gid_t *t_groups; + int n, t, rval = 0; + + maxgroups = *ngroups; + *ngroups = 0; + t_groups = (gid_t *)malloc(maxgroups * sizeof(gid_t)); + if (!t_groups) { + errno = ENOMEM; + return (-1); + } + + for (rule = pvt->rules; rule; rule = rule->next) { + t_ngroups = maxgroups; + gr = rule->inst->gr; + t = (*gr->list)(gr, name, basegid, t_groups, &t_ngroups); + for (n = 0; n < t_ngroups; n++) { + if (newgid(*ngroups, groups, t_groups[n])) { + if (*ngroups == maxgroups) { + rval = -1; + goto done; + } + groups[(*ngroups)++] = t_groups[n]; + } + } + if (t == 0) { + if (!(rule->flags & IRS_MERGE)) + break; + } else { + if (!(rule->flags & IRS_CONTINUE)) + break; + } + } + done: + free(t_groups); + return (rval); +} + +static void +gr_minimize(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_gr *gr = rule->inst->gr; + + (*gr->minimize)(gr); + } +} + +static struct __res_state * +gr_res_get(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + gr_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +gr_res_set(struct irs_gr *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_gr *gr = rule->inst->gr; + + if (gr->res_set) + (*gr->res_set)(gr, pvt->res, NULL); + } +} + +/* Private. */ + +static void +grmerge(struct irs_gr *this, const struct group *src, int preserve) { + struct pvt *pvt = (struct pvt *)this->private; + char *cp, **m, **p, *oldmembuf; + int n, ndst, nnew; + size_t used; + + if (!preserve) { + pvt->group.gr_gid = src->gr_gid; + if (pvt->nmemb < 1) { + m = malloc(sizeof *m); + if (!m) { + /* No harm done, no work done. */ + return; + } + pvt->group.gr_mem = m; + pvt->nmemb = 1; + } + pvt->group.gr_mem[0] = NULL; + } + ndst = countvec(pvt->group.gr_mem); + nnew = countnew(pvt->group.gr_mem, src->gr_mem); + + /* + * Make sure destination member array is large enough. + * p points to new portion. + */ + n = ndst + nnew + 1; + if ((size_t)n > pvt->nmemb) { + m = realloc(pvt->group.gr_mem, n * sizeof *m); + if (!m) { + /* No harm done, no work done. */ + return; + } + pvt->group.gr_mem = m; + pvt->nmemb = n; + } + p = pvt->group.gr_mem + ndst; + + /* + * Enlarge destination membuf; cp points at new portion. + */ + n = sizenew(pvt->group.gr_mem, src->gr_mem); + INSIST((nnew == 0) == (n == 0)); + if (!preserve) { + n += strlen(src->gr_name) + 1; + n += strlen(src->gr_passwd) + 1; + } + if (n == 0) { + /* No work to do. */ + return; + } + used = preserve ? pvt->membufsize : 0; + cp = malloc(used + n); + if (!cp) { + /* No harm done, no work done. */ + return; + } + if (used != 0) + memcpy(cp, pvt->membuf, used); + oldmembuf = pvt->membuf; + pvt->membuf = cp; + pvt->membufsize = used + n; + cp += used; + + /* + * Adjust group.gr_mem. + */ + if (pvt->membuf != oldmembuf) + for (m = pvt->group.gr_mem; *m; m++) + *m = pvt->membuf + (*m - oldmembuf); + + /* + * Add new elements. + */ + for (m = src->gr_mem; *m; m++) + if (isnew(pvt->group.gr_mem, *m)) { + *p++ = cp; + *p = NULL; + strcpy(cp, *m); + cp += strlen(cp) + 1; + } + if (preserve) { + pvt->group.gr_name = pvt->membuf + + (pvt->group.gr_name - oldmembuf); + pvt->group.gr_passwd = pvt->membuf + + (pvt->group.gr_passwd - oldmembuf); + } else { + pvt->group.gr_name = cp; + strcpy(cp, src->gr_name); + cp += strlen(src->gr_name) + 1; + pvt->group.gr_passwd = cp; + strcpy(cp, src->gr_passwd); + cp += strlen(src->gr_passwd) + 1; + } + if (oldmembuf != NULL) + free(oldmembuf); + INSIST(cp >= pvt->membuf && cp <= &pvt->membuf[pvt->membufsize]); +} + +static int +countvec(char **vec) { + int n = 0; + + while (*vec++) + n++; + return (n); +} + +static int +isnew(char **old, char *new) { + for (; *old; old++) + if (strcmp(*old, new) == 0) + return (0); + return (1); +} + +static int +countnew(char **old, char **new) { + int n = 0; + + for (; *new; new++) + n += isnew(old, *new); + return (n); +} + +static size_t +sizenew(char **old, char **new) { + size_t n = 0; + + for (; *new; new++) + if (isnew(old, *new)) + n += strlen(*new) + 1; + return (n); +} + +static int +newgid(int ngroups, gid_t *groups, gid_t group) { + ngroups--, groups++; + for (; ngroups-- > 0; groups++) + if (*groups == group) + return (0); + return (1); +} + +#endif /* WANT_IRS_GR */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/gen_gr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/gen_ho.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/gen_ho.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/gen_ho.c (revision 109985) @@ -0,0 +1,391 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: gen_ho.c,v 1.16 2001/05/29 05:48:36 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Definitions */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct irs_ho * ho; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forwards */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); +static struct __res_state * ho_res_get(struct irs_ho *this); +static void ho_res_set(struct irs_ho *this, + struct __res_state *res, + void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +static int init(struct irs_ho *this); + +/* Exports */ + +struct irs_ho * +irs_gen_ho(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_ho *ho; + struct pvt *pvt; + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(ho = memget(sizeof *ho))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + pvt->rules = accpvt->map_rules[irs_ho]; + pvt->rule = pvt->rules; + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->res_get = ho_res_get; + ho->res_set = ho_res_set; + ho->addrinfo = ho_addrinfo; + return (ho); +} + +/* Methods. */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct hostent *rval; + struct irs_ho *ho; + int therrno = NETDB_INTERNAL; + int softerror = 0; + + if (init(this) == -1) + return (NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = 0; + rval = (*ho->byname)(ho, name); + if (rval != NULL) + return (rval); + if (softerror == 0 && + pvt->res->res_h_errno != HOST_NOT_FOUND && + pvt->res->res_h_errno != NETDB_INTERNAL) { + softerror = 1; + therrno = pvt->res->res_h_errno; + } + if (rule->flags & IRS_CONTINUE) + continue; + /* + * The value TRY_AGAIN can mean that the service + * is not available, or just that this particular name + * cannot be resolved now. We use the errno ECONNREFUSED + * to distinguish. If a lookup sets that errno when + * H_ERRNO is TRY_AGAIN, we continue to try other lookup + * functions, otherwise we return the TRY_AGAIN error. + */ + if (pvt->res->res_h_errno != TRY_AGAIN || errno != ECONNREFUSED) + break; + } + if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND) + RES_SET_H_ERRNO(pvt->res, therrno); + return (NULL); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct hostent *rval; + struct irs_ho *ho; + int therrno = NETDB_INTERNAL; + int softerror = 0; + + if (init(this) == -1) + return (NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = 0; + rval = (*ho->byname2)(ho, name, af); + if (rval != NULL) + return (rval); + if (softerror == 0 && + pvt->res->res_h_errno != HOST_NOT_FOUND && + pvt->res->res_h_errno != NETDB_INTERNAL) { + softerror = 1; + therrno = pvt->res->res_h_errno; + } + if (rule->flags & IRS_CONTINUE) + continue; + /* + * See the comments in ho_byname() explaining + * the interpretation of TRY_AGAIN and ECONNREFUSED. + */ + if (pvt->res->res_h_errno != TRY_AGAIN || errno != ECONNREFUSED) + break; + } + if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND) + RES_SET_H_ERRNO(pvt->res, therrno); + return (NULL); +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct hostent *rval; + struct irs_ho *ho; + int therrno = NETDB_INTERNAL; + int softerror = 0; + + + if (init(this) == -1) + return (NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = 0; + rval = (*ho->byaddr)(ho, addr, len, af); + if (rval != NULL) + return (rval); + if (softerror == 0 && + pvt->res->res_h_errno != HOST_NOT_FOUND && + pvt->res->res_h_errno != NETDB_INTERNAL) { + softerror = 1; + therrno = pvt->res->res_h_errno; + } + + if (rule->flags & IRS_CONTINUE) + continue; + /* + * See the comments in ho_byname() explaining + * the interpretation of TRY_AGAIN and ECONNREFUSED. + */ + if (pvt->res->res_h_errno != TRY_AGAIN || errno != ECONNREFUSED) + break; + } + if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND) + RES_SET_H_ERRNO(pvt->res, therrno); + return (NULL); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *rval; + struct irs_ho *ho; + + while (pvt->rule) { + ho = pvt->rule->inst->ho; + rval = (*ho->next)(ho); + if (rval) + return (rval); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + ho = pvt->rule->inst->ho; + (*ho->rewind)(ho); + } + } + return (NULL); +} + +static void +ho_rewind(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_ho *ho; + + pvt->rule = pvt->rules; + if (pvt->rule) { + ho = pvt->rule->inst->ho; + (*ho->rewind)(ho); + } +} + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res) + res_nclose(pvt->res); + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_ho *ho = rule->inst->ho; + + (*ho->minimize)(ho); + } +} + +static struct __res_state * +ho_res_get(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + ho_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +ho_res_set(struct irs_ho *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_ho *ho = rule->inst->ho; + + (*ho->res_set)(ho, pvt->res, NULL); + } +} + +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct addrinfo *rval = NULL; + struct irs_ho *ho; + int therrno = NETDB_INTERNAL; + int softerror = 0; + + if (init(this) == -1) + return (NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = 0; + if (ho->addrinfo == NULL) /* for safety */ + continue; + rval = (*ho->addrinfo)(ho, name, pai); + if (rval != NULL) + return (rval); + if (softerror == 0 && + pvt->res->res_h_errno != HOST_NOT_FOUND && + pvt->res->res_h_errno != NETDB_INTERNAL) { + softerror = 1; + therrno = pvt->res->res_h_errno; + } + if (rule->flags & IRS_CONTINUE) + continue; + /* + * See the comments in ho_byname() explaining + * the interpretation of TRY_AGAIN and ECONNREFUSED. + */ + if (pvt->res->res_h_errno != TRY_AGAIN || + errno != ECONNREFUSED) + break; + } + if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND) + RES_SET_H_ERRNO(pvt->res, therrno); + if (rval) + freeaddrinfo(rval); + return (NULL); +} + +static int +init(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !ho_res_get(this)) + return (-1); + + if (((pvt->res->options & RES_INIT) == 0) && + (res_ninit(pvt->res) == -1)) + return (-1); + + return (0); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/gen_ho.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/gen_ng.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/gen_ng.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/gen_ng.c (revision 109985) @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_ng.c,v 1.15 2001/05/29 05:48:38 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + char * curgroup; +}; + +/* Forward */ + +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); +static int ng_test(struct irs_ng *, const char *, + const char *, const char *, + const char *); +static void ng_rewind(struct irs_ng *, const char *); +static void ng_minimize(struct irs_ng *); + +/* Public */ + +struct irs_ng * +irs_gen_ng(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_ng *ng; + struct pvt *pvt; + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + if (!(pvt = memget(sizeof *pvt))) { + memput(ng, sizeof *ng); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_ng]; + pvt->rule = pvt->rules; + ng->private = pvt; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods */ + +static void +ng_close(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ng_minimize(this); + if (pvt->curgroup) + free(pvt->curgroup); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static int +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct irs_ng *ng; + + while (pvt->rule) { + ng = pvt->rule->inst->ng; + if ((*ng->next)(ng, host, user, domain) == 1) + return (1); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + ng = pvt->rule->inst->ng; + (*ng->rewind)(ng, pvt->curgroup); + } + } + return (0); +} + +static int +ng_test(struct irs_ng *this, const char *name, + const char *user, const char *host, const char *domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct irs_ng *ng; + int rval; + + rval = 0; + for (rule = pvt->rules; rule; rule = rule->next) { + ng = rule->inst->ng; + rval = (*ng->test)(ng, name, user, host, domain); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +ng_rewind(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_ng *ng; + + pvt->rule = pvt->rules; + if (pvt->rule) { + if (pvt->curgroup) + free(pvt->curgroup); + pvt->curgroup = strdup(group); + ng = pvt->rule->inst->ng; + (*ng->rewind)(ng, pvt->curgroup); + } +} + +static void +ng_minimize(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_ng *ng = rule->inst->ng; + + (*ng->minimize)(ng); + } +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/gen_ng.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/gen_p.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/gen_p.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/gen_p.h (revision 109985) @@ -0,0 +1,113 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * $Id: gen_p.h,v 1.11 2001/05/29 05:48:39 marka Exp $ + */ + +/* Notes: + * We hope to create a complete set of thread-safe entry points someday, + * which will mean a set of getXbyY() functions that take as an argument + * a pointer to the map class, which will have a pointer to the private + * data, which will be used preferentially to the static variables that + * are necessary to support the "classic" interface. This "classic" + * interface will then be reimplemented as stubs on top of the thread + * safe modules, and will keep the map class pointers as their only + * static data. HOWEVER, we are not there yet. So while we will call + * the just-barely-converted map class methods with map class pointers, + * right now they probably all still use statics. We're not fooling + * anybody, and we're not trying to (yet). + */ + +#ifndef _GEN_P_H_INCLUDED +#define _GEN_P_H_INCLUDED + +/* + * These are the access methods. + */ +enum irs_acc_id { + irs_lcl, /* Local. */ + irs_dns, /* DNS or Hesiod. */ + irs_nis, /* Sun NIS ("YP"). */ + irs_irp, /* IR protocol. */ + irs_nacc +}; + +/* + * These are the map types. + */ +enum irs_map_id { + irs_gr, /* "group" */ + irs_pw, /* "passwd" */ + irs_sv, /* "services" */ + irs_pr, /* "protocols" */ + irs_ho, /* "hosts" */ + irs_nw, /* "networks" */ + irs_ng, /* "netgroup" */ + irs_nmap +}; + +/* + * This is an accessor instance. + */ +struct irs_inst { + struct irs_acc *acc; + struct irs_gr * gr; + struct irs_pw * pw; + struct irs_sv * sv; + struct irs_pr * pr; + struct irs_ho * ho; + struct irs_nw * nw; + struct irs_ng * ng; +}; + +/* + * This is a search rule for some map type. + */ +struct irs_rule { + struct irs_rule * next; + struct irs_inst * inst; + int flags; +}; +#define IRS_MERGE 0x0001 /* Don't stop if acc. has data? */ +#define IRS_CONTINUE 0x0002 /* Don't stop if acc. has no data? */ + +/* + * This is the private data for a search access class. + */ +struct gen_p { + char * options; + struct irs_rule * map_rules[(int)irs_nmap]; + struct irs_inst accessors[(int)irs_nacc]; + struct __res_state * res; + void (*free_res) __P((void *)); +}; + +/* + * Externs. + */ + +extern struct irs_acc * irs_gen_acc __P((const char *, const char *conf_file)); +extern struct irs_gr * irs_gen_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_gen_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_gen_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_gen_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_gen_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_gen_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_gen_ng __P((struct irs_acc *)); + +#endif /*_IRS_P_H_INCLUDED*/ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/gen_p.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/getgrent.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/getgrent.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/getgrent.c (revision 109985) @@ -0,0 +1,223 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: getgrent.c,v 1.20 2001/05/29 05:48:41 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(WANT_IRS_GR) || defined(__BIND_NOSTATIC) +static int __bind_irs_gr_unneeded; +#else + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct net_data *init(void); +void endgrent(void); + +/* Public */ + +struct group * +getgrent() { + struct net_data *net_data = init(); + + return (getgrent_p(net_data)); +} + +struct group * +getgrnam(const char *name) { + struct net_data *net_data = init(); + + return (getgrnam_p(name, net_data)); +} + +struct group * +getgrgid(gid_t gid) { + struct net_data *net_data = init(); + + return (getgrgid_p(gid, net_data)); +} + +int +setgroupent(int stayopen) { + struct net_data *net_data = init(); + + return (setgroupent_p(stayopen, net_data)); +} + +#ifdef SETGRENT_VOID +void +setgrent(void) { + struct net_data *net_data = init(); + + setgrent_p(net_data); +} +#else +int +setgrent(void) { + struct net_data *net_data = init(); + + return (setgrent_p(net_data)); +} +#endif /* SETGRENT_VOID */ + +void +endgrent() { + struct net_data *net_data = init(); + + endgrent_p(net_data); +} + +int +getgrouplist(GETGROUPLIST_ARGS) { + struct net_data *net_data = init(); + + return (getgrouplist_p(name, basegid, groups, ngroups, net_data)); +} + +/* Shared private. */ + +struct group * +getgrent_p(struct net_data *net_data) { + struct irs_gr *gr; + + if (!net_data || !(gr = net_data->gr)) + return (NULL); + net_data->gr_last = (*gr->next)(gr); + return (net_data->gr_last); +} + +struct group * +getgrnam_p(const char *name, struct net_data *net_data) { + struct irs_gr *gr; + + if (!net_data || !(gr = net_data->gr)) + return (NULL); + if (net_data->gr_stayopen && net_data->gr_last && + !strcmp(net_data->gr_last->gr_name, name)) + return (net_data->gr_last); + net_data->gr_last = (*gr->byname)(gr, name); + if (!net_data->gr_stayopen) + endgrent(); + return (net_data->gr_last); +} + +struct group * +getgrgid_p(gid_t gid, struct net_data *net_data) { + struct irs_gr *gr; + + if (!net_data || !(gr = net_data->gr)) + return (NULL); + if (net_data->gr_stayopen && net_data->gr_last && + (gid_t)net_data->gr_last->gr_gid == gid) + return (net_data->gr_last); + net_data->gr_last = (*gr->bygid)(gr, gid); + if (!net_data->gr_stayopen) + endgrent(); + return (net_data->gr_last); +} + +int +setgroupent_p(int stayopen, struct net_data *net_data) { + struct irs_gr *gr; + + if (!net_data || !(gr = net_data->gr)) + return (0); + (*gr->rewind)(gr); + net_data->gr_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); + return (1); +} + +#ifdef SETGRENT_VOID +void +setgrent_p(struct net_data *net_data) { + (void)setgroupent_p(0, net_data); +} +#else +int +setgrent_p(struct net_data *net_data) { + return (setgroupent_p(0, net_data)); +} +#endif /* SETGRENT_VOID */ + +void +endgrent_p(struct net_data *net_data) { + struct irs_gr *gr; + + if ((net_data != NULL) && ((gr = net_data->gr) != NULL)) + (*gr->minimize)(gr); +} + +int +getgrouplist_p(const char *name, gid_t basegid, gid_t *groups, int *ngroups, + struct net_data *net_data) { + struct irs_gr *gr; + + if (!net_data || !(gr = net_data->gr)) { + *ngroups = 0; + return (-1); + } + return ((*gr->list)(gr, name, basegid, groups, ngroups)); +} + +/* Private */ + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->gr) { + net_data->gr = (*net_data->irs->gr_map)(net_data->irs); + + if (!net_data->gr || !net_data->res) { + error: + errno = EIO; + return (NULL); + } + (*net_data->gr->res_set)(net_data->gr, net_data->res, + NULL); + } + + return (net_data); +} + +#endif /* WANT_IRS_GR */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/getgrent.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/getgrent_r.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/getgrent_r.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/getgrent_r.c (revision 109985) @@ -0,0 +1,229 @@ +/* + * Copyright (c) 1998-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getgrent_r.c,v 8.7 2001/11/01 08:02:08 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) || !defined(WANT_IRS_PW) + static int getgrent_r_not_required = 0; +#else +#include +#include +#include +#include +#if (defined(POSIX_GETGRNAM_R) || defined(POSIX_GETGRGID_R)) && \ + defined(_POSIX_PTHREAD_SEMANTICS) + /* turn off solaris remapping in */ +#define _UNIX95 +#undef _POSIX_PTHREAD_SEMANTICS +#include +#define _POSIX_PTHREAD_SEMANTICS 1 +#else +#include +#endif +#include +#include + +#ifdef GROUP_R_RETURN + +static int +copy_group(struct group *, struct group *, char *buf, int buflen); + +/* POSIX 1003.1c */ +#ifdef POSIX_GETGRNAM_R +int +__posix_getgrnam_r(const char *name, struct group *gptr, + char *buf, int buflen, struct group **result) { +#else +int +getgrnam_r(const char *name, struct group *gptr, + char *buf, size_t buflen, struct group **result) { +#endif + struct group *ge = getgrnam(name); + int res; + + if (ge == NULL) { + *result = NULL; + return (0); + } + + res = copy_group(ge, gptr, buf, buflen); + *result = res ? NULL : gptr; + return (res); +} + +#ifdef POSIX_GETGRNAM_R +struct group * +getgrnam_r(const char *name, struct group *gptr, + char *buf, int buflen) { + struct group *ge = getgrnam(name); + int res; + + if (ge == NULL) + return (NULL); + res = copy_group(ge, gptr, buf, buflen); + return (res ? NULL : gptr); +} +#endif /* POSIX_GETGRNAM_R */ + +/* POSIX 1003.1c */ +#ifdef POSIX_GETGRGID_R +int +__posix_getgrgid_r(gid_t gid, struct group *gptr, + char *buf, int buflen, struct group **result) { +#else /* POSIX_GETGRGID_R */ +int +getgrgid_r(gid_t gid, struct group *gptr, + char *buf, size_t buflen, struct group **result) { +#endif /* POSIX_GETGRGID_R */ + struct group *ge = getgrgid(gid); + int res; + + if (ge == NULL) { + *result = NULL; + return (0); + } + + res = copy_group(ge, gptr, buf, buflen); + *result = res ? NULL : gptr; + return (res); +} + +#ifdef POSIX_GETGRGID_R +struct group * +getgrgid_r(gid_t gid, struct group *gptr, + char *buf, int buflen) { + struct group *ge = getgrgid(gid); + int res; + + if (ge == NULL) + return (NULL); + + res = copy_group(ge, gptr, buf, buflen); + return (res ? NULL : gptr); +} +#endif + +/* + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +GROUP_R_RETURN +getgrent_r(struct group *gptr, GROUP_R_ARGS) { + struct group *ge = getgrent(); + int res; + + if (ge == NULL) { + return (GROUP_R_BAD); + } + + res = copy_group(ge, gptr, buf, buflen); + return (res ? GROUP_R_BAD : GROUP_R_OK); +} + +GROUP_R_SET_RETURN +setgrent_r(GROUP_R_ENT_ARGS) { + + setgrent(); +#ifdef GROUP_R_SET_RESULT + return (GROUP_R_SET_RESULT); +#endif +} + +GROUP_R_END_RETURN +endgrent_r(GROUP_R_ENT_ARGS) { + + endgrent(); + GROUP_R_END_RESULT(GROUP_R_OK); +} + + +#if 0 + /* XXX irs does not have a fgetgrent() */ +GROUP_R_RETURN +fgetgrent_r(FILE *f, struct group *gptr, GROUP_R_ARGS) { + struct group *ge = fgetgrent(f); + int res; + + if (ge == NULL) + return (GROUP_R_BAD); + + res = copy_group(ge, gptr, buf, buflen); + return (res ? GROUP_R_BAD : GROUP_R_OK); +} +#endif + +/* Private */ + +static int +copy_group(struct group *ge, struct group *gptr, char *buf, int buflen) { + char *cp; + int i, n; + int numptr, len; + + /* Find out the amount of space required to store the answer. */ + numptr = 1; /* NULL ptr */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; ge->gr_mem[i]; i++, numptr++) { + len += strlen(ge->gr_mem[i]) + 1; + } + len += strlen(ge->gr_name) + 1; + len += strlen(ge->gr_passwd) + 1; + len += numptr * sizeof(char*); + + if (len > buflen) { + errno = ERANGE; + return (ERANGE); + } + + /* copy group id */ + gptr->gr_gid = ge->gr_gid; + + cp = (char *)ALIGN(buf) + numptr * sizeof(char *); + + /* copy official name */ + n = strlen(ge->gr_name) + 1; + strcpy(cp, ge->gr_name); + gptr->gr_name = cp; + cp += n; + + /* copy member list */ + gptr->gr_mem = (char **)ALIGN(buf); + for (i = 0 ; ge->gr_mem[i]; i++) { + n = strlen(ge->gr_mem[i]) + 1; + strcpy(cp, ge->gr_mem[i]); + gptr->gr_mem[i] = cp; + cp += n; + } + gptr->gr_mem[i] = NULL; + + /* copy password */ + n = strlen(ge->gr_passwd) + 1; + strcpy(cp, ge->gr_passwd); + gptr->gr_passwd = cp; + cp += n; + + return (0); +} +#else /* GROUP_R_RETURN */ + static int getgrent_r_unknown_system = 0; +#endif /* GROUP_R_RETURN */ +#endif /* !def(_REENTRANT) || !def(DO_PTHREADS) || !def(WANT_IRS_PW) */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/getgrent_r.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/gethostent_r.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/gethostent_r.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/gethostent_r.c (revision 109985) @@ -0,0 +1,264 @@ +/* + * Copyright (c) 1998-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: gethostent_r.c,v 8.7 2001/11/01 08:02:09 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int gethostent_r_not_required = 0; +#else +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HOST_R_RETURN + +static HOST_R_RETURN +copy_hostent(struct hostent *, struct hostent *, HOST_R_COPY_ARGS); + +HOST_R_RETURN +gethostbyname_r(const char *name, struct hostent *hptr, HOST_R_ARGS) { + struct hostent *he = gethostbyname(name); +#ifdef HOST_R_SETANSWER + int n = 0; +#endif + + HOST_R_ERRNO; + +#ifdef HOST_R_SETANSWER + if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) == 0) + *answerp = NULL; + else + *answerp = hptr; + + return (n); +#else + if (he == NULL) + return (HOST_R_BAD); + + return (copy_hostent(he, hptr, HOST_R_COPY)); +#endif +} + +HOST_R_RETURN +gethostbyaddr_r(const char *addr, int len, int type, + struct hostent *hptr, HOST_R_ARGS) { + struct hostent *he = gethostbyaddr(addr, len, type); +#ifdef HOST_R_SETANSWER + int n = 0; +#endif + + HOST_R_ERRNO; + +#ifdef HOST_R_SETANSWER + if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) == 0) + *answerp = NULL; + else + *answerp = hptr; + + return (n); +#else + if (he == NULL) + return (HOST_R_BAD); + + return (copy_hostent(he, hptr, HOST_R_COPY)); +#endif +} + +/* + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +HOST_R_RETURN +gethostent_r(struct hostent *hptr, HOST_R_ARGS) { + struct hostent *he = gethostent(); +#ifdef HOST_R_SETANSWER + int n = 0; +#endif + + HOST_R_ERRNO; + +#ifdef HOST_R_SETANSWER + if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) == 0) + *answerp = NULL; + else + *answerp = hptr; + + return (n); +#else + if (he == NULL) + return (HOST_R_BAD); + + return (copy_hostent(he, hptr, HOST_R_COPY)); +#endif +} + +HOST_R_SET_RETURN +#ifdef HOST_R_ENT_ARGS +sethostent_r(int stay_open, HOST_R_ENT_ARGS) +#else +sethostent_r(int stay_open) +#endif +{ + sethostent(stay_open); +#ifdef HOST_R_SET_RESULT + return (HOST_R_SET_RESULT); +#endif +} + +HOST_R_END_RETURN +#ifdef HOST_R_ENT_ARGS +endhostent_r(HOST_R_ENT_ARGS) +#else +endhostent_r(void) +#endif +{ + endhostent(); + HOST_R_END_RESULT(HOST_R_OK); +} + +/* Private */ + +#ifndef HOSTENT_DATA +static HOST_R_RETURN +copy_hostent(struct hostent *he, struct hostent *hptr, HOST_R_COPY_ARGS) { + char *cp; + char **ptr; + int i, n; + int nptr, len; + + /* Find out the amount of space required to store the answer. */ + nptr = 2; /* NULL ptrs */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; he->h_addr_list[i]; i++, nptr++) { + len += he->h_length; + } + for (i = 0; he->h_aliases[i]; i++, nptr++) { + len += strlen(he->h_aliases[i]) + 1; + } + len += strlen(he->h_name) + 1; + len += nptr * sizeof(char*); + + if (len > buflen) { + errno = ERANGE; + return (HOST_R_BAD); + } + + /* copy address size and type */ + hptr->h_addrtype = he->h_addrtype; + n = hptr->h_length = he->h_length; + + ptr = (char **)ALIGN(buf); + cp = (char *)ALIGN(buf) + nptr * sizeof(char *); + + /* copy address list */ + hptr->h_addr_list = ptr; + for (i = 0; he->h_addr_list[i]; i++ , ptr++) { + memcpy(cp, he->h_addr_list[i], n); + hptr->h_addr_list[i] = cp; + cp += n; + } + hptr->h_addr_list[i] = NULL; + ptr++; + + /* copy official name */ + n = strlen(he->h_name) + 1; + strcpy(cp, he->h_name); + hptr->h_name = cp; + cp += n; + + /* copy aliases */ + hptr->h_aliases = ptr; + for (i = 0 ; he->h_aliases[i]; i++) { + n = strlen(he->h_aliases[i]) + 1; + strcpy(cp, he->h_aliases[i]); + hptr->h_aliases[i] = cp; + cp += n; + } + hptr->h_aliases[i] = NULL; + + return (HOST_R_OK); +} +#else /* !HOSTENT_DATA */ +static int +copy_hostent(struct hostent *he, struct hostent *hptr, HOST_R_COPY_ARGS) { + char *cp, *eob; + int i, n; + + /* copy address size and type */ + hptr->h_addrtype = he->h_addrtype; + n = hptr->h_length = he->h_length; + + /* copy up to first 35 addresses */ + i = 0; + cp = hdptr->hostaddr; + eob = hdptr->hostaddr + sizeof(hdptr->hostaddr); + hptr->h_addr_list = hdptr->h_addr_ptrs; + while (he->h_addr_list[i] && i < (_MAXADDRS)) { + if (n < (eob - cp)) { + memcpy(cp, he->h_addr_list[i], n); + hptr->h_addr_list[i] = cp; + cp += n; + } else { + break; + } + i++; + } + hptr->h_addr_list[i] = NULL; + + /* copy official name */ + cp = hdptr->hostbuf; + eob = hdptr->hostbuf + sizeof(hdptr->hostbuf); + if ((n = strlen(he->h_name) + 1) < (eob - cp)) { + strcpy(cp, he->h_name); + hptr->h_name = cp; + cp += n; + } else { + return (-1); + } + + /* copy aliases */ + i = 0; + hptr->h_aliases = hdptr->host_aliases; + while (he->h_aliases[i] && i < (_MAXALIASES-1)) { + if ((n = strlen(he->h_aliases[i]) + 1) < (eob - cp)) { + strcpy(cp, he->h_aliases[i]); + hptr->h_aliases[i] = cp; + cp += n; + } else { + break; + } + i++; + } + hptr->h_aliases[i] = NULL; + + return (HOST_R_OK); +} +#endif /* !HOSTENT_DATA */ +#else /* HOST_R_RETURN */ + static int gethostent_r_unknown_system = 0; +#endif /* HOST_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/gethostent_r.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/getnetent.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/getnetent.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/getnetent.c (revision 109985) @@ -0,0 +1,343 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: getnetent.c,v 1.19 2001/05/29 05:48:47 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "irs_data.h" + +/* Definitions */ + +struct pvt { + struct netent netent; + char * aliases[1]; + char name[MAXDNAME + 1]; +}; + +/* Forward */ + +static struct net_data *init(void); +static struct netent *nw_to_net(struct nwent *, struct net_data *); +static void freepvt(struct net_data *); +static struct netent *fakeaddr(const char *, int af, struct net_data *); + +/* Portability */ + +#ifndef INADDR_NONE +# define INADDR_NONE 0xffffffff +#endif + +/* Public */ + +struct netent * +getnetent() { + struct net_data *net_data = init(); + + return (getnetent_p(net_data)); +} + +struct netent * +getnetbyname(const char *name) { + struct net_data *net_data = init(); + + return (getnetbyname_p(name, net_data)); +} + +struct netent * +getnetbyaddr(unsigned long net, int type) { + struct net_data *net_data = init(); + + return (getnetbyaddr_p(net, type, net_data)); +} + +void +setnetent(int stayopen) { + struct net_data *net_data = init(); + + setnetent_p(stayopen, net_data); +} + + +void +endnetent() { + struct net_data *net_data = init(); + + endnetent_p(net_data); +} + +/* Shared private. */ + +struct netent * +getnetent_p(struct net_data *net_data) { + struct irs_nw *nw; + + if (!net_data || !(nw = net_data->nw)) + return (NULL); + net_data->nww_last = (*nw->next)(nw); + net_data->nw_last = nw_to_net(net_data->nww_last, net_data); + return (net_data->nw_last); +} + +struct netent * +getnetbyname_p(const char *name, struct net_data *net_data) { + struct irs_nw *nw; + struct netent *np; + char **nap; + + if (!net_data || !(nw = net_data->nw)) + return (NULL); + if (net_data->nw_stayopen && net_data->nw_last) { + if (!strcmp(net_data->nw_last->n_name, name)) + return (net_data->nw_last); + for (nap = net_data->nw_last->n_aliases; nap && *nap; nap++) + if (!strcmp(name, *nap)) + return (net_data->nw_last); + } + if ((np = fakeaddr(name, AF_INET, net_data)) != NULL) + return (np); + net_data->nww_last = (*nw->byname)(nw, name, AF_INET); + net_data->nw_last = nw_to_net(net_data->nww_last, net_data); + if (!net_data->nw_stayopen) + endnetent(); + return (net_data->nw_last); +} + +struct netent * +getnetbyaddr_p(unsigned long net, int type, struct net_data *net_data) { + struct irs_nw *nw; + u_char addr[4]; + int bits; + + if (!net_data || !(nw = net_data->nw)) + return (NULL); + if (net_data->nw_stayopen && net_data->nw_last) + if (type == net_data->nw_last->n_addrtype && + net == net_data->nw_last->n_net) + return (net_data->nw_last); + + /* cannonize net(host order) */ + if (net < 256) { + net <<= 24; + bits = 8; + } else if (net < 65536) { + net <<= 16; + bits = 16; + } else if (net < 16777216) { + net <<= 8; + bits = 24; + } else + bits = 32; + + /* convert to net order */ + addr[0] = (0xFF000000 & net) >> 24; + addr[1] = (0x00FF0000 & net) >> 16; + addr[2] = (0x0000FF00 & net) >> 8; + addr[3] = (0x000000FF & net); + + /* reduce bits to as close to natural number as possible */ + if ((bits == 32) && (addr[0] < 224) && (addr[3] == 0)) { + if ((addr[0] < 192) && (addr[2] == 0)) { + if ((addr[0] < 128) && (addr[1] == 0)) + bits = 8; + else + bits = 16; + } else { + bits = 24; + } + } + + net_data->nww_last = (*nw->byaddr)(nw, addr, bits, AF_INET); + net_data->nw_last = nw_to_net(net_data->nww_last, net_data); + if (!net_data->nw_stayopen) + endnetent(); + return (net_data->nw_last); +} + + + + +void +setnetent_p(int stayopen, struct net_data *net_data) { + struct irs_nw *nw; + + if (!net_data || !(nw = net_data->nw)) + return; + freepvt(net_data); + (*nw->rewind)(nw); + net_data->nw_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); +} + +void +endnetent_p(struct net_data *net_data) { + struct irs_nw *nw; + + if ((net_data != NULL) && ((nw = net_data->nw) != NULL)) + (*nw->minimize)(nw); +} + +/* Private */ + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->nw) { + net_data->nw = (*net_data->irs->nw_map)(net_data->irs); + + if (!net_data->nw || !net_data->res) { + error: + errno = EIO; + return (NULL); + } + (*net_data->nw->res_set)(net_data->nw, net_data->res, NULL); + } + + return (net_data); +} + +static void +freepvt(struct net_data *net_data) { + if (net_data->nw_data) { + free(net_data->nw_data); + net_data->nw_data = NULL; + } +} + +static struct netent * +fakeaddr(const char *name, int af, struct net_data *net_data) { + struct pvt *pvt; + const char *cp; + u_long tmp; + + if (af != AF_INET) { + /* XXX should support IPv6 some day */ + errno = EAFNOSUPPORT; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + if (!isascii((unsigned char)(name[0])) || + !isdigit((unsigned char)(name[0]))) + return (NULL); + for (cp = name; *cp; ++cp) + if (!isascii(*cp) || (!isdigit((unsigned char)*cp) && *cp != '.')) + return (NULL); + if (*--cp == '.') + return (NULL); + + /* All-numeric, no dot at the end. */ + + tmp = inet_network(name); + if (tmp == INADDR_NONE) { + RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); + return (NULL); + } + + /* Valid network number specified. + * Fake up a netent as if we'd actually + * done a lookup. + */ + freepvt(net_data); + net_data->nw_data = malloc(sizeof (struct pvt)); + if (!net_data->nw_data) { + errno = ENOMEM; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + pvt = net_data->nw_data; + + strncpy(pvt->name, name, MAXDNAME); + pvt->name[MAXDNAME] = '\0'; + pvt->netent.n_name = pvt->name; + pvt->netent.n_addrtype = AF_INET; + pvt->netent.n_aliases = pvt->aliases; + pvt->aliases[0] = NULL; + pvt->netent.n_net = tmp; + + return (&pvt->netent); +} + +static struct netent * +nw_to_net(struct nwent *nwent, struct net_data *net_data) { + struct pvt *pvt; + u_long addr = 0; + int i; + int msbyte; + + if (!nwent || nwent->n_addrtype != AF_INET) + return (NULL); + freepvt(net_data); + net_data->nw_data = malloc(sizeof (struct pvt)); + if (!net_data->nw_data) { + errno = ENOMEM; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + pvt = net_data->nw_data; + pvt->netent.n_name = nwent->n_name; + pvt->netent.n_aliases = nwent->n_aliases; + pvt->netent.n_addrtype = nwent->n_addrtype; + +/* + * What this code does: Converts net addresses from network to host form. + * + * msbyte: the index of the most significant byte in the n_addr array. + * + * Shift bytes in significant order into addr. When all signicant + * bytes are in, zero out bits in the LSB that are not part of the network. + */ + msbyte = nwent->n_length / 8 + + ((nwent->n_length % 8) != 0 ? 1 : 0) - 1; + for (i = 0; i <= msbyte; i++) + addr = (addr << 8) | ((unsigned char *)nwent->n_addr)[i]; + i = (32 - nwent->n_length) % 8; + if (i != 0) + addr &= ~((1 << (i + 1)) - 1); + pvt->netent.n_net = addr; + return (&pvt->netent); +} + +#endif /*__BIND_NOSTATIC*/ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/getnetent.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/getnetent_r.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/getnetent_r.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/getnetent_r.c (revision 109985) @@ -0,0 +1,227 @@ +/* + * Copyright (c) 1998-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getnetent_r.c,v 8.6 2001/11/01 08:02:11 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int getnetent_r_not_required = 0; +#else +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef NET_R_RETURN + +static NET_R_RETURN +copy_netent(struct netent *, struct netent *, NET_R_COPY_ARGS); + +NET_R_RETURN +getnetbyname_r(const char *name, struct netent *nptr, NET_R_ARGS) { + struct netent *ne = getnetbyname(name); +#ifdef NET_R_SETANSWER + int n = 0; + + if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = ne; + if (ne == NULL) + *h_errnop = h_errno; + return (n); +#else + if (ne == NULL) + return (NET_R_BAD); + + return (copy_netent(ne, nptr, NET_R_COPY)); +#endif +} + +#ifndef GETNETBYADDR_ADDR_T +#define GETNETBYADDR_ADDR_T long +#endif +NET_R_RETURN +getnetbyaddr_r(GETNETBYADDR_ADDR_T addr, int type, struct netent *nptr, NET_R_ARGS) { + struct netent *ne = getnetbyaddr(addr, type); +#ifdef NET_R_SETANSWER + int n = 0; + + if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = ne; + if (ne == NULL) + *h_errnop = h_errno; + return (n); +#else + + if (ne == NULL) + return (NET_R_BAD); + + return (copy_netent(ne, nptr, NET_R_COPY)); +#endif +} + +/* + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +NET_R_RETURN +getnetent_r(struct netent *nptr, NET_R_ARGS) { + struct netent *ne = getnetent(); +#ifdef NET_R_SETANSWER + int n = 0; + + if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = ne; + if (ne == NULL) + *h_errnop = h_errno; + return (n); +#else + + if (ne == NULL) + return (NET_R_BAD); + + return (copy_netent(ne, nptr, NET_R_COPY)); +#endif +} + +NET_R_SET_RETURN +#ifdef NET_R_ENT_ARGS +setnetent_r(int stay_open, NET_R_ENT_ARGS) +#else +setnetent_r(int stay_open) +#endif +{ + setnetent(stay_open); +#ifdef NET_R_SET_RESULT + return (NET_R_SET_RESULT); +#endif +} + +NET_R_END_RETURN +#ifdef NET_R_ENT_ARGS +endnetent_r(NET_R_ENT_ARGS) +#else +endnetent_r() +#endif +{ + endnetent(); + NET_R_END_RESULT(NET_R_OK); +} + +/* Private */ + +#ifndef NETENT_DATA +static NET_R_RETURN +copy_netent(struct netent *ne, struct netent *nptr, NET_R_COPY_ARGS) { + char *cp; + int i, n; + int numptr, len; + + /* Find out the amount of space required to store the answer. */ + numptr = 1; /* NULL ptr */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; ne->n_aliases[i]; i++, numptr++) { + len += strlen(ne->n_aliases[i]) + 1; + } + len += strlen(ne->n_name) + 1; + len += numptr * sizeof(char*); + + if (len > (int)buflen) { + errno = ERANGE; + return (NET_R_BAD); + } + + /* copy net value and type */ + nptr->n_addrtype = ne->n_addrtype; + nptr->n_net = ne->n_net; + + cp = (char *)ALIGN(buf) + numptr * sizeof(char *); + + /* copy official name */ + n = strlen(ne->n_name) + 1; + strcpy(cp, ne->n_name); + nptr->n_name = cp; + cp += n; + + /* copy aliases */ + nptr->n_aliases = (char **)ALIGN(buf); + for (i = 0 ; ne->n_aliases[i]; i++) { + n = strlen(ne->n_aliases[i]) + 1; + strcpy(cp, ne->n_aliases[i]); + nptr->n_aliases[i] = cp; + cp += n; + } + nptr->n_aliases[i] = NULL; + + return (NET_R_OK); +} +#else /* !NETENT_DATA */ +static int +copy_netent(struct netent *ne, struct netent *nptr, NET_R_COPY_ARGS) { + char *cp, *eob; + int i, n; + + /* copy net value and type */ + nptr->n_addrtype = ne->n_addrtype; + nptr->n_net = ne->n_net; + + /* copy official name */ + cp = ndptr->line; + eob = ndptr->line + sizeof(ndptr->line); + if ((n = strlen(ne->n_name) + 1) < (eob - cp)) { + strcpy(cp, ne->n_name); + nptr->n_name = cp; + cp += n; + } else { + return (-1); + } + + /* copy aliases */ + i = 0; + nptr->n_aliases = ndptr->net_aliases; + while (ne->n_aliases[i] && i < (_MAXALIASES-1)) { + if ((n = strlen(ne->n_aliases[i]) + 1) < (eob - cp)) { + strcpy(cp, ne->n_aliases[i]); + nptr->n_aliases[i] = cp; + cp += n; + } else { + break; + } + i++; + } + nptr->n_aliases[i] = NULL; + + return (NET_R_OK); +} +#endif /* !NETENT_DATA */ +#else /* NET_R_RETURN */ + static int getnetent_r_unknown_system = 0; +#endif /* NET_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/getnetent_r.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/getnetgrent.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/getnetgrent.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/getnetgrent.c (revision 109985) @@ -0,0 +1,141 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getnetgrent.c,v 1.15 2001/05/29 05:48:49 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include + +#include +#include + +#include +#include +#include + +#include + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct net_data *init(void); + + +/* Public */ + +void +setnetgrent(const char *netgroup) { + struct net_data *net_data = init(); + + setnetgrent_p(netgroup, net_data); +} + +void +endnetgrent(void) { + struct net_data *net_data = init(); + + endnetgrent_p(net_data); +} + +int +innetgr(const char *netgroup, const char *host, + const char *user, const char *domain) { + struct net_data *net_data = init(); + + return (innetgr_p(netgroup, host, user, domain, net_data)); +} + +int +getnetgrent(const char **host, const char **user, const char **domain) { + struct net_data *net_data = init(); + + return (getnetgrent_p(host, user, domain, net_data)); +} + +/* Shared private. */ + +void +setnetgrent_p(const char *netgroup, struct net_data *net_data) { + struct irs_ng *ng; + + if ((net_data != NULL) && ((ng = net_data->ng) != NULL)) + (*ng->rewind)(ng, netgroup); +} + +void +endnetgrent_p(struct net_data *net_data) { + struct irs_ng *ng; + + if (!net_data) + return; + if ((ng = net_data->ng) != NULL) + (*ng->close)(ng); + net_data->ng = NULL; +} + +int +innetgr_p(const char *netgroup, const char *host, + const char *user, const char *domain, + struct net_data *net_data) { + struct irs_ng *ng; + + if (!net_data || !(ng = net_data->ng)) + return (0); + return ((*ng->test)(ng, netgroup, host, user, domain)); +} + +int +getnetgrent_p(const char **host, const char **user, const char **domain, + struct net_data *net_data ) { + struct irs_ng *ng; + + if (!net_data || !(ng = net_data->ng)) + return (0); + return ((*ng->next)(ng, host, user, domain)); +} + +/* Private */ + +static struct net_data * +init(void) { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->ng) { + net_data->ng = (*net_data->irs->ng_map)(net_data->irs); + if (!net_data->ng) { + error: + errno = EIO; + return (NULL); + } + } + + return (net_data); +} + +#endif /*__BIND_NOSTATIC*/ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/getnetgrent.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/getnetgrent_r.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/getnetgrent_r.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/getnetgrent_r.c (revision 109985) @@ -0,0 +1,159 @@ +/* + * Copyright (c) 1998-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getnetgrent_r.c,v 8.6 2001/11/01 08:02:12 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int getnetgrent_r_not_required = 0; +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef NGR_R_RETURN + +static NGR_R_RETURN +copy_protoent(char **, char **, char **, const char *, const char *, + const char *, NGR_R_COPY_ARGS); + +NGR_R_RETURN +innetgr_r(const char *netgroup, const char *host, const char *user, + const char *domain) { + + return (innetgr(netgroup, host, user, domain)); +} + +/* + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +NGR_R_RETURN +getnetgrent_r(char **machinep, char **userp, char **domainp, NGR_R_ARGS) { + const char *mp, *up, *dp; + int res = getnetgrent(&mp, &up, &dp); + + if (res != 1) + return (res); + + return (copy_protoent(machinep, userp, domainp, + mp, up, dp, NGR_R_COPY)); +} + +NGR_R_SET_RETURN +#ifdef NGR_R_ENT_ARGS +setnetgrent_r(const char *netgroup, NGR_R_ENT_ARGS) +#else +setnetgrent_r(const char *netgroup) +#endif +{ + setnetgrent(netgroup); +#ifdef NGR_R_PRIVATE + *buf = NULL; +#endif +#ifdef NGR_R_SET_RESULT + return (NGR_R_SET_RESULT); +#endif +} + +NGR_R_END_RETURN +#ifdef NGR_R_ENT_ARGS +endnetgrent_r(NGR_R_ENT_ARGS) +#else +endnetgrent_r(void) +#endif +{ + endnetgrent(); +#ifdef NGR_R_PRIVATE + if (*buf != NULL) + free(*buf); + *buf = NULL; +#endif + NGR_R_END_RESULT(NGR_R_OK); +} + +/* Private */ + +static int +copy_protoent(char **machinep, char **userp, char **domainp, + const char *mp, const char *up, const char *dp, + NGR_R_COPY_ARGS) { + char *cp; + int n; + int len; + + /* Find out the amount of space required to store the answer. */ + len = 0; + if (mp != NULL) len += strlen(mp) + 1; + if (up != NULL) len += strlen(up) + 1; + if (dp != NULL) len += strlen(dp) + 1; + +#ifdef NGR_R_PRIVATE + free(*buf); + *buf = malloc(len); + if (*buf == NULL) + return(NGR_R_BAD); + cp = *buf; +#else + if (len > (int)buflen) { + errno = ERANGE; + return (NGR_R_BAD); + } + cp = buf; +#endif + + + if (mp != NULL) { + n = strlen(mp) + 1; + strcpy(cp, mp); + *machinep = cp; + cp += n; + } else + *machinep = NULL; + + if (up != NULL) { + n = strlen(up) + 1; + strcpy(cp, up); + *userp = cp; + cp += n; + } else + *userp = NULL; + + if (dp != NULL) { + n = strlen(dp) + 1; + strcpy(cp, dp); + *domainp = cp; + cp += n; + } else + *domainp = NULL; + + return (NGR_R_OK); +} +#else /* NGR_R_RETURN */ + static int getnetgrent_r_unknown_system = 0; +#endif /* NGR_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/getnetgrent_r.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/getprotoent.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/getprotoent.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/getprotoent.c (revision 109985) @@ -0,0 +1,174 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: getprotoent.c,v 1.16 2001/11/01 07:34:33 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct net_data *init(void); + +/* Public */ + +struct protoent * +getprotoent() { + struct net_data *net_data = init(); + + return (getprotoent_p(net_data)); +} + +struct protoent * +getprotobyname(const char *name) { + struct net_data *net_data = init(); + + return (getprotobyname_p(name, net_data)); +} + +struct protoent * +getprotobynumber(int proto) { + struct net_data *net_data = init(); + + return (getprotobynumber_p(proto, net_data)); +} + +void +setprotoent(int stayopen) { + struct net_data *net_data = init(); + + setprotoent_p(stayopen, net_data); +} + +void +endprotoent() { + struct net_data *net_data = init(); + + endprotoent_p(net_data); +} + +/* Shared private. */ + +struct protoent * +getprotoent_p(struct net_data *net_data) { + struct irs_pr *pr; + + if (!net_data || !(pr = net_data->pr)) + return (NULL); + net_data->pr_last = (*pr->next)(pr); + return (net_data->pr_last); +} + +struct protoent * +getprotobyname_p(const char *name, struct net_data *net_data) { + struct irs_pr *pr; + char **pap; + + if (!net_data || !(pr = net_data->pr)) + return (NULL); + if (net_data->pr_stayopen && net_data->pr_last) { + if (!strcmp(net_data->pr_last->p_name, name)) + return (net_data->pr_last); + for (pap = net_data->pr_last->p_aliases; pap && *pap; pap++) + if (!strcmp(name, *pap)) + return (net_data->pr_last); + } + net_data->pr_last = (*pr->byname)(pr, name); + if (!net_data->pr_stayopen) + endprotoent(); + return (net_data->pr_last); +} + +struct protoent * +getprotobynumber_p(int proto, struct net_data *net_data) { + struct irs_pr *pr; + + if (!net_data || !(pr = net_data->pr)) + return (NULL); + if (net_data->pr_stayopen && net_data->pr_last) + if (net_data->pr_last->p_proto == proto) + return (net_data->pr_last); + net_data->pr_last = (*pr->bynumber)(pr, proto); + if (!net_data->pr_stayopen) + endprotoent(); + return (net_data->pr_last); +} + +void +setprotoent_p(int stayopen, struct net_data *net_data) { + struct irs_pr *pr; + + if (!net_data || !(pr = net_data->pr)) + return; + (*pr->rewind)(pr); + net_data->pr_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); +} + +void +endprotoent_p(struct net_data *net_data) { + struct irs_pr *pr; + + if ((net_data != NULL) && ((pr = net_data->pr) != NULL)) + (*pr->minimize)(pr); +} + +/* Private */ + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->pr) { + net_data->pr = (*net_data->irs->pr_map)(net_data->irs); + + if (!net_data->pr || !net_data->res) { + error: + errno = EIO; + return (NULL); + } + (*net_data->pr->res_set)(net_data->pr, net_data->res, NULL); + } + + return (net_data); +} + +#endif /*__BIND_NOSTATIC*/ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/getprotoent.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/getprotoent_r.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/getprotoent_r.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/getprotoent_r.c (revision 109985) @@ -0,0 +1,216 @@ +/* + * Copyright (c) 1998-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getprotoent_r.c,v 8.6 2001/11/01 08:02:14 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int getprotoent_r_not_required = 0; +#else +#include +#include +#include +#include +#include +#include +#include + +#ifdef PROTO_R_RETURN + +static PROTO_R_RETURN +copy_protoent(struct protoent *, struct protoent *, PROTO_R_COPY_ARGS); + +PROTO_R_RETURN +getprotobyname_r(const char *name, struct protoent *pptr, PROTO_R_ARGS) { + struct protoent *pe = getprotobyname(name); +#ifdef PROTO_R_SETANSWER + int n = 0; + + if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = pptr; + + return (n); +#else + if (pe == NULL) + return (PROTO_R_BAD); + + return (copy_protoent(pe, pptr, PROTO_R_COPY)); +#endif +} + +PROTO_R_RETURN +getprotobynumber_r(int proto, struct protoent *pptr, PROTO_R_ARGS) { + struct protoent *pe = getprotobynumber(proto); +#ifdef PROTO_R_SETANSWER + int n = 0; + + if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = pptr; + + return (n); +#else + if (pe == NULL) + return (PROTO_R_BAD); + + return (copy_protoent(pe, pptr, PROTO_R_COPY)); +#endif +} + +/* + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +PROTO_R_RETURN +getprotoent_r(struct protoent *pptr, PROTO_R_ARGS) { + struct protoent *pe = getprotoent(); +#ifdef PROTO_R_SETANSWER + int n = 0; + + if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = pptr; + + return (n); +#else + if (pe == NULL) + return (PROTO_R_BAD); + + return (copy_protoent(pe, pptr, PROTO_R_COPY)); +#endif +} + +PROTO_R_SET_RETURN +#ifdef PROTO_R_ENT_ARGS +setprotoent_r(int stay_open, PROTO_R_ENT_ARGS) +#else +setprotoent_r(int stay_open) +#endif +{ + setprotoent(stay_open); +#ifdef PROTO_R_SET_RESULT + return (PROTO_R_SET_RESULT); +#endif +} + +PROTO_R_END_RETURN +#ifdef PROTO_R_ENT_ARGS +endprotoent_r(PROTO_R_ENT_ARGS) +#else +endprotoent_r() +#endif +{ + endprotoent(); + PROTO_R_END_RESULT(PROTO_R_OK); +} + +/* Private */ + +#ifndef PROTOENT_DATA +static PROTO_R_RETURN +copy_protoent(struct protoent *pe, struct protoent *pptr, PROTO_R_COPY_ARGS) { + char *cp; + int i, n; + int numptr, len; + + /* Find out the amount of space required to store the answer. */ + numptr = 1; /* NULL ptr */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; pe->p_aliases[i]; i++, numptr++) { + len += strlen(pe->p_aliases[i]) + 1; + } + len += strlen(pe->p_name) + 1; + len += numptr * sizeof(char*); + + if (len > (int)buflen) { + errno = ERANGE; + return (PROTO_R_BAD); + } + + /* copy protocol value*/ + pptr->p_proto = pe->p_proto; + + cp = (char *)ALIGN(buf) + numptr * sizeof(char *); + + /* copy official name */ + n = strlen(pe->p_name) + 1; + strcpy(cp, pe->p_name); + pptr->p_name = cp; + cp += n; + + /* copy aliases */ + pptr->p_aliases = (char **)ALIGN(buf); + for (i = 0 ; pe->p_aliases[i]; i++) { + n = strlen(pe->p_aliases[i]) + 1; + strcpy(cp, pe->p_aliases[i]); + pptr->p_aliases[i] = cp; + cp += n; + } + pptr->p_aliases[i] = NULL; + + return (PROTO_R_OK); +} +#else /* !PROTOENT_DATA */ +static int +copy_protoent(struct protoent *pe, struct protoent *pptr, PROTO_R_COPY_ARGS) { + char *cp, *eob; + int i, n; + + /* copy protocol value */ + pptr->p_proto = pe->p_proto; + + /* copy official name */ + cp = pdptr->line; + eob = pdptr->line + sizeof(pdptr->line); + if ((n = strlen(pe->p_name) + 1) < (eob - cp)) { + strcpy(cp, pe->p_name); + pptr->p_name = cp; + cp += n; + } else { + return (-1); + } + + /* copy aliases */ + i = 0; + pptr->p_aliases = pdptr->proto_aliases; + while (pe->p_aliases[i] && i < (_MAXALIASES-1)) { + if ((n = strlen(pe->p_aliases[i]) + 1) < (eob - cp)) { + strcpy(cp, pe->p_aliases[i]); + pptr->p_aliases[i] = cp; + cp += n; + } else { + break; + } + i++; + } + pptr->p_aliases[i] = NULL; + + return (PROTO_R_OK); +} +#endif /* PROTOENT_DATA */ +#else /* PROTO_R_RETURN */ + static int getprotoent_r_unknown_system = 0; +#endif /* PROTO_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/getprotoent_r.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/getpwent_r.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/getpwent_r.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/getpwent_r.c (revision 109985) @@ -0,0 +1,275 @@ +/* + * Copyright (c) 1998-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getpwent_r.c,v 8.6 2001/11/01 08:02:15 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) || !defined(WANT_IRS_PW) + static int getpwent_r_not_required = 0; +#else +#include +#include +#include +#include +#if (defined(POSIX_GETPWNAM_R) || defined(POSIX_GETPWUID_R)) +#if defined(_POSIX_PTHREAD_SEMANTICS) + /* turn off solaris remapping in */ +#undef _POSIX_PTHREAD_SEMANTICS +#include +#define _POSIX_PTHREAD_SEMANTICS 1 +#else +#define _UNIX95 1 +#include +#endif +#else +#include +#endif +#include + +#ifdef PASS_R_RETURN + +static int +copy_passwd(struct passwd *, struct passwd *, char *buf, int buflen); + +/* POSIX 1003.1c */ +#ifdef POSIX_GETPWNAM_R +int +__posix_getpwnam_r(const char *login, struct passwd *pwptr, + char *buf, size_t buflen, struct passwd **result) { +#else +int +getpwnam_r(const char *login, struct passwd *pwptr, + char *buf, size_t buflen, struct passwd **result) { +#endif + struct passwd *pw = getpwnam(login); + int res; + + if (pw == NULL) { + *result = NULL; + return (0); + } + + res = copy_passwd(pw, pwptr, buf, buflen); + *result = res ? NULL : pwptr; + return (res); +} + +#ifdef POSIX_GETPWNAM_R +struct passwd * +getpwnam_r(const char *login, struct passwd *pwptr, char *buf, int buflen) { + struct passwd *pw = getpwnam(login); + int res; + + if (pw == NULL) + return (NULL); + + res = copy_passwd(pw, pwptr, buf, buflen); + return (res ? NULL : pwptr); +} +#endif + +/* POSIX 1003.1c */ +#ifdef POSIX_GETPWUID_R +int +__posix_getpwuid_r(uid_t uid, struct passwd *pwptr, + char *buf, int buflen, struct passwd **result) { +#else +int +getpwuid_r(uid_t uid, struct passwd *pwptr, + char *buf, size_t buflen, struct passwd **result) { +#endif + struct passwd *pw = getpwuid(uid); + int res; + + if (pw == NULL) { + *result = NULL; + return (0); + } + + res = copy_passwd(pw, pwptr, buf, buflen); + *result = res ? NULL : pwptr; + return (res); +} + +#ifdef POSIX_GETPWUID_R +struct passwd * +getpwuid_r(uid_t uid, struct passwd *pwptr, char *buf, int buflen) { + struct passwd *pw = getpwuid(uid); + int res; + + if (pw == NULL) + return (NULL); + + res = copy_passwd(pw, pwptr, buf, buflen); + return (res ? NULL : pwptr); +} +#endif + +/* + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +PASS_R_RETURN +getpwent_r(struct passwd *pwptr, PASS_R_ARGS) { + struct passwd *pw = getpwent(); + int res; + + if (pw == NULL) + return (PASS_R_BAD); + + res = copy_passwd(pw, pwptr, buf, buflen); + return (res ? PASS_R_BAD : PASS_R_OK); +} + +PASS_R_SET_RETURN +#ifdef PASS_R_ENT_ARGS +setpassent_r(int stayopen, PASS_R_ENT_ARGS) +#else +setpassent_r(int stayopen) +#endif +{ + + setpassent(stayopen); +#ifdef PASS_R_SET_RESULT + return (PASS_R_SET_RESULT); +#endif +} + +PASS_R_SET_RETURN +#ifdef PASS_R_ENT_ARGS +setpwent_r(PASS_R_ENT_ARGS) +#else +setpwent_r(void) +#endif +{ + + setpwent(); +#ifdef PASS_R_SET_RESULT + return (PASS_R_SET_RESULT); +#endif +} + +PASS_R_END_RETURN +#ifdef PASS_R_ENT_ARGS +endpwent_r(PASS_R_ENT_ARGS) +#else +endpwent_r(void) +#endif +{ + + endpwent(); + PASS_R_END_RESULT(PASS_R_OK); +} + + +#ifdef HAS_FGETPWENT +PASS_R_RETURN +fgetpwent_r(FILE *f, struct passwd *pwptr, PASS_R_COPY_ARGS) { + struct passwd *pw = fgetpwent(f); + int res; + + if (pw == NULL) + return (PASS_R_BAD); + + res = copy_passwd(pw, pwptr, PASS_R_COPY); + return (res ? PASS_R_BAD : PASS_R_OK ); +} +#endif + +/* Private */ + +static int +copy_passwd(struct passwd *pw, struct passwd *pwptr, char *buf, int buflen) { + char *cp; + int n; + int len; + + /* Find out the amount of space required to store the answer. */ + len = strlen(pw->pw_name) + 1; + len += strlen(pw->pw_passwd) + 1; +#ifdef HAVE_PW_CLASS + len += strlen(pw->pw_class) + 1; +#endif + len += strlen(pw->pw_gecos) + 1; + len += strlen(pw->pw_dir) + 1; + len += strlen(pw->pw_shell) + 1; + + if (len > buflen) { + errno = ERANGE; + return (ERANGE); + } + + /* copy fixed atomic values*/ + pwptr->pw_uid = pw->pw_uid; + pwptr->pw_gid = pw->pw_gid; +#ifdef HAVE_PW_CHANGE + pwptr->pw_change = pw->pw_change; +#endif +#ifdef HAVE_PW_EXPIRE + pwptr->pw_expire = pw->pw_expire; +#endif + + cp = buf; + + /* copy official name */ + n = strlen(pw->pw_name) + 1; + strcpy(cp, pw->pw_name); + pwptr->pw_name = cp; + cp += n; + + /* copy password */ + n = strlen(pw->pw_passwd) + 1; + strcpy(cp, pw->pw_passwd); + pwptr->pw_passwd = cp; + cp += n; + +#ifdef HAVE_PW_CLASS + /* copy class */ + n = strlen(pw->pw_class) + 1; + strcpy(cp, pw->pw_class); + pwptr->pw_class = cp; + cp += n; +#endif + + /* copy gecos */ + n = strlen(pw->pw_gecos) + 1; + strcpy(cp, pw->pw_gecos); + pwptr->pw_gecos = cp; + cp += n; + + /* copy directory */ + n = strlen(pw->pw_dir) + 1; + strcpy(cp, pw->pw_dir); + pwptr->pw_dir = cp; + cp += n; + + /* copy login shell */ + n = strlen(pw->pw_shell) + 1; + strcpy(cp, pw->pw_shell); + pwptr->pw_shell = cp; + cp += n; + + return (0); +} +#else /* PASS_R_RETURN */ + static int getpwent_r_unknown_system = 0; +#endif /* PASS_R_RETURN */ +#endif /* !def(_REENTRANT) || !def(DO_PTHREADS) || !def(WANT_IRS_PW) */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/getpwent_r.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/getservent.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/getservent.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/getservent.c (revision 109985) @@ -0,0 +1,177 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: getservent.c,v 1.17 2001/11/01 07:33:16 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct net_data *init(void); + +/* Public */ + +struct servent * +getservent(void) { + struct net_data *net_data = init(); + + return (getservent_p(net_data)); +} + +struct servent * +getservbyname(const char *name, const char *proto) { + struct net_data *net_data = init(); + + return (getservbyname_p(name, proto, net_data)); +} + +struct servent * +getservbyport(int port, const char *proto) { + struct net_data *net_data = init(); + + return (getservbyport_p(port, proto, net_data)); +} + +void +setservent(int stayopen) { + struct net_data *net_data = init(); + + setservent_p(stayopen, net_data); +} + +void +endservent() { + struct net_data *net_data = init(); + + endservent_p(net_data); +} + +/* Shared private. */ + +struct servent * +getservent_p(struct net_data *net_data) { + struct irs_sv *sv; + + if (!net_data || !(sv = net_data->sv)) + return (NULL); + net_data->sv_last = (*sv->next)(sv); + return (net_data->sv_last); +} + +struct servent * +getservbyname_p(const char *name, const char *proto, + struct net_data *net_data) { + struct irs_sv *sv; + char **sap; + + if (!net_data || !(sv = net_data->sv)) + return (NULL); + if (net_data->sv_stayopen && net_data->sv_last) + if (!proto || !strcmp(net_data->sv_last->s_proto, proto)) { + if (!strcmp(net_data->sv_last->s_name, name)) + return (net_data->sv_last); + for (sap = net_data->sv_last->s_aliases; + sap && *sap; sap++) + if (!strcmp(name, *sap)) + return (net_data->sv_last); + } + net_data->sv_last = (*sv->byname)(sv, name, proto); + if (!net_data->sv_stayopen) + endservent(); + return (net_data->sv_last); +} + +struct servent * +getservbyport_p(int port, const char *proto, struct net_data *net_data) { + struct irs_sv *sv; + + if (!net_data || !(sv = net_data->sv)) + return (NULL); + if (net_data->sv_stayopen && net_data->sv_last) + if (port == net_data->sv_last->s_port && + ( !proto || + !strcmp(net_data->sv_last->s_proto, proto))) + return (net_data->sv_last); + net_data->sv_last = (*sv->byport)(sv, port, proto); + return (net_data->sv_last); +} + +void +setservent_p(int stayopen, struct net_data *net_data) { + struct irs_sv *sv; + + if (!net_data || !(sv = net_data->sv)) + return; + (*sv->rewind)(sv); + net_data->sv_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); +} + +void +endservent_p(struct net_data *net_data) { + struct irs_sv *sv; + + if ((net_data != NULL) && ((sv = net_data->sv) != NULL)) + (*sv->minimize)(sv); +} + +/* Private */ + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->sv) { + net_data->sv = (*net_data->irs->sv_map)(net_data->irs); + + if (!net_data->sv || !net_data->res) { + error: + errno = EIO; + return (NULL); + } + (*net_data->sv->res_set)(net_data->sv, net_data->res, NULL); + } + + return (net_data); +} + +#endif /*__BIND_NOSTATIC*/ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/getservent.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/getservent_r.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/getservent_r.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/getservent_r.c (revision 109985) @@ -0,0 +1,237 @@ +/* + * Copyright (c) 1998-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getservent_r.c,v 8.5 2001/11/01 08:02:16 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int getservent_r_not_required = 0; +#else +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef SERV_R_RETURN + +static SERV_R_RETURN +copy_servent(struct servent *, struct servent *, SERV_R_COPY_ARGS); + +SERV_R_RETURN +getservbyname_r(const char *name, const char *proto, + struct servent *sptr, SERV_R_ARGS) { + struct servent *se = getservbyname(name, proto); +#ifdef SERV_R_SETANSWER + int n = 0; + + if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = sptr; + + return (n); +#else + if (se == NULL) + return (SERV_R_BAD); + + return (copy_servent(se, sptr, SERV_R_COPY)); +#endif +} + +SERV_R_RETURN +getservbyport_r(int port, const char *proto, + struct servent *sptr, SERV_R_ARGS) { + struct servent *se = getservbyport(port, proto); +#ifdef SERV_R_SETANSWER + int n = 0; + + if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = sptr; + + return (n); +#else + if (se == NULL) + return (SERV_R_BAD); + + return (copy_servent(se, sptr, SERV_R_COPY)); +#endif +} + +/* + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +SERV_R_RETURN +getservent_r(struct servent *sptr, SERV_R_ARGS) { + struct servent *se = getservent(); +#ifdef SERV_R_SETANSWER + int n = 0; + + if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = sptr; + + return (n); +#else + if (se == NULL) + return (SERV_R_BAD); + + return (copy_servent(se, sptr, SERV_R_COPY)); +#endif +} + +SERV_R_SET_RETURN +#ifdef SERV_R_ENT_ARGS +setservent_r(int stay_open, SERV_R_ENT_ARGS) +#else +setservent_r(int stay_open) +#endif +{ + + setservent(stay_open); +#ifdef SERV_R_SET_RESULT + return (SERV_R_SET_RESULT); +#endif +} + +SERV_R_END_RETURN +#ifdef SERV_R_ENT_ARGS +endservent_r(SERV_R_ENT_ARGS) +#else +endservent_r() +#endif +{ + + endservent(); + SERV_R_END_RESULT(SERV_R_OK); +} + +/* Private */ + +#ifndef SERVENT_DATA +static SERV_R_RETURN +copy_servent(struct servent *se, struct servent *sptr, SERV_R_COPY_ARGS) { + char *cp; + int i, n; + int numptr, len; + + /* Find out the amount of space required to store the answer. */ + numptr = 1; /* NULL ptr */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; se->s_aliases[i]; i++, numptr++) { + len += strlen(se->s_aliases[i]) + 1; + } + len += strlen(se->s_name) + 1; + len += strlen(se->s_proto) + 1; + len += numptr * sizeof(char*); + + if (len > (int)buflen) { + errno = ERANGE; + return (SERV_R_BAD); + } + + /* copy port value */ + sptr->s_port = se->s_port; + + cp = (char *)ALIGN(buf) + numptr * sizeof(char *); + + /* copy official name */ + n = strlen(se->s_name) + 1; + strcpy(cp, se->s_name); + sptr->s_name = cp; + cp += n; + + /* copy aliases */ + sptr->s_aliases = (char **)ALIGN(buf); + for (i = 0 ; se->s_aliases[i]; i++) { + n = strlen(se->s_aliases[i]) + 1; + strcpy(cp, se->s_aliases[i]); + sptr->s_aliases[i] = cp; + cp += n; + } + sptr->s_aliases[i] = NULL; + + /* copy proto */ + n = strlen(se->s_proto) + 1; + strcpy(cp, se->s_proto); + sptr->s_proto = cp; + cp += n; + + return (SERV_R_OK); +} +#else /* !SERVENT_DATA */ +static int +copy_servent(struct servent *se, struct servent *sptr, SERV_R_COPY_ARGS) { + char *cp, *eob; + int i, n; + + /* copy port value */ + sptr->s_port = se->s_port; + + /* copy official name */ + cp = ndptr->line; + eob = ndptr->line + sizeof(ndptr->line); + if ((n = strlen(se->s_name) + 1) < (eob - cp)) { + strcpy(cp, se->s_name); + sptr->s_name = cp; + cp += n; + } else { + return (-1); + } + + /* copy aliases */ + i = 0; + sptr->s_aliases = ndptr->serv_aliases; + while (se->s_aliases[i] && i < (_MAXALIASES-1)) { + if ((n = strlen(se->s_aliases[i]) + 1) < (eob - cp)) { + strcpy(cp, se->s_aliases[i]); + sptr->s_aliases[i] = cp; + cp += n; + } else { + break; + } + i++; + } + sptr->s_aliases[i] = NULL; + + /* copy proto */ + if ((n = strlen(se->s_proto) + 1) < (eob - cp)) { + strcpy(cp, se->s_proto); + sptr->s_proto = cp; + cp += n; + } else { + return (-1); + } + + return (SERV_R_OK); +} +#endif /* !SERVENT_DATA */ +#else /*SERV_R_RETURN */ + static int getservent_r_unknown_system = 0; +#endif /*SERV_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/getservent_r.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/hesiod.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/hesiod.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/hesiod.c (revision 109985) @@ -0,0 +1,506 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: hesiod.c,v 1.22 2001/05/29 05:48:55 marka Exp $"; +#endif + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * This file is primarily maintained by and . + */ + +/* + * hesiod.c --- the core portion of the hesiod resolver. + * + * This file is derived from the hesiod library from Project Athena; + * It has been extensively rewritten by Theodore Ts'o to have a more + * thread-safe interface. + */ + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +#include "pathnames.h" +#include "hesiod.h" +#include "hesiod_p.h" + +/* Forward */ + +int hesiod_init(void **context); +void hesiod_end(void *context); +char * hesiod_to_bind(void *context, const char *name, + const char *type); +char ** hesiod_resolve(void *context, const char *name, + const char *type); +void hesiod_free_list(void *context, char **list); + +static int parse_config_file(struct hesiod_p *ctx, const char *filename); +static char ** get_txt_records(struct hesiod_p *ctx, int class, + const char *name); +static int init(struct hesiod_p *ctx); + +/* Public */ + +/* + * This function is called to initialize a hesiod_p. + */ +int +hesiod_init(void **context) { + struct hesiod_p *ctx; + char *cp; + + ctx = malloc(sizeof(struct hesiod_p)); + if (ctx == 0) { + errno = ENOMEM; + return (-1); + } + + ctx->LHS = NULL; + ctx->RHS = NULL; + ctx->res = NULL; + + if (parse_config_file(ctx, _PATH_HESIOD_CONF) < 0) { +#ifdef DEF_RHS + /* + * Use compiled in defaults. + */ + ctx->LHS = malloc(strlen(DEF_LHS)+1); + ctx->RHS = malloc(strlen(DEF_RHS)+1); + if (ctx->LHS == 0 || ctx->RHS == 0) { + errno = ENOMEM; + goto cleanup; + } + strcpy(ctx->LHS, DEF_LHS); + strcpy(ctx->RHS, DEF_RHS); +#else + goto cleanup; +#endif + } + /* + * The default RHS can be overridden by an environment + * variable. + */ + if ((cp = getenv("HES_DOMAIN")) != NULL) { + if (ctx->RHS) + free(ctx->RHS); + ctx->RHS = malloc(strlen(cp)+2); + if (!ctx->RHS) { + errno = ENOMEM; + goto cleanup; + } + if (cp[0] == '.') + strcpy(ctx->RHS, cp); + else { + strcpy(ctx->RHS, "."); + strcat(ctx->RHS, cp); + } + } + + /* + * If there is no default hesiod realm set, we return an + * error. + */ + if (!ctx->RHS) { + errno = ENOEXEC; + goto cleanup; + } + +#if 0 + if (res_ninit(ctx->res) < 0) + goto cleanup; +#endif + + *context = ctx; + return (0); + + cleanup: + hesiod_end(ctx); + return (-1); +} + +/* + * This function deallocates the hesiod_p + */ +void +hesiod_end(void *context) { + struct hesiod_p *ctx = (struct hesiod_p *) context; + int save_errno = errno; + + if (ctx->res) + res_nclose(ctx->res); + if (ctx->RHS) + free(ctx->RHS); + if (ctx->LHS) + free(ctx->LHS); + if (ctx->res && ctx->free_res) + (*ctx->free_res)(ctx->res); + free(ctx); + errno = save_errno; +} + +/* + * This function takes a hesiod (name, type) and returns a DNS + * name which is to be resolved. + */ +char * +hesiod_to_bind(void *context, const char *name, const char *type) { + struct hesiod_p *ctx = (struct hesiod_p *) context; + char *bindname; + char **rhs_list = NULL; + const char *RHS, *cp; + + /* Decide what our RHS is, and set cp to the end of the actual name. */ + if ((cp = strchr(name, '@')) != NULL) { + if (strchr(cp + 1, '.')) + RHS = cp + 1; + else if ((rhs_list = hesiod_resolve(context, cp + 1, + "rhs-extension")) != NULL) + RHS = *rhs_list; + else { + errno = ENOENT; + return (NULL); + } + } else { + RHS = ctx->RHS; + cp = name + strlen(name); + } + + /* + * Allocate the space we need, including up to three periods and + * the terminating NUL. + */ + if ((bindname = malloc((cp - name) + strlen(type) + strlen(RHS) + + (ctx->LHS ? strlen(ctx->LHS) : 0) + 4)) == NULL) { + errno = ENOMEM; + if (rhs_list) + hesiod_free_list(context, rhs_list); + return NULL; + } + + /* Now put together the DNS name. */ + memcpy(bindname, name, cp - name); + bindname[cp - name] = '\0'; + strcat(bindname, "."); + strcat(bindname, type); + if (ctx->LHS) { + if (ctx->LHS[0] != '.') + strcat(bindname, "."); + strcat(bindname, ctx->LHS); + } + if (RHS[0] != '.') + strcat(bindname, "."); + strcat(bindname, RHS); + + if (rhs_list) + hesiod_free_list(context, rhs_list); + + return (bindname); +} + +/* + * This is the core function. Given a hesiod (name, type), it + * returns an array of strings returned by the resolver. + */ +char ** +hesiod_resolve(void *context, const char *name, const char *type) { + struct hesiod_p *ctx = (struct hesiod_p *) context; + char *bindname = hesiod_to_bind(context, name, type); + char **retvec; + + if (bindname == NULL) + return (NULL); + if (init(ctx) == -1) { + free(bindname); + return (NULL); + } + + if ((retvec = get_txt_records(ctx, C_IN, bindname))) { + free(bindname); + return (retvec); + } + + if (errno != ENOENT) + return (NULL); + + retvec = get_txt_records(ctx, C_HS, bindname); + free(bindname); + return (retvec); +} + +void +hesiod_free_list(void *context, char **list) { + char **p; + + UNUSED(context); + + for (p = list; *p; p++) + free(*p); + free(list); +} + +/* + * This function parses the /etc/hesiod.conf file + */ +static int +parse_config_file(struct hesiod_p *ctx, const char *filename) { + char *key, *data, *cp, **cpp; + char buf[MAXDNAME+7]; + FILE *fp; + + /* + * Clear the existing configuration variable, just in case + * they're set. + */ + if (ctx->RHS) + free(ctx->RHS); + if (ctx->LHS) + free(ctx->LHS); + ctx->RHS = ctx->LHS = 0; + + /* + * Now open and parse the file... + */ + if (!(fp = fopen(filename, "r"))) + return (-1); + + while (fgets(buf, sizeof(buf), fp) != NULL) { + cp = buf; + if (*cp == '#' || *cp == '\n' || *cp == '\r') + continue; + while(*cp == ' ' || *cp == '\t') + cp++; + key = cp; + while(*cp != ' ' && *cp != '\t' && *cp != '=') + cp++; + *cp++ = '\0'; + + while(*cp == ' ' || *cp == '\t' || *cp == '=') + cp++; + data = cp; + while(*cp != ' ' && *cp != '\n' && *cp != '\r') + cp++; + *cp++ = '\0'; + + if (strcmp(key, "lhs") == 0) + cpp = &ctx->LHS; + else if (strcmp(key, "rhs") == 0) + cpp = &ctx->RHS; + else + continue; + + *cpp = malloc(strlen(data) + 1); + if (!*cpp) { + errno = ENOMEM; + goto cleanup; + } + strcpy(*cpp, data); + } + fclose(fp); + return (0); + + cleanup: + fclose(fp); + if (ctx->RHS) + free(ctx->RHS); + if (ctx->LHS) + free(ctx->LHS); + ctx->RHS = ctx->LHS = 0; + return (-1); +} + +/* + * Given a DNS class and a DNS name, do a lookup for TXT records, and + * return a list of them. + */ +static char ** +get_txt_records(struct hesiod_p *ctx, int class, const char *name) { + struct { + int type; /* RR type */ + int class; /* RR class */ + int dlen; /* len of data section */ + u_char *data; /* pointer to data */ + } rr; + HEADER *hp; + u_char qbuf[MAX_HESRESP], abuf[MAX_HESRESP]; + u_char *cp, *erdata, *eom; + char *dst, *edst, **list; + int ancount, qdcount; + int i, j, n, skip; + + /* + * Construct the query and send it. + */ + n = res_nmkquery(ctx->res, QUERY, name, class, T_TXT, NULL, 0, + NULL, qbuf, MAX_HESRESP); + if (n < 0) { + errno = EMSGSIZE; + return (NULL); + } + n = res_nsend(ctx->res, qbuf, n, abuf, MAX_HESRESP); + if (n < 0) { + errno = ECONNREFUSED; + return (NULL); + } + if (n < HFIXEDSZ) { + errno = EMSGSIZE; + return (NULL); + } + + /* + * OK, parse the result. + */ + hp = (HEADER *) abuf; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + cp = abuf + sizeof(HEADER); + eom = abuf + n; + + /* Skip query, trying to get to the answer section which follows. */ + for (i = 0; i < qdcount; i++) { + skip = dn_skipname(cp, eom); + if (skip < 0 || cp + skip + QFIXEDSZ > eom) { + errno = EMSGSIZE; + return (NULL); + } + cp += skip + QFIXEDSZ; + } + + list = malloc((ancount + 1) * sizeof(char *)); + if (!list) { + errno = ENOMEM; + return (NULL); + } + j = 0; + for (i = 0; i < ancount; i++) { + skip = dn_skipname(cp, eom); + if (skip < 0) { + errno = EMSGSIZE; + goto cleanup; + } + cp += skip; + if (cp + 3 * INT16SZ + INT32SZ > eom) { + errno = EMSGSIZE; + goto cleanup; + } + rr.type = ns_get16(cp); + cp += INT16SZ; + rr.class = ns_get16(cp); + cp += INT16SZ + INT32SZ; /* skip the ttl, too */ + rr.dlen = ns_get16(cp); + cp += INT16SZ; + if (cp + rr.dlen > eom) { + errno = EMSGSIZE; + goto cleanup; + } + rr.data = cp; + cp += rr.dlen; + if (rr.class != class || rr.type != T_TXT) + continue; + if (!(list[j] = malloc(rr.dlen))) + goto cleanup; + dst = list[j++]; + edst = dst + rr.dlen; + erdata = rr.data + rr.dlen; + cp = rr.data; + while (cp < erdata) { + n = (unsigned char) *cp++; + if (cp + n > eom || dst + n > edst) { + errno = EMSGSIZE; + goto cleanup; + } + memcpy(dst, cp, n); + cp += n; + dst += n; + } + if (cp != erdata) { + errno = EMSGSIZE; + goto cleanup; + } + *dst = '\0'; + } + list[j] = NULL; + if (j == 0) { + errno = ENOENT; + goto cleanup; + } + return (list); + + cleanup: + for (i = 0; i < j; i++) + free(list[i]); + free(list); + return (NULL); +} + +struct __res_state * +__hesiod_res_get(void *context) { + struct hesiod_p *ctx = context; + + if (!ctx->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + __hesiod_res_set(ctx, res, free); + } + + return (ctx->res); +} + +void +__hesiod_res_set(void *context, struct __res_state *res, + void (*free_res)(void *)) { + struct hesiod_p *ctx = context; + + if (ctx->res && ctx->free_res) { + res_nclose(ctx->res); + (*ctx->free_res)(ctx->res); + } + + ctx->res = res; + ctx->free_res = free_res; +} + +static int +init(struct hesiod_p *ctx) { + + if (!ctx->res && !__hesiod_res_get(ctx)) + return (-1); + + if (((ctx->res->options & RES_INIT) == 0) && + (res_ninit(ctx->res) == -1)) + return (-1); + + return (0); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/hesiod.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/irp.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/irp.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/irp.c (revision 109985) @@ -0,0 +1,592 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: irp.c,v 8.8 2001/09/25 04:50:29 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "irs_p.h" +#include "irp_p.h" + +#include "port_after.h" + +/* Forward. */ + +static void irp_close(struct irs_acc *); + +#define LINEINCR 128 + +#if !defined(SUN_LEN) +#define SUN_LEN(su) \ + (sizeof (*(su)) - sizeof ((su)->sun_path) + strlen((su)->sun_path)) +#endif + + +/* Public */ + + +/* send errors to syslog if true. */ +int irp_log_errors = 1; + +/* + * This module handles the irp module connection to irpd. + * + * The client expects a synchronous interface to functions like + * getpwnam(3), so we can't use the ctl_* i/o library on this end of + * the wire (it's used in the server). + */ + +/* + * irs_acc *irs_irp_acc(const char *options); + * + * Initialize the irp module. + */ +struct irs_acc * +irs_irp_acc(const char *options) { + struct irs_acc *acc; + struct irp_p *irp; + + UNUSED(options); + + if (!(acc = memget(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(irp = memget(sizeof *irp))) { + errno = ENOMEM; + free(acc); + return (NULL); + } + irp->inlast = 0; + irp->incurr = 0; + irp->fdCxn = -1; + acc->private = irp; + +#ifdef WANT_IRS_GR + acc->gr_map = irs_irp_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_irp_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_irp_sv; + acc->pr_map = irs_irp_pr; + acc->ho_map = irs_irp_ho; + acc->nw_map = irs_irp_nw; + acc->ng_map = irs_irp_ng; + acc->close = irp_close; + return (acc); +} + + +int +irs_irp_connection_setup(struct irp_p *cxndata, int *warned) { + if (irs_irp_is_connected(cxndata)) { + return (0); + } else if (irs_irp_connect(cxndata) != 0) { + if (warned != NULL && !*warned) { + syslog(LOG_ERR, "irpd connection failed: %m\n"); + (*warned)++; + } + + return (-1); + } + + return (0); +} + + +/* + * int irs_irp_connect(void); + * + * Sets up the connection to the remote irpd server. + * + * Returns: + * + * 0 on success, -1 on failure. + * + */ +int +irs_irp_connect(struct irp_p *pvt) { + int flags; + struct sockaddr *addr; + struct sockaddr_in iaddr; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un uaddr; +#endif + long ipaddr; + const char *irphost; + int code; + char text[256]; + int socklen = 0; + + if (pvt->fdCxn != -1) { + perror("fd != 1"); + return (-1); + } + +#ifndef NO_SOCKADDR_UN + memset(&uaddr, 0, sizeof uaddr); +#endif + memset(&iaddr, 0, sizeof iaddr); + + irphost = getenv(IRPD_HOST_ENV); + if (irphost == NULL) { + irphost = "127.0.0.1"; + } + +#ifndef NO_SOCKADDR_UN + if (irphost[0] == '/') { + addr = (struct sockaddr *)&uaddr; + strncpy(uaddr.sun_path, irphost, sizeof uaddr.sun_path); + uaddr.sun_family = AF_UNIX; + socklen = SUN_LEN(&uaddr); +#ifdef HAVE_SA_LEN + uaddr.sun_len = socklen; +#endif + } else +#endif + { + if (inet_pton(AF_INET, irphost, &ipaddr) != 1) { + errno = EADDRNOTAVAIL; + perror("inet_pton"); + return (-1); + } + + addr = (struct sockaddr *)&iaddr; + socklen = sizeof iaddr; +#ifdef HAVE_SA_LEN + iaddr.sin_len = socklen; +#endif + iaddr.sin_family = AF_INET; + iaddr.sin_port = htons(IRPD_PORT); + iaddr.sin_addr.s_addr = ipaddr; + } + + + pvt->fdCxn = socket(addr->sa_family, SOCK_STREAM, PF_UNSPEC); + if (pvt->fdCxn < 0) { + perror("socket"); + return (-1); + } + + if (connect(pvt->fdCxn, addr, socklen) != 0) { + perror("connect"); + return (-1); + } + + flags = fcntl(pvt->fdCxn, F_GETFL, 0); + if (flags < 0) { + close(pvt->fdCxn); + perror("close"); + return (-1); + } + +#if 0 + flags |= O_NONBLOCK; + if (fcntl(pvt->fdCxn, F_SETFL, flags) < 0) { + close(pvt->fdCxn); + perror("fcntl"); + return (-1); + } +#endif + + code = irs_irp_read_response(pvt, text, sizeof text); + if (code != IRPD_WELCOME_CODE) { + if (irp_log_errors) { + syslog(LOG_WARNING, "Connection failed: %s", text); + } + irs_irp_disconnect(pvt); + return (-1); + } + + return (0); +} + + + +/* + * int irs_irp_is_connected(struct irp_p *pvt); + * + * Returns: + * + * Non-zero if streams are setup to remote. + * + */ + +int +irs_irp_is_connected(struct irp_p *pvt) { + return (pvt->fdCxn >= 0); +} + + + +/* + * void + * irs_irp_disconnect(struct irp_p *pvt); + * + * Closes streams to remote. + */ + +void +irs_irp_disconnect(struct irp_p *pvt) { + if (pvt->fdCxn != -1) { + close(pvt->fdCxn); + pvt->fdCxn = -1; + } +} + + + +int +irs_irp_read_line(struct irp_p *pvt, char *buffer, int len) { + char *realstart = &pvt->inbuffer[0]; + char *p, *start, *end; + int spare; + int i; + int buffpos = 0; + int left = len - 1; + + while (left > 0) { + start = p = &pvt->inbuffer[pvt->incurr]; + end = &pvt->inbuffer[pvt->inlast]; + + while (p != end && *p != '\n') + p++; + + if (p == end) { + /* Found no newline so shift data down if necessary + * and append new data to buffer + */ + if (start > realstart) { + memmove(realstart, start, end - start); + pvt->inlast = end - start; + start = realstart; + pvt->incurr = 0; + end = &pvt->inbuffer[pvt->inlast]; + } + + spare = sizeof (pvt->inbuffer) - pvt->inlast; + + p = end; + i = read(pvt->fdCxn, end, spare); + if (i < 0) { + close(pvt->fdCxn); + pvt->fdCxn = -1; + return (buffpos > 0 ? buffpos : -1); + } else if (i == 0) { + return (buffpos); + } + + end += i; + pvt->inlast += i; + + while (p != end && *p != '\n') + p++; + } + + if (p == end) { + /* full buffer and still no newline */ + i = sizeof pvt->inbuffer; + } else { + /* include newline */ + i = p - start + 1; + } + + if (i > left) + i = left; + memcpy(buffer + buffpos, start, i); + pvt->incurr += i; + buffpos += i; + buffer[buffpos] = '\0'; + + if (p != end) { + left = 0; + } else { + left -= i; + } + } + +#if 0 + fprintf(stderr, "read line: %s\n", buffer); +#endif + return (buffpos); +} + + + + + +/* + * int irp_read_response(struct irp_p *pvt); + * + * Returns: + * + * The number found at the beginning of the line read from + * FP. 0 on failure(0 is not a legal response code). The + * rest of the line is discarded. + * + */ + +int +irs_irp_read_response(struct irp_p *pvt, char *text, size_t textlen) { + char line[1024]; + int code; + char *p; + + if (irs_irp_read_line(pvt, line, sizeof line) <= 0) { + return (0); + } + + p = strchr(line, '\n'); + if (p == NULL) { + return (0); + } + + if (sscanf(line, "%d", &code) != 1) { + code = 0; + } else if (text != NULL && textlen > 0) { + p = line; + while (isspace((unsigned char)*p)) p++; + while (isdigit((unsigned char)*p)) p++; + while (isspace((unsigned char)*p)) p++; + strncpy(text, p, textlen - 1); + p[textlen - 1] = '\0'; + } + + return (code); +} + + + +/* + * char *irp_read_body(struct irp_p *pvt, size_t *size); + * + * Read in the body of a response. Terminated by a line with + * just a dot on it. Lines should be terminated with a CR-LF + * sequence, but we're nt piccky if the CR is missing. + * No leading dot escaping is done as the protcol doesn't + * use leading dots anywhere. + * + * Returns: + * + * Pointer to null-terminated buffer allocated by memget. + * *SIZE is set to the length of the buffer. + * + */ + +char * +irs_irp_read_body(struct irp_p *pvt, size_t *size) { + char line[1024]; + u_int linelen; + size_t len = LINEINCR; + char *buffer = memget(len); + int idx = 0; + + for (;;) { + if (irs_irp_read_line(pvt, line, sizeof line) <= 0 || + strchr(line, '\n') == NULL) + goto death; + + linelen = strlen(line); + + if (line[linelen - 1] != '\n') + goto death; + + /* We're not strict about missing \r. Should we be?? */ + if (linelen > 2 && line[linelen - 2] == '\r') { + line[linelen - 2] = '\n'; + line[linelen - 1] = '\0'; + linelen--; + } + + if (linelen == 2 && line[0] == '.') { + *size = len; + buffer[idx] = '\0'; + + return (buffer); + } + + if (linelen > (len - (idx + 1))) { + char *p = memget(len + LINEINCR); + + if (p == NULL) + goto death; + memcpy(p, buffer, len); + memput(buffer, len); + buffer = p; + len += LINEINCR; + } + + memcpy(buffer + idx, line, linelen); + idx += linelen; + } + death: + memput(buffer, len); + return (NULL); +} + + +/* + * int irs_irp_get_full_response(struct irp_p *pvt, int *code, + * char **body, size_t *bodylen); + * + * Gets the response to a command. If the response indicates + * there's a body to follow(code % 10 == 1), then the + * body buffer is allcoated with memget and stored in + * *BODY. The length of the allocated body buffer is stored + * in *BODY. The caller must give the body buffer back to + * memput when done. The results code is stored in *CODE. + * + * Returns: + * + * 0 if a result was read. -1 on some sort of failure. + * + */ + +int +irs_irp_get_full_response(struct irp_p *pvt, int *code, char *text, + size_t textlen, char **body, size_t *bodylen) { + int result = irs_irp_read_response(pvt, text, textlen); + + *body = NULL; + + if (result == 0) { + return (-1); + } + + *code = result; + + /* Code that matches 2xx is a good result code. + * Code that matches xx1 means there's a response body coming. + */ + if ((result / 100) == 2 && (result % 10) == 1) { + *body = irs_irp_read_body(pvt, bodylen); + if (*body == NULL) { + return (-1); + } + } + + return (0); +} + + +/* + * int irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...); + * + * Sends command to remote connected via the PVT + * struture. FMT and args after it are fprintf-like + * arguments for formatting. + * + * Returns: + * + * 0 on success, -1 on failure. + */ + +int +irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...) { + va_list ap; + char buffer[1024]; + int pos = 0; + int i, todo; + + + if (pvt->fdCxn < 0) { + return (-1); + } + + va_start(ap, fmt); + todo = vsprintf(buffer, fmt, ap); + va_end(ap); + if (todo > (int)sizeof(buffer) - 3) { + syslog(LOG_CRIT, "memory overrun in irs_irp_send_command()"); + exit(1); + } + strcat(buffer, "\r\n"); + todo = strlen(buffer); + + while (todo > 0) { + i = write(pvt->fdCxn, buffer + pos, todo); +#if 0 + /* XXX brister */ + fprintf(stderr, "Wrote: \""); + fwrite(buffer + pos, sizeof (char), todo, stderr); + fprintf(stderr, "\"\n"); +#endif + if (i < 0) { + close(pvt->fdCxn); + pvt->fdCxn = -1; + return (-1); + } + todo -= i; + } + + return (0); +} + + +/* Methods */ + + + +/* + * void irp_close(struct irs_acc *this) + * + */ + +static void +irp_close(struct irs_acc *this) { + struct irp_p *irp = (struct irp_p *)this->private; + + if (irp != NULL) { + irs_irp_disconnect(irp); + memput(irp, sizeof *irp); + } + + memput(this, sizeof *this); +} + + + Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/irp.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/irp_gr.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/irp_gr.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/irp_gr.c (revision 109985) @@ -0,0 +1,408 @@ +/* + * Portions Copyright(c) 1996, 1998 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irp_gr.c,v 8.3 2001/05/29 05:48:57 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_gr_unneeded; +#else + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "irs_p.h" +#include "lcl_p.h" +#include "irp_p.h" + +#include "port_after.h" + + +/* Types. */ + +/* + * Module for the getnetgrent(3) family to use when connected to a + * remote irp daemon. + * + * See irpd.c for justification of caching done here. + * + */ + +struct pvt { + struct irp_p *girpdata; /* global IRP data */ + int warned; + struct group group; +}; + +/* Forward. */ + +static void gr_close(struct irs_gr *); +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static void gr_minimize(struct irs_gr *); + +/* Private */ +static void free_group(struct group *gr); + + +/* Public. */ + + + + + +/* + * struct irs_gr * irs_irp_gr(struct irs_acc *this) + * + * Notes: + * + * Initialize the group sub-module. + * + * Notes: + * + * Module data. + * + */ + +struct irs_gr * +irs_irp_gr(struct irs_acc *this) { + struct irs_gr *gr; + struct pvt *pvt; + + if (!(gr = memget(sizeof *gr))) { + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x0, sizeof *gr); + + if (!(pvt = memget(sizeof *pvt))) { + memput(gr, sizeof *gr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0x0, sizeof *pvt); + pvt->girpdata = this->private; + + gr->private = pvt; + gr->close = gr_close; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->list = make_group_list; + gr->minimize = gr_minimize; + return (gr); +} + +/* Methods. */ + + + +/* + * void gr_close(struct irs_gr *this) + * + * Notes: + * + * Close the sub-module. + * + */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + gr_minimize(this); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + + +/* + * struct group * gr_next(struct irs_gr *this) + * + * Notes: + * + * Gets the next group out of the cached data and returns it. + * + */ + +static struct group * +gr_next(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct group *gr = &pvt->group; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getgrent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + if (irp_log_errors) { + syslog(LOG_WARNING, "getgrent failed: %s", text); + } + return (NULL); + } + + if (code == IRPD_GETGROUP_OK) { + free_group(gr); + if (irp_unmarshall_gr(gr, body) != 0) { + gr = NULL; + } + } else { + gr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (gr); +} + + + + + +/* + * struct group * gr_byname(struct irs_gr *this, const char *name) + * + * Notes: + * + * Gets a group by name from irpd and returns it. + * + */ + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct group *gr = &pvt->group; + char *body; + size_t bodylen; + int code; + char text[256]; + + + if (gr->gr_name != NULL && strcmp(name, gr->gr_name) == 0) { + return (gr); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getgrnam %s", name) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETGROUP_OK) { + free_group(gr); + if (irp_unmarshall_gr(gr, body) != 0) { + gr = NULL; + } + } else { + gr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (gr); +} + + + + + +/* + * struct group * gr_bygid(struct irs_gr *this, gid_t gid) + * + * Notes: + * + * Gets a group by gid from irpd and returns it. + * + */ + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + struct pvt *pvt = (struct pvt *)this->private; + struct group *gr = &pvt->group; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (gr->gr_name != NULL && (gid_t)gr->gr_gid == gid) { + return (gr); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getgrgid %d", gid) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETGROUP_OK) { + free_group(gr); + if (irp_unmarshall_gr(gr, body) != 0) { + gr = NULL; + } + } else { + gr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (gr); +} + + + + +/* + * void gr_rewind(struct irs_gr *this) + * + */ + +static void +gr_rewind(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "setgrent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETGROUP_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setgrent failed: %s", text); + } + } + + return; +} + + + + +/* + * void gr_minimize(struct irs_gr *this) + * + * Notes: + * + * Frees up cached data and disconnects(if necessary) from the remote. + * + */ + +static void +gr_minimize(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + free_group(&pvt->group); + irs_irp_disconnect(pvt->girpdata); +} + +/* Private. */ + + + +/* + * static void free_group(struct group *gr); + * + * Deallocate all the memory irp_unmarshall_gr allocated. + * + */ + +static void +free_group(struct group *gr) { + char **p; + + if (gr == NULL) + return; + + if (gr->gr_name != NULL) + free(gr->gr_name); + + if (gr->gr_passwd != NULL) + free(gr->gr_passwd); + + for (p = gr->gr_mem ; p != NULL && *p != NULL ; p++) + free(*p); + + if (gr->gr_mem) + free(gr->gr_mem); + + if (p != NULL) + free(p); +} + + +#endif /* WANT_IRS_GR */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/irp_gr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/irp_ho.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/irp_ho.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/irp_ho.c (revision 109985) @@ -0,0 +1,429 @@ +/* + * Portions Copyright (c) 1996,1998 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irp_ho.c,v 8.3 2001/05/29 05:48:59 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "irs_p.h" +#include "dns_p.h" +#include "irp_p.h" + +#include "port_after.h" + +/* Definitions. */ + +#define MAXALIASES 35 +#define MAXADDRS 35 +#define Max(a,b) ((a) > (b) ? (a) : (b)) + + +struct pvt { + struct irp_p *girpdata; + int warned; + struct hostent host; +}; + +/* Forward. */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); + +static void free_host(struct hostent *ho); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +/* Public. */ + + + +/* + * struct irs_ho * irs_irp_ho(struct irs_acc *this) + * + * Notes: + * + * Initializes the irp_ho module. + * + */ + +struct irs_ho * +irs_irp_ho(struct irs_acc *this) { + struct irs_ho *ho; + struct pvt *pvt; + + if (!(ho = memget(sizeof *ho))) { + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x0, sizeof *ho); + + if (!(pvt = memget(sizeof *pvt))) { + memput(ho, sizeof *ho); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->addrinfo = ho_addrinfo; + + return (ho); +} + +/* Methods. */ + + + +/* + * void ho_close(struct irs_ho *this) + * + * Notes: + * + * Closes down the module. + * + */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + + free_host(&pvt->host); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + +/* + * struct hostent * ho_byname(struct irs_ho *this, const char *name) + * + */ + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + return (ho_byname2(this, name, AF_INET)); +} + + + + + +/* + * struct hostent * ho_byname2(struct irs_ho *this, const char *name, int af) + * + */ + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *ho = &pvt->host; + char *body = NULL; + size_t bodylen; + int code; + char text[256]; + + if (ho->h_name != NULL && + strcmp(name, ho->h_name) == 0 && + af == ho->h_addrtype) { + return (ho); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "gethostbyname2 %s %s", + name, ADDR_T_STR(af)) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETHOST_OK) { + free_host(ho); + if (irp_unmarshall_ho(ho, body) != 0) { + ho = NULL; + } + } else { + ho = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (ho); +} + + + +/* + * struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + * int len, int af) + * + */ + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *ho = &pvt->host; + char *body = NULL; + size_t bodylen; + int code; + char **p; + char paddr[MAXPADDRSIZE]; + char text[256]; + + if (ho->h_name != NULL && + af == ho->h_addrtype && + len == ho->h_length) { + for (p = ho->h_addr_list ; *p != NULL ; p++) { + if (memcmp(*p, addr, len) == 0) + return (ho); + } + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (inet_ntop(af, addr, paddr, sizeof paddr) == NULL) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "gethostbyaddr %s %s", + paddr, ADDR_T_STR(af)) != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETHOST_OK) { + free_host(ho); + if (irp_unmarshall_ho(ho, body) != 0) { + ho = NULL; + } + } else { + ho = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (ho); +} + + + + + +/* + * struct hostent * ho_next(struct irs_ho *this) + * + * Notes: + * + * The implementation for gethostent(3). The first time it's + * called all the data is pulled from the remote(i.e. what + * the maximum number of gethostent(3) calls would return) + * and that data is cached. + * + */ + +static struct hostent * +ho_next(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *ho = &pvt->host; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "gethostent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETHOST_OK) { + free_host(ho); + if (irp_unmarshall_ho(ho, body) != 0) { + ho = NULL; + } + } else { + ho = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (ho); +} + + + + + +/* + * void ho_rewind(struct irs_ho *this) + * + */ + +static void +ho_rewind(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "sethostent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETHOST_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "sethostent failed: %s", text); + } + } + + return; +} + + + + +/* + * void ho_minimize(struct irs_ho *this) + * + */ + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + free_host(&pvt->host); + + irs_irp_disconnect(pvt->girpdata); +} + + + + +/* + * void free_host(struct hostent *ho) + * + */ + +static void +free_host(struct hostent *ho) { + char **p; + + if (ho == NULL) { + return; + } + + if (ho->h_name != NULL) + free(ho->h_name); + + if (ho->h_aliases != NULL) { + for (p = ho->h_aliases ; *p != NULL ; p++) + free(*p); + free(ho->h_aliases); + } + + if (ho->h_addr_list != NULL) { + for (p = ho->h_addr_list ; *p != NULL ; p++) + free(*p); + free(ho->h_addr_list); + } +} + +/* dummy */ +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + UNUSED(this); + UNUSED(name); + UNUSED(pai); + return(NULL); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/irp_ho.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/irp_ng.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/irp_ng.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/irp_ng.c (revision 109985) @@ -0,0 +1,272 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: irp_ng.c,v 8.3 2001/05/29 05:49:00 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "irs_p.h" +#include "irp_p.h" + +#include "port_after.h" + +/* Definitions */ + +struct pvt { + struct irp_p *girpdata; + int warned; +}; + + +/* Forward */ + +static void ng_rewind(struct irs_ng *, const char*); +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, const char **, + const char **); +static int ng_test(struct irs_ng *, const char *, + const char *, const char *, + const char *); +static void ng_minimize(struct irs_ng *); + + +/* Public */ + + + +/* + * struct irs_ng * irs_irp_ng(struct irs_acc *this) + * + * Notes: + * + * Intialize the irp netgroup module. + * + */ + +struct irs_ng * +irs_irp_ng(struct irs_acc *this) { + struct irs_ng *ng; + struct pvt *pvt; + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + + if (!(pvt = memget(sizeof *pvt))) { + memput(ng, sizeof *ng); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + ng->private = pvt; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods */ + + + +/* + * void ng_close(struct irs_ng *this) + * + */ + +static void +ng_close(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ng_minimize(this); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + + +/* + * void ng_rewind(struct irs_ng *this, const char *group) + * + * + */ + +static void +ng_rewind(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, + "setnetgrent %s", group) != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETNETGR_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setnetgrent(%s) failed: %s", + group, text); + } + } + + return; +} + + + + +/* + * int ng_next(struct irs_ng *this, const char **host, const char **user, + * const char **domain) + * + * Notes: + * + * Get the next netgroup item from the cache. + * + */ + +static int +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + int code; + char *body = NULL; + size_t bodylen; + int rval = 0; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (0); + } + + if (irs_irp_send_command(pvt->girpdata, "getnetgrent") != 0) + return (0); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (0); + } + + if (code == IRPD_GETNETGR_OK) { + if (irp_unmarshall_ng(host, user, domain, body) == 0) { + rval = 1; + } + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (rval); +} + + + +/* + * int ng_test(struct irs_ng *this, const char *name, const char *host, + * const char *user, const char *domain) + * + * Notes: + * + * Search for a match in a netgroup. + * + */ + +static int +ng_test(struct irs_ng *this, const char *name, + const char *host, const char *user, const char *domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + char *body = NULL; + size_t bodylen = 0; + int code; + char text[256]; + int rval = 0; + + UNUSED(name); + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (0); + } + + if (irp_marshall_ng(host, user, domain, &body, &bodylen) != 0) { + return (0); + } + + if (irs_irp_send_command(pvt->girpdata, "innetgr %s", body) == 0) { + memput(body, bodylen); + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code == IRPD_GETNETGR_MATCHES) { + rval = 1; + } + } + + return (rval); +} + + + + +/* + * void ng_minimize(struct irs_ng *this) + * + */ + +static void +ng_minimize(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + + + + +/* Private */ + Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/irp_ng.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/irp_p.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/irp_p.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/irp_p.h (revision 109985) @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * $Id: irp_p.h,v 8.2 2001/08/10 02:40:52 marka Exp $ + */ + +#ifndef _IRP_P_H_INCLUDED +#define _IRP_P_H_INCLUDED + +#include + +struct irp_p { + char inbuffer[1024]; + int inlast; /* index of one past the last char in buffer */ + int incurr; /* index of the next char to be read from buffer */ + + int fdCxn; +}; + +/* + * Externs. + */ + +extern struct irs_acc * irs_irp_acc __P((const char *)); +extern struct irs_gr * irs_irp_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_irp_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_irp_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_irp_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_irp_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_irp_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_irp_ng __P((struct irs_acc *)); + +int irs_irp_connect(struct irp_p *pvt); +int irs_irp_is_connected(struct irp_p *pvt); +void irs_irp_disconnect(struct irp_p *pvt); +int irs_irp_read_response(struct irp_p *pvt, char *text, size_t textlen); +char *irs_irp_read_body(struct irp_p *pvt, size_t *size); +int irs_irp_get_full_response(struct irp_p *pvt, int *code, + char *text, size_t textlen, + char **body, size_t *bodylen); +int irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3); + + +extern int irp_log_errors; + +#endif Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/irp_p.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/irp_pw.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/irp_pw.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/irp_pw.c (revision 109985) @@ -0,0 +1,358 @@ +/* + * Portions Copyright (c) 1996 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irp_pw.c,v 8.2 2001/11/01 07:29:26 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Extern */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_pw_unneeded; +#else + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "irp_p.h" + + +/* Types */ + +struct pvt { + struct irp_p *girpdata; /* global IRP data */ + int warned; + struct passwd passwd; /* password structure */ +}; + +/* Forward */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_next(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); + +static void free_passwd(struct passwd *pw); + +/* Public */ +struct irs_pw * +irs_irp_pw(struct irs_acc *this) { + struct irs_pw *pw; + struct pvt *pvt; + + if (!(pw = memget(sizeof *pw))) { + errno = ENOMEM; + return (NULL); + } + memset(pw, 0, sizeof *pw); + + if (!(pvt = memget(sizeof *pvt))) { + memput(pw, sizeof *pw); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + pw->private = pvt; + pw->close = pw_close; + pw->next = pw_next; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + + return (pw); +} + +/* Methods */ + + + +/* + * void pw_close(struct irs_pw *this) + * + */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pw_minimize(this); + + free_passwd(&pvt->passwd); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + + +/* + * struct passwd * pw_next(struct irs_pw *this) + * + */ + +static struct passwd * +pw_next(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct passwd *pw = &pvt->passwd; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getpwent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETUSER_OK) { + free_passwd(pw); + if (irp_unmarshall_pw(pw, body) != 0) { + pw = NULL; + } + } else { + pw = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pw); +} + + + + +/* + * struct passwd * pw_byname(struct irs_pw *this, const char *name) + * + */ + +static struct passwd * +pw_byname(struct irs_pw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct passwd *pw = &pvt->passwd; + char *body = NULL; + char text[256]; + size_t bodylen; + int code; + + if (pw->pw_name != NULL && strcmp(name, pw->pw_name) == 0) { + return (pw); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getpwnam %s", name) != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETUSER_OK) { + free_passwd(pw); + if (irp_unmarshall_pw(pw, body) != 0) { + pw = NULL; + } + } else { + pw = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pw); +} + + + + +/* + * struct passwd * pw_byuid(struct irs_pw *this, uid_t uid) + * + */ + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + struct pvt *pvt = (struct pvt *)this->private; + char *body; + char text[256]; + size_t bodylen; + int code; + struct passwd *pw = &pvt->passwd; + + if (pw->pw_name != NULL && pw->pw_uid == uid) { + return (pw); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getpwuid %d", uid) != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETUSER_OK) { + free_passwd(pw); + if (irp_unmarshall_pw(pw, body) != 0) { + pw = NULL; + } + } else { + pw = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pw); +} + + + + +/* + * void pw_rewind(struct irs_pw *this) + * + */ + +static void +pw_rewind(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "setpwent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETUSER_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setpwent failed: %s", text); + } + } + + return; +} + + +/* + * void pw_minimize(struct irs_pw *this) + * + */ + +static void +pw_minimize(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + + +/* Private. */ + + + +/* + * static void free_passwd(struct passwd *pw); + * + * Deallocate all the memory irp_unmarshall_pw allocated. + * + */ + +static void +free_passwd(struct passwd *pw) { + if (pw == NULL) + return; + + if (pw->pw_name != NULL) + free(pw->pw_name); + + if (pw->pw_passwd != NULL) + free(pw->pw_passwd); + +#ifdef HAVE_PW_CLASS + if (pw->pw_class != NULL) + free(pw->pw_class); +#endif + + if (pw->pw_gecos != NULL) + free(pw->pw_gecos); + + if (pw->pw_dir != NULL) + free(pw->pw_dir); + + if (pw->pw_shell != NULL) + free(pw->pw_shell); +} + +#endif /* WANT_IRS_PW */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/irp_pw.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/irpmarshall.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/irpmarshall.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/irpmarshall.c (revision 109985) @@ -0,0 +1,2344 @@ +/* + * Copyright(c) 1989, 1993, 1995 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irpmarshall.c,v 8.7 2001/05/29 05:49:01 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#if 0 + +Check values are in approrpriate endian order. + +Double check memory allocations on unmarhsalling + +#endif + + +/* Extern */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "port_after.h" + + +#ifndef HAVE_STRNDUP +static char *strndup(const char *str, size_t len); +#endif + +static char **splitarray(const char *buffer, const char *buffend, char delim); +static int joinarray(char * const * argv, char *buffer, char delim); +static char *getfield(char **res, size_t reslen, char **buffer, char delim); +static size_t joinlength(char * const *argv); +static void free_array(char **argv, size_t entries); + +#define ADDR_T_STR(x) (x == AF_INET ? "AF_INET" :\ + (x == AF_INET6 ? "AF_INET6" : "UNKNOWN")) + +#define MAXPADDRSIZE (sizeof "255.255.255.255" + 1) + +static char COMMA = ','; + +static const char *COMMASTR = ","; +static const char *COLONSTR = ":"; + + + +/* See big comment at bottom of irpmarshall.h for description. */ + + +#ifdef WANT_IRS_PW +/* +++++++++++++++++++++++++ struct passwd +++++++++++++++++++++++++ */ + + +/* + * int irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len) + * + * notes: + * + * See above + * + * return: + * + * 0 on sucess, -1 on failure. + * + */ + +int +irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len) { + size_t need = 1 ; /* for null byte */ + char pwUid[24]; + char pwGid[24]; + char pwChange[24]; + char pwExpire[24]; + const char *pwClass; + const char *fieldsep = COLONSTR; + + if (pw == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + sprintf(pwUid, "%ld", (long)pw->pw_uid); + sprintf(pwGid, "%ld", (long)pw->pw_gid); + +#ifdef HAVE_PW_CHANGE + sprintf(pwChange, "%ld", (long)pw->pw_change); +#else + pwChange[0] = '0'; + pwChange[1] = '\0'; +#endif + +#ifdef HAVE_PW_EXPIRE + sprintf(pwExpire, "%ld", (long)pw->pw_expire); +#else + pwExpire[0] = '0'; + pwExpire[1] = '\0'; +#endif + +#ifdef HAVE_PW_CLASS + pwClass = pw->pw_class; +#else + pwClass = ""; +#endif + + need += strlen(pw->pw_name) + 1; /* one for fieldsep */ + need += strlen(pw->pw_passwd) + 1; + need += strlen(pwUid) + 1; + need += strlen(pwGid) + 1; + need += strlen(pwClass) + 1; + need += strlen(pwChange) + 1; + need += strlen(pwExpire) + 1; + need += strlen(pw->pw_gecos) + 1; + need += strlen(pw->pw_dir) + 1; + need += strlen(pw->pw_shell) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, pw->pw_name); strcat(*buffer, fieldsep); + strcat(*buffer, pw->pw_passwd); strcat(*buffer, fieldsep); + strcat(*buffer, pwUid); strcat(*buffer, fieldsep); + strcat(*buffer, pwGid); strcat(*buffer, fieldsep); + strcat(*buffer, pwClass); strcat(*buffer, fieldsep); + strcat(*buffer, pwChange); strcat(*buffer, fieldsep); + strcat(*buffer, pwExpire); strcat(*buffer, fieldsep); + strcat(*buffer, pw->pw_gecos); strcat(*buffer, fieldsep); + strcat(*buffer, pw->pw_dir); strcat(*buffer, fieldsep); + strcat(*buffer, pw->pw_shell); strcat(*buffer, fieldsep); + + return (0); +} + + + + + +/* + * int irp_unmarshall_pw(struct passwd *pw, char *buffer) + * + * notes: + * + * see above + * + * return: + * + * 0 on success, -1 on failure + * + */ + +int +irp_unmarshall_pw(struct passwd *pw, char *buffer) { + char *name, *pass, *class, *gecos, *dir, *shell; + uid_t pwuid; + gid_t pwgid; + time_t pwchange; + time_t pwexpire; + char *p; + long t; + char tmpbuf[24]; + char *tb = &tmpbuf[0]; + char fieldsep = ':'; + int myerrno = EINVAL; + + name = pass = class = gecos = dir = shell = NULL; + p = buffer; + + /* pw_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + /* pw_passwd field */ + pass = NULL; + if (getfield(&pass, 0, &p, fieldsep) == NULL) { /* field can be empty */ + goto error; + } + + + /* pw_uid field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + pwuid = (uid_t)t; + if ((long) pwuid != t) { /* value must have been too big. */ + goto error; + } + + + + /* pw_gid field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + pwgid = (gid_t)t; + if ((long)pwgid != t) { /* value must have been too big. */ + goto error; + } + + + + /* pw_class field */ + class = NULL; + if (getfield(&class, 0, &p, fieldsep) == NULL) { + goto error; + } + + + + /* pw_change field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + pwchange = (time_t)t; + if ((long)pwchange != t) { /* value must have been too big. */ + goto error; + } + + + + /* pw_expire field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + pwexpire = (time_t)t; + if ((long) pwexpire != t) { /* value must have been too big. */ + goto error; + } + + + + /* pw_gecos field */ + gecos = NULL; + if (getfield(&gecos, 0, &p, fieldsep) == NULL) { + goto error; + } + + + + /* pw_dir field */ + dir = NULL; + if (getfield(&dir, 0, &p, fieldsep) == NULL) { + goto error; + } + + + + /* pw_shell field */ + shell = NULL; + if (getfield(&shell, 0, &p, fieldsep) == NULL) { + goto error; + } + + + + pw->pw_name = name; + pw->pw_passwd = pass; + pw->pw_uid = pwuid; + pw->pw_gid = pwgid; + pw->pw_gecos = gecos; + pw->pw_dir = dir; + pw->pw_shell = shell; + +#ifdef HAVE_PW_CHANGE + pw->pw_change = pwchange; +#endif +#ifdef HAVE_PW_CLASS + pw->pw_class = class; +#endif +#ifdef HAVE_PW_EXPIRE + pw->pw_expire = pwexpire; +#endif + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + if (pass != NULL) free(pass); + if (gecos != NULL) free(gecos); + if (dir != NULL) free(dir); + if (shell != NULL) free(shell); + + return (-1); +} + +/* ------------------------- struct passwd ------------------------- */ +#endif /* WANT_IRS_PW */ + + + +/* +++++++++++++++++++++++++ struct group +++++++++++++++++++++++++ */ + + + +/* + * int irp_marshall_gr(const struct group *gr, char **buffer, size_t *len) + * + * notes: + * + * see above. + * + * return: + * + * 0 on success, -1 on failure + */ + +int +irp_marshall_gr(const struct group *gr, char **buffer, size_t *len) { + size_t need = 1; /* for null byte */ + char grGid[24]; + const char *fieldsep = COLONSTR; + + if (gr == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + sprintf(grGid, "%ld", (long)gr->gr_gid); + + need += strlen(gr->gr_name) + 1; +#ifndef MISSING_GR_PASSWD + need += strlen(gr->gr_passwd) + 1; +#else + need++; +#endif + need += strlen(grGid) + 1; + need += joinlength(gr->gr_mem) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, gr->gr_name); strcat(*buffer, fieldsep); +#ifndef MISSING_GR_PASSWD + strcat(*buffer, gr->gr_passwd); +#endif + strcat(*buffer, fieldsep); + strcat(*buffer, grGid); strcat(*buffer, fieldsep); + joinarray(gr->gr_mem, *buffer, COMMA) ; strcat(*buffer, fieldsep); + + return (0); +} + + + + +/* + * int irp_unmarshall_gr(struct group *gr, char *buffer) + * + * notes: + * + * see above + * + * return: + * + * 0 on success and -1 on failure. + * + */ + +int +irp_unmarshall_gr(struct group *gr, char *buffer) { + char *p, *q; + gid_t grgid; + long t; + char *name = NULL; + char *pass = NULL; + char **members = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (gr == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + p = buffer; + + /* gr_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + + /* gr_passwd field */ + pass = NULL; + if (getfield(&pass, 0, &p, fieldsep) == NULL) { + goto error; + } + + + /* gr_gid field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + grgid = (gid_t)t; + if ((long) grgid != t) { /* value must have been too big. */ + goto error; + } + + + /* gr_mem field. Member names are separated by commas */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + members = splitarray(p, q, COMMA); + if (members == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + gr->gr_name = name; +#ifndef MISSING_GR_PASSWD + gr->gr_passwd = pass; +#endif + gr->gr_gid = grgid; + gr->gr_mem = members; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + if (pass != NULL) free(pass); + + return (-1); +} + + +/* ------------------------- struct group ------------------------- */ + + + + +/* +++++++++++++++++++++++++ struct servent +++++++++++++++++++++++++ */ + + + +/* + * int irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len) + * + * notes: + * + * see above + * + * return: + * + * 0 on success, -1 on failure. + * + */ + +int +irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len) { + size_t need = 1; /* for null byte */ + char svPort[24]; + const char *fieldsep = COLONSTR; + short realport; + + if (sv == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + /* the int s_port field is actually a short in network order. We + want host order to make the marshalled data look correct */ + realport = ntohs((short)sv->s_port); + sprintf(svPort, "%d", realport); + + need += strlen(sv->s_name) + 1; + need += joinlength(sv->s_aliases) + 1; + need += strlen(svPort) + 1; + need += strlen(sv->s_proto) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, sv->s_name); strcat(*buffer, fieldsep); + joinarray(sv->s_aliases, *buffer, COMMA); strcat(*buffer, fieldsep); + strcat(*buffer, svPort); strcat(*buffer, fieldsep); + strcat(*buffer, sv->s_proto); strcat(*buffer, fieldsep); + + return (0); +} + + + + + +/* + * int irp_unmarshall_sv(struct servent *sv, char *buffer) + * + * notes: + * + * see above + * + * return: + * + * 0 on success, -1 on failure. + * + */ + +int +irp_unmarshall_sv(struct servent *sv, char *buffer) { + char *p, *q; + short svport; + long t; + char *name = NULL; + char *proto = NULL; + char **aliases = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (sv == NULL || buffer == NULL) + return (-1); + + p = buffer; + + + /* s_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + + /* s_aliases field */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* s_port field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + svport = (short)t; + if ((long) svport != t) { /* value must have been too big. */ + goto error; + } + svport = htons(svport); + + /* s_proto field */ + proto = NULL; + if (getfield(&proto, 0, &p, fieldsep) == NULL) { + goto error; + } + + sv->s_name = name; + sv->s_aliases = aliases; + sv->s_port = svport; + sv->s_proto = proto; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + if (proto != NULL) free(proto); + free_array(aliases, 0); + + return (-1); +} + + +/* ------------------------- struct servent ------------------------- */ + +/* +++++++++++++++++++++++++ struct protoent +++++++++++++++++++++++++ */ + + + +/* + * int irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len) + * + * notes: + * + * see above + * + * return: + * + * 0 on success and -1 on failure. + * + */ + +int +irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len) { + size_t need = 1; /* for null byte */ + char prProto[24]; + const char *fieldsep = COLONSTR; + + if (pr == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + sprintf(prProto, "%d", (int)pr->p_proto); + + need += strlen(pr->p_name) + 1; + need += joinlength(pr->p_aliases) + 1; + need += strlen(prProto) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, pr->p_name); strcat(*buffer, fieldsep); + joinarray(pr->p_aliases, *buffer, COMMA); strcat(*buffer, fieldsep); + strcat(*buffer, prProto); strcat(*buffer, fieldsep); + + return (0); + +} + + + +/* + * int irp_unmarshall_pr(struct protoent *pr, char *buffer) + * + * notes: + * + * See above + * + * return: + * + * 0 on success, -1 on failure + * + */ + +int irp_unmarshall_pr(struct protoent *pr, char *buffer) { + char *p, *q; + int prproto; + long t; + char *name = NULL; + char **aliases = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (pr == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + p = buffer; + + /* p_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + + /* p_aliases field */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* p_proto field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + prproto = (int)t; + if ((long) prproto != t) { /* value must have been too big. */ + goto error; + } + + pr->p_name = name; + pr->p_aliases = aliases; + pr->p_proto = prproto; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + free_array(aliases, 0); + + return (-1); +} + +/* ------------------------- struct protoent ------------------------- */ + + + +/* +++++++++++++++++++++++++ struct hostent +++++++++++++++++++++++++ */ + + +/* + * int irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len) + * + * notes: + * + * see above. + * + * return: + * + * 0 on success, -1 on failure. + * + */ + +int +irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len) { + size_t need = 1; /* for null byte */ + char hoaddrtype[24]; + char holength[24]; + char **av; + char *p; + int addrlen; + int malloced = 0; + size_t remlen; + const char *fieldsep = "@"; + + if (ho == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + switch(ho->h_addrtype) { + case AF_INET: + strcpy(hoaddrtype, "AF_INET"); + break; + + case AF_INET6: + strcpy(hoaddrtype, "AF_INET6"); + break; + + default: + errno = EINVAL; + return (-1); + } + + sprintf(holength, "%d", ho->h_length); + + need += strlen(ho->h_name) + 1; + need += joinlength(ho->h_aliases) + 1; + need += strlen(hoaddrtype) + 1; + need += strlen(holength) + 1; + + /* we determine an upper bound on the string length needed, not an + exact length. */ + addrlen = (ho->h_addrtype == AF_INET ? 16 : 46) ; /* XX other AF's?? */ + for (av = ho->h_addr_list; av != NULL && *av != NULL ; av++) + need += addrlen; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + malloced = 1; + } + + strcpy(*buffer, ho->h_name); strcat(*buffer, fieldsep); + joinarray(ho->h_aliases, *buffer, COMMA); strcat(*buffer, fieldsep); + strcat(*buffer, hoaddrtype); strcat(*buffer, fieldsep); + strcat(*buffer, holength); strcat(*buffer, fieldsep); + + p = *buffer + strlen(*buffer); + remlen = need - strlen(*buffer); + for (av = ho->h_addr_list ; av != NULL && *av != NULL ; av++) { + if (inet_ntop(ho->h_addrtype, *av, p, remlen) == NULL) { + goto error; + } + if (*(av + 1) != NULL) + strcat(p, COMMASTR); + remlen -= strlen(p); + p += strlen(p); + } + strcat(*buffer, fieldsep); + + return (0); + + error: + if (malloced) { + memput(*buffer, need); + } + + return (-1); +} + + + +/* + * int irp_unmarshall_ho(struct hostent *ho, char *buffer) + * + * notes: + * + * See above. + * + * return: + * + * 0 on success, -1 on failure. + * + */ + +int +irp_unmarshall_ho(struct hostent *ho, char *buffer) { + char *p, *q, *r; + int hoaddrtype; + int holength; + long t; + char *name = NULL; + char **aliases = NULL; + char **hohaddrlist = NULL; + size_t hoaddrsize; + char tmpbuf[24]; + char *tb; + char **alist; + int addrcount; + char fieldsep = '@'; + int myerrno = EINVAL; + + if (ho == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + p = buffer; + + /* h_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + + /* h_aliases field */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* h_addrtype field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + if (strcmp(tmpbuf, "AF_INET") == 0) + hoaddrtype = AF_INET; + else if (strcmp(tmpbuf, "AF_INET6") == 0) + hoaddrtype = AF_INET6; + else + goto error; + + + /* h_length field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + holength = (int)t; + if ((long) holength != t) { /* value must have been too big. */ + goto error; + } + + + /* h_addr_list field */ + q = strchr(p, fieldsep); + if (q == NULL) + goto error; + + /* count how many addresss are in there */ + if (q > p + 1) { + for (addrcount = 1, r = p ; r != q ; r++) { + if (*r == COMMA) + addrcount++; + } + } else { + addrcount = 0; + } + + hoaddrsize = (addrcount + 1) * sizeof (char *); + hohaddrlist = malloc(hoaddrsize); + if (hohaddrlist == NULL) { + myerrno = ENOMEM; + goto error; + } + + memset(hohaddrlist, 0x0, hoaddrsize); + + alist = hohaddrlist; + for (t = 0, r = p ; r != q ; p = r + 1, t++) { + char saved; + while (r != q && *r != COMMA) r++; + saved = *r; + *r = 0x0; + + alist[t] = malloc(hoaddrtype == AF_INET ? 4 : 16); + if (alist[t] == NULL) { + myerrno = ENOMEM; + goto error; + } + + if (inet_pton(hoaddrtype, p, alist[t]) == -1) + goto error; + *r = saved; + } + alist[t] = NULL; + + ho->h_name = name; + ho->h_aliases = aliases; + ho->h_addrtype = hoaddrtype; + ho->h_length = holength; + ho->h_addr_list = hohaddrlist; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + free_array(aliases, 0); + + return (-1); +} + +/* ------------------------- struct hostent------------------------- */ + + + +/* +++++++++++++++++++++++++ struct netgrp +++++++++++++++++++++++++ */ + + +/* + * int irp_marshall_ng(const char *host, const char *user, + * const char *domain, char *buffer, size_t *len) + * + * notes: + * + * See note for irp_marshall_ng_start + * + * return: + * + * 0 on success, 0 on failure. + * + */ + +int +irp_marshall_ng(const char *host, const char *user, const char *domain, + char **buffer, size_t *len) { + size_t need = 1; /* for nul byte */ + const char *fieldsep = ","; + + if (len == NULL) { + errno = EINVAL; + return (-1); + } + + need += 4; /* two parens and two commas */ + need += (host == NULL ? 0 : strlen(host)); + need += (user == NULL ? 0 : strlen(user)); + need += (domain == NULL ? 0 : strlen(domain)); + + if (buffer == NULL) { + *len = need; + return (0); + } else if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + (*buffer)[0] = '('; + (*buffer)[1] = '\0'; + + if (host != NULL) + strcat(*buffer, host); + strcat(*buffer, fieldsep); + + if (user != NULL) + strcat(*buffer, user); + strcat(*buffer, fieldsep); + + if (domain != NULL) + strcat(*buffer, domain); + strcat(*buffer, ")"); + + return (0); +} + + + +/* ---------- */ + + +/* + * int irp_unmarshall_ng(const char **host, const char **user, + * const char **domain, char *buffer) + * + * notes: + * + * Unpacks the BUFFER into 3 character arrays it allocates and assigns + * to *HOST, *USER and *DOMAIN. If any field of the value is empty, + * then the corresponding paramater value will be set to NULL. + * + * return: + * + * 0 on success and -1 on failure. + */ + +int +irp_unmarshall_ng(const char **hostp, const char **userp, const char **domainp, + char *buffer) +{ + char *p, *q; + char fieldsep = ','; + int myerrno = EINVAL; + char *host, *user, *domain; + + if (userp == NULL || hostp == NULL || + domainp == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + host = user = domain = NULL; + + p = buffer; + while (isspace((unsigned char)*p)) { + p++; + } + if (*p != '(') { + goto error; + } + + q = p + 1; + while (*q && *q != fieldsep) + q++; + if (!*q) { + goto error; + } else if (q > p + 1) { + host = strndup(p, q - p); + } + + p = q + 1; + if (!*p) { + goto error; + } else if (*p != fieldsep) { + q = p + 1; + while (*q && *q != fieldsep) + q++; + if (!*q) { + goto error; + } + user = strndup(p, q - p); + } else { + p++; + } + + if (!*p) { + goto error; + } else if (*p != ')') { + q = p + 1; + while (*q && *q != ')') + q++; + if (!*q) { + goto error; + } + domain = strndup(p, q - p); + } + *hostp = host; + *userp = user; + *domainp = domain; + + return (0); + + error: + errno = myerrno; + + if (host != NULL) free(host); + if (user != NULL) free(user); + if (domain != NULL) free(domain); + + return (-1); +} + +/* ------------------------- struct netgrp ------------------------- */ + + + + +/* +++++++++++++++++++++++++ struct nwent +++++++++++++++++++++++++ */ + + +/* + * int irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len) + * + * notes: + * + * See at top. + * + * return: + * + * 0 on success and -1 on failure. + * + */ + +int +irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len) { + size_t need = 1; /* for null byte */ + char nAddrType[24]; + char nNet[MAXPADDRSIZE]; + const char *fieldsep = COLONSTR; + + if (ne == NULL || len == NULL) { + return (-1); + } + + strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype)); + + if (inet_net_ntop(ne->n_addrtype, ne->n_addr, ne->n_length, + nNet, sizeof nNet) == NULL) { + return (-1); + } + + + need += strlen(ne->n_name) + 1; + need += joinlength(ne->n_aliases) + 1; + need += strlen(nAddrType) + 1; + need += strlen(nNet) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, ne->n_name); strcat(*buffer, fieldsep); + joinarray(ne->n_aliases, *buffer, COMMA) ; strcat(*buffer, fieldsep); + strcat(*buffer, nAddrType); strcat(*buffer, fieldsep); + strcat(*buffer, nNet); strcat(*buffer, fieldsep); + + return (0); +} + + + +/* + * int irp_unmarshall_nw(struct nwent *ne, char *buffer) + * + * notes: + * + * See note up top. + * + * return: + * + * 0 on success and -1 on failure. + * + */ + +int +irp_unmarshall_nw(struct nwent *ne, char *buffer) { + char *p, *q; + int naddrtype; + long nnet; + int bits; + char *name = NULL; + char **aliases = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (ne == NULL || buffer == NULL) { + goto error; + } + + p = buffer; + + /* n_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + + /* n_aliases field. Aliases are separated by commas */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* h_addrtype field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + if (strcmp(tmpbuf, "AF_INET") == 0) + naddrtype = AF_INET; + else if (strcmp(tmpbuf, "AF_INET6") == 0) + naddrtype = AF_INET6; + else + goto error; + + + /* n_net field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + nnet = 0; + bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet); + if (bits < 0) { + goto error; + } + + /* nnet = ntohl(nnet); */ /* keep in network order for nwent */ + + ne->n_name = name; + ne->n_aliases = aliases; + ne->n_addrtype = naddrtype; + ne->n_length = bits; + ne->n_addr = malloc(sizeof nnet); + if (ne->n_addr == NULL) { + goto error; + } + + memcpy(ne->n_addr, &nnet, sizeof nnet); + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + free_array(aliases, 0); + + return (-1); +} + + +/* ------------------------- struct nwent ------------------------- */ + + +/* +++++++++++++++++++++++++ struct netent +++++++++++++++++++++++++ */ + + +/* + * int irp_marshall_ne(struct netent *ne, char **buffer, size_t *len) + * + * notes: + * + * See at top. + * + * return: + * + * 0 on success and -1 on failure. + * + */ + +int +irp_marshall_ne(struct netent *ne, char **buffer, size_t *len) { + size_t need = 1; /* for null byte */ + char nAddrType[24]; + char nNet[MAXPADDRSIZE]; + const char *fieldsep = COLONSTR; + long nval; + + if (ne == NULL || len == NULL) { + return (-1); + } + + strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype)); + + nval = htonl(ne->n_net); + if (inet_ntop(ne->n_addrtype, &nval, nNet, sizeof nNet) == NULL) { + return (-1); + } + + need += strlen(ne->n_name) + 1; + need += joinlength(ne->n_aliases) + 1; + need += strlen(nAddrType) + 1; + need += strlen(nNet) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, ne->n_name); strcat(*buffer, fieldsep); + joinarray(ne->n_aliases, *buffer, COMMA) ; strcat(*buffer, fieldsep); + strcat(*buffer, nAddrType); strcat(*buffer, fieldsep); + strcat(*buffer, nNet); strcat(*buffer, fieldsep); + + return (0); +} + + + +/* + * int irp_unmarshall_ne(struct netent *ne, char *buffer) + * + * notes: + * + * See note up top. + * + * return: + * + * 0 on success and -1 on failure. + * + */ + +int +irp_unmarshall_ne(struct netent *ne, char *buffer) { + char *p, *q; + int naddrtype; + long nnet; + int bits; + char *name = NULL; + char **aliases = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (ne == NULL || buffer == NULL) { + goto error; + } + + p = buffer; + + /* n_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + + /* n_aliases field. Aliases are separated by commas */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* h_addrtype field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + if (strcmp(tmpbuf, "AF_INET") == 0) + naddrtype = AF_INET; + else if (strcmp(tmpbuf, "AF_INET6") == 0) + naddrtype = AF_INET6; + else + goto error; + + + /* n_net field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet); + if (bits < 0) { + goto error; + } + nnet = ntohl(nnet); + + ne->n_name = name; + ne->n_aliases = aliases; + ne->n_addrtype = naddrtype; + ne->n_net = nnet; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + free_array(aliases, 0); + + return (-1); +} + + +/* ------------------------- struct netent ------------------------- */ + + +/* =========================================================================== */ + + +/* + * static char ** splitarray(const char *buffer, const char *buffend, char delim) + * + * notes: + * + * Split a delim separated astring. Not allowed + * to have two delims next to each other. BUFFER points to begining of + * string, BUFFEND points to one past the end of the string + * (i.e. points at where the null byte would be if null + * terminated). + * + * return: + * + * Returns a malloced array of pointers, each pointer pointing to a + * malloced string. If BUFEER is an empty string, then return values is + * array of 1 pointer that is NULL. Returns NULL on failure. + * + */ + +static char ** +splitarray(const char *buffer, const char *buffend, char delim) { + const char *p, *q; + int count = 0; + char **arr = NULL; + char **aptr; + + if (buffend < buffer) + return (NULL); + else if (buffend > buffer && *buffer == delim) + return (NULL); + else if (buffend > buffer && *(buffend - 1) == delim) + return (NULL); + + /* count the number of field and make sure none are empty */ + if (buffend > buffer + 1) { + for (count = 1, q = buffer ; q != buffend ; q++) { + if (*q == delim) { + if (q > buffer && (*(q - 1) == delim)) { + errno = EINVAL; + return (NULL); + } + count++; + } + } + } + + if (count > 0) { + count++ ; /* for NULL at end */ + aptr = arr = malloc(count * sizeof (char *)); + if (aptr == NULL) { + errno = ENOMEM; + return (NULL); + } + + memset(arr, 0x0, count * sizeof (char *)); + for (p = buffer ; p < buffend ; p++) { + for (q = p ; *q != delim && q != buffend ; q++) + /* nothing */; + *aptr = strndup(p, q - p); + + p = q; + aptr++; + } + *aptr = NULL; + } else { + arr = malloc(sizeof (char *)); + if (arr == NULL) { + errno = ENOMEM; + return (NULL); + } + + *arr = NULL; + } + + return (arr); +} + + + + +/* + * static size_t joinlength(char * const *argv) + * + * return: + * + * the number of bytes in all the arrays pointed at + * by argv, including their null bytes(which will usually be turned + * into commas). + * + * + */ + +static size_t +joinlength(char * const *argv) { + int len = 0; + + while (argv && *argv) { + len += (strlen(*argv) + 1); + argv++; + } + + return (len); +} + + + +/* + * int joinarray(char * const *argv, char *buffer, char delim) + * + * notes: + * + * Copy all the ARGV strings into the end of BUFFER + * separating them with DELIM. BUFFER is assumed to have + * enough space to hold everything and to be already null-terminated. + * + * return: + * + * 0 unless argv or buffer is NULL. + * + * + */ + +static int +joinarray(char * const *argv, char *buffer, char delim) { + char * const *p; + char sep[2]; + + if (argv == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + sep[0] = delim; + sep[1] = 0x0; + + for (p = argv ; *p != NULL ; p++) { + strcat(buffer, *p); + if (*(p + 1) != NULL) { + strcat(buffer, sep); + } + } + + return (0); +} + + +/* + * static char * getfield(char **res, size_t reslen, char **ptr, char delim) + * + * notes: + * + * Stores in *RES, which is a buffer of length RESLEN, a + * copy of the bytes from *PTR up to and including the first + * instance of DELIM. If *RES is NULL, then it will be + * assigned a malloced buffer to hold the copy. *PTR is + * modified to point at the found delimiter. + * + * return: + * + * If there was no delimiter, then NULL is returned, + * otherewise *RES is returned. + * + */ + +static char * +getfield(char **res, size_t reslen, char **ptr, char delim) { + char *q; + + if (res == NULL || ptr == NULL || *ptr == NULL) { + errno = EINVAL; + return (NULL); + } + + q = strchr(*ptr, delim); + + if (q == NULL) { + errno = EINVAL; + return (NULL); + } else { + if (*res == NULL) { + *res = strndup(*ptr, q - *ptr); + } else { + if ((size_t)(q - *ptr + 1) > reslen) { /* to big for res */ + errno = EINVAL; + return (NULL); + } else { + strncpy(*res, *ptr, q - *ptr); + (*res)[q - *ptr] = 0x0; + } + } + *ptr = q + 1; + } + + return (*res); +} + + + + + +#ifndef HAVE_STRNDUP +/* + * static char * strndup(const char *str, size_t len) + * + * notes: + * + * like strdup, except do len bytes instead of the whole string. Always + * null-terminates. + * + * return: + * + * The newly malloced string. + * + */ + +static char * +strndup(const char *str, size_t len) { + char *p = malloc(len + 1); + + if (p == NULL) + return (NULL); + strncpy(p, str, len); + p[len] = 0x0; + return (p); +} +#endif + +#if WANT_MAIN + +/* + * static int strcmp_nws(const char *a, const char *b) + * + * notes: + * + * do a strcmp, except uneven lengths of whitespace compare the same + * + * return: + * + */ + +static int +strcmp_nws(const char *a, const char *b) { + while (*a && *b) { + if (isspace(*a) && isspace(*b)) { + do { + a++; + } while (isspace(*a)); + do { + b++; + } while (isspace(*b)); + } + if (*a < *b) + return (-1); + else if (*a > *b) + return (1); + + a++; + b++;; + } + + if (*a == *b) + return (0); + else if (*a > *b) + return (1); + else + return (-1); +} + +#endif + + + + + +/* + * static void free_array(char **argv, size_t entries) + * + * notes: + * + * Free argv and each of the pointers inside it. The end of + * the array is when a NULL pointer is found inside. If + * entries is > 0, then NULL pointers inside the array do + * not indicate the end of the array. + * + */ + +static void +free_array(char **argv, size_t entries) { + char **p = argv; + int useEntries = (entries > 0); + + if (argv == NULL) + return; + + while ((useEntries && entries > 0) || *p) { + if (*p) + free(*p); + p++; + if (useEntries) + entries--; + } + free(argv); +} + + + + + +/* ************************************************** */ + +#if WANT_MAIN + +/* takes an option to indicate what sort of marshalling(read the code) and + an argument. If the argument looks like a marshalled buffer(has a ':' + embedded) then it's unmarshalled and the remarshalled and the new string + is compared to the old one. +*/ + +int +main(int argc, char **argv) { + char buffer[1024]; + char *b = &buffer[0]; + size_t len = sizeof buffer; + char option; + + if (argc < 2 || argv[1][0] != '-') + exit(1); + + option = argv[1][1]; + argv++; + argc--; + + +#if 0 + { + char buff[10]; + char *p = argv[1], *q = &buff[0]; + + while (getfield(&q, sizeof buff, &p, ':') != NULL) { + printf("field: \"%s\"\n", q); + p++; + } + printf("p is now \"%s\"\n", p); + } +#endif + +#if 0 + { + char **x = splitarray(argv[1], argv[1] + strlen(argv[1]), + argv[2][0]); + char **p; + + if (x == NULL) + printf("split failed\n"); + + for (p = x ; p != NULL && *p != NULL ; p++) { + printf("\"%s\"\n", *p); + } + } +#endif + +#if 1 + switch(option) { + case 'n': { + struct nwent ne; + int i; + + if (strchr(argv[1], ':') != NULL) { + if (irp_unmarshall_nw(&ne, argv[1]) != 0) { + printf("Unmarhsalling failed\n"); + exit(1); + } + + printf("Name: \"%s\"\n", ne.n_name); + printf("Aliases:"); + for (i = 0 ; ne.n_aliases[i] != NULL ; i++) + printf("\n\t\"%s\"", ne.n_aliases[i]); + printf("\nAddrtype: %s\n", ADDR_T_STR(ne.n_addrtype)); + inet_net_ntop(ne.n_addrtype, ne.n_addr, ne.n_length, + buffer, sizeof buffer); + printf("Net: \"%s\"\n", buffer); + *((long*)ne.n_addr) = htonl(*((long*)ne.n_addr)); + inet_net_ntop(ne.n_addrtype, ne.n_addr, ne.n_length, + buffer, sizeof buffer); + printf("Corrected Net: \"%s\"\n", buffer); + } else { + struct netent *np1 = getnetbyname(argv[1]); + ne.n_name = np1->n_name; + ne.n_aliases = np1->n_aliases; + ne.n_addrtype = np1->n_addrtype; + ne.n_addr = &np1->n_net; + ne.n_length = (IN_CLASSA(np1->n_net) ? + 8 : + (IN_CLASSB(np1->n_net) ? + 16 : + (IN_CLASSC(np1->n_net) ? + 24 : -1))); + np1->n_net = htonl(np1->n_net); + if (irp_marshall_nw(&ne, &b, &len) != 0) { + printf("Marshalling failed\n"); + } + printf("%s\n", b); + } + break; + } + + + case 'r': { + char **hosts, **users, **domains; + size_t entries; + int i; + char *buff; + size_t size; + char *ngname; + + if (strchr(argv[1], '(') != NULL) { + if (irp_unmarshall_ng(&ngname, &entries, + &hosts, &users, &domains, + argv[1]) != 0) { + printf("unmarshall failed\n"); + exit(1); + } + +#define STRVAL(x) (x == NULL ? "*" : x) + + printf("%s {\n", ngname); + for (i = 0 ; i < entries ; i++) + printf("\t\"%s\" : \"%s\" : \"%s\"\n", + STRVAL(hosts[i]), + STRVAL(users[i]), + STRVAL(domains[i])); + printf("}\n\n\n"); + + + irp_marshall_ng_start(ngname, NULL, &size); + for (i = 0 ; i < entries ; i++) + irp_marshall_ng_next(hosts[i], users[i], + domains[i], NULL, &size); + irp_marshall_ng_end(NULL, &size); + + buff = malloc(size); + + irp_marshall_ng_start(ngname, buff, &size); + for (i = 0 ; i < entries ; i++) { + if (irp_marshall_ng_next(hosts[i], users[i], + domains[i], buff, + &size) != 0) + printf("next marshalling failed.\n"); + } + irp_marshall_ng_end(buff, &size); + + if (strcmp_nws(argv[1], buff) != 0) { + printf("compare failed:\n\t%s\n\t%s\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + char *h, *u, *d, *buff; + size_t size; + + /* run through two times. First to figure out how + much of a buffer we need. Second to do the + actual marshalling */ + + setnetgrent(argv[1]); + irp_marshall_ng_start(argv[1], NULL, &size); + while (getnetgrent(&h, &u, &d) == 1) + irp_marshall_ng_next(h, u, d, NULL, &size); + irp_marshall_ng_end(NULL, &size); + endnetgrent(argv[1]); + + buff = malloc(size); + + setnetgrent(argv[1]); + if (irp_marshall_ng_start(argv[1], buff, &size) != 0) + printf("Marshalling start failed\n"); + + while (getnetgrent(&h, &u, &d) == 1) { + if (irp_marshall_ng_next(h, u, d, buff, &size) + != 0) { + printf("Marshalling failed\n"); + } + } + + irp_marshall_ng_end(buff, &size); + endnetgrent(); + + printf("success: %s\n", buff); + } + break; + } + + + + case 'h': { + struct hostent he, *hp; + int i; + + + if (strchr(argv[1], '@') != NULL) { + if (irp_unmarshall_ho(&he, argv[1]) != 0) { + printf("unmarshall failed\n"); + exit(1); + } + + printf("Host: \"%s\"\nAliases:", he.h_name); + for (i = 0 ; he.h_aliases[i] != NULL ; i++) + printf("\n\t\t\"%s\"", he.h_aliases[i]); + printf("\nAddr Type: \"%s\"\n", + ADDR_T_STR(he.h_addrtype)); + printf("Length: %d\nAddresses:", he.h_length); + for (i = 0 ; he.h_addr_list[i] != 0 ; i++) { + inet_ntop(he.h_addrtype, he.h_addr_list[i], + buffer, sizeof buffer); + printf("\n\t\"%s\"\n", buffer); + } + printf("\n\n"); + + irp_marshall_ho(&he, &b, &len); + if (strcmp(argv[1], buffer) != 0) { + printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + if ((hp = gethostbyname(argv[1])) == NULL) { + perror("gethostbyname"); + printf("\"%s\"\n", argv[1]); + exit(1); + } + + if (irp_marshall_ho(hp, &b, &len) != 0) { + printf("irp_marshall_ho failed\n"); + exit(1); + } + + printf("success: \"%s\"\n", buffer); + } + break; + } + + + case 's': { + struct servent *sv; + struct servent sv1; + + if (strchr(argv[1], ':') != NULL) { + sv = &sv1; + memset(sv, 0xef, sizeof (struct servent)); + if (irp_unmarshall_sv(sv, argv[1]) != 0) { + printf("unmarshall failed\n"); + + } + + irp_marshall_sv(sv, &b, &len); + if (strcmp(argv[1], buffer) != 0) { + printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + if ((sv = getservbyname(argv[1], argv[2])) == NULL) { + perror("getservent"); + exit(1); + } + + if (irp_marshall_sv(sv, &b, &len) != 0) { + printf("irp_marshall_sv failed\n"); + exit(1); + } + + printf("success: \"%s\"\n", buffer); + } + break; + } + + case 'g': { + struct group *gr; + struct group gr1; + + if (strchr(argv[1], ':') != NULL) { + gr = &gr1; + memset(gr, 0xef, sizeof (struct group)); + if (irp_unmarshall_gr(gr, argv[1]) != 0) { + printf("unmarshall failed\n"); + + } + + irp_marshall_gr(gr, &b, &len); + if (strcmp(argv[1], buffer) != 0) { + printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + if ((gr = getgrnam(argv[1])) == NULL) { + perror("getgrnam"); + exit(1); + } + + if (irp_marshall_gr(gr, &b, &len) != 0) { + printf("irp_marshall_gr failed\n"); + exit(1); + } + + printf("success: \"%s\"\n", buffer); + } + break; + } + + + case 'p': { + struct passwd *pw; + struct passwd pw1; + + if (strchr(argv[1], ':') != NULL) { + pw = &pw1; + memset(pw, 0xef, sizeof (*pw)); + if (irp_unmarshall_pw(pw, argv[1]) != 0) { + printf("unmarshall failed\n"); + exit(1); + } + + printf("User: \"%s\"\nPasswd: \"%s\"\nUid: %ld\nGid: %ld\n", + pw->pw_name, pw->pw_passwd, (long)pw->pw_uid, + (long)pw->pw_gid); + printf("Class: \"%s\"\nChange: %ld\nGecos: \"%s\"\n", + pw->pw_class, (long)pw->pw_change, pw->pw_gecos); + printf("Shell: \"%s\"\nDirectory: \"%s\"\n", + pw->pw_shell, pw->pw_dir); + + pw = getpwnam(pw->pw_name); + irp_marshall_pw(pw, &b, &len); + if (strcmp(argv[1], buffer) != 0) { + printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + if ((pw = getpwnam(argv[1])) == NULL) { + perror("getpwnam"); + exit(1); + } + + if (irp_marshall_pw(pw, &b, &len) != 0) { + printf("irp_marshall_pw failed\n"); + exit(1); + } + + printf("success: \"%s\"\n", buffer); + } + break; + } + + default: + printf("Wrong option: %c\n", option); + break; + } + +#endif + + return (0); +} + +#endif Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/irpmarshall.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/irs_data.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/irs_data.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/irs_data.c (revision 109985) @@ -0,0 +1,197 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: irs_data.c,v 1.19 2001/08/20 07:08:41 marka Exp $"; +#endif + +#include "port_before.h" + +#ifndef __BIND_NOSTATIC + +#include + +#include +#include + +#include +#include +#include +#include + +#ifdef DO_PTHREADS +#include +#endif + +#include + +#include "port_after.h" + +#include "irs_data.h" +#undef _res +#undef h_errno + +extern struct __res_state _res; +extern int h_errno; + +#ifdef DO_PTHREADS +static pthread_key_t key; +static int once = 0; +#else +static struct net_data *net_data; +#endif + +void +irs_destroy(void) { +#ifndef DO_PTHREADS + if (net_data != NULL) + net_data_destroy(net_data); + net_data = NULL; +#endif +} + +void +net_data_destroy(void *p) { + struct net_data *net_data = p; + + res_ndestroy(net_data->res); + if (net_data->gr != NULL) { + (*net_data->gr->close)(net_data->gr); + net_data->gr = NULL; + } + if (net_data->pw != NULL) { + (*net_data->pw->close)(net_data->pw); + net_data->pw = NULL; + } + if (net_data->sv != NULL) { + (*net_data->sv->close)(net_data->sv); + net_data->sv = NULL; + } + if (net_data->pr != NULL) { + (*net_data->pr->close)(net_data->pr); + net_data->pr = NULL; + } + if (net_data->ho != NULL) { + (*net_data->ho->close)(net_data->ho); + net_data->ho = NULL; + } + if (net_data->nw != NULL) { + (*net_data->nw->close)(net_data->nw); + net_data->nw = NULL; + } + if (net_data->ng != NULL) { + (*net_data->ng->close)(net_data->ng); + net_data->ng = NULL; + } + + (*net_data->irs->close)(net_data->irs); + memput(net_data, sizeof *net_data); +} + +/* applications that need a specific config file other than + * _PATH_IRS_CONF should call net_data_init directly rather than letting + * the various wrapper functions make the first call. - brister + */ + +struct net_data * +net_data_init(const char *conf_file) { +#ifdef DO_PTHREADS + static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER; + struct net_data *net_data; + + if (!once) { + pthread_mutex_lock(&keylock); + if (!once++) + pthread_key_create(&key, net_data_destroy); + pthread_mutex_unlock(&keylock); + } + net_data = pthread_getspecific(key); +#endif + + if (net_data == NULL) { + net_data = net_data_create(conf_file); + if (net_data == NULL) + return (NULL); +#ifdef DO_PTHREADS + pthread_setspecific(key, net_data); +#endif + } + + return (net_data); +} + +struct net_data * +net_data_create(const char *conf_file) { + struct net_data *net_data; + + net_data = memget(sizeof (struct net_data)); + if (net_data == NULL) + return (NULL); + memset(net_data, 0, sizeof (struct net_data)); + + if ((net_data->irs = irs_gen_acc("", conf_file)) == NULL) + return (NULL); +#ifndef DO_PTHREADS + (*net_data->irs->res_set)(net_data->irs, &_res, NULL); +#endif + + net_data->res = (*net_data->irs->res_get)(net_data->irs); + if (net_data->res == NULL) + return (NULL); + + if ((net_data->res->options & RES_INIT) == 0 && + res_ninit(net_data->res) == -1) + return (NULL); + + return (net_data); +} + + + +void +net_data_minimize(struct net_data *net_data) { + res_nclose(net_data->res); +} + +#ifdef _REENTRANT +struct __res_state * +__res_state(void) { + /* NULL param here means use the default config file. */ + struct net_data *net_data = net_data_init(NULL); + if (net_data && net_data->res) + return (net_data->res); + + return (&_res); +} +#endif + +int * +__h_errno(void) { + /* NULL param here means use the default config file. */ + struct net_data *net_data = net_data_init(NULL); + if (net_data && net_data->res) + return (&net_data->res->res_h_errno); + return (&h_errno); +} + +void +__h_errno_set(struct __res_state *res, int err) { + + h_errno = res->res_h_errno = err; +} + +#endif /*__BIND_NOSTATIC*/ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/irs_data.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/lcl.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/lcl.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/lcl.c (revision 109985) @@ -0,0 +1,140 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: lcl.c,v 1.17 2001/05/29 05:49:02 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +/* Forward. */ + +static void lcl_close(struct irs_acc *); +static struct __res_state * lcl_res_get(struct irs_acc *); +static void lcl_res_set(struct irs_acc *, struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_acc * +irs_lcl_acc(const char *options) { + struct irs_acc *acc; + struct lcl_p *lcl; + + UNUSED(options); + + if (!(acc = memget(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(lcl = memget(sizeof *lcl))) { + errno = ENOMEM; + free(acc); + return (NULL); + } + memset(lcl, 0x5e, sizeof *lcl); + lcl->res = NULL; + lcl->free_res = NULL; + acc->private = lcl; +#ifdef WANT_IRS_GR + acc->gr_map = irs_lcl_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_lcl_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_lcl_sv; + acc->pr_map = irs_lcl_pr; + acc->ho_map = irs_lcl_ho; + acc->nw_map = irs_lcl_nw; + acc->ng_map = irs_lcl_ng; + acc->res_get = lcl_res_get; + acc->res_set = lcl_res_set; + acc->close = lcl_close; + return (acc); +} + +/* Methods */ +static struct __res_state * +lcl_res_get(struct irs_acc *this) { + struct lcl_p *lcl = (struct lcl_p *)this->private; + + if (lcl->res == NULL) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) + return (NULL); + memset(res, 0, sizeof *res); + lcl_res_set(this, res, free); + } + + if ((lcl->res->options & RES_INIT) == 0 && + res_ninit(lcl->res) < 0) + return (NULL); + + return (lcl->res); +} + +static void +lcl_res_set(struct irs_acc *this, struct __res_state *res, + void (*free_res)(void *)) { + struct lcl_p *lcl = (struct lcl_p *)this->private; + + if (lcl->res && lcl->free_res) { + res_nclose(lcl->res); + (*lcl->free_res)(lcl->res); + } + + lcl->res = res; + lcl->free_res = free_res; +} + +static void +lcl_close(struct irs_acc *this) { + struct lcl_p *lcl = (struct lcl_p *)this->private; + + if (lcl) { + if (lcl->free_res) + (*lcl->free_res)(lcl->res); + memput(lcl, sizeof *lcl); + } + memput(this, sizeof *this); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/lcl.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_gr.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_gr.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_gr.c (revision 109985) @@ -0,0 +1,354 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_gr.c,v 1.26 2001/05/29 05:49:03 marka Exp $"; +/* from getgrent.c 8.2 (Berkeley) 3/21/94"; */ +/* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */ +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_gr_unneeded; +#else + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "irs_p.h" +#include "lcl_p.h" +#include "irp_p.h" + +#include "port_after.h" + + +/* Types. */ + +struct pvt { + FILE * fp; + /* + * Need space to store the entries read from the group file. + * The members list also needs space per member, and the + * strings making up the user names must be allocated + * somewhere. Rather than doing lots of small allocations, + * we keep one buffer and resize it as needed. + */ + struct group group; + size_t nmemb; /* Malloc'd max index of gr_mem[]. */ + char * membuf; + size_t membufsize; +}; + +/* Forward. */ + +static void gr_close(struct irs_gr *); +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static void gr_minimize(struct irs_gr *); + +static int grstart(struct pvt *); +static char * grnext(struct pvt *); +static struct group * grscan(struct irs_gr *, int, gid_t, const char *); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public. */ + +struct irs_gr * +irs_lcl_gr(struct irs_acc *this) { + struct irs_gr *gr; + struct pvt *pvt; + + UNUSED(this); + + if (!(gr = memget(sizeof *gr))) { + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x5e, sizeof *gr); + if (!(pvt = memget(sizeof *pvt))) { + memput(gr, sizeof *gr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + gr->private = pvt; + gr->close = gr_close; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->list = make_group_list; + gr->minimize = gr_minimize; + gr->res_get = NULL; + gr->res_set = NULL; + return (gr); +} + +/* Methods. */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) + (void)fclose(pvt->fp); + if (pvt->group.gr_mem) + free(pvt->group.gr_mem); + if (pvt->membuf) + free(pvt->membuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct group * +gr_next(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->fp && !grstart(pvt)) + return (NULL); + return (grscan(this, 0, 0, NULL)); +} + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + if (!grstart((struct pvt *)this->private)) + return (NULL); + return (grscan(this, 1, 0, name)); +} + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + if (!grstart((struct pvt *)this->private)) + return (NULL); + return (grscan(this, 1, gid, NULL)); +} + +static void +gr_rewind(struct irs_gr *this) { + (void) grstart((struct pvt *)this->private); +} + +static void +gr_minimize(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +/* Private. */ + +static int +grstart(struct pvt *pvt) { + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return (1); + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_GROUP, "r"))) + return (0); + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + fclose(pvt->fp); + return (0); + } + return (1); +} + +#define INITIAL_NMEMB 30 /* about 120 bytes */ +#define INITIAL_BUFSIZ (INITIAL_NMEMB * 8) /* about 240 bytes */ + +static char * +grnext(struct pvt *pvt) { + char *w, *e; + int ch; + + /* Make sure we have a buffer. */ + if (pvt->membuf == NULL) { + pvt->membuf = malloc(INITIAL_BUFSIZ); + if (pvt->membuf == NULL) { + enomem: + errno = ENOMEM; + return (NULL); + } + pvt->membufsize = INITIAL_BUFSIZ; + } + + /* Read until EOF or EOL. */ + w = pvt->membuf; + e = pvt->membuf + pvt->membufsize; + while ((ch = fgetc(pvt->fp)) != EOF && ch != '\n') { + /* Make sure we have room for this character and a \0. */ + if (w + 1 == e) { + size_t o = w - pvt->membuf; + size_t n = pvt->membufsize * 2; + char *t = realloc(pvt->membuf, n); + + if (t == NULL) + goto enomem; + pvt->membuf = t; + pvt->membufsize = n; + w = pvt->membuf + o; + e = pvt->membuf + pvt->membufsize; + } + /* Store it. */ + *w++ = (char)ch; + } + + /* Hitting EOF on the first character really does mean EOF. */ + if (w == pvt->membuf && ch == EOF) { + errno = ENOENT; + return (NULL); + } + + /* Last line of /etc/group need not end with \n; we don't care. */ + *w = '\0'; + return (pvt->membuf); +} + +static struct group * +grscan(struct irs_gr *this, int search, gid_t gid, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + size_t n; + char *bp, **m, *p; + + /* Read lines until we find one that matches our search criteria. */ + for (;;) { + if ((bp = grnext(pvt)) == NULL) + return (NULL); + + /* Optimize the usual case of searching for a name. */ + pvt->group.gr_name = strsep(&bp, ":"); + if (search && name != NULL && + strcmp(pvt->group.gr_name, name) != 0) + continue; + if (bp == NULL || *bp == '\0') + goto corrupt; + + /* Skip past the password field. */ + pvt->group.gr_passwd = strsep(&bp, ":"); + if (bp == NULL || *bp == '\0') + goto corrupt; + + /* Checking for a gid. */ + if ((p = strsep(&bp, ":")) == NULL) + continue; + /* + * Unlike the tests above, the test below is supposed to be + * testing 'p' and not 'bp', in case you think it's a typo. + */ + if (p == NULL || *p == '\0') { + corrupt: + /* warning: corrupted %s file!", _PATH_GROUP */ + continue; + } + pvt->group.gr_gid = atoi(p); + if (search && name == NULL && (gid_t)pvt->group.gr_gid != gid) + continue; + + /* We want this record. */ + break; + } + + /* + * Count commas to find out how many members there might be. + * Note that commas separate, so if there is one comma there + * can be two members (group:*:id:user1,user2). Add another + * to account for the NULL terminator. As above, allocate + * largest of INITIAL_NMEMB, or 2*n. + */ + n = 1; + if (bp != NULL) + for (n = 2, p = bp; (p = strpbrk(p, ", ")) != NULL; ++n) + p += strspn(p, ", "); + if (n > pvt->nmemb || pvt->group.gr_mem == NULL) { + if ((n *= 2) < INITIAL_NMEMB) + n = INITIAL_NMEMB; + if ((m = realloc(pvt->group.gr_mem, n * sizeof *m)) == NULL) + return (NULL); + pvt->group.gr_mem = m; + pvt->nmemb = n; + } + + /* Set the name pointers. */ + for (m = pvt->group.gr_mem; (p = strsep(&bp, ", ")) != NULL;) + if (p[0] != '\0') + *m++ = p; + *m = NULL; + + return (&pvt->group); +} + +#endif /* WANT_IRS_GR */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_gr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_ho.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_ho.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_ho.c (revision 109985) @@ -0,0 +1,576 @@ +/* + * Copyright (c) 1985, 1988, 1993 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* from gethostnamadr.c 8.1 (Berkeley) 6/4/93 */ +/* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_ho.c,v 1.26 2001/05/29 05:49:04 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "dns_p.h" +#include "lcl_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +/* Definitions. */ + +#define MAXALIASES 35 +#define MAXADDRS 35 +#define Max(a,b) ((a) > (b) ? (a) : (b)) + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +struct pvt { + FILE * fp; + struct hostent host; + char * h_addr_ptrs[MAXADDRS + 1]; + char * host_aliases[MAXALIASES]; + char hostbuf[8*1024]; + u_char host_addr[16]; /* IPv4 or IPv6 */ + struct __res_state *res; + void (*free_res)(void *); +}; + +typedef union { + int32_t al; + char ac; +} align; + +static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; +static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; + +/* Forward. */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); +static struct __res_state * ho_res_get(struct irs_ho *this); +static void ho_res_set(struct irs_ho *this, + struct __res_state *res, + void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +static size_t ns_namelen(const char *); +static int init(struct irs_ho *this); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public. */ + +struct irs_ho * +irs_lcl_ho(struct irs_acc *this) { + struct irs_ho *ho; + struct pvt *pvt; + + UNUSED(this); + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(ho = memget(sizeof *ho))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->res_get = ho_res_get; + ho->res_set = ho_res_set; + ho->addrinfo = ho_addrinfo; + return (ho); +} + +/* Methods. */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + if (pvt->fp) + (void) fclose(pvt->fp); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + + if (init(this) == -1) + return (NULL); + + if (pvt->res->options & RES_USE_INET6) { + hp = ho_byname2(this, name, AF_INET6); + if (hp) + return (hp); + } + return (ho_byname2(this, name, AF_INET)); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + char **hap; + size_t n; + + if (init(this) == -1) + return (NULL); + + ho_rewind(this); + n = ns_namelen(name); + while ((hp = ho_next(this)) != NULL) { + size_t nn; + + if (hp->h_addrtype != af) + continue; + nn = ns_namelen(hp->h_name); + if (strncasecmp(hp->h_name, name, Max(n, nn)) == 0) + goto found; + for (hap = hp->h_aliases; *hap; hap++) { + nn = ns_namelen(*hap); + if (strncasecmp(*hap, name, Max(n, nn)) == 0) + goto found; + } + } + found: + if (!hp) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (hp); +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + const u_char *uaddr = addr; + struct hostent *hp; + int size; + + if (init(this) == -1) + return (NULL); + + if (af == AF_INET6 && len == IN6ADDRSZ && + (!memcmp(uaddr, mapped, sizeof mapped) || + !memcmp(uaddr, tunnelled, sizeof tunnelled))) { + /* Unmap. */ + addr = (const u_char *)addr + sizeof mapped; + uaddr += sizeof mapped; + af = AF_INET; + len = INADDRSZ; + } + switch (af) { + case AF_INET: + size = INADDRSZ; + break; + case AF_INET6: + size = IN6ADDRSZ; + break; + default: + errno = EAFNOSUPPORT; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + if (size > len) { + errno = EINVAL; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + + /* + * Do the search. + */ + ho_rewind(this); + while ((hp = ho_next(this)) != NULL) { + char **hap; + + for (hap = hp->h_addr_list; *hap; hap++) { + const u_char *taddr = (const u_char *)*hap; + int taf = hp->h_addrtype; + int tlen = hp->h_length; + + if (taf == AF_INET6 && tlen == IN6ADDRSZ && + (!memcmp(taddr, mapped, sizeof mapped) || + !memcmp(taddr, tunnelled, sizeof tunnelled))) { + /* Unmap. */ + taddr += sizeof mapped; + taf = AF_INET; + tlen = INADDRSZ; + } + if (taf == af && tlen == len && + !memcmp(taddr, uaddr, tlen)) + goto found; + } + } + found: + if (!hp) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (hp); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *cp, **q, *p; + char *bufp, *ndbuf, *dbuf = NULL; + int c, af, len, bufsiz, offset; + + if (init(this) == -1) + return (NULL); + + if (!pvt->fp) + ho_rewind(this); + if (!pvt->fp) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + bufp = pvt->hostbuf; + bufsiz = sizeof pvt->hostbuf; + offset = 0; + again: + if (!(p = fgets(bufp + offset, bufsiz - offset, pvt->fp))) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + if (dbuf) + free(dbuf); + return (NULL); + } + if (!strchr(p, '\n') && !feof(pvt->fp)) { +#define GROWBUF 1024 + /* allocate space for longer line */ + if (dbuf == NULL) { + if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL) + strcpy(ndbuf, bufp); + } else + ndbuf = realloc(dbuf, bufsiz + GROWBUF); + if (ndbuf) { + dbuf = ndbuf; + bufp = dbuf; + bufsiz += GROWBUF; + offset = strlen(dbuf); + } else { + /* allocation failed; skip this long line */ + while ((c = getc(pvt->fp)) != EOF) + if (c == '\n') + break; + if (c != EOF) + ungetc(c, pvt->fp); + } + goto again; + } + + p -= offset; + offset = 0; + + if (*p == '#') + goto again; + if ((cp = strpbrk(p, "#\n")) != NULL) + *cp = '\0'; + if (!(cp = strpbrk(p, " \t"))) + goto again; + *cp++ = '\0'; + if (inet_pton(AF_INET6, p, pvt->host_addr) > 0) { + af = AF_INET6; + len = IN6ADDRSZ; + } else if (inet_aton(p, (struct in_addr *)pvt->host_addr) > 0) { + if (pvt->res->options & RES_USE_INET6) { + map_v4v6_address((char*)pvt->host_addr, + (char*)pvt->host_addr); + af = AF_INET6; + len = IN6ADDRSZ; + } else { + af = AF_INET; + len = INADDRSZ; + } + } else { + goto again; + } + pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; + pvt->h_addr_ptrs[1] = NULL; + pvt->host.h_addr_list = pvt->h_addr_ptrs; + pvt->host.h_length = len; + pvt->host.h_addrtype = af; + while (*cp == ' ' || *cp == '\t') + cp++; + pvt->host.h_name = cp; + q = pvt->host.h_aliases = pvt->host_aliases; + if ((cp = strpbrk(cp, " \t")) != NULL) + *cp++ = '\0'; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->host_aliases[MAXALIASES - 1]) + *q++ = cp; + if ((cp = strpbrk(cp, " \t")) != NULL) + *cp++ = '\0'; + } + *q = NULL; + if (dbuf) + free(dbuf); + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (&pvt->host); +} + +static void +ho_rewind(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_HOSTS, "r"))) + return; + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +ho_res_get(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + ho_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +ho_res_set(struct irs_ho *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +struct lcl_res_target { + struct lcl_res_target *next; + int family; +}; + +/* XXX */ +extern struct addrinfo *hostent2addrinfo __P((struct hostent *, + const struct addrinfo *pai)); + +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + struct lcl_res_target q, q2, *p; + struct addrinfo sentinel, *cur; + + memset(&q, 0, sizeof(q2)); + memset(&q2, 0, sizeof(q2)); + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + switch(pai->ai_family) { + case AF_UNSPEC: /* INET6 then INET4 */ + q.family = AF_INET6; + q.next = &q2; + q2.family = AF_INET; + break; + case AF_INET6: + q.family = AF_INET6; + break; + case AF_INET: + q.family = AF_INET; + break; + default: + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /* ??? */ + return(NULL); + } + + for (p = &q; p; p = p->next) { + struct addrinfo *ai; + + hp = (*this->byname2)(this, name, p->family); + if (hp == NULL) { + /* byname2 should've set an appropriate error */ + continue; + } + if ((hp->h_name == NULL) || (hp->h_name[0] == 0) || + (hp->h_addr_list[0] == NULL)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + continue; + } + + ai = hostent2addrinfo(hp, pai); + if (ai) { + cur->ai_next = ai; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + } + + if (sentinel.ai_next == NULL) + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + + return(sentinel.ai_next); +} + +/* Private. */ + +static size_t +ns_namelen(const char *s) { + int i; + + for (i = strlen(s); i > 0 && s[i-1] == '.'; i--) + (void)NULL; + return ((size_t) i); +} + +static int +init(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !ho_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_ho.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_ng.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_ng.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_ng.c (revision 109985) @@ -0,0 +1,444 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: lcl_ng.c,v 1.17 2001/05/29 05:49:05 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +/* Definitions */ + +#define NG_HOST 0 /* Host name */ +#define NG_USER 1 /* User name */ +#define NG_DOM 2 /* and Domain name */ +#define LINSIZ 1024 /* Length of netgroup file line */ + +/* + * XXX Warning XXX + * This code is a hack-and-slash special. It realy needs to be + * rewritten with things like strdup, and realloc in mind. + * More reasonable data structures would not be a bad thing. + */ + +/* + * Static Variables and functions used by setnetgrent(), getnetgrent() and + * endnetgrent(). + * There are two linked lists: + * - linelist is just used by setnetgrent() to parse the net group file via. + * parse_netgrp() + * - netgrp is the list of entries for the current netgroup + */ +struct linelist { + struct linelist *l_next; /* Chain ptr. */ + int l_parsed; /* Flag for cycles */ + char * l_groupname; /* Name of netgroup */ + char * l_line; /* Netgroup entrie(s) to be parsed */ +}; + +struct ng_old_struct { + struct ng_old_struct *ng_next; /* Chain ptr */ + char * ng_str[3]; /* Field pointers, see below */ +}; + +struct pvt { + FILE *fp; + struct linelist *linehead; + struct ng_old_struct *nextgrp; + struct { + struct ng_old_struct *gr; + char *grname; + } grouphead; +}; + +/* Forward */ + +static void ng_rewind(struct irs_ng *, const char*); +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); +static int ng_test(struct irs_ng *, const char *, + const char *, const char *, + const char *); +static void ng_minimize(struct irs_ng *); + +static int parse_netgrp(struct irs_ng *, const char*); +static struct linelist *read_for_group(struct irs_ng *, const char *); +static void freelists(struct irs_ng *); + +/* Public */ + +struct irs_ng * +irs_lcl_ng(struct irs_acc *this) { + struct irs_ng *ng; + struct pvt *pvt; + + UNUSED(this); + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + if (!(pvt = memget(sizeof *pvt))) { + memput(ng, sizeof *ng); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + ng->private = pvt; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods */ + +static void +ng_close(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) + fclose(pvt->fp); + freelists(this); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +/* + * Parse the netgroup file looking for the netgroup and build the list + * of netgrp structures. Let parse_netgrp() and read_for_group() do + * most of the work. + */ +static void +ng_rewind(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL && fseek(pvt->fp, SEEK_CUR, 0L) == -1) { + fclose(pvt->fp); + pvt->fp = NULL; + } + + if (pvt->fp == NULL || pvt->grouphead.gr == NULL || + strcmp(group, pvt->grouphead.grname)) { + freelists(this); + if (pvt->fp != NULL) + fclose(pvt->fp); + pvt->fp = fopen(_PATH_NETGROUP, "r"); + if (pvt->fp != NULL) { + if (parse_netgrp(this, group)) + freelists(this); + if (!(pvt->grouphead.grname = strdup(group))) + freelists(this); + fclose(pvt->fp); + pvt->fp = NULL; + } + } + pvt->nextgrp = pvt->grouphead.gr; +} + +/* + * Get the next netgroup off the list. + */ +static int +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->nextgrp) { + *host = pvt->nextgrp->ng_str[NG_HOST]; + *user = pvt->nextgrp->ng_str[NG_USER]; + *domain = pvt->nextgrp->ng_str[NG_DOM]; + pvt->nextgrp = pvt->nextgrp->ng_next; + return (1); + } + return (0); +} + +/* + * Search for a match in a netgroup. + */ +static int +ng_test(struct irs_ng *this, const char *name, + const char *host, const char *user, const char *domain) +{ + const char *ng_host, *ng_user, *ng_domain; + + ng_rewind(this, name); + while (ng_next(this, &ng_host, &ng_user, &ng_domain)) + if ((host == NULL || ng_host == NULL || + !strcmp(host, ng_host)) && + (user == NULL || ng_user == NULL || + !strcmp(user, ng_user)) && + (domain == NULL || ng_domain == NULL || + !strcmp(domain, ng_domain))) { + freelists(this); + return (1); + } + freelists(this); + return (0); +} + +static void +ng_minimize(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +/* Private */ + +/* + * endnetgrent() - cleanup + */ +static void +freelists(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct linelist *lp, *olp; + struct ng_old_struct *gp, *ogp; + + lp = pvt->linehead; + while (lp) { + olp = lp; + lp = lp->l_next; + free(olp->l_groupname); + free(olp->l_line); + free((char *)olp); + } + pvt->linehead = NULL; + if (pvt->grouphead.grname) { + free(pvt->grouphead.grname); + pvt->grouphead.grname = NULL; + } + gp = pvt->grouphead.gr; + while (gp) { + ogp = gp; + gp = gp->ng_next; + if (ogp->ng_str[NG_HOST]) + free(ogp->ng_str[NG_HOST]); + if (ogp->ng_str[NG_USER]) + free(ogp->ng_str[NG_USER]); + if (ogp->ng_str[NG_DOM]) + free(ogp->ng_str[NG_DOM]); + free((char *)ogp); + } + pvt->grouphead.gr = NULL; +} + +/* + * Parse the netgroup file setting up the linked lists. + */ +static int +parse_netgrp(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + char *spos, *epos; + int len, strpos; + char *pos, *gpos; + struct ng_old_struct *grp; + struct linelist *lp = pvt->linehead; + + /* + * First, see if the line has already been read in. + */ + while (lp) { + if (!strcmp(group, lp->l_groupname)) + break; + lp = lp->l_next; + } + if (lp == NULL && + (lp = read_for_group(this, group)) == NULL) + return (1); + if (lp->l_parsed) { + /*fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);*/ + return (1); + } else + lp->l_parsed = 1; + pos = lp->l_line; + while (*pos != '\0') { + if (*pos == '(') { + if (!(grp = malloc(sizeof (struct ng_old_struct)))) { + freelists(this); + errno = ENOMEM; + return (1); + } + memset(grp, 0, sizeof (struct ng_old_struct)); + grp->ng_next = pvt->grouphead.gr; + pvt->grouphead.gr = grp; + pos++; + gpos = strsep(&pos, ")"); + for (strpos = 0; strpos < 3; strpos++) { + if ((spos = strsep(&gpos, ","))) { + while (*spos == ' ' || *spos == '\t') + spos++; + if ((epos = strpbrk(spos, " \t"))) { + *epos = '\0'; + len = epos - spos; + } else + len = strlen(spos); + if (len > 0) { + if(!(grp->ng_str[strpos] + = (char *) + malloc(len + 1))) { + freelists(this); + return (1); + } + memcpy(grp->ng_str[strpos], + spos, + len + 1); + } + } else + goto errout; + } + } else { + spos = strsep(&pos, ", \t"); + if (spos != NULL && parse_netgrp(this, spos)) { + freelists(this); + return (1); + } + } + if (pos == NULL) + break; + while (*pos == ' ' || *pos == ',' || *pos == '\t') + pos++; + } + return (0); + errout: + /*fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname, + spos);*/ + return (1); +} + +/* + * Read the netgroup file and save lines until the line for the netgroup + * is found. Return 1 if eof is encountered. + */ +static struct linelist * +read_for_group(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + char *pos, *spos, *linep = NULL, *olinep; + int len, olen, cont; + struct linelist *lp; + char line[LINSIZ + 1]; + + while (fgets(line, LINSIZ, pvt->fp) != NULL) { + pos = line; + if (*pos == '#') + continue; + while (*pos == ' ' || *pos == '\t') + pos++; + spos = pos; + while (*pos != ' ' && *pos != '\t' && *pos != '\n' && + *pos != '\0') + pos++; + len = pos - spos; + while (*pos == ' ' || *pos == '\t') + pos++; + if (*pos != '\n' && *pos != '\0') { + if (!(lp = malloc(sizeof (*lp)))) { + freelists(this); + return (NULL); + } + lp->l_parsed = 0; + if (!(lp->l_groupname = malloc(len + 1))) { + free(lp); + freelists(this); + return (NULL); + } + memcpy(lp->l_groupname, spos, len); + *(lp->l_groupname + len) = '\0'; + len = strlen(pos); + olen = 0; + olinep = NULL; + + /* + * Loop around handling line continuations. + */ + do { + if (*(pos + len - 1) == '\n') + len--; + if (*(pos + len - 1) == '\\') { + len--; + cont = 1; + } else + cont = 0; + if (len > 0) { + if (!(linep = malloc(olen + len + 1))){ + if (olen > 0) + free(olinep); + free(lp->l_groupname); + free(lp); + freelists(this); + errno = ENOMEM; + return (NULL); + } + if (olen > 0) { + memcpy(linep, olinep, olen); + free(olinep); + } + memcpy(linep + olen, pos, len); + olen += len; + *(linep + olen) = '\0'; + olinep = linep; + } + if (cont) { + if (fgets(line, LINSIZ, pvt->fp)) { + pos = line; + len = strlen(pos); + } else + cont = 0; + } + } while (cont); + lp->l_line = linep; + lp->l_next = pvt->linehead; + pvt->linehead = lp; + + /* + * If this is the one we wanted, we are done. + */ + if (!strcmp(lp->l_groupname, group)) + return (lp); + } + } + return (NULL); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_ng.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_nw.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_nw.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_nw.c (revision 109985) @@ -0,0 +1,371 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_nw.c,v 1.22 2001/05/29 05:49:07 marka Exp $"; +/* from getgrent.c 8.2 (Berkeley) 3/21/94"; */ +/* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */ +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include +#include "irs_p.h" +#include "lcl_p.h" + +#define MAXALIASES 35 +#define MAXADDRSIZE 4 + +struct pvt { + FILE * fp; + char line[BUFSIZ+1]; + struct nwent net; + char * aliases[MAXALIASES]; + char addr[MAXADDRSIZE]; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void nw_close(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static struct nwent * nw_next(struct irs_nw *); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); +static struct __res_state * nw_res_get(struct irs_nw *this); +static void nw_res_set(struct irs_nw *this, + struct __res_state *res, + void (*free_res)(void *)); + +static int init(struct irs_nw *this); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public */ + +struct irs_nw * +irs_lcl_nw(struct irs_acc *this) { + struct irs_nw *nw; + struct pvt *pvt; + + UNUSED(this); + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + nw->private = pvt; + nw->close = nw_close; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->next = nw_next; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + nw->res_get = nw_res_get; + nw->res_set = nw_res_set; + return (nw); +} + +/* Methods */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + if (pvt->fp) + (void)fclose(pvt->fp); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int length, int type) { + struct nwent *p; + + if (init(this) == -1) + return(NULL); + + nw_rewind(this); + while ((p = nw_next(this)) != NULL) + if (p->n_addrtype == type && p->n_length == length) + if (bitncmp(p->n_addr, net, length) == 0) + break; + return (p); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int type) { + struct nwent *p; + char **ap; + + if (init(this) == -1) + return(NULL); + + nw_rewind(this); + while ((p = nw_next(this)) != NULL) { + if (ns_samename(p->n_name, name) == 1 && + p->n_addrtype == type) + break; + for (ap = p->n_aliases; *ap; ap++) + if ((ns_samename(*ap, name) == 1) && + (p->n_addrtype == type)) + goto found; + } + found: + return (p); +} + +static void +nw_rewind(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_NETWORKS, "r"))) + return; + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static struct nwent * +nw_next(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *ret = NULL; + char *p, *cp, **q; + char *bufp, *ndbuf, *dbuf = NULL; + int c, bufsiz, offset = 0; + + if (init(this) == -1) + return(NULL); + + if (pvt->fp == NULL) + nw_rewind(this); + if (pvt->fp == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + bufp = pvt->line; + bufsiz = sizeof(pvt->line); + + again: + p = fgets(bufp + offset, bufsiz - offset, pvt->fp); + if (p == NULL) + goto cleanup; + if (!strchr(p, '\n') && !feof(pvt->fp)) { +#define GROWBUF 1024 + /* allocate space for longer line */ + if (dbuf == NULL) { + if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL) + strcpy(ndbuf, bufp); + } else + ndbuf = realloc(dbuf, bufsiz + GROWBUF); + if (ndbuf) { + dbuf = ndbuf; + bufp = dbuf; + bufsiz += GROWBUF; + offset = strlen(dbuf); + } else { + /* allocation failed; skip this long line */ + while ((c = getc(pvt->fp)) != EOF) + if (c == '\n') + break; + if (c != EOF) + ungetc(c, pvt->fp); + } + goto again; + } + + p -= offset; + offset = 0; + + if (*p == '#') + goto again; + + cp = strpbrk(p, "#\n"); + if (cp != NULL) + *cp = '\0'; + pvt->net.n_name = p; + cp = strpbrk(p, " \t"); + if (cp == NULL) + goto again; + *cp++ = '\0'; + while (*cp == ' ' || *cp == '\t') + cp++; + p = strpbrk(cp, " \t"); + if (p != NULL) + *p++ = '\0'; + pvt->net.n_length = inet_net_pton(AF_INET, cp, pvt->addr, + sizeof pvt->addr); + if (pvt->net.n_length < 0) + goto again; + pvt->net.n_addrtype = AF_INET; + pvt->net.n_addr = pvt->addr; + q = pvt->net.n_aliases = pvt->aliases; + if (p != NULL) { + cp = p; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->aliases[MAXALIASES - 1]) + *q++ = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + } + *q = NULL; + ret = &pvt->net; + + cleanup: + if (dbuf) + free(dbuf); + + return (ret); +} + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static struct __res_state * +nw_res_get(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + nw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +nw_res_set(struct irs_nw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +static int +init(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !nw_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_nw.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_pw.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_pw.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_pw.c (revision 109985) @@ -0,0 +1,308 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_pw.c,v 1.20 2001/05/29 05:49:08 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Extern */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_pw_unneeded; +#else + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +/* + * The lookup techniques and data extraction code here must be kept + * in sync with that in `pwd_mkdb'. + */ + + +/* Types */ + +struct pvt { + struct passwd passwd; /* password structure */ + DB *pw_db; /* password database */ + int pw_keynum; /* key counter */ + int warned; + u_int max; + char * line; +}; + +/* Forward */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_next(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); + +static int initdb(struct pvt *); +static int hashpw(struct irs_pw *, DBT *); + +/* Public */ +struct irs_pw * +irs_lcl_pw(struct irs_acc *this) { + struct irs_pw *pw; + struct pvt *pvt; + + UNUSED(this); + + if (!(pw = memget(sizeof *pw))) { + errno = ENOMEM; + return (NULL); + } + memset(pw, 0x5e, sizeof *pw); + if (!(pvt = memget(sizeof *pvt))) { + free(pw); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pw->private = pvt; + pw->close = pw_close; + pw->next = pw_next; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + pw->res_get = NULL; + pw->res_set = NULL; + return (pw); +} + +/* Methods */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->pw_db) { + (void)(pvt->pw_db->close)(pvt->pw_db); + pvt->pw_db = NULL; + } + if (pvt->line) + memput(pvt->line, pvt->max); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct passwd * +pw_next(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + DBT key; + char bf[sizeof(pvt->pw_keynum) + 1]; + + if (!initdb(pvt)) + return (NULL); + + ++pvt->pw_keynum; + bf[0] = _PW_KEYBYNUM; + memcpy(bf + 1, (char *)&pvt->pw_keynum, sizeof(pvt->pw_keynum)); + key.data = (u_char *)bf; + key.size = sizeof(pvt->pw_keynum) + 1; + return (hashpw(this, &key) ? &pvt->passwd : NULL); +} + +static struct passwd * +pw_byname(struct irs_pw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + DBT key; + int len, rval; + char bf[UT_NAMESIZE + 1]; + + if (!initdb(pvt)) + return (NULL); + + bf[0] = _PW_KEYBYNAME; + len = strlen(name); + memcpy(bf + 1, name, MIN(len, UT_NAMESIZE)); + key.data = (u_char *)bf; + key.size = len + 1; + rval = hashpw(this, &key); + + return (rval ? &pvt->passwd : NULL); +} + + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + struct pvt *pvt = (struct pvt *)this->private; + DBT key; + int keyuid, rval; + char bf[sizeof(keyuid) + 1]; + + if (!initdb(pvt)) + return (NULL); + + bf[0] = _PW_KEYBYUID; + keyuid = uid; + memcpy(bf + 1, &keyuid, sizeof(keyuid)); + key.data = (u_char *)bf; + key.size = sizeof(keyuid) + 1; + rval = hashpw(this, &key); + + return (rval ? &pvt->passwd : NULL); +} + +static void +pw_rewind(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->pw_keynum = 0; +} + +static void +pw_minimize(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->pw_db != NULL) { + (void) (*pvt->pw_db->close)(pvt->pw_db); + pvt->pw_db = NULL; + } +} + +/* Private. */ + +static int +initdb(struct pvt *pvt) { + const char *p; + + if (pvt->pw_db) { + if (lseek((*pvt->pw_db->fd)(pvt->pw_db), 0L, SEEK_CUR) >= 0L) + return (1); + else + (void) (*pvt->pw_db->close)(pvt->pw_db); + } + pvt->pw_db = dbopen((p = _PATH_SMP_DB), O_RDONLY, 0, DB_HASH, NULL); + if (!pvt->pw_db) + pvt->pw_db = dbopen((p =_PATH_MP_DB), O_RDONLY, + 0, DB_HASH, NULL); + if (pvt->pw_db) + return (1); + if (!pvt->warned) { + syslog(LOG_ERR, "%s: %m", p); + pvt->warned++; + } + return (0); +} + +static int +hashpw(struct irs_pw *this, DBT *key) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *t, *l; + DBT data; + + if ((pvt->pw_db->get)(pvt->pw_db, key, &data, 0)) + return (0); + p = (char *)data.data; + if (data.size > pvt->max) { + size_t newlen = pvt->max + 1024; + char *p = memget(newlen); + if (p == NULL) { + return (0); + } + if (pvt->line != NULL) { + memcpy(p, pvt->line, pvt->max); + memput(pvt->line, pvt->max); + } + pvt->max = newlen; + pvt->line = p; + } + + /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */ + t = pvt->line; + l = pvt->line + pvt->max; +#define EXPAND(e) if ((e = t) == NULL) return (0); else \ + do if (t >= l) return (0); while ((*t++ = *p++) != '\0') +#define SCALAR(v) if (t + sizeof v >= l) return (0); else \ + (memmove(&(v), p, sizeof v), p += sizeof v) + EXPAND(pvt->passwd.pw_name); + EXPAND(pvt->passwd.pw_passwd); + SCALAR(pvt->passwd.pw_uid); + SCALAR(pvt->passwd.pw_gid); + SCALAR(pvt->passwd.pw_change); + EXPAND(pvt->passwd.pw_class); + EXPAND(pvt->passwd.pw_gecos); + EXPAND(pvt->passwd.pw_dir); + EXPAND(pvt->passwd.pw_shell); + SCALAR(pvt->passwd.pw_expire); + return (1); +} + +#endif /* WANT_IRS_PW */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_pw.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_sv.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_sv.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_sv.c (revision 109985) @@ -0,0 +1,431 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_sv.c,v 1.22 2001/06/18 14:43:59 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#include +#include +#include +#include +#include + +#ifdef IRS_LCL_SV_DB +#include +#endif +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Types */ + +struct pvt { +#ifdef IRS_LCL_SV_DB + DB * dbh; + int dbf; +#endif + struct lcl_sv sv; +}; + +/* Forward */ + +static void sv_close(struct irs_sv*); +static struct servent * sv_next(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, const char *, + const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); +/*global*/ struct servent * irs_lclsv_fnxt(struct lcl_sv *); +#ifdef IRS_LCL_SV_DB +static struct servent * sv_db_rec(struct lcl_sv *, DBT *, DBT *); +#endif + +/* Portability */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public */ + +struct irs_sv * +irs_lcl_sv(struct irs_acc *this) { + struct irs_sv *sv; + struct pvt *pvt; + + UNUSED(this); + + if ((sv = memget(sizeof *sv)) == NULL) { + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + if ((pvt = memget(sizeof *pvt)) == NULL) { + memput(sv, sizeof *sv); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + sv->private = pvt; + sv->close = sv_close; + sv->next = sv_next; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->rewind = sv_rewind; + sv->minimize = sv_minimize; + sv->res_get = NULL; + sv->res_set = NULL; +#ifdef IRS_LCL_SV_DB + pvt->dbf = R_FIRST; +#endif + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) + (*pvt->dbh->close)(pvt->dbh); +#endif + if (pvt->sv.fp) + fclose(pvt->sv.fp); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { +#ifdef IRS_LCL_SV_DB + struct pvt *pvt = (struct pvt *)this->private; +#endif + struct servent *p; + char **cp; + + sv_rewind(this); +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) { + DBT key, data; + + /* Note that (sizeof "/") == 2. */ + if ((strlen(name) + sizeof "/" + proto ? strlen(proto) : 0) + > sizeof pvt->sv.line) + goto try_local; + key.data = pvt->sv.line; + key.size = SPRINTF((pvt->sv.line, "%s/%s", name, + proto ? proto : "")) + 1; + if (proto != NULL) { + if ((*pvt->dbh->get)(pvt->dbh, &key, &data, 0) != 0) + return (NULL); + } else if ((*pvt->dbh->seq)(pvt->dbh, &key, &data, R_CURSOR) + != 0) + return (NULL); + return (sv_db_rec(&pvt->sv, &key, &data)); + } + try_local: +#endif + + while ((p = sv_next(this))) { + if (strcmp(name, p->s_name) == 0) + goto gotname; + for (cp = p->s_aliases; *cp; cp++) + if (strcmp(name, *cp) == 0) + goto gotname; + continue; + gotname: + if (proto == NULL || strcmp(p->s_proto, proto) == 0) + break; + } + return (p); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { +#ifdef IRS_LCL_SV_DB + struct pvt *pvt = (struct pvt *)this->private; +#endif + struct servent *p; + + sv_rewind(this); +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) { + DBT key, data; + u_short *ports; + + ports = (u_short *)pvt->sv.line; + ports[0] = 0; + ports[1] = port; + key.data = ports; + key.size = sizeof(u_short) * 2; + if (proto && *proto) { + strncpy((char *)ports + key.size, proto, + BUFSIZ - key.size); + key.size += strlen((char *)ports + key.size) + 1; + if ((*pvt->dbh->get)(pvt->dbh, &key, &data, 0) != 0) + return (NULL); + } else { + if ((*pvt->dbh->seq)(pvt->dbh, &key, &data, R_CURSOR) + != 0) + return (NULL); + } + return (sv_db_rec(&pvt->sv, &key, &data)); + } +#endif + while ((p = sv_next(this))) { + if (p->s_port != port) + continue; + if (proto == NULL || strcmp(p->s_proto, proto) == 0) + break; + } + return (p); +} + +static void +sv_rewind(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->sv.fp) { + if (fseek(pvt->sv.fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->sv.fp); + pvt->sv.fp = NULL; + } +#ifdef IRS_LCL_SV_DB + pvt->dbf = R_FIRST; + if (pvt->dbh != NULL) + return; + pvt->dbh = dbopen(_PATH_SERVICES_DB, O_RDONLY,O_RDONLY,DB_BTREE, NULL); + if (pvt->dbh != NULL) { + if (fcntl((*pvt->dbh->fd)(pvt->dbh), F_SETFD, 1) < 0) { + (*pvt->dbh->close)(pvt->dbh); + pvt->dbh = NULL; + } + return; + } +#endif + if ((pvt->sv.fp = fopen(_PATH_SERVICES, "r")) == NULL) + return; + if (fcntl(fileno(pvt->sv.fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->sv.fp); + pvt->sv.fp = NULL; + } +} + +static struct servent * +sv_next(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + +#ifdef IRS_LCL_SV_DB + if (pvt->dbh == NULL && pvt->sv.fp == NULL) +#else + if (pvt->sv.fp == NULL) +#endif + sv_rewind(this); + +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) { + DBT key, data; + + while ((*pvt->dbh->seq)(pvt->dbh, &key, &data, pvt->dbf) == 0){ + pvt->dbf = R_NEXT; + if (((char *)key.data)[0]) + continue; + return (sv_db_rec(&pvt->sv, &key, &data)); + } + } +#endif + + if (pvt->sv.fp == NULL) + return (NULL); + return (irs_lclsv_fnxt(&pvt->sv)); +} + +static void +sv_minimize(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) { + (*pvt->dbh->close)(pvt->dbh); + pvt->dbh = NULL; + } +#endif + if (pvt->sv.fp != NULL) { + (void)fclose(pvt->sv.fp); + pvt->sv.fp = NULL; + } +} + +/* Quasipublic. */ + +struct servent * +irs_lclsv_fnxt(struct lcl_sv *sv) { + char *p, *cp, **q; + + again: + if ((p = fgets(sv->line, BUFSIZ, sv->fp)) == NULL) + return (NULL); + if (*p == '#') + goto again; + sv->serv.s_name = p; + while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#') + ++p; + if (*p == '\0' || *p == '#' || *p == '\n') + goto again; + *p++ = '\0'; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '\0' || *p == '#' || *p == '\n') + goto again; + sv->serv.s_port = htons((u_short)strtol(p, &cp, 10)); + if (cp == p || (*cp != '/' && *cp != ',')) + goto again; + p = cp + 1; + sv->serv.s_proto = p; + + q = sv->serv.s_aliases = sv->serv_aliases; + + while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#') + ++p; + + while (*p == ' ' || *p == '\t') { + *p++ = '\0'; + while (*p == ' ' || *p == '\t') + ++p; + if (*p == '\0' || *p == '#' || *p == '\n') + break; + if (q < &sv->serv_aliases[IRS_SV_MAXALIASES - 1]) + *q++ = p; + while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#') + ++p; + } + + *p = '\0'; + *q = NULL; + return (&sv->serv); +} + +/* Private. */ + +#ifdef IRS_LCL_SV_DB +static struct servent * +sv_db_rec(struct lcl_sv *sv, DBT *key, DBT *data) { + char *p, **q; + int n; + + p = data->data; + p[data->size - 1] = '\0'; /* should be, but we depend on it */ + + if (((char *)key->data)[0] == '\0') { + if (key->size < sizeof(u_short)*2 || data->size < 2) + return (NULL); + sv->serv.s_port = ((u_short *)key->data)[1]; + n = strlen(p) + 1; + if ((size_t)n > sizeof(sv->line)) { + n = sizeof(sv->line); + } + memcpy(sv->line, p, n); + sv->serv.s_name = sv->line; + if ((sv->serv.s_proto = strchr(sv->line, '/')) != NULL) + *(sv->serv.s_proto)++ = '\0'; + p += n; + data->size -= n; + } else { + if (data->size < sizeof(u_short) + 1) + return (NULL); + if (key->size > sizeof(sv->line)) + key->size = sizeof(sv->line); + ((char *)key->data)[key->size - 1] = '\0'; + memcpy(sv->line, key->data, key->size); + sv->serv.s_name = sv->line; + if ((sv->serv.s_proto = strchr(sv->line, '/')) != NULL) + *(sv->serv.s_proto)++ = '\0'; + sv->serv.s_port = *(u_short *)data->data; + p += sizeof(u_short); + data->size -= sizeof(u_short); + } + q = sv->serv.s_aliases = sv->serv_aliases; + while (data->size > 0 && q < &sv->serv_aliases[IRS_SV_MAXALIASES - 1]) { + + *q++ = p; + n = strlen(p) + 1; + data->size -= n; + p += n; + } + *q = NULL; + return (&sv->serv); +} +#endif Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_sv.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/nis.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/nis.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/nis.c (revision 109985) @@ -0,0 +1,151 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis.c,v 1.15 2001/05/29 05:49:11 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifdef WANT_IRS_NIS + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "nis_p.h" + +/* Forward */ + +static void nis_close(struct irs_acc *); +static struct __res_state * nis_res_get(struct irs_acc *); +static void nis_res_set(struct irs_acc *, struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_acc * +irs_nis_acc(const char *options) { + struct nis_p *nis; + struct irs_acc *acc; + char *domain; + + UNUSED(options); + + if (yp_get_default_domain(&domain) != 0) + return (NULL); + if (!(nis = memget(sizeof *nis))) { + errno = ENOMEM; + return (NULL); + } + memset(nis, 0, sizeof *nis); + if (!(acc = memget(sizeof *acc))) { + memput(nis, sizeof *nis); + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + acc->private = nis; + nis->domain = strdup(domain); +#ifdef WANT_IRS_GR + acc->gr_map = irs_nis_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_nis_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_nis_sv; + acc->pr_map = irs_nis_pr; + acc->ho_map = irs_nis_ho; + acc->nw_map = irs_nis_nw; + acc->ng_map = irs_nis_ng; + acc->res_get = nis_res_get; + acc->res_set = nis_res_set; + acc->close = nis_close; + return (acc); +} + +/* Methods */ + +static struct __res_state * +nis_res_get(struct irs_acc *this) { + struct nis_p *nis = (struct nis_p *)this->private; + + if (nis->res == NULL) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) + return (NULL); + memset(res, 0, sizeof *res); + nis_res_set(this, res, free); + } + + if ((nis->res->options & RES_INIT) == 0 && + res_ninit(nis->res) < 0) + return (NULL); + + return (nis->res); +} + +static void +nis_res_set(struct irs_acc *this, struct __res_state *res, + void (*free_res)(void *)) { + struct nis_p *nis = (struct nis_p *)this->private; + + if (nis->res && nis->free_res) { + res_nclose(nis->res); + (*nis->free_res)(nis->res); + } + + nis->res = res; + nis->free_res = free_res; +} + +static void +nis_close(struct irs_acc *this) { + struct nis_p *nis = (struct nis_p *)this->private; + + if (nis->res && nis->free_res) + (*nis->free_res)(nis->res); + free(nis->domain); + memput(nis, sizeof *nis); + memput(this, sizeof *this); +} + +#endif /*WANT_IRS_NIS*/ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/nis.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/nis_gr.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/nis_gr.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/nis_gr.c (revision 109985) @@ -0,0 +1,353 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_gr.c,v 1.21 2001/05/29 05:49:12 marka Exp $"; +/* from getgrent.c 8.2 (Berkeley) 3/21/94"; */ +/* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */ +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#if !defined(WANT_IRS_GR) || !defined(WANT_IRS_NIS) +static int __bind_irs_gr_unneeded; +#else + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + /* + * Need space to store the entries read from the group file. + * The members list also needs space per member, and the + * strings making up the user names must be allocated + * somewhere. Rather than doing lots of small allocations, + * we keep one buffer and resize it as needed. + */ + struct group group; + size_t nmemb; /* Malloc'd max index of gr_mem[]. */ + char * membuf; + size_t membufsize; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char group_bygid[] = "group.bygid"; +static /*const*/ char group_byname[] = "group.byname"; + +/* Forward */ + +static void gr_close(struct irs_gr *); +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static void gr_minimize(struct irs_gr *); + +static struct group * makegroupent(struct irs_gr *); +static void nisfree(struct pvt *, enum do_what); + +/* Public */ + +struct irs_gr * +irs_nis_gr(struct irs_acc *this) { + struct irs_gr *gr; + struct pvt *pvt; + + if (!(gr = memget(sizeof *gr))) { + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x5e, sizeof *gr); + if (!(pvt = memget(sizeof *pvt))) { + memput(gr, sizeof *gr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + gr->private = pvt; + gr->close = gr_close; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->list = make_group_list; + gr->minimize = gr_minimize; + gr->res_get = NULL; + gr->res_set = NULL; + return (gr); +} + +/* Methods */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->group.gr_mem) + free(pvt->group.gr_mem); + if (pvt->membuf) + free(pvt->membuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct group * +gr_next(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct group *rval; + int r; + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, group_byname, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, group_byname, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + errno = ENOENT; + return (NULL); + } + rval = makegroupent(this); + } while (rval == NULL); + return (rval); +} + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, group_byname, name, strlen(name), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makegroupent(this)); +} + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "4294967295"]; + int r; + + nisfree(pvt, do_val); + (void) sprintf(tmp, "%u", (unsigned int)gid); + r = yp_match(pvt->nis_domain, group_bygid, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makegroupent(this)); +} + +static void +gr_rewind(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static void +gr_minimize(struct irs_gr *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static struct group * +makegroupent(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + unsigned int num_members = 0; + char *cp, **new; + u_long t; + + if (pvt->group.gr_mem) { + free(pvt->group.gr_mem); + pvt->group.gr_mem = NULL; + pvt->nmemb = 0; + } + if (pvt->membuf) + free(pvt->membuf); + pvt->membuf = pvt->curval_data; + pvt->curval_data = NULL; + + cp = pvt->membuf; + pvt->group.gr_name = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->group.gr_passwd = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + errno = -1; + t = strtoul(cp, NULL, 10); + if (errno == ERANGE) + goto cleanup; + pvt->group.gr_gid = (gid_t) t; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + cp++; + + if (*cp && cp[strlen(cp)-1] == '\n') + cp[strlen(cp)-1] = '\0'; + + /* + * Parse the members out. + */ + while (*cp) { + if (num_members+1 >= pvt->nmemb || pvt->group.gr_mem == NULL) { + pvt->nmemb += 10; + new = realloc(pvt->group.gr_mem, + pvt->nmemb * sizeof(char *)); + if (new == NULL) + goto cleanup; + pvt->group.gr_mem = new; + } + pvt->group.gr_mem[num_members++] = cp; + if (!(cp = strchr(cp, ','))) + break; + *cp++ = '\0'; + } + if (pvt->group.gr_mem == NULL) { + pvt->group.gr_mem = malloc(sizeof(char*)); + if (!pvt->group.gr_mem) + goto cleanup; + pvt->nmemb = 1; + } + pvt->group.gr_mem[num_members] = NULL; + + return (&pvt->group); + + cleanup: + if (pvt->group.gr_mem) { + free(pvt->group.gr_mem); + pvt->group.gr_mem = NULL; + pvt->nmemb = 0; + } + if (pvt->membuf) { + free(pvt->membuf); + pvt->membuf = NULL; + } + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +#endif /* WANT_IRS_GR && WANT_IRS_NIS */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/nis_gr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/nis_ho.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/nis_ho.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/nis_ho.c (revision 109985) @@ -0,0 +1,463 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_ho.c,v 1.18 2001/06/18 14:44:00 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +#define MAXALIASES 35 +#define MAXADDRS 35 + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + struct hostent host; + char * h_addr_ptrs[MAXADDRS + 1]; + char * host_aliases[MAXALIASES + 1]; + char hostbuf[8*1024]; + u_char host_addr[16]; /* IPv4 or IPv6 */ + struct __res_state *res; + void (*free_res)(void *); +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; +static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; +static /*const*/ char hosts_byname[] = "hosts.byname"; +static /*const*/ char hosts_byaddr[] = "hosts.byaddr"; + +/* Forwards */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); +static struct __res_state * ho_res_get(struct irs_ho *this); +static void ho_res_set(struct irs_ho *this, + struct __res_state *res, + void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +static struct hostent * makehostent(struct irs_ho *this); +static void nisfree(struct pvt *, enum do_what); +static int init(struct irs_ho *this); + +/* Public */ + +struct irs_ho * +irs_nis_ho(struct irs_acc *this) { + struct irs_ho *ho; + struct pvt *pvt; + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(ho = memget(sizeof *ho))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->res_set = ho_res_set; + ho->res_get = ho_res_get; + ho->addrinfo = ho_addrinfo; + return (ho); +} + +/* Methods */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + nisfree(pvt, do_all); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + + if (init(this) == -1) + return (NULL); + + if (pvt->res->options & RES_USE_INET6) { + hp = ho_byname2(this, name, AF_INET6); + if (hp) + return (hp); + } + return (ho_byname2(this, name, AF_INET)); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + char *tmp; + + UNUSED(af); + + if (init(this) == -1) + return (NULL); + + nisfree(pvt, do_val); + DE_CONST(name, tmp); + r = yp_match(pvt->nis_domain, hosts_byname, tmp, + strlen(tmp), &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + return (makehostent(this)); +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; + const u_char *uaddr = addr; + int r; + + if (init(this) == -1) + return (NULL); + + if (af == AF_INET6 && len == IN6ADDRSZ && + (!memcmp(uaddr, mapped, sizeof mapped) || + !memcmp(uaddr, tunnelled, sizeof tunnelled))) { + /* Unmap. */ + addr = (const u_char *)addr + sizeof mapped; + uaddr += sizeof mapped; + af = AF_INET; + len = INADDRSZ; + } + if (inet_ntop(af, uaddr, tmp, sizeof tmp) == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, hosts_byaddr, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + return (makehostent(this)); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *rval; + int r; + + if (init(this) == -1) + return (NULL); + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, hosts_byaddr, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, hosts_byaddr, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + rval = makehostent(this); + } while (rval == NULL); + return (rval); +} + +static void +ho_rewind(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +ho_res_get(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + ho_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +ho_res_set(struct irs_ho *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +struct nis_res_target { + struct nis_res_target *next; + int family; +}; + +/* XXX */ +extern struct addrinfo *hostent2addrinfo __P((struct hostent *, + const struct addrinfo *pai)); + +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + struct nis_res_target q, q2, *p; + struct addrinfo sentinel, *cur; + + memset(&q, 0, sizeof(q2)); + memset(&q2, 0, sizeof(q2)); + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + switch(pai->ai_family) { + case AF_UNSPEC: /* INET6 then INET4 */ + q.family = AF_INET6; + q.next = &q2; + q2.family = AF_INET; + break; + case AF_INET6: + q.family = AF_INET6; + break; + case AF_INET: + q.family = AF_INET; + break; + default: + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /* ??? */ + return(NULL); + } + + for (p = &q; p; p = p->next) { + struct addrinfo *ai; + + hp = (*this->byname2)(this, name, p->family); + if (hp == NULL) { + /* byname2 should've set an appropriate error */ + continue; + } + if ((hp->h_name == NULL) || (hp->h_name[0] == 0) || + (hp->h_addr_list[0] == NULL)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + continue; + } + ai = hostent2addrinfo(hp, pai); + if (ai) { + cur->ai_next = ai; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + } + + if (sentinel.ai_next == NULL) + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + + return(sentinel.ai_next); +} + +/* Private */ + +static struct hostent * +makehostent(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + static const char spaces[] = " \t"; + char *cp, **q, *p; + int af, len; + + p = pvt->curval_data; + if ((cp = strpbrk(p, "#\n")) != NULL) + *cp = '\0'; + if (!(cp = strpbrk(p, spaces))) + return (NULL); + *cp++ = '\0'; + if ((pvt->res->options & RES_USE_INET6) && + inet_pton(AF_INET6, p, pvt->host_addr) > 0) { + af = AF_INET6; + len = IN6ADDRSZ; + } else if (inet_pton(AF_INET, p, pvt->host_addr) > 0) { + if (pvt->res->options & RES_USE_INET6) { + map_v4v6_address((char*)pvt->host_addr, + (char*)pvt->host_addr); + af = AF_INET6; + len = IN6ADDRSZ; + } else { + af = AF_INET; + len = INADDRSZ; + } + } else { + return (NULL); + } + pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; + pvt->h_addr_ptrs[1] = NULL; + pvt->host.h_addr_list = pvt->h_addr_ptrs; + pvt->host.h_length = len; + pvt->host.h_addrtype = af; + cp += strspn(cp, spaces); + pvt->host.h_name = cp; + q = pvt->host.h_aliases = pvt->host_aliases; + if ((cp = strpbrk(cp, spaces)) != NULL) + *cp++ = '\0'; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->host_aliases[MAXALIASES]) + *q++ = cp; + if ((cp = strpbrk(cp, spaces)) != NULL) + *cp++ = '\0'; + } + *q = NULL; + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (&pvt->host); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +static int +init(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !ho_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} +#endif /*WANT_IRS_NIS*/ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/nis_ho.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/nis_ng.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/nis_ng.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/nis_ng.c (revision 109985) @@ -0,0 +1,299 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_ng.c,v 1.17 2001/05/29 05:49:14 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct tmpgrp { + const char * name; + const char * host; + const char * user; + const char * domain; + struct tmpgrp * next; +}; + +struct pvt { + char * nis_domain; + struct tmpgrp * tmp; + struct tmpgrp * cur; + char * tmpgroup; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char netgroup_map[] = "netgroup"; + +/* Forward */ + +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); +static int ng_test(struct irs_ng *, + const char *, const char *, + const char *, const char *); +static void ng_rewind(struct irs_ng *, const char *); +static void ng_minimize(struct irs_ng *); + +static void add_group_to_list(struct pvt *, const char *, int); +static void add_tuple_to_list(struct pvt *, const char *, char *); +static void tmpfree(struct pvt *); + +/* Public */ + +struct irs_ng * +irs_nis_ng(struct irs_acc *this) { + struct irs_ng *ng; + struct pvt *pvt; + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + if (!(pvt = memget(sizeof *pvt))) { + memput(ng, sizeof *ng); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + ng->private = pvt; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods */ + +static void +ng_close(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + tmpfree(pvt); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static int +ng_next(struct irs_ng *this, const char **host, const char **user, const char **domain) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->cur) + return (0); + *host = pvt->cur->host; + *user = pvt->cur->user; + *domain = pvt->cur->domain; + pvt->cur = pvt->cur->next; + return (1); +} + +static int +ng_test(struct irs_ng *this, const char *name, + const char *host, const char *user, const char *domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct tmpgrp *cur; + + tmpfree(pvt); + add_group_to_list(pvt, name, strlen(name)); + for (cur = pvt->tmp; cur; cur = cur->next) { + if ((!host || !cur->host || !strcmp(host, cur->host)) && + (!user || !cur->user || !strcmp(user, cur->user)) && + (!domain || !cur->domain || !strcmp(domain, cur->domain))) + break; + } + tmpfree(pvt); + return ((cur == NULL) ? 0 : 1); +} + +static void +ng_rewind(struct irs_ng *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + + /* Either hand back or free the existing list. */ + if (pvt->tmpgroup) { + if (pvt->tmp && !strcmp(pvt->tmpgroup, name)) + goto reset; + tmpfree(pvt); + } + pvt->tmpgroup = strdup(name); + add_group_to_list(pvt, name, strlen(name)); + reset: + pvt->cur = pvt->tmp; +} + +static void +ng_minimize(struct irs_ng *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static void +add_group_to_list(struct pvt *pvt, const char *name, int len) { + char *vdata, *cp, *np; + struct tmpgrp *tmp; + int vlen, r; + char *nametmp; + + /* Don't add the same group to the list more than once. */ + for (tmp = pvt->tmp; tmp; tmp = tmp->next) + if (!strcmp(tmp->name, name)) + return; + + DE_CONST(name, nametmp); + r = yp_match(pvt->nis_domain, netgroup_map, nametmp, len, + &vdata, &vlen); + if (r == 0) { + cp = vdata; + if (*cp && cp[strlen(cp)-1] == '\n') + cp[strlen(cp)-1] = '\0'; + for ( ; cp; cp = np) { + np = strchr(cp, ' '); + if (np) + *np++ = '\0'; + if (*cp == '(') + add_tuple_to_list(pvt, name, cp); + else + add_group_to_list(pvt, cp, strlen(cp)); + } + free(vdata); + } +} + +static void +add_tuple_to_list(struct pvt *pvt, const char *name, char *cp) { + struct tmpgrp *tmp; + char *tp, *np; + + INSIST(*cp++ == '('); + + tmp = malloc(sizeof *tmp + strlen(name) + sizeof '\0' + + strlen(cp) - sizeof ')'); + if (!tmp) + return; + memset(tmp, 0, sizeof *tmp); + tp = ((char *)tmp) + sizeof *tmp; + + /* Name */ + strcpy(tp, name); + tmp->name = tp; + tp += strlen(tp) + 1; + + /* Host */ + if (!(np = strchr(cp, ','))) + goto cleanup; + *np++ = '\0'; + strcpy(tp, cp); + tmp->host = tp; + tp += strlen(tp) + 1; + cp = np; + + /* User */ + if (!(np = strchr(cp, ','))) + goto cleanup; + *np++ = '\0'; + strcpy(tp, cp); + tmp->user = tp; + tp += strlen(tp) + 1; + cp = np; + + /* Domain */ + if (!(np = strchr(cp, ')'))) + goto cleanup; + *np++ = '\0'; + strcpy(tp, cp); + tmp->domain = tp; + + /* + * Empty string in file means wildcard, but + * NULL string in return value means wildcard. + */ + if (!*tmp->host) + tmp->host = NULL; + if (!*tmp->user) + tmp->user = NULL; + if (!*tmp->domain) + tmp->domain = NULL; + + /* Add to list (LIFO). */ + tmp->next = pvt->tmp; + pvt->tmp = tmp; + return; + + cleanup: + free(tmp); +} + +static void +tmpfree(struct pvt *pvt) { + struct tmpgrp *cur, *next; + + if (pvt->tmpgroup) { + free(pvt->tmpgroup); + pvt->tmpgroup = NULL; + } + for (cur = pvt->tmp; cur; cur = next) { + next = cur->next; + free(cur); + } + pvt->tmp = NULL; +} + +#endif /*WANT_IRS_NIS*/ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/nis_ng.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/nis_nw.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/nis_nw.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/nis_nw.c (revision 109985) @@ -0,0 +1,381 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_nw.c,v 1.16 2001/05/29 05:49:15 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +#define MAXALIASES 35 +#define MAXADDRSIZE 4 + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + + struct nwent nwent; + char * nwbuf; + + char * aliases[MAXALIASES + 1]; + u_char addr[MAXADDRSIZE]; + + struct __res_state * res; + void (*free_res)(void *); +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char networks_byname[] = "networks.byname"; +static /*const*/ char networks_byaddr[] = "networks.byaddr"; + +/* Forward */ + +static void nw_close(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static struct nwent * nw_next(struct irs_nw *); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); +static struct __res_state * nw_res_get(struct irs_nw *this); +static void nw_res_set(struct irs_nw *this, + struct __res_state *res, + void (*free_res)(void *)); + +static struct nwent * makenwent(struct irs_nw *this); +static void nisfree(struct pvt *, enum do_what); +static int init(struct irs_nw *this); + +/* Public */ + +struct irs_nw * +irs_nis_nw(struct irs_acc *this) { + struct irs_nw *nw; + struct pvt *pvt; + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + nw->private = pvt; + nw->close = nw_close; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->next = nw_next; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + nw->res_get = nw_res_get; + nw->res_set = nw_res_set; + return (nw); +} + +/* Methods */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + if (pvt->nwbuf) + free(pvt->nwbuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int length, int af) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "255.255.255.255/32"], *t; + int r; + + if (init(this) == -1) + return (NULL); + + if (af != AF_INET) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + return (NULL); + } + nisfree(pvt, do_val); + /* Try it with /CIDR first. */ + if (inet_net_ntop(AF_INET, net, length, tmp, sizeof tmp) == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + r = yp_match(pvt->nis_domain, networks_byaddr, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + /* Give it a shot without the /CIDR. */ + if ((t = strchr(tmp, '/')) != NULL) { + *t = '\0'; + r = yp_match(pvt->nis_domain, networks_byaddr, + tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + } + if (r != 0) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + } + return (makenwent(this)); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + char *tmp; + + if (init(this) == -1) + return (NULL); + + if (af != AF_INET) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + return (NULL); + } + nisfree(pvt, do_val); + DE_CONST(name, tmp); + r = yp_match(pvt->nis_domain, networks_byname, tmp, + strlen(tmp), &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + return (makenwent(this)); +} + +static void +nw_rewind(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static struct nwent * +nw_next(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *rval; + int r; + + if (init(this) == -1) + return (NULL); + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, networks_byaddr, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, networks_byaddr, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + rval = makenwent(this); + } while (rval == NULL); + return (rval); +} + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +nw_res_get(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + nw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +nw_res_set(struct irs_nw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +/* Private */ + +static struct nwent * +makenwent(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + static const char spaces[] = " \t"; + char *t, *cp, **ap; + + if (pvt->nwbuf) + free(pvt->nwbuf); + pvt->nwbuf = pvt->curval_data; + pvt->curval_data = NULL; + + if ((cp = strpbrk(pvt->nwbuf, "#\n")) != NULL) + *cp = '\0'; + cp = pvt->nwbuf; + + /* Name */ + pvt->nwent.n_name = cp; + cp += strcspn(cp, spaces); + if (!*cp) + goto cleanup; + *cp++ = '\0'; + cp += strspn(cp, spaces); + + /* Network */ + pvt->nwent.n_addrtype = AF_INET; + t = cp + strcspn(cp, spaces); + if (*t) + *t++ = '\0'; + pvt->nwent.n_length = inet_net_pton(AF_INET, cp, + pvt->addr, sizeof pvt->addr); + if (pvt->nwent.n_length < 0) + goto cleanup; + pvt->nwent.n_addr = pvt->addr; + cp = t; + + /* Aliases */ + ap = pvt->nwent.n_aliases = pvt->aliases; + while (*cp) { + if (ap >= &pvt->aliases[MAXALIASES]) + break; + *ap++ = cp; + cp += strcspn(cp, spaces); + if (!*cp) + break; + *cp++ = '\0'; + cp += strspn(cp, spaces); + } + *ap = NULL; + + return (&pvt->nwent); + + cleanup: + if (pvt->nwbuf) { + free(pvt->nwbuf); + pvt->nwbuf = NULL; + } + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +static int +init(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !nw_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} + +#endif /*WANT_IRS_NIS*/ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/nis_nw.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/nis_pr.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/nis_pr.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/nis_pr.c (revision 109985) @@ -0,0 +1,297 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_pr.c,v 1.14 2001/05/29 05:49:16 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + struct protoent proto; + char * prbuf; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char protocols_byname[] = "protocols.byname"; +static /*const*/ char protocols_bynumber[] = "protocols.bynumber"; + +/* Forward */ + +static void pr_close(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static struct protoent * pr_next(struct irs_pr *); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); + +static struct protoent * makeprotoent(struct irs_pr *this); +static void nisfree(struct pvt *, enum do_what); + +/* Public */ + +struct irs_pr * +irs_nis_pr(struct irs_acc *this) { + struct irs_pr *pr; + struct pvt *pvt; + + if (!(pr = memget(sizeof *pr))) { + errno = ENOMEM; + return (NULL); + } + memset(pr, 0x5e, sizeof *pr); + if (!(pvt = memget(sizeof *pvt))) { + memput(pr, sizeof *pr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + pr->private = pvt; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->next = pr_next; + pr->rewind = pr_rewind; + pr->close = pr_close; + pr->minimize = pr_minimize; + pr->res_get = NULL; + pr->res_set = NULL; + return (pr); +} + +/* Methods. */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nisfree(pvt, do_all); + if (pvt->proto.p_aliases) + free(pvt->proto.p_aliases); + if (pvt->prbuf) + free(pvt->prbuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + char *tmp; + + nisfree(pvt, do_val); + DE_CONST(name, tmp); + r = yp_match(pvt->nis_domain, protocols_byname, tmp, + strlen(tmp), &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makeprotoent(this)); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int num) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "-4294967295"]; + int r; + + nisfree(pvt, do_val); + (void) sprintf(tmp, "%d", num); + r = yp_match(pvt->nis_domain, protocols_bynumber, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makeprotoent(this)); +} + +static struct protoent * +pr_next(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *rval; + int r; + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, protocols_bynumber, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, protocols_bynumber, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + errno = ENOENT; + return (NULL); + } + rval = makeprotoent(this); + } while (rval == NULL); + return (rval); +} + +static void +pr_rewind(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static void +pr_minimize(struct irs_pr *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static struct protoent * +makeprotoent(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, **t; + int n, m; + + if (pvt->prbuf) + free(pvt->prbuf); + pvt->prbuf = pvt->curval_data; + pvt->curval_data = NULL; + + for (p = pvt->prbuf; *p && *p != '#';) + p++; + while (p > pvt->prbuf && isspace((unsigned char)(p[-1]))) + p--; + *p = '\0'; + + p = pvt->prbuf; + n = m = 0; + + pvt->proto.p_name = p; + while (*p && !isspace((unsigned char)*p)) + p++; + if (!*p) + return (NULL); + *p++ = '\0'; + + while (*p && isspace((unsigned char)*p)) + p++; + pvt->proto.p_proto = atoi(p); + while (*p && !isspace((unsigned char)*p)) + p++; + *p++ = '\0'; + + while (*p) { + if ((n + 1) >= m || !pvt->proto.p_aliases) { + m += 10; + t = realloc(pvt->proto.p_aliases, + m * sizeof(char *)); + if (!t) { + errno = ENOMEM; + goto cleanup; + } + pvt->proto.p_aliases = t; + } + pvt->proto.p_aliases[n++] = p; + while (*p && !isspace((unsigned char)*p)) + p++; + if (*p) + *p++ = '\0'; + } + if (!pvt->proto.p_aliases) + pvt->proto.p_aliases = malloc(sizeof(char *)); + if (!pvt->proto.p_aliases) + goto cleanup; + pvt->proto.p_aliases[n] = NULL; + return (&pvt->proto); + + cleanup: + if (pvt->proto.p_aliases) { + free(pvt->proto.p_aliases); + pvt->proto.p_aliases = NULL; + } + if (pvt->prbuf) { + free(pvt->prbuf); + pvt->prbuf = NULL; + } + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +#endif /*WANT_IRS_NIS*/ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/nis_pr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/nis_pw.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/nis_pw.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/nis_pw.c (revision 109985) @@ -0,0 +1,287 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_pw.c,v 1.17 2001/05/29 05:49:18 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#if !defined(WANT_IRS_PW) || !defined(WANT_IRS_NIS) +static int __bind_irs_pw_unneeded; +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + struct passwd passwd; + char * pwbuf; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char passwd_byname[] = "passwd.byname"; +static /*const*/ char passwd_byuid[] = "passwd.byuid"; + +/* Forward */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_next(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); + +static struct passwd * makepasswdent(struct irs_pw *); +static void nisfree(struct pvt *, enum do_what); + +/* Public */ + +struct irs_pw * +irs_nis_pw(struct irs_acc *this) { + struct irs_pw *pw; + struct pvt *pvt; + + if (!(pw = memget(sizeof *pw))) { + errno = ENOMEM; + return (NULL); + } + memset(pw, 0x5e, sizeof *pw); + if (!(pvt = memget(sizeof *pvt))) { + memput(pw, sizeof *pw); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + pw->private = pvt; + pw->close = pw_close; + pw->next = pw_next; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + pw->res_get = NULL; + pw->res_set = NULL; + return (pw); +} + +/* Methods */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->pwbuf) + free(pvt->pwbuf); + nisfree(pvt, do_all); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct passwd * +pw_next(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct passwd *rval; + int r; + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, passwd_byname, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, passwd_byname, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + errno = ENOENT; + return (NULL); + } + rval = makepasswdent(this); + } while (rval == NULL); + return (rval); +} + +static struct passwd * +pw_byname(struct irs_pw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + char *tmp; + + nisfree(pvt, do_val); + DE_CONST(name, tmp); + r = yp_match(pvt->nis_domain, passwd_byname, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makepasswdent(this)); +} + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "4294967295"]; + int r; + + nisfree(pvt, do_val); + (void) sprintf(tmp, "%u", (unsigned int)uid); + r = yp_match(pvt->nis_domain, passwd_byuid, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makepasswdent(this)); +} + +static void +pw_rewind(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static void +pw_minimize(struct irs_pw *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static struct passwd * +makepasswdent(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *cp; + + memset(&pvt->passwd, 0, sizeof pvt->passwd); + if (pvt->pwbuf) + free(pvt->pwbuf); + pvt->pwbuf = pvt->curval_data; + pvt->curval_data = NULL; + + cp = pvt->pwbuf; + pvt->passwd.pw_name = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; +#ifdef HAS_PW_CLASS + pvt->passwd.pw_class = cp; /* Needs to point at a \0. */ +#endif + *cp++ = '\0'; + + pvt->passwd.pw_passwd = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_uid = atoi(cp); + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_gid = atoi(cp); + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_gecos = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_dir = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_shell = cp; + + if ((cp = strchr(cp, '\n')) != NULL) + *cp = '\0'; + + return (&pvt->passwd); + + cleanup: + free(pvt->pwbuf); + pvt->pwbuf = NULL; + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +#endif /* WANT_IRS_PW && WANT_IRS_NIS */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/nis_pw.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/nis_sv.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/nis_sv.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/nis_sv.c (revision 109985) @@ -0,0 +1,305 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_sv.c,v 1.15 2001/05/29 05:49:19 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + char line[BUFSIZ+1]; + struct servent serv; + char * svbuf; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char services_byname[] = "services.byname"; + +/* Forward */ + +static void sv_close(struct irs_sv*); +static struct servent * sv_next(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, const char *, + const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); + +static struct servent * makeservent(struct irs_sv *this); +static void nisfree(struct pvt *, enum do_what); + +/* Public */ + +struct irs_sv * +irs_nis_sv(struct irs_acc *this) { + struct irs_sv *sv; + struct pvt *pvt; + + if (!(sv = memget(sizeof *sv))) { + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + if (!(pvt = memget(sizeof *pvt))) { + memput(sv, sizeof *sv); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + sv->private = pvt; + sv->close = sv_close; + sv->next = sv_next; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->rewind = sv_rewind; + sv->minimize = sv_minimize; + sv->res_get = NULL; + sv->res_set = NULL; + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nisfree(pvt, do_all); + if (pvt->serv.s_aliases) + free(pvt->serv.s_aliases); + if (pvt->svbuf) + free(pvt->svbuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + struct servent *serv; + char **sap; + + sv_rewind(this); + while ((serv = sv_next(this)) != NULL) { + if (proto != NULL && strcmp(proto, serv->s_proto)) + continue; + if (!strcmp(name, serv->s_name)) + break; + for (sap = serv->s_aliases; sap && *sap; sap++) + if (!strcmp(name, *sap)) + break; + } + return (serv); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + struct servent *serv; + + sv_rewind(this); + while ((serv = sv_next(this)) != NULL) { + if (proto != NULL && strcmp(proto, serv->s_proto)) + continue; + if (serv->s_port == port) + break; + } + return (serv); +} + +static void +sv_rewind(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static struct servent * +sv_next(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *rval; + int r; + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, services_byname, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, services_byname, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + errno = ENOENT; + return (NULL); + } + rval = makeservent(this); + } while (rval == NULL); + return (rval); +} + +static void +sv_minimize(struct irs_sv *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static struct servent * +makeservent(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + static const char spaces[] = " \t"; + char *p, **t; + int n, m; + + if (pvt->svbuf) + free(pvt->svbuf); + pvt->svbuf = pvt->curval_data; + pvt->curval_data = NULL; + + if (pvt->serv.s_aliases) { + free(pvt->serv.s_aliases); + pvt->serv.s_aliases = NULL; + } + + if ((p = strpbrk(pvt->svbuf, "#\n"))) + *p = '\0'; + + p = pvt->svbuf; + + pvt->serv.s_name = p; + p += strcspn(p, spaces); + if (!*p) + goto cleanup; + *p++ = '\0'; + p += strspn(p, spaces); + + pvt->serv.s_port = htons((u_short) atoi(p)); + pvt->serv.s_proto = NULL; + + while (*p && !isspace((unsigned char)*p)) + if (*p++ == '/') + pvt->serv.s_proto = p; + if (!pvt->serv.s_proto) + goto cleanup; + if (*p) { + *p++ = '\0'; + p += strspn(p, spaces); + } + + n = m = 0; + while (*p) { + if ((n + 1) >= m || !pvt->serv.s_aliases) { + m += 10; + t = realloc(pvt->serv.s_aliases, m * sizeof(char *)); + if (!t) { + errno = ENOMEM; + goto cleanup; + } + pvt->serv.s_aliases = t; + } + pvt->serv.s_aliases[n++] = p; + p += strcspn(p, spaces); + if (!*p) + break; + *p++ = '\0'; + p += strspn(p, spaces); + } + if (!pvt->serv.s_aliases) + pvt->serv.s_aliases = malloc(sizeof(char *)); + if (!pvt->serv.s_aliases) + goto cleanup; + pvt->serv.s_aliases[n] = NULL; + return (&pvt->serv); + + cleanup: + if (pvt->serv.s_aliases) { + free(pvt->serv.s_aliases); + pvt->serv.s_aliases = NULL; + } + if (pvt->svbuf) { + free(pvt->svbuf); + pvt->svbuf = NULL; + } + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +#endif /*WANT_IRS_NIS*/ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/nis_sv.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/nul_ng.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/nul_ng.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/nul_ng.c (revision 109985) @@ -0,0 +1,126 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nul_ng.c,v 1.11 2001/05/29 05:49:20 marka Exp $"; +#endif + +/* + * nul_ng.c - the netgroup accessor null map + */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Forward. */ + +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); +static int ng_test(struct irs_ng *, + const char *, const char *, + const char *, const char *); +static void ng_rewind(struct irs_ng *, const char *); +static void ng_minimize(struct irs_ng *); + +/* Public. */ + +struct irs_ng * +irs_nul_ng(struct irs_acc *this) { + struct irs_ng *ng; + + UNUSED(this); + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + ng->private = NULL; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods. */ + +static void +ng_close(struct irs_ng *this) { + memput(this, sizeof *this); +} + +/* ARGSUSED */ +static int +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ + UNUSED(this); + UNUSED(host); + UNUSED(user); + UNUSED(domain); + errno = ENOENT; + return (-1); +} + +static int +ng_test(struct irs_ng *this, const char *name, + const char *user, const char *host, const char *domain) +{ + UNUSED(this); + UNUSED(name); + UNUSED(user); + UNUSED(host); + UNUSED(domain); + errno = ENODEV; + return (-1); +} + +static void +ng_rewind(struct irs_ng *this, const char *netgroup) { + UNUSED(this); + UNUSED(netgroup); + /* NOOP */ +} + +static void +ng_minimize(struct irs_ng *this) { + UNUSED(this); + /* NOOP */ +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/nul_ng.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/util.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/util.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/util.c (revision 109985) @@ -0,0 +1,107 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: util.c,v 1.12 2001/05/29 05:49:21 marka Exp $"; +#endif + +#include "port_before.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "port_after.h" + +#include "irs_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +void +map_v4v6_address(const char *src, char *dst) { + u_char *p = (u_char *)dst; + char tmp[NS_INADDRSZ]; + int i; + + /* Stash a temporary copy so our caller can update in place. */ + memcpy(tmp, src, NS_INADDRSZ); + /* Mark this ipv6 addr as a mapped ipv4. */ + for (i = 0; i < 10; i++) + *p++ = 0x00; + *p++ = 0xff; + *p++ = 0xff; + /* Retrieve the saved copy and we're done. */ + memcpy((void*)p, tmp, NS_INADDRSZ); +} + +int +make_group_list(struct irs_gr *this, const char *name, + gid_t basegid, gid_t *groups, int *ngroups) +{ + struct group *grp; + int i, ng; + int ret, maxgroups; + + ret = -1; + ng = 0; + maxgroups = *ngroups; + /* + * When installing primary group, duplicate it; + * the first element of groups is the effective gid + * and will be overwritten when a setgid file is executed. + */ + if (ng >= maxgroups) + goto done; + groups[ng++] = basegid; + if (ng >= maxgroups) + goto done; + groups[ng++] = basegid; + /* + * Scan the group file to find additional groups. + */ + (*this->rewind)(this); + while ((grp = (*this->next)(this)) != NULL) { + if ((gid_t)grp->gr_gid == basegid) + continue; + for (i = 0; grp->gr_mem[i]; i++) { + if (!strcmp(grp->gr_mem[i], name)) { + if (ng >= maxgroups) + goto done; + groups[ng++] = grp->gr_gid; + break; + } + } + } + ret = 0; + done: + *ngroups = ng; + return (ret); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/util.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/getpwent.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/getpwent.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/getpwent.c (revision 109985) @@ -0,0 +1,199 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: getpwent.c,v 1.21 2000/02/21 21:40:56 vixie Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(WANT_IRS_PW) || defined(__BIND_NOSTATIC) +static int __bind_irs_pw_unneeded; +#else + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct net_data * init(void); + +/* Public */ + +struct passwd * +getpwent(void) { + struct net_data *net_data = init(); + + return (getpwent_p(net_data)); +} + +struct passwd * +getpwnam(const char *name) { + struct net_data *net_data = init(); + + return (getpwnam_p(name, net_data)); +} + +struct passwd * +getpwuid(uid_t uid) { + struct net_data *net_data = init(); + + return (getpwuid_p(uid, net_data)); +} + +int +setpassent(int stayopen) { + struct net_data *net_data = init(); + + return (setpassent_p(stayopen, net_data)); +} + +#ifdef SETPWENT_VOID +void +setpwent() { + struct net_data *net_data = init(); + + setpwent_p(net_data); +} +#else +int +setpwent() { + struct net_data *net_data = init(); + + return (setpwent_p(net_data)); +} +#endif + +void +endpwent() { + struct net_data *net_data = init(); + + endpwent_p(net_data); +} + +/* Shared private. */ + +struct passwd * +getpwent_p(struct net_data *net_data) { + struct irs_pw *pw; + + if (!net_data || !(pw = net_data->pw)) + return (NULL); + net_data->pw_last = (*pw->next)(pw); + return (net_data->pw_last); +} + +struct passwd * +getpwnam_p(const char *name, struct net_data *net_data) { + struct irs_pw *pw; + + if (!net_data || !(pw = net_data->pw)) + return (NULL); + if (net_data->pw_stayopen && net_data->pw_last && + !strcmp(net_data->pw_last->pw_name, name)) + return (net_data->pw_last); + net_data->pw_last = (*pw->byname)(pw, name); + if (!net_data->pw_stayopen) + endpwent(); + return (net_data->pw_last); +} + +struct passwd * +getpwuid_p(uid_t uid, struct net_data *net_data) { + struct irs_pw *pw; + + if (!net_data || !(pw = net_data->pw)) + return (NULL); + if (net_data->pw_stayopen && net_data->pw_last && + net_data->pw_last->pw_uid == uid) + return (net_data->pw_last); + net_data->pw_last = (*pw->byuid)(pw, uid); + if (!net_data->pw_stayopen) + endpwent(); + return (net_data->pw_last); +} + +int +setpassent_p(int stayopen, struct net_data *net_data) { + struct irs_pw *pw; + + if (!net_data || !(pw = net_data->pw)) + return (0); + (*pw->rewind)(pw); + net_data->pw_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); + return (1); +} + +#ifdef SETPWENT_VOID +void +setpwent_p(struct net_data *net_data) { + (void) setpassent_p(0, net_data); +} +#else +int +setpwent_p(struct net_data *net_data) { + return (setpassent_p(0, net_data)); +} +#endif + +void +endpwent_p(struct net_data *net_data) { + struct irs_pw *pw; + + if ((net_data != NULL) && ((pw = net_data->pw) != NULL)) + (*pw->minimize)(pw); +} + +/* Private */ + +static struct net_data * +init() { + struct net_data *net_data; + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->pw) { + net_data->pw = (*net_data->irs->pw_map)(net_data->irs); + + if (!net_data->pw || !net_data->res) { + error: + errno = EIO; + return (NULL); + } + (*net_data->pw->res_set)(net_data->pw, net_data->res, NULL); + } + + return (net_data); +} + +#endif /* WANT_IRS_PW */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/getpwent.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/Makefile.BSD =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/Makefile.BSD (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/Makefile.BSD (revision 109985) @@ -0,0 +1,25 @@ +# BSDI $Id: Makefile.BSD,v 1.5 1999/01/18 07:46:47 vixie Exp $ +# +# @(#)Makefile 5.12 (Berkeley) 7/15/92 + +CFLAGS= -g + +CC= gcc2 +CFLAGS+= -Wall -Wno-unused + +LIB= irs +CFLAGS+= -I${.CURDIR}/.. +SRCS= lcl.c lcl_gr.c lcl_pw.c lcl_sv.c lcl_pr.c lcl_ho.c lcl_nw.c lcl_ng.c \ + dns.c dns_gr.c dns_pw.c dns_sv.c dns_pr.c dns_ho.c dns_nw.c \ + nis.c nis_gr.c nis_pw.c nis_sv.c nis_pr.c nis_ho.c nis_nw.c nis_ng.c \ + gen.c gen_gr.c gen_pw.c gen_sv.c gen_pr.c gen_ho.c gen_nw.c gen_ng.c \ + getgrent.c getpwent.c getservent.c getprotoent.c gethostent.c \ + getnetent.c getnetgrent.c \ + nul_ng.c irs_data.c irp.c irp_gr.c irp_ho.c irp_ng.c irp_nw.c \ + irp_pr.c irp_pw.c irp_sv.c irpd.c irpmarshall.c \ + hesiod.c util.c bitncmp.c +NOMAN= + +all: libirs.a + +.include Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/Makefile.BSD ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/README =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/README (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/README (revision 109985) @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +This is the Information Retrieval Service (IRS). +Designed by Paul Vixie (ISC) and Ted T'so (MIT), 1995. +Written by Paul Vixie, Ted T'so and Sam Stoller, 1996. +$Id: README,v 1.5 1999/01/08 19:23:52 vixie Exp $ + +Introduction: + + The /etc/irs.conf file defines access methods (like DNS or NIS or +LOCAL) for each map (like PASSWD or GROUP or HOSTS). One of the access +methods is "generic" in that it uses the rules from /etc/irs.conf to decide +which of potentially several different access methods to use for any given +map. Stubs have been written for all of the system getXbyY() functions so +that old programs can get this new "multiple access method" capability without +any source code changes. + +Thread Safety: + + It is possible for a thread safe program to be altered to call the +underlying interface (rather than the standard getXbyY() stubs) and get some +reentrance capabilities. Note that the underlying libraries (which we call) +are not all thread-safe, for example, the YP and DNS resolvers. A lot more +work will need to be done before we have full thread safety. But we believe +that the native API for this system does not impose any reentrancy problems. +We don't use global or static variables anywhere except in the getXbyY() stubs. + +Apologies: + + We did cheap object orientation without using C++. This stuff is +standard C, and it suffers from some of the defects shared by all object +systems implemented in C. Even so, this is the smallest design we could +think of that would be extensible to more access methods, more map types, +and more map operations (like BYNAME or BYGID or whatever) in the future. + + There's a fair amount of duplicated code between the different +access methods for a given map. For example, the code that parses the +passwd entries is almost identical between the DNS and NIS map objects. To +clean this up, the almost-identical functions need to be split into similar +and dissimilar parts, and some parts of the "struct pvt"'s need to be made +shared via substructures. Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/README ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/dns_p.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/dns_p.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/dns_p.h (revision 109985) @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * $Id: dns_p.h,v 1.11 1999/06/03 20:50:36 vixie Exp $ + */ + +#ifndef _DNS_P_H_INCLUDED +#define _DNS_P_H_INCLUDED + +#define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0 || \ + (ok)(nm) != 0) +#define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok) +#define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok) + +/* + * Object state. + */ +struct dns_p { + void *hes_ctx; + struct __res_state *res; + void (*free_res) __P((void *)); +}; + +/* + * Methods. + */ + +extern struct irs_gr * irs_dns_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_dns_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_dns_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_dns_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_dns_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_dns_nw __P((struct irs_acc *)); + +#endif /*_DNS_P_H_INCLUDED*/ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/dns_p.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/gen_nw.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/gen_nw.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/gen_nw.c (revision 109985) @@ -0,0 +1,262 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_nw.c,v 1.13 1999/10/13 16:39:29 vixie Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void nw_close(struct irs_nw*); +static struct nwent * nw_next(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); +static struct __res_state * nw_res_get(struct irs_nw *this); +static void nw_res_set(struct irs_nw *this, + struct __res_state *res, + void (*free_res)(void *)); + +static int init(struct irs_nw *this); + +/* Public */ + +struct irs_nw * +irs_gen_nw(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_nw *nw; + struct pvt *pvt; + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + pvt->rules = accpvt->map_rules[irs_nw]; + pvt->rule = pvt->rules; + nw->private = pvt; + nw->close = nw_close; + nw->next = nw_next; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + nw->res_get = nw_res_get; + nw->res_set = nw_res_set; + return (nw); +} + +/* Methods */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct nwent * +nw_next(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *rval; + struct irs_nw *nw; + + if (init(this) == -1) + return(NULL); + + while (pvt->rule) { + nw = pvt->rule->inst->nw; + rval = (*nw->next)(nw); + if (rval) + return (rval); + if (!(pvt->rules->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + nw = pvt->rule->inst->nw; + (*nw->rewind)(nw); + } + } + return (NULL); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int type) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct nwent *rval; + struct irs_nw *nw; + + if (init(this) == -1) + return(NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + nw = rule->inst->nw; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + rval = (*nw->byname)(nw, name, type); + if (rval != NULL) + return (rval); + if (pvt->res->res_h_errno != TRY_AGAIN && + !(rule->flags & IRS_CONTINUE)) + break; + } + return (NULL); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int length, int type) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct nwent *rval; + struct irs_nw *nw; + + if (init(this) == -1) + return(NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + nw = rule->inst->nw; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + rval = (*nw->byaddr)(nw, net, length, type); + if (rval != NULL) + return (rval); + if (pvt->res->res_h_errno != TRY_AGAIN && + !(rule->flags & IRS_CONTINUE)) + break; + } + return (NULL); +} + +static void +nw_rewind(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_nw *nw; + + pvt->rule = pvt->rules; + if (pvt->rule) { + nw = pvt->rule->inst->nw; + (*nw->rewind)(nw); + } +} + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res) + res_nclose(pvt->res); + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_nw *nw = rule->inst->nw; + + (*nw->minimize)(nw); + } +} + +static struct __res_state * +nw_res_get(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + nw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +nw_res_set(struct irs_nw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_nw *nw = rule->inst->nw; + + (*nw->res_set)(nw, pvt->res, NULL); + } +} + +static int +init(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !nw_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/gen_nw.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/gen_pr.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/gen_pr.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/gen_pr.c (revision 109985) @@ -0,0 +1,226 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_pr.c,v 1.12 1999/10/13 16:39:30 vixie Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void pr_close(struct irs_pr*); +static struct protoent * pr_next(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); +static struct __res_state * pr_res_get(struct irs_pr *); +static void pr_res_set(struct irs_pr *, + struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_pr * +irs_gen_pr(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_pr *pr; + struct pvt *pvt; + + if (!(pr = memget(sizeof *pr))) { + errno = ENOMEM; + return (NULL); + } + memset(pr, 0x5e, sizeof *pr); + if (!(pvt = memget(sizeof *pvt))) { + memput(pr, sizeof *pr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_pr]; + pvt->rule = pvt->rules; + pr->private = pvt; + pr->close = pr_close; + pr->next = pr_next; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->rewind = pr_rewind; + pr->minimize = pr_minimize; + pr->res_get = pr_res_get; + pr->res_set = pr_res_set; + return (pr); +} + +/* Methods */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct protoent * +pr_next(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *rval; + struct irs_pr *pr; + + while (pvt->rule) { + pr = pvt->rule->inst->pr; + rval = (*pr->next)(pr); + if (rval) + return (rval); + if (!(pvt->rules->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + pr = pvt->rule->inst->pr; + (*pr->rewind)(pr); + } + } + return (NULL); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct protoent *rval; + struct irs_pr *pr; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + pr = rule->inst->pr; + rval = (*pr->byname)(pr, name); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct protoent *rval; + struct irs_pr *pr; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + pr = rule->inst->pr; + rval = (*pr->bynumber)(pr, proto); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +pr_rewind(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_pr *pr; + + pvt->rule = pvt->rules; + if (pvt->rule) { + pr = pvt->rule->inst->pr; + (*pr->rewind)(pr); + } +} + +static void +pr_minimize(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_pr *pr = rule->inst->pr; + + (*pr->minimize)(pr); + } +} + +static struct __res_state * +pr_res_get(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + pr_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +pr_res_set(struct irs_pr *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_pr *pr = rule->inst->pr; + + if (pr->res_set) + (*pr->res_set)(pr, pvt->res, NULL); + } +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/gen_pr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/gen_pw.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/gen_pw.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/gen_pw.c (revision 109985) @@ -0,0 +1,233 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_pw.c,v 1.14 1999/10/13 16:39:30 vixie Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_pw_unneeded; +#else + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_next(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); +static struct __res_state * pw_res_get(struct irs_pw *); +static void pw_res_set(struct irs_pw *, + struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_pw * +irs_gen_pw(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_pw *pw; + struct pvt *pvt; + + if (!(pw = memget(sizeof *pw))) { + errno = ENOMEM; + return (NULL); + } + memset(pw, 0x5e, sizeof *pw); + if (!(pvt = memget(sizeof *pvt))) { + memput(pw, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_pw]; + pvt->rule = pvt->rules; + pw->private = pvt; + pw->close = pw_close; + pw->next = pw_next; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + pw->res_get = pw_res_get; + pw->res_set = pw_res_set; + return (pw); +} + +/* Methods */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct passwd * +pw_next(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct passwd *rval; + struct irs_pw *pw; + + while (pvt->rule) { + pw = pvt->rule->inst->pw; + rval = (*pw->next)(pw); + if (rval) + return (rval); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + pw = pvt->rule->inst->pw; + (*pw->rewind)(pw); + } + } + return (NULL); +} + +static void +pw_rewind(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_pw *pw; + + pvt->rule = pvt->rules; + if (pvt->rule) { + pw = pvt->rule->inst->pw; + (*pw->rewind)(pw); + } +} + +static struct passwd * +pw_byname(struct irs_pw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct passwd *rval; + struct irs_pw *pw; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + pw = rule->inst->pw; + rval = (*pw->byname)(pw, name); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct passwd *rval; + struct irs_pw *pw; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + pw = rule->inst->pw; + rval = (*pw->byuid)(pw, uid); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +pw_minimize(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_pw *pw = rule->inst->pw; + + (*pw->minimize)(pw); + } +} + +static struct __res_state * +pw_res_get(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + pw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +pw_res_set(struct irs_pw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_pw *pw = rule->inst->pw; + + if (pw->res_set) + (*pw->res_set)(pw, pvt->res, NULL); + } +} + +#endif /* WANT_IRS_PW */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/gen_pw.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/gen_sv.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/gen_sv.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/gen_sv.c (revision 109985) @@ -0,0 +1,227 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_sv.c,v 1.12 1999/10/13 16:39:30 vixie Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void sv_close(struct irs_sv*); +static struct servent * sv_next(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, const char *, + const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); +static struct __res_state * sv_res_get(struct irs_sv *); +static void sv_res_set(struct irs_sv *, + struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_sv * +irs_gen_sv(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_sv *sv; + struct pvt *pvt; + + if (!(sv = memget(sizeof *sv))) { + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + if (!(pvt = memget(sizeof *pvt))) { + memput(sv, sizeof *sv); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_sv]; + pvt->rule = pvt->rules; + sv->private = pvt; + sv->close = sv_close; + sv->next = sv_next; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->rewind = sv_rewind; + sv->minimize = sv_minimize; + sv->res_get = sv_res_get; + sv->res_set = sv_res_set; + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct servent * +sv_next(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *rval; + struct irs_sv *sv; + + while (pvt->rule) { + sv = pvt->rule->inst->sv; + rval = (*sv->next)(sv); + if (rval) + return (rval); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + sv = pvt->rule->inst->sv; + (*sv->rewind)(sv); + } + } + return (NULL); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct servent *rval; + struct irs_sv *sv; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + sv = rule->inst->sv; + rval = (*sv->byname)(sv, name, proto); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct servent *rval; + struct irs_sv *sv; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + sv = rule->inst->sv; + rval = (*sv->byport)(sv, port, proto); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +sv_rewind(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_sv *sv; + + pvt->rule = pvt->rules; + if (pvt->rule) { + sv = pvt->rule->inst->sv; + (*sv->rewind)(sv); + } +} + +static void +sv_minimize(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_sv *sv = rule->inst->sv; + + (*sv->minimize)(sv); + } +} + +static struct __res_state * +sv_res_get(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + sv_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +sv_res_set(struct irs_sv *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_sv *sv = rule->inst->sv; + + if (sv->res_set) + (*sv->res_set)(sv, pvt->res, NULL); + } +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/gen_sv.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/hesiod_p.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/hesiod_p.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/hesiod_p.h (revision 109985) @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * This file is primarily maintained by and . + */ + +/* + * $Id: hesiod_p.h,v 1.9 1999/01/08 19:24:39 vixie Exp $ + */ + +/* + * hesiod_p.h -- private definitions for the hesiod library + */ + +#ifndef _HESIOD_P_H_INCLUDED +#define _HESIOD_P_H_INCLUDED + +#define DEF_RHS ".Athena.MIT.EDU" /* Defaults if HESIOD_CONF */ +#define DEF_LHS ".ns" /* file is not */ + /* present. */ +struct hesiod_p { + char * LHS; /* normally ".ns" */ + char * RHS; /* AKA the default hesiod domain */ + struct __res_state * res; /* resolver context */ + void (*free_res)(void *); + void (*res_set)(struct hesiod_p *, struct __res_state *, + void (*)(void *)); + struct __res_state * (*res_get)(struct hesiod_p *); +}; + +#define MAX_HESRESP 1024 + +#endif /*_HESIOD_P_H_INCLUDED*/ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/hesiod_p.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/irp_nw.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/irp_nw.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/irp_nw.c (revision 109985) @@ -0,0 +1,375 @@ +/* + * Portions Copyright (c) 1996,1998 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irp_nw.c,v 8.1 1999/01/18 07:46:54 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#if 0 + +#endif + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "irs_p.h" +#include "lcl_p.h" +#include "irp_p.h" + +#include "port_after.h" + +#define MAXALIASES 35 +#define MAXADDRSIZE 4 + +struct pvt { + struct irp_p *girpdata; + int warned; + struct nwent net; +}; + +/* Forward */ + +static void nw_close(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static struct nwent * nw_next(struct irs_nw *); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); + +static void free_nw(struct nwent *nw); + + +/* Public */ + + + +/* + * struct irs_nw * irs_irp_nw(struct irs_acc *this) + * + */ + +struct irs_nw * +irs_irp_nw(struct irs_acc *this) { + struct irs_nw *nw; + struct pvt *pvt; + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x0, sizeof *nw); + pvt->girpdata = this->private; + + nw->private = pvt; + nw->close = nw_close; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->next = nw_next; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + return (nw); +} + +/* Methods */ + + + +/* + * void nw_close(struct irs_nw *this) + * + */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + + free_nw(&pvt->net); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + + +/* + * struct nwent * nw_byaddr(struct irs_nw *this, void *net, + * int length, int type) + * + */ + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int length, int type) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *nw = &pvt->net; + char *body = NULL; + size_t bodylen; + int code; + char paddr[24]; /* bigenough for ip4 w/ cidr spec. */ + char text[256]; + + if (inet_net_ntop(type, net, length, paddr, sizeof paddr) == NULL) { + return (NULL); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getnetbyaddr %s %s", + paddr, ADDR_T_STR(type)) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETNET_OK) { + free_nw(nw); + if (irp_unmarshall_nw(nw, body) != 0) { + nw = NULL; + } + } else { + nw = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (nw); +} + + + + +/* + * struct nwent * nw_byname(struct irs_nw *this, const char *name, int type) + * + */ + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int type) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *nw = &pvt->net; + char *body = NULL; + size_t bodylen; + int code; + char text[256]; + + if (nw->n_name != NULL && + strcmp(name, nw->n_name) == 0 && + nw->n_addrtype == type) { + return (nw); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getnetbyname %s", name) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETNET_OK) { + free_nw(nw); + if (irp_unmarshall_nw(nw, body) != 0) { + nw = NULL; + } + } else { + nw = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (nw); +} + + + + +/* + * void nw_rewind(struct irs_nw *this) + * + */ + +static void +nw_rewind(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "setnetent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETNET_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setnetent failed: %s", text); + } + } + + return; +} + + + + + + +/* + * struct nwent * nw_next(struct irs_nw *this) + * + * Notes: + * + * Prepares the cache if necessary and returns the first, or + * next item from it. + */ + +static struct nwent * +nw_next(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *nw = &pvt->net; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getnetent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETNET_OK) { + free_nw(nw); + if (irp_unmarshall_nw(nw, body) != 0) { + nw = NULL; + } + } else { + nw = NULL; + } + + return (nw); +} + + + + + + +/* + * void nw_minimize(struct irs_nw *this) + * + */ + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + + + + +/* private. */ + + + +/* + * static void free_passwd(struct passwd *pw); + * + * deallocate all the memory irp_unmarshall_pw allocated. + * + */ + +static void +free_nw(struct nwent *nw) { + char **p; + + if (nw == NULL) + return; + + if (nw->n_name != NULL) + free(nw->n_name); + + if (nw->n_aliases != NULL) { + for (p = nw->n_aliases ; *p != NULL ; p++) { + free(*p); + } + free(nw->n_aliases); + } + + if (nw->n_addr != NULL) + free(nw->n_addr); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/irp_nw.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/irp_pr.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/irp_pr.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/irp_pr.c (revision 109985) @@ -0,0 +1,353 @@ +/* + * Portions Copyright (c) 1996 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irp_pr.c,v 8.1 1999/01/18 07:46:54 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "irs_p.h" +#include "lcl_p.h" +#include "irp_p.h" + +#include "port_after.h" + + +#define MAXALIASES 35 + +/* Types */ + +struct pvt { + struct irp_p *girpdata; + int warned; + struct protoent proto; +}; + +/* Forward */ + +static void pr_close(struct irs_pr *); +static struct protoent * pr_next(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); + +static void free_proto(struct protoent *pr); + +/* Public */ + + + +/* + * struct irs_pr * irs_irp_pr(struct irs_acc *this) + * + */ + +struct irs_pr * +irs_irp_pr(struct irs_acc *this) { + struct irs_pr *pr; + struct pvt *pvt; + + if (!(pr = memget(sizeof *pr))) { + errno = ENOMEM; + return (NULL); + } + memset(pr, 0x0, sizeof *pr); + + if (!(pvt = memget(sizeof *pvt))) { + memput(pr, sizeof *pr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + pr->private = pvt; + pr->close = pr_close; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->next = pr_next; + pr->rewind = pr_rewind; + pr->minimize = pr_minimize; + return (pr); +} + +/* Methods */ + + + +/* + * void pr_close(struct irs_pr *this) + * + */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pr_minimize(this); + + free_proto(&pvt->proto); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + +/* + * struct protoent * pr_byname(struct irs_pr *this, const char *name) + * + */ + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *pr = &pvt->proto; + char *body = NULL; + size_t bodylen; + int code; + int i; + char text[256]; + + if (pr->p_name != NULL && strcmp(name, pr->p_name) == 0) { + return (pr); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + i = irs_irp_send_command(pvt->girpdata, "getprotobyname %s", name); + if (i != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETPROTO_OK) { + free_proto(pr); + if (irp_unmarshall_pr(pr, body) != 0) { + pr = NULL; + } + } else { + pr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pr); +} + + + +/* + * struct protoent * pr_bynumber(struct irs_pr *this, int proto) + * + */ + +static struct protoent * +pr_bynumber(struct irs_pr *this, int proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *pr = &pvt->proto; + char *body = NULL; + size_t bodylen; + int code; + int i; + char text[256]; + + if (pr->p_name != NULL && proto == pr->p_proto) { + return (pr); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + i = irs_irp_send_command(pvt->girpdata, "getprotobynumber %d", proto); + if (i != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETPROTO_OK) { + free_proto(pr); + if (irp_unmarshall_pr(pr, body) != 0) { + pr = NULL; + } + } else { + pr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pr); +} + + + + +/* + * void pr_rewind(struct irs_pr *this) + * + */ + +static void +pr_rewind(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "setprotoent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETPROTO_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setprotoent failed: %s", text); + } + } + + return; +} + + + + +/* + * struct protoent * pr_next(struct irs_pr *this) + * + * Notes: + * + * Prepares the cache if necessary and returns the next item in it. + * + */ + +static struct protoent * +pr_next(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *pr = &pvt->proto; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getprotoent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETPROTO_OK) { + free_proto(pr); + if (irp_unmarshall_pr(pr, body) != 0) { + pr = NULL; + } + } else { + pr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pr); +} + + + + +/* + * void pr_minimize(struct irs_pr *this) + * + */ + +static void +pr_minimize(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + + + + + + +/* + * static void free_proto(struct protoent *pw); + * + * Deallocate all the memory irp_unmarshall_pr allocated. + * + */ + +static void +free_proto(struct protoent *pr) { + char **p; + + if (pr == NULL) + return; + + if (pr->p_name != NULL) + free(pr->p_name); + + for (p = pr->p_aliases ; p != NULL && *p != NULL ; p++) + free(*p); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/irp_pr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/irp_sv.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/irp_sv.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/irp_sv.c (revision 109985) @@ -0,0 +1,369 @@ +/* + * Portions Copyright (c) 1996,1998 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irp_sv.c,v 8.1 1999/01/18 07:46:54 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#include +#include +#include + +#ifdef IRS_LCL_SV_DB +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "irs_p.h" +#include "lcl_p.h" +#include "irp_p.h" + +#include "port_after.h" + +/* Types */ + +struct pvt { + struct irp_p *girpdata; + int warned; + struct servent service; +}; + +/* Forward */ + +static void sv_close(struct irs_sv*); +static struct servent * sv_next(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, const char *, + const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); + +static void free_service(struct servent *sv); + + + +/* Public */ + + + +/* + * struct irs_sv * irs_irp_sv(struct irs_acc *this) + * + */ + +struct irs_sv * +irs_irp_sv(struct irs_acc *this) { + struct irs_sv *sv; + struct pvt *pvt; + + if ((sv = memget(sizeof *sv)) == NULL) { + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x0, sizeof *sv); + + if ((pvt = memget(sizeof *pvt)) == NULL) { + memput(sv, sizeof *sv); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + sv->private = pvt; + sv->close = sv_close; + sv->next = sv_next; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->rewind = sv_rewind; + sv->minimize = sv_minimize; + + return (sv); +} + +/* Methods */ + + + +/* + * void sv_close(struct irs_sv *this) + * + */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + sv_minimize(this); + + free_service(&pvt->service); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + + +/* + * struct servent * sv_next(struct irs_sv *this) + * + * Notes: + * + * Fills the cache if necessary and returns the next item from it. + * + */ + +static struct servent * +sv_next(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *sv = &pvt->service; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getservent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETSERVICE_OK) { + free_service(sv); + if (irp_unmarshall_sv(sv, body) != 0) { + sv = NULL; + } + } else { + sv = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (sv); +} + + + + +/* + * struct servent * sv_byname(struct irs_sv *this, const char *name, + * const char *proto) + * + */ + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *sv = &pvt->service; + char *body; + char text[256]; + size_t bodylen; + int code; + + if (sv->s_name != NULL && + strcmp(name, sv->s_name) == 0 && + strcasecmp(proto, sv->s_proto) == 0) { + return (sv); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getservbyname %s %s", + name, proto) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETSERVICE_OK) { + free_service(sv); + if (irp_unmarshall_sv(sv, body) != 0) { + sv = NULL; + } + } else { + sv = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (sv); +} + + + + +/* + * struct servent * sv_byport(struct irs_sv *this, int port, + * const char *proto) + * + */ + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *sv = &pvt->service; + char *body; + size_t bodylen; + char text[256]; + int code; + + if (sv->s_name != NULL && + port == sv->s_port && + strcasecmp(proto, sv->s_proto) == 0) { + return (sv); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getservbyport %d %s", + ntohs((short)port), proto) != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETSERVICE_OK) { + free_service(sv); + if (irp_unmarshall_sv(sv, body) != 0) { + sv = NULL; + } + } else { + sv = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (sv); +} + + + + + +/* + * void sv_rewind(struct irs_sv *this) + * + */ + +static void +sv_rewind(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "setservent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETSERVICE_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setservent failed: %s", text); + } + } + + return; +} + + + + + +/* + * void sv_minimize(struct irs_sv *this) + * + */ + +static void +sv_minimize(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + + + + + + +static void +free_service(struct servent *sv) { + char **p; + + if (sv == NULL) { + return; + } + + if (sv->s_name != NULL) { + free(sv->s_name); + } + + for (p = sv->s_aliases ; p != NULL && *p != NULL ; p++) { + free(*p); + } + + if (sv->s_proto != NULL) { + free(sv->s_proto); + } +} + + Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/irp_sv.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/irs_data.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/irs_data.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/irs_data.h (revision 109985) @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * $Id: irs_data.h,v 1.12 1999/01/18 07:46:55 vixie Exp $ + */ + +#ifndef __BIND_NOSTATIC + +#define net_data_init __net_data_init + +struct net_data { + struct irs_acc * irs; + + struct irs_gr * gr; + struct irs_pw * pw; + struct irs_sv * sv; + struct irs_pr * pr; + struct irs_ho * ho; + struct irs_nw * nw; + struct irs_ng * ng; + + struct group * gr_last; + struct passwd * pw_last; + struct servent * sv_last; + struct protoent * pr_last; + struct netent * nw_last; /* should have been ne_last */ + struct nwent * nww_last; + struct hostent * ho_last; + + unsigned int gr_stayopen :1; + unsigned int pw_stayopen :1; + unsigned int sv_stayopen :1; + unsigned int pr_stayopen :1; + unsigned int ho_stayopen :1; + unsigned int nw_stayopen :1; + + void * nw_data; + void * ho_data; + + struct __res_state * res; /* for gethostent.c */ + +}; + +extern struct net_data * net_data_init(const char *conf_file); +extern void net_data_minimize(struct net_data *); + +#endif /*__BIND_NOSTATIC*/ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/irs_data.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/irs_p.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/irs_p.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/irs_p.h (revision 109985) @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * $Id: irs_p.h,v 1.8 1999/01/08 19:24:42 vixie Exp $ + */ + +#ifndef _IRS_P_H_INCLUDED +#define _IRS_P_H_INCLUDED + +#include + +#include "pathnames.h" + +#define IRS_SV_MAXALIASES 35 + +struct lcl_sv { + FILE * fp; + char line[BUFSIZ+1]; + struct servent serv; + char * serv_aliases[IRS_SV_MAXALIASES]; +}; + +#define irs_nul_ng __irs_nul_ng +#define map_v4v6_address __map_v4v6_address +#define make_group_list __make_group_list +#define irs_lclsv_fnxt __irs_lclsv_fnxt + +extern void map_v4v6_address(const char *src, char *dst); +extern int make_group_list(struct irs_gr *, const char *, + gid_t, gid_t *, int *); +extern struct irs_ng * irs_nul_ng(struct irs_acc *); +extern struct servent * irs_lclsv_fnxt(struct lcl_sv *); + +#endif Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/irs_p.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_p.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_p.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_p.h (revision 109985) @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * $Id: lcl_p.h,v 1.7 1999/01/08 19:24:51 vixie Exp $ + */ + +/* + * lcl_p.h - private include file for the local accessor functions. + */ + +#ifndef _LCL_P_H_INCLUDED +#define _LCL_P_H_INCLUDED + +/* + * Object state. + */ +struct lcl_p { + struct __res_state * res; + void (*free_res) __P((void *)); +}; + +/* + * Externs. + */ + +extern struct irs_acc * irs_lcl_acc __P((const char *)); +extern struct irs_gr * irs_lcl_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_lcl_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_lcl_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_lcl_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_lcl_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_lcl_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_lcl_ng __P((struct irs_acc *)); + +#endif /*_LCL_P_H_INCLUDED*/ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_p.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_pr.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_pr.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_pr.c (revision 109985) @@ -0,0 +1,284 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_pr.c,v 1.18 1999/10/13 17:11:20 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +#ifndef _PATH_PROTOCOLS +#define _PATH_PROTOCOLS "/etc/protocols" +#endif +#define MAXALIASES 35 + +/* Types */ + +struct pvt { + FILE * fp; + char line[BUFSIZ+1]; + struct protoent proto; + char * proto_aliases[MAXALIASES]; +}; + +/* Forward */ + +static void pr_close(struct irs_pr *); +static struct protoent * pr_next(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public */ + +struct irs_pr * +irs_lcl_pr(struct irs_acc *this) { + struct irs_pr *pr; + struct pvt *pvt; + + if (!(pr = memget(sizeof *pr))) { + errno = ENOMEM; + return (NULL); + } + if (!(pvt = memget(sizeof *pvt))) { + memput(pr, sizeof *this); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pr->private = pvt; + pr->close = pr_close; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->next = pr_next; + pr->rewind = pr_rewind; + pr->minimize = pr_minimize; + pr->res_get = NULL; + pr->res_set = NULL; + return (pr); +} + +/* Methods */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) + (void) fclose(pvt->fp); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + + struct protoent *p; + char **cp; + + pr_rewind(this); + while ((p = pr_next(this))) { + if (!strcmp(p->p_name, name)) + goto found; + for (cp = p->p_aliases; *cp; cp++) + if (!strcmp(*cp, name)) + goto found; + } + found: + return (p); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int proto) { + struct protoent *p; + + pr_rewind(this); + while ((p = pr_next(this))) + if (p->p_proto == proto) + break; + return (p); +} + +static void +pr_rewind(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_PROTOCOLS, "r" ))) + return; + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static struct protoent * +pr_next(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *cp, **q; + char *bufp, *ndbuf, *dbuf = NULL; + int c, bufsiz, offset; + + if (!pvt->fp) + pr_rewind(this); + if (!pvt->fp) + return (NULL); + bufp = pvt->line; + bufsiz = BUFSIZ; + offset = 0; + again: + if ((p = fgets(bufp + offset, bufsiz - offset, pvt->fp)) == NULL) { + if (dbuf) + free(dbuf); + return (NULL); + } + if (!strchr(p, '\n') && !feof(pvt->fp)) { +#define GROWBUF 1024 + /* allocate space for longer line */ + if (dbuf == NULL) { + if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL) + strcpy(ndbuf, bufp); + } else + ndbuf = realloc(dbuf, bufsiz + GROWBUF); + if (ndbuf) { + dbuf = ndbuf; + bufp = dbuf; + bufsiz += GROWBUF; + offset = strlen(dbuf); + } else { + /* allocation failed; skip this long line */ + while ((c = getc(pvt->fp)) != EOF) + if (c == '\n') + break; + if (c != EOF) + ungetc(c, pvt->fp); + } + goto again; + } + + p -= offset; + offset = 0; + + if (*p == '#') + goto again; + cp = strpbrk(p, "#\n"); + if (cp != NULL) + *cp = '\0'; + pvt->proto.p_name = p; + cp = strpbrk(p, " \t"); + if (cp == NULL) + goto again; + *cp++ = '\0'; + while (*cp == ' ' || *cp == '\t') + cp++; + p = strpbrk(cp, " \t"); + if (p != NULL) + *p++ = '\0'; + pvt->proto.p_proto = atoi(cp); + q = pvt->proto.p_aliases = pvt->proto_aliases; + if (p != NULL) { + cp = p; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->proto_aliases[MAXALIASES - 1]) + *q++ = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + } + *q = NULL; + return (&pvt->proto); +} + +static void +pr_minimize(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/lcl_pr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/nis_p.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/nis_p.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/nis_p.h (revision 109985) @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * $Id: nis_p.h,v 1.6 1999/01/08 19:25:03 vixie Exp $ + */ + +/* + * nis_p.h - private include file for the NIS functions. + */ + +/* + * Object state. + */ +struct nis_p { + char * domain; + struct __res_state * res; + void (*free_res) __P((void *)); +}; + + +/* + * Methods. + */ + +extern struct irs_gr * irs_nis_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_nis_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_nis_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_nis_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_nis_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_nis_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_nis_ng __P((struct irs_acc *)); Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/nis_p.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/irs/pathnames.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/irs/pathnames.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/irs/pathnames.h (revision 109985) @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * $Id: pathnames.h,v 1.7 1999/01/08 19:25:10 vixie Exp $ + */ + +#ifndef _PATH_IRS_CONF +#define _PATH_IRS_CONF "/etc/irs.conf" +#endif + +#ifndef _PATH_NETWORKS +#define _PATH_NETWORKS "/etc/networks" +#endif + +#ifndef _PATH_GROUP +#define _PATH_GROUP "/etc/group" +#endif + +#ifndef _PATH_NETGROUP +#define _PATH_NETGROUP "/etc/netgroup" +#endif + +#ifndef _PATH_SERVICES +#define _PATH_SERVICES "/etc/services" +#endif + +#ifdef IRS_LCL_SV_DB +#ifndef _PATH_SERVICES_DB +#define _PATH_SERVICES_DB _PATH_SERVICES ".db" +#endif +#endif + +#ifndef _PATH_HESIOD_CONF +#define _PATH_HESIOD_CONF "/etc/hesiod.conf" +#endif Property changes on: vendor/bind/8.3.4/contrib/bind/lib/irs/pathnames.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_debug.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/resolv/res_debug.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/resolv/res_debug.c (revision 109985) @@ -0,0 +1,1133 @@ +/* + * Copyright (c) 1985 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: res_debug.c,v 8.46 2002/05/21 01:57:45 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +extern const char *_res_opcodes[]; +extern const char *_res_sectioncodes[]; + +/* + * Print the current options. + */ +void +fp_resstat(const res_state statp, FILE *file) { + u_long mask; + + fprintf(file, ";; res options:"); + for (mask = 1; mask != 0; mask <<= 1) + if (statp->options & mask) + fprintf(file, " %s", p_option(mask)); + putc('\n', file); +} + +static void +do_section(const res_state statp, + ns_msg *handle, ns_sect section, + int pflag, FILE *file) +{ + int n, sflag, rrnum; + static int buflen = 2048; + char *buf; + ns_opcode opcode; + ns_rr rr; + + /* + * Print answer records. + */ + sflag = (statp->pfcode & pflag); + if (statp->pfcode && !sflag) + return; + + buf = malloc(buflen); + if (buf == NULL) { + fprintf(file, ";; memory allocation failure\n"); + return; + } + + opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode); + rrnum = 0; + for (;;) { + if (ns_parserr(handle, section, rrnum, &rr)) { + if (errno != ENODEV) + fprintf(file, ";; ns_parserr: %s\n", + strerror(errno)); + else if (rrnum > 0 && sflag != 0 && + (statp->pfcode & RES_PRF_HEAD1)) + putc('\n', file); + goto cleanup; + } + if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1)) + fprintf(file, ";; %s SECTION:\n", + p_section(section, opcode)); + if (section == ns_s_qd) + fprintf(file, ";;\t%s, type = %s, class = %s\n", + ns_rr_name(rr), + p_type(ns_rr_type(rr)), + p_class(ns_rr_class(rr))); + else if (section == ns_s_ar && ns_rr_type(rr) == ns_t_opt) { + u_int32_t ttl = ns_rr_ttl(rr); + fprintf(file, + "; EDNS: version: %u, udp=%u, flags=%04x\n", + (ttl>>16)&0xff, ns_rr_class(rr), ttl&0xffff); + } else { + n = ns_sprintrr(handle, &rr, NULL, NULL, + buf, buflen); + if (n < 0) { + if (errno == ENOSPC) { + free(buf); + buf = NULL; + if (buflen < 131072) + buf = malloc(buflen += 1024); + if (buf == NULL) { + fprintf(file, + ";; memory allocation failure\n"); + return; + } + continue; + } + fprintf(file, ";; ns_sprintrr: %s\n", + strerror(errno)); + goto cleanup; + } + fputs(buf, file); + fputc('\n', file); + } + rrnum++; + } + cleanup: + if (buf != NULL) + free(buf); +} + +/* + * Print the contents of a query. + * This is intended to be primarily a debugging routine. + */ +void +res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) { + ns_msg handle; + int qdcount, ancount, nscount, arcount; + u_int opcode, rcode, id; + + if (ns_initparse(msg, len, &handle) < 0) { + fprintf(file, ";; ns_initparse: %s\n", strerror(errno)); + return; + } + opcode = ns_msg_getflag(handle, ns_f_opcode); + rcode = ns_msg_getflag(handle, ns_f_rcode); + id = ns_msg_id(handle); + qdcount = ns_msg_count(handle, ns_s_qd); + ancount = ns_msg_count(handle, ns_s_an); + nscount = ns_msg_count(handle, ns_s_ns); + arcount = ns_msg_count(handle, ns_s_ar); + + /* + * Print header fields. + */ + if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode) + fprintf(file, + ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n", + _res_opcodes[opcode], p_rcode(rcode), id); + if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX)) + putc(';', file); + if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) { + fprintf(file, "; flags:"); + if (ns_msg_getflag(handle, ns_f_qr)) + fprintf(file, " qr"); + if (ns_msg_getflag(handle, ns_f_aa)) + fprintf(file, " aa"); + if (ns_msg_getflag(handle, ns_f_tc)) + fprintf(file, " tc"); + if (ns_msg_getflag(handle, ns_f_rd)) + fprintf(file, " rd"); + if (ns_msg_getflag(handle, ns_f_ra)) + fprintf(file, " ra"); + if (ns_msg_getflag(handle, ns_f_z)) + fprintf(file, " ??"); + if (ns_msg_getflag(handle, ns_f_ad)) + fprintf(file, " ad"); + if (ns_msg_getflag(handle, ns_f_cd)) + fprintf(file, " cd"); + } + if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) { + fprintf(file, "; %s: %d", + p_section(ns_s_qd, opcode), qdcount); + fprintf(file, ", %s: %d", + p_section(ns_s_an, opcode), ancount); + fprintf(file, ", %s: %d", + p_section(ns_s_ns, opcode), nscount); + fprintf(file, ", %s: %d", + p_section(ns_s_ar, opcode), arcount); + } + if ((!statp->pfcode) || (statp->pfcode & + (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) { + putc('\n',file); + } + /* + * Print the various sections. + */ + do_section(statp, &handle, ns_s_qd, RES_PRF_QUES, file); + do_section(statp, &handle, ns_s_an, RES_PRF_ANS, file); + do_section(statp, &handle, ns_s_ns, RES_PRF_AUTH, file); + do_section(statp, &handle, ns_s_ar, RES_PRF_ADD, file); + if (qdcount == 0 && ancount == 0 && + nscount == 0 && arcount == 0) + putc('\n', file); +} + +const u_char * +p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) { + char name[MAXDNAME]; + int n; + + if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0) + return (NULL); + if (name[0] == '\0') + putc('.', file); + else + fputs(name, file); + return (cp + n); +} + +const u_char * +p_cdname(const u_char *cp, const u_char *msg, FILE *file) { + return (p_cdnname(cp, msg, PACKETSZ, file)); +} + +/* Return a fully-qualified domain name from a compressed name (with + length supplied). */ + +const u_char * +p_fqnname(cp, msg, msglen, name, namelen) + const u_char *cp, *msg; + int msglen; + char *name; + int namelen; +{ + int n, newlen; + + if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0) + return (NULL); + newlen = strlen(name); + if (newlen == 0 || name[newlen - 1] != '.') { + if (newlen + 1 >= namelen) /* Lack space for final dot */ + return (NULL); + else + strcpy(name + newlen, "."); + } + return (cp + n); +} + +/* XXX: the rest of these functions need to become length-limited, too. */ + +const u_char * +p_fqname(const u_char *cp, const u_char *msg, FILE *file) { + char name[MAXDNAME]; + const u_char *n; + + n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name); + if (n == NULL) + return (NULL); + fputs(name, file); + return (n); +} + +/* + * Names of RR classes and qclasses. Classes and qclasses are the same, except + * that C_ANY is a qclass but not a class. (You can ask for records of class + * C_ANY, but you can't have any records of that class in the database.) + */ +const struct res_sym __p_class_syms[] = { + {C_IN, "IN", (char *)0}, + {C_CHAOS, "CHAOS", (char *)0}, + {C_HS, "HS", (char *)0}, + {C_HS, "HESIOD", (char *)0}, + {C_ANY, "ANY", (char *)0}, + {C_NONE, "NONE", (char *)0}, + {C_IN, (char *)0, (char *)0} +}; + +/* + * Names of message sections. + */ +const struct res_sym __p_default_section_syms[] = { + {ns_s_qd, "QUERY", (char *)0}, + {ns_s_an, "ANSWER", (char *)0}, + {ns_s_ns, "AUTHORITY", (char *)0}, + {ns_s_ar, "ADDITIONAL", (char *)0}, + {0, (char *)0, (char *)0} +}; + +const struct res_sym __p_update_section_syms[] = { + {S_ZONE, "ZONE", (char *)0}, + {S_PREREQ, "PREREQUISITE", (char *)0}, + {S_UPDATE, "UPDATE", (char *)0}, + {S_ADDT, "ADDITIONAL", (char *)0}, + {0, (char *)0, (char *)0} +}; + +const struct res_sym __p_key_syms[] = { + {NS_ALG_MD5RSA, "RSA", "RSA KEY with MD5 hash"}, + {NS_ALG_DH, "DH", "Diffie Hellman"}, + {NS_ALG_DSA, "DSA", "Digital Signature Algorithm"}, + {NS_ALG_EXPIRE_ONLY, "EXPIREONLY", "No algorithm"}, + {NS_ALG_PRIVATE_OID, "PRIVATE", "Algorithm obtained from OID"}, + {0, NULL, NULL} +}; + +const struct res_sym __p_cert_syms[] = { + {cert_t_pkix, "PKIX", "PKIX (X.509v3) Certificate"}, + {cert_t_spki, "SPKI", "SPKI certificate"}, + {cert_t_pgp, "PGP", "PGP certificate"}, + {cert_t_url, "URL", "URL Private"}, + {cert_t_oid, "OID", "OID Private"}, + {0, NULL, NULL} +}; + +/* + * Names of RR types and qtypes. Types and qtypes are the same, except + * that T_ANY is a qtype but not a type. (You can ask for records of type + * T_ANY, but you can't have any records of that type in the database.) + */ +const struct res_sym __p_type_syms[] = { + {ns_t_a, "A", "address"}, + {ns_t_ns, "NS", "name server"}, + {ns_t_md, "MD", "mail destination (deprecated)"}, + {ns_t_mf, "MF", "mail forwarder (deprecated)"}, + {ns_t_cname, "CNAME", "canonical name"}, + {ns_t_soa, "SOA", "start of authority"}, + {ns_t_mb, "MB", "mailbox"}, + {ns_t_mg, "MG", "mail group member"}, + {ns_t_mr, "MR", "mail rename"}, + {ns_t_null, "NULL", "null"}, + {ns_t_wks, "WKS", "well-known service (deprecated)"}, + {ns_t_ptr, "PTR", "domain name pointer"}, + {ns_t_hinfo, "HINFO", "host information"}, + {ns_t_minfo, "MINFO", "mailbox information"}, + {ns_t_mx, "MX", "mail exchanger"}, + {ns_t_txt, "TXT", "text"}, + {ns_t_rp, "RP", "responsible person"}, + {ns_t_afsdb, "AFSDB", "DCE or AFS server"}, + {ns_t_x25, "X25", "X25 address"}, + {ns_t_isdn, "ISDN", "ISDN address"}, + {ns_t_rt, "RT", "router"}, + {ns_t_nsap, "NSAP", "nsap address"}, + {ns_t_nsap_ptr, "NSAP_PTR", "domain name pointer"}, + {ns_t_sig, "SIG", "signature"}, + {ns_t_key, "KEY", "key"}, + {ns_t_px, "PX", "mapping information"}, + {ns_t_gpos, "GPOS", "geographical position (withdrawn)"}, + {ns_t_aaaa, "AAAA", "IPv6 address"}, + {ns_t_loc, "LOC", "location"}, + {ns_t_nxt, "NXT", "next valid name (unimplemented)"}, + {ns_t_eid, "EID", "endpoint identifier (unimplemented)"}, + {ns_t_nimloc, "NIMLOC", "NIMROD locator (unimplemented)"}, + {ns_t_srv, "SRV", "server selection"}, + {ns_t_atma, "ATMA", "ATM address (unimplemented)"}, + {ns_t_tkey, "TKEY", "tkey"}, + {ns_t_tsig, "TSIG", "transaction signature"}, + {ns_t_ixfr, "IXFR", "incremental zone transfer"}, + {ns_t_axfr, "AXFR", "zone transfer"}, + {ns_t_zxfr, "ZXFR", "compressed zone transfer"}, + {ns_t_mailb, "MAILB", "mailbox-related data (deprecated)"}, + {ns_t_maila, "MAILA", "mail agent (deprecated)"}, + {ns_t_naptr, "NAPTR", "URN Naming Authority"}, + {ns_t_kx, "KX", "Key Exchange"}, + {ns_t_cert, "CERT", "Certificate"}, + {ns_t_a6, "A6", "IPv6 Address"}, + {ns_t_dname, "DNAME", "dname"}, + {ns_t_sink, "SINK", "Kitchen Sink (experimental)"}, + {ns_t_opt, "OPT", "EDNS Options"}, + {ns_t_any, "ANY", "\"any\""}, + {0, NULL, NULL} +}; + +/* + * Names of DNS rcodes. + */ +const struct res_sym __p_rcode_syms[] = { + {ns_r_noerror, "NOERROR", "no error"}, + {ns_r_formerr, "FORMERR", "format error"}, + {ns_r_servfail, "SERVFAIL", "server failed"}, + {ns_r_nxdomain, "NXDOMAIN", "no such domain name"}, + {ns_r_notimpl, "NOTIMP", "not implemented"}, + {ns_r_refused, "REFUSED", "refused"}, + {ns_r_yxdomain, "YXDOMAIN", "domain name exists"}, + {ns_r_yxrrset, "YXRRSET", "rrset exists"}, + {ns_r_nxrrset, "NXRRSET", "rrset doesn't exist"}, + {ns_r_notauth, "NOTAUTH", "not authoritative"}, + {ns_r_notzone, "NOTZONE", "Not in zone"}, + {ns_r_max, "", ""}, + {ns_r_badsig, "BADSIG", "bad signature"}, + {ns_r_badkey, "BADKEY", "bad key"}, + {ns_r_badtime, "BADTIME", "bad time"}, + {0, NULL, NULL} +}; + +int +sym_ston(const struct res_sym *syms, const char *name, int *success) { + for ((void)NULL; syms->name != 0; syms++) { + if (strcasecmp (name, syms->name) == 0) { + if (success) + *success = 1; + return (syms->number); + } + } + if (success) + *success = 0; + return (syms->number); /* The default value. */ +} + +const char * +sym_ntos(const struct res_sym *syms, int number, int *success) { + static char unname[20]; + + for ((void)NULL; syms->name != 0; syms++) { + if (number == syms->number) { + if (success) + *success = 1; + return (syms->name); + } + } + + sprintf(unname, "%d", number); /* XXX nonreentrant */ + if (success) + *success = 0; + return (unname); +} + +const char * +sym_ntop(const struct res_sym *syms, int number, int *success) { + static char unname[20]; + + for ((void)NULL; syms->name != 0; syms++) { + if (number == syms->number) { + if (success) + *success = 1; + return (syms->humanname); + } + } + sprintf(unname, "%d", number); /* XXX nonreentrant */ + if (success) + *success = 0; + return (unname); +} + +/* + * Return a string for the type. + */ +const char * +p_type(int type) { + int success; + const char *result; + static char typebuf[20]; + + result = sym_ntos(__p_type_syms, type, &success); + if (success) + return (result); + if (type < 0 || type > 0xfff) + return ("BADTYPE"); + sprintf(typebuf, "TYPE%d", type); + return (typebuf); +} + +/* + * Return a string for the type. + */ +const char * +p_section(int section, int opcode) { + const struct res_sym *symbols; + + switch (opcode) { + case ns_o_update: + symbols = __p_update_section_syms; + break; + default: + symbols = __p_default_section_syms; + break; + } + return (sym_ntos(symbols, section, (int *)0)); +} + +/* + * Return a mnemonic for class. + */ +const char * +p_class(int class) { + int success; + const char *result; + static char classbuf[20]; + + result = sym_ntos(__p_class_syms, class, &success); + if (success) + return (result); + if (class < 0 || class > 0xfff) + return ("BADCLASS"); + sprintf(classbuf, "CLASS%d", class); + return (classbuf); +} + +/* + * Return a mnemonic for an option + */ +const char * +p_option(u_long option) { + static char nbuf[40]; + + switch (option) { + case RES_INIT: return "init"; + case RES_DEBUG: return "debug"; + case RES_AAONLY: return "aaonly(unimpl)"; + case RES_USEVC: return "usevc"; + case RES_PRIMARY: return "primry(unimpl)"; + case RES_IGNTC: return "igntc"; + case RES_RECURSE: return "recurs"; + case RES_DEFNAMES: return "defnam"; + case RES_STAYOPEN: return "styopn"; + case RES_DNSRCH: return "dnsrch"; + case RES_INSECURE1: return "insecure1"; + case RES_INSECURE2: return "insecure2"; + case RES_NOALIASES: return "noaliases"; + case RES_USE_INET6: return "inet6"; +#ifdef RES_USE_EDNS0 /* KAME extension */ + case RES_USE_EDNS0: return "edns0"; +#endif +#ifdef RES_USE_A6 + case RES_USE_A6: return "a6"; +#endif +#ifdef RES_USE_DNAME + case RES_USE_DNAME: return "dname"; +#endif +#ifdef RES_USE_DNSSEC + case RES_USE_DNSSEC: return "dnssec"; +#endif +#ifdef RES_NOTLDQUERY + case RES_NOTLDQUERY: return "no-tld-query"; +#endif + + /* XXX nonreentrant */ + default: sprintf(nbuf, "?0x%lx?", (u_long)option); + return (nbuf); + } +} + +/* + * Return a mnemonic for a time to live. + */ +const char * +p_time(u_int32_t value) { + static char nbuf[40]; /* XXX nonreentrant */ + + if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0) + sprintf(nbuf, "%u", value); + return (nbuf); +} + +/* + * Return a string for the rcode. + */ +const char * +p_rcode(int rcode) { + return (sym_ntos(__p_rcode_syms, rcode, (int *)0)); +} + +/* + * routines to convert between on-the-wire RR format and zone file format. + * Does not contain conversion to/from decimal degrees; divide or multiply + * by 60*60*1000 for that. + */ + +static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000, + 1000000,10000000,100000000,1000000000}; + +/* takes an XeY precision/size value, returns a string representation. */ +static const char * +precsize_ntoa(prec) + u_int8_t prec; +{ + static char retbuf[sizeof "90000000.00"]; /* XXX nonreentrant */ + unsigned long val; + int mantissa, exponent; + + mantissa = (int)((prec >> 4) & 0x0f) % 10; + exponent = (int)((prec >> 0) & 0x0f) % 10; + + val = mantissa * poweroften[exponent]; + + (void) sprintf(retbuf, "%lu.%.2lu", val/100, val%100); + return (retbuf); +} + +/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */ +static u_int8_t +precsize_aton(const char **strptr) { + unsigned int mval = 0, cmval = 0; + u_int8_t retval = 0; + const char *cp; + int exponent; + int mantissa; + + cp = *strptr; + + while (isdigit((unsigned char)*cp)) + mval = mval * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* centimeters */ + cp++; + if (isdigit((unsigned char)*cp)) { + cmval = (*cp++ - '0') * 10; + if (isdigit((unsigned char)*cp)) { + cmval += (*cp++ - '0'); + } + } + } + cmval = (mval * 100) + cmval; + + for (exponent = 0; exponent < 9; exponent++) + if (cmval < poweroften[exponent+1]) + break; + + mantissa = cmval / poweroften[exponent]; + if (mantissa > 9) + mantissa = 9; + + retval = (mantissa << 4) | exponent; + + *strptr = cp; + + return (retval); +} + +/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */ +static u_int32_t +latlon2ul(const char **latlonstrptr, int *which) { + const char *cp; + u_int32_t retval; + int deg = 0, min = 0, secs = 0, secsfrac = 0; + + cp = *latlonstrptr; + + while (isdigit((unsigned char)*cp)) + deg = deg * 10 + (*cp++ - '0'); + + while (isspace((unsigned char)*cp)) + cp++; + + if (!(isdigit((unsigned char)*cp))) + goto fndhemi; + + while (isdigit((unsigned char)*cp)) + min = min * 10 + (*cp++ - '0'); + + while (isspace((unsigned char)*cp)) + cp++; + + if (!(isdigit((unsigned char)*cp))) + goto fndhemi; + + while (isdigit((unsigned char)*cp)) + secs = secs * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* decimal seconds */ + cp++; + if (isdigit((unsigned char)*cp)) { + secsfrac = (*cp++ - '0') * 100; + if (isdigit((unsigned char)*cp)) { + secsfrac += (*cp++ - '0') * 10; + if (isdigit((unsigned char)*cp)) { + secsfrac += (*cp++ - '0'); + } + } + } + } + + while (!isspace((unsigned char)*cp)) /* if any trailing garbage */ + cp++; + + while (isspace((unsigned char)*cp)) + cp++; + + fndhemi: + switch (*cp) { + case 'N': case 'n': + case 'E': case 'e': + retval = ((unsigned)1<<31) + + (((((deg * 60) + min) * 60) + secs) * 1000) + + secsfrac; + break; + case 'S': case 's': + case 'W': case 'w': + retval = ((unsigned)1<<31) + - (((((deg * 60) + min) * 60) + secs) * 1000) + - secsfrac; + break; + default: + retval = 0; /* invalid value -- indicates error */ + break; + } + + switch (*cp) { + case 'N': case 'n': + case 'S': case 's': + *which = 1; /* latitude */ + break; + case 'E': case 'e': + case 'W': case 'w': + *which = 2; /* longitude */ + break; + default: + *which = 0; /* error */ + break; + } + + cp++; /* skip the hemisphere */ + + while (!isspace((unsigned char)*cp)) /* if any trailing garbage */ + cp++; + + while (isspace((unsigned char)*cp)) /* move to next field */ + cp++; + + *latlonstrptr = cp; + + return (retval); +} + +/* converts a zone file representation in a string to an RDATA on-the-wire + * representation. */ +int +loc_aton(ascii, binary) + const char *ascii; + u_char *binary; +{ + const char *cp, *maxcp; + u_char *bcp; + + u_int32_t latit = 0, longit = 0, alt = 0; + u_int32_t lltemp1 = 0, lltemp2 = 0; + int altmeters = 0, altfrac = 0, altsign = 1; + u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */ + u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */ + u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */ + int which1 = 0, which2 = 0; + + cp = ascii; + maxcp = cp + strlen(ascii); + + lltemp1 = latlon2ul(&cp, &which1); + + lltemp2 = latlon2ul(&cp, &which2); + + switch (which1 + which2) { + case 3: /* 1 + 2, the only valid combination */ + if ((which1 == 1) && (which2 == 2)) { /* normal case */ + latit = lltemp1; + longit = lltemp2; + } else if ((which1 == 2) && (which2 == 1)) { /* reversed */ + longit = lltemp1; + latit = lltemp2; + } else { /* some kind of brokenness */ + return (0); + } + break; + default: /* we didn't get one of each */ + return (0); + } + + /* altitude */ + if (*cp == '-') { + altsign = -1; + cp++; + } + + if (*cp == '+') + cp++; + + while (isdigit((unsigned char)*cp)) + altmeters = altmeters * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* decimal meters */ + cp++; + if (isdigit((unsigned char)*cp)) { + altfrac = (*cp++ - '0') * 10; + if (isdigit((unsigned char)*cp)) { + altfrac += (*cp++ - '0'); + } + } + } + + alt = (10000000 + (altsign * (altmeters * 100 + altfrac))); + + while (!isspace((unsigned char)*cp) && (cp < maxcp)) /* if trailing garbage or m */ + cp++; + + while (isspace((unsigned char)*cp) && (cp < maxcp)) + cp++; + + if (cp >= maxcp) + goto defaults; + + siz = precsize_aton(&cp); + + while (!isspace((unsigned char)*cp) && (cp < maxcp)) /* if trailing garbage or m */ + cp++; + + while (isspace((unsigned char)*cp) && (cp < maxcp)) + cp++; + + if (cp >= maxcp) + goto defaults; + + hp = precsize_aton(&cp); + + while (!isspace((unsigned char)*cp) && (cp < maxcp)) /* if trailing garbage or m */ + cp++; + + while (isspace((unsigned char)*cp) && (cp < maxcp)) + cp++; + + if (cp >= maxcp) + goto defaults; + + vp = precsize_aton(&cp); + + defaults: + + bcp = binary; + *bcp++ = (u_int8_t) 0; /* version byte */ + *bcp++ = siz; + *bcp++ = hp; + *bcp++ = vp; + PUTLONG(latit,bcp); + PUTLONG(longit,bcp); + PUTLONG(alt,bcp); + + return (16); /* size of RR in octets */ +} + +/* takes an on-the-wire LOC RR and formats it in a human readable format. */ +const char * +loc_ntoa(binary, ascii) + const u_char *binary; + char *ascii; +{ + static const char *error = "?"; + static char tmpbuf[sizeof +"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"]; + const u_char *cp = binary; + + int latdeg, latmin, latsec, latsecfrac; + int longdeg, longmin, longsec, longsecfrac; + char northsouth, eastwest; + const char *altsign; + int altmeters, altfrac; + + const u_int32_t referencealt = 100000 * 100; + + int32_t latval, longval, altval; + u_int32_t templ; + u_int8_t sizeval, hpval, vpval, versionval; + + char *sizestr, *hpstr, *vpstr; + + versionval = *cp++; + + if (ascii == NULL) + ascii = tmpbuf; + + if (versionval) { + (void) sprintf(ascii, "; error: unknown LOC RR version"); + return (ascii); + } + + sizeval = *cp++; + + hpval = *cp++; + vpval = *cp++; + + GETLONG(templ, cp); + latval = (templ - ((unsigned)1<<31)); + + GETLONG(templ, cp); + longval = (templ - ((unsigned)1<<31)); + + GETLONG(templ, cp); + if (templ < referencealt) { /* below WGS 84 spheroid */ + altval = referencealt - templ; + altsign = "-"; + } else { + altval = templ - referencealt; + altsign = ""; + } + + if (latval < 0) { + northsouth = 'S'; + latval = -latval; + } else + northsouth = 'N'; + + latsecfrac = latval % 1000; + latval = latval / 1000; + latsec = latval % 60; + latval = latval / 60; + latmin = latval % 60; + latval = latval / 60; + latdeg = latval; + + if (longval < 0) { + eastwest = 'W'; + longval = -longval; + } else + eastwest = 'E'; + + longsecfrac = longval % 1000; + longval = longval / 1000; + longsec = longval % 60; + longval = longval / 60; + longmin = longval % 60; + longval = longval / 60; + longdeg = longval; + + altfrac = altval % 100; + altmeters = (altval / 100); + + sizestr = strdup(precsize_ntoa(sizeval)); + hpstr = strdup(precsize_ntoa(hpval)); + vpstr = strdup(precsize_ntoa(vpval)); + + sprintf(ascii, + "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %s%d.%.2dm %sm %sm %sm", + latdeg, latmin, latsec, latsecfrac, northsouth, + longdeg, longmin, longsec, longsecfrac, eastwest, + altsign, altmeters, altfrac, + (sizestr != NULL) ? sizestr : error, + (hpstr != NULL) ? hpstr : error, + (vpstr != NULL) ? vpstr : error); + + if (sizestr != NULL) + free(sizestr); + if (hpstr != NULL) + free(hpstr); + if (vpstr != NULL) + free(vpstr); + + return (ascii); +} + + +/* Return the number of DNS hierarchy levels in the name. */ +int +dn_count_labels(const char *name) { + int i, len, count; + + len = strlen(name); + for (i = 0, count = 0; i < len; i++) { + /* XXX need to check for \. or use named's nlabels(). */ + if (name[i] == '.') + count++; + } + + /* don't count initial wildcard */ + if (name[0] == '*') + if (count) + count--; + + /* don't count the null label for root. */ + /* if terminating '.' not found, must adjust */ + /* count to include last label */ + if (len > 0 && name[len-1] != '.') + count++; + return (count); +} + + +/* + * Make dates expressed in seconds-since-Jan-1-1970 easy to read. + * SIG records are required to be printed like this, by the Secure DNS RFC. + */ +char * +p_secstodate (u_long secs) { + /* XXX nonreentrant */ + static char output[15]; /* YYYYMMDDHHMMSS and null */ + time_t clock = secs; + struct tm *time; + +#ifdef HAVE_TIME_R + gmtime_r(&clock, &time); +#else + time = gmtime(&clock); +#endif + time->tm_year += 1900; + time->tm_mon += 1; + sprintf(output, "%04d%02d%02d%02d%02d%02d", + time->tm_year, time->tm_mon, time->tm_mday, + time->tm_hour, time->tm_min, time->tm_sec); + return (output); +} + +u_int16_t +res_nametoclass(const char *buf, int *successp) { + unsigned long result; + char *endptr; + int success; + + result = sym_ston(__p_class_syms, buf, &success); + if (success) + goto done; + + if (strncasecmp(buf, "CLASS", 5) != 0 || + !isdigit((unsigned char)buf[5])) + goto done; + result = strtoul(buf + 5, &endptr, 10); + if (*endptr == '\0' && result <= 0xffff) + success = 1; + done: + if (successp) + *successp = success; + return (result); +} + +u_int16_t +res_nametotype(const char *buf, int *successp) { + unsigned long result; + char *endptr; + int success; + + result = sym_ston(__p_type_syms, buf, &success); + if (success) + goto done; + + if (strncasecmp(buf, "type", 4) != 0 || + !isdigit((unsigned char)buf[4])) + goto done; + result = strtoul(buf + 4, &endptr, 10); + if (*endptr == '\0' && result <= 0xffff) + success = 1; + done: + if (successp) + *successp = success; + return (result); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_debug.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_init.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/resolv/res_init.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/resolv/res_init.c (revision 109985) @@ -0,0 +1,733 @@ +/* + * Copyright (c) 1985, 1989, 1993 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; +static const char rcsid[] = "$Id: res_init.c,v 8.29 2002/05/31 06:05:31 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +/* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */ +#include + +#include "res_private.h" + +/* Options. Should all be left alone. */ +#define RESOLVSORT +#define DEBUG + +static void res_setoptions __P((res_state, const char *, const char *)); + +#ifdef RESOLVSORT +static const char sort_mask[] = "/&"; +#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL) +static u_int32_t net_mask __P((struct in_addr)); +#endif + +#if !defined(isascii) /* XXX - could be a function */ +# define isascii(c) (!(c & 0200)) +#endif + +/* + * Resolver state default settings. + */ + +/* + * Set up default settings. If the configuration file exist, the values + * there will have precedence. Otherwise, the server address is set to + * INADDR_ANY and the default domain name comes from the gethostname(). + * + * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1 + * rather than INADDR_ANY ("0.0.0.0") as the default name server address + * since it was noted that INADDR_ANY actually meant ``the first interface + * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface, + * it had to be "up" in order for you to reach your own name server. It + * was later decided that since the recommended practice is to always + * install local static routes through 127.0.0.1 for all your network + * interfaces, that we could solve this problem without a code change. + * + * The configuration file should always be used, since it is the only way + * to specify a default domain. If you are running a server on your local + * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1" + * in the configuration file. + * + * Return 0 if completes successfully, -1 on error + */ +int +res_ninit(res_state statp) { + extern int __res_vinit(res_state, int); + + return (__res_vinit(statp, 0)); +} + +/* This function has to be reachable by res_data.c but not publically. */ +int +__res_vinit(res_state statp, int preinit) { + register FILE *fp; + register char *cp, **pp; + register int n; + char buf[BUFSIZ]; + int nserv = 0; /* number of nameserver records read from file */ + int haveenv = 0; + int havesearch = 0; +#ifdef RESOLVSORT + int nsort = 0; + char *net; +#endif + int dots; + + if (!preinit) { + statp->retrans = RES_TIMEOUT; + statp->retry = RES_DFLRETRY; + statp->options = RES_DEFAULT; + statp->id = res_randomid(); + } + + if ((statp->options & RES_INIT) != 0) + res_ndestroy(statp); + +#ifdef USELOOPBACK + statp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); +#else + statp->nsaddr.sin_addr.s_addr = INADDR_ANY; +#endif + statp->nsaddr.sin_family = AF_INET; + statp->nsaddr.sin_port = htons(NAMESERVER_PORT); +#ifdef HAVE_SA_LEN + statp->nsaddr.sin_len = sizeof(struct sockaddr_in); +#endif + statp->nscount = 1; + statp->ndots = 1; + statp->pfcode = 0; + statp->_vcsock = -1; + statp->_flags = 0; + statp->qhook = NULL; + statp->rhook = NULL; + statp->_u._ext.nscount = 0; + statp->_u._ext.ext = malloc(sizeof(*statp->_u._ext.ext)); + if (statp->_u._ext.ext != NULL) { + memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext)); + statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr; + strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa"); + strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int"); + strcpy(statp->_u._ext.ext->bsuffix, "ip6.arpa"); + } +#ifdef RESOLVSORT + statp->nsort = 0; +#endif + + /* Allow user to override the local domain definition */ + if ((cp = getenv("LOCALDOMAIN")) != NULL) { + (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); + statp->defdname[sizeof(statp->defdname) - 1] = '\0'; + haveenv++; + + /* + * Set search list to be blank-separated strings + * from rest of env value. Permits users of LOCALDOMAIN + * to still have a search list, and anyone to set the + * one that they want to use as an individual (even more + * important now that the rfc1535 stuff restricts searches) + */ + cp = statp->defdname; + pp = statp->dnsrch; + *pp++ = cp; + for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { + if (*cp == '\n') /* silly backwards compat */ + break; + else if (*cp == ' ' || *cp == '\t') { + *cp = 0; + n = 1; + } else if (n) { + *pp++ = cp; + n = 0; + havesearch = 1; + } + } + /* null terminate last domain if there are excess */ + while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n') + cp++; + *cp = '\0'; + *pp++ = 0; + } + +#define MATCH(line, name) \ + (!strncmp(line, name, sizeof(name) - 1) && \ + (line[sizeof(name) - 1] == ' ' || \ + line[sizeof(name) - 1] == '\t')) + + if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { + /* read the config file */ + while (fgets(buf, sizeof(buf), fp) != NULL) { + /* skip comments */ + if (*buf == ';' || *buf == '#') + continue; + /* read default domain name */ + if (MATCH(buf, "domain")) { + if (haveenv) /* skip if have from environ */ + continue; + cp = buf + sizeof("domain") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + if ((*cp == '\0') || (*cp == '\n')) + continue; + strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); + statp->defdname[sizeof(statp->defdname) - 1] = '\0'; + if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL) + *cp = '\0'; + havesearch = 0; + continue; + } + /* set search list */ + if (MATCH(buf, "search")) { + if (haveenv) /* skip if have from environ */ + continue; + cp = buf + sizeof("search") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + if ((*cp == '\0') || (*cp == '\n')) + continue; + strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); + statp->defdname[sizeof(statp->defdname) - 1] = '\0'; + if ((cp = strchr(statp->defdname, '\n')) != NULL) + *cp = '\0'; + /* + * Set search list to be blank-separated strings + * on rest of line. + */ + cp = statp->defdname; + pp = statp->dnsrch; + *pp++ = cp; + for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { + if (*cp == ' ' || *cp == '\t') { + *cp = 0; + n = 1; + } else if (n) { + *pp++ = cp; + n = 0; + } + } + /* null terminate last domain if there are excess */ + while (*cp != '\0' && *cp != ' ' && *cp != '\t') + cp++; + *cp = '\0'; + *pp++ = 0; + havesearch = 1; + continue; + } + /* read nameservers to query */ + if (MATCH(buf, "nameserver") && nserv < MAXNS) { + struct addrinfo hints, *ai; + char sbuf[NI_MAXSERV]; + const size_t minsiz = + sizeof(statp->_u._ext.ext->nsaddrs[0]); + + cp = buf + sizeof("nameserver") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + cp[strcspn(cp, ";# \t\n")] = '\0'; + if ((*cp != '\0') && (*cp != '\n')) { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + hints.ai_flags = AI_NUMERICHOST; + sprintf(sbuf, "%u", NAMESERVER_PORT); + if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 && + ai->ai_addrlen <= minsiz) { + if (statp->_u._ext.ext != NULL) { + memcpy(&statp->_u._ext.ext->nsaddrs[nserv], + ai->ai_addr, ai->ai_addrlen); + } + if (ai->ai_addrlen <= + sizeof(statp->nsaddr_list[nserv])) { + memcpy(&statp->nsaddr_list[nserv], + ai->ai_addr, ai->ai_addrlen); + } else + statp->nsaddr_list[nserv].sin_family = 0; + freeaddrinfo(ai); + nserv++; + } + } + continue; + } +#ifdef RESOLVSORT + if (MATCH(buf, "sortlist")) { + struct in_addr a; + + cp = buf + sizeof("sortlist") - 1; + while (nsort < MAXRESOLVSORT) { + while (*cp == ' ' || *cp == '\t') + cp++; + if (*cp == '\0' || *cp == '\n' || *cp == ';') + break; + net = cp; + while (*cp && !ISSORTMASK(*cp) && *cp != ';' && + isascii(*cp) && !isspace((unsigned char)*cp)) + cp++; + n = *cp; + *cp = 0; + if (inet_aton(net, &a)) { + statp->sort_list[nsort].addr = a; + if (ISSORTMASK(n)) { + *cp++ = n; + net = cp; + while (*cp && *cp != ';' && + isascii(*cp) && + !isspace((unsigned char)*cp)) + cp++; + n = *cp; + *cp = 0; + if (inet_aton(net, &a)) { + statp->sort_list[nsort].mask = a.s_addr; + } else { + statp->sort_list[nsort].mask = + net_mask(statp->sort_list[nsort].addr); + } + } else { + statp->sort_list[nsort].mask = + net_mask(statp->sort_list[nsort].addr); + } + nsort++; + } + *cp = n; + } + continue; + } +#endif + if (MATCH(buf, "options")) { + res_setoptions(statp, buf + sizeof("options") - 1, "conf"); + continue; + } + } + if (nserv > 1) + statp->nscount = nserv; +#ifdef RESOLVSORT + statp->nsort = nsort; +#endif + (void) fclose(fp); + } +/* + * Last chance to get a nameserver. This should not normally + * be necessary + */ +#ifdef NO_RESOLV_CONF + if(nserv == 0) + nserv = get_nameservers(statp); +#endif + + if (statp->defdname[0] == 0 && + gethostname(buf, sizeof(statp->defdname) - 1) == 0 && + (cp = strchr(buf, '.')) != NULL) + strcpy(statp->defdname, cp + 1); + + /* find components of local domain that might be searched */ + if (havesearch == 0) { + pp = statp->dnsrch; + *pp++ = statp->defdname; + *pp = NULL; + + dots = 0; + for (cp = statp->defdname; *cp; cp++) + dots += (*cp == '.'); + + cp = statp->defdname; + while (pp < statp->dnsrch + MAXDFLSRCH) { + if (dots < LOCALDOMAINPARTS) + break; + cp = strchr(cp, '.') + 1; /* we know there is one */ + *pp++ = cp; + dots--; + } + *pp = NULL; +#ifdef DEBUG + if (statp->options & RES_DEBUG) { + printf(";; res_init()... default dnsrch list:\n"); + for (pp = statp->dnsrch; *pp; pp++) + printf(";;\t%s\n", *pp); + printf(";;\t..END..\n"); + } +#endif + } + + if ((cp = getenv("RES_OPTIONS")) != NULL) + res_setoptions(statp, cp, "env"); + statp->options |= RES_INIT; + return (0); +} + +static void +res_setoptions(res_state statp, const char *options, const char *source) +{ + const char *cp = options; + int i; + struct __res_state_ext *ext = statp->_u._ext.ext; + +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_setoptions(\"%s\", \"%s\")...\n", + options, source); +#endif + while (*cp) { + /* skip leading and inner runs of spaces */ + while (*cp == ' ' || *cp == '\t') + cp++; + /* search for and process individual options */ + if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) { + i = atoi(cp + sizeof("ndots:") - 1); + if (i <= RES_MAXNDOTS) + statp->ndots = i; + else + statp->ndots = RES_MAXNDOTS; +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";;\tndots=%d\n", statp->ndots); +#endif + } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) { + i = atoi(cp + sizeof("timeout:") - 1); + if (i <= RES_MAXRETRANS) + statp->retrans = i; + else + statp->retrans = RES_MAXRETRANS; + } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){ + i = atoi(cp + sizeof("attempts:") - 1); + if (i <= RES_MAXRETRY) + statp->retry = i; + else + statp->retry = RES_MAXRETRY; + } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) { +#ifdef DEBUG + if (!(statp->options & RES_DEBUG)) { + printf(";; res_setoptions(\"%s\", \"%s\")..\n", + options, source); + statp->options |= RES_DEBUG; + } + printf(";;\tdebug\n"); +#endif + } else if (!strncmp(cp, "no_tld_query", + sizeof("no_tld_query") - 1) || + !strncmp(cp, "no-tld-query", + sizeof("no-tld-query") - 1)) { + statp->options |= RES_NOTLDQUERY; + } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) { + statp->options |= RES_USE_INET6; + } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) { + statp->options |= RES_ROTATE; + } else if (!strncmp(cp, "no-check-names", + sizeof("no-check-names") - 1)) { + statp->options |= RES_NOCHECKNAME; + } +#ifdef RES_USE_EDNS0 + else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) { + statp->options |= RES_USE_EDNS0; + } +#endif + else if (!strncmp(cp, "a6", sizeof("a6") - 1)) { + statp->options |= RES_USE_A6; + } + else if (!strncmp(cp, "dname", sizeof("dname") - 1)) { + statp->options |= RES_USE_DNAME; + } + else if (!strncmp(cp, "nibble:", sizeof("nibble:") - 1)) { + if (ext == NULL) + goto skip; + cp += sizeof("nibble:") - 1; + i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix) - 1); + strncpy(ext->nsuffix, cp, i); + ext->nsuffix[i] = '\0'; + } + else if (!strncmp(cp, "nibble2:", sizeof("nibble2:") - 1)) { + if (ext == NULL) + goto skip; + cp += sizeof("nibble2:") - 1; + i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix2) - 1); + strncpy(ext->nsuffix2, cp, i); + ext->nsuffix2[i] = '\0'; + } + else if (!strncmp(cp, "bitstring:", sizeof("bitstring:") - 1)) { + if (ext == NULL) + goto skip; + cp += sizeof("bitstring:") - 1; + i = MIN(strcspn(cp, " \t"), sizeof(ext->bsuffix) - 1); + strncpy(ext->bsuffix, cp, i); + ext->bsuffix[i] = '\0'; + } + else if (!strncmp(cp, "v6revmode:", sizeof("v6revmode:") - 1)) { + cp += sizeof("v6revmode:") - 1; + /* "nibble" and "bitstring" used to be valid */ + if (!strncmp(cp, "single", sizeof("single") - 1)) { + statp->options |= RES_NO_NIBBLE2; + } else if (!strncmp(cp, "both", sizeof("both") - 1)) { + statp->options &= + ~RES_NO_NIBBLE2; + } + } + else { + /* XXX - print a warning here? */ + } + skip: + /* skip to next run of spaces */ + while (*cp && *cp != ' ' && *cp != '\t') + cp++; + } +} + +#ifdef RESOLVSORT +/* XXX - should really support CIDR which means explicit masks always. */ +static u_int32_t +net_mask(in) /* XXX - should really use system's version of this */ + struct in_addr in; +{ + register u_int32_t i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return (htonl(IN_CLASSA_NET)); + else if (IN_CLASSB(i)) + return (htonl(IN_CLASSB_NET)); + return (htonl(IN_CLASSC_NET)); +} +#endif + +u_int +res_randomid(void) { + struct timeval now; + + gettimeofday(&now, NULL); + return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid())); +} + +/* + * This routine is for closing the socket if a virtual circuit is used and + * the program wants to close it. This provides support for endhostent() + * which expects to close the socket. + * + * This routine is not expected to be user visible. + */ +void +res_nclose(res_state statp) { + int ns; + + if (statp->_vcsock >= 0) { + (void) close(statp->_vcsock); + statp->_vcsock = -1; + statp->_flags &= ~(RES_F_VC | RES_F_CONN); + } + for (ns = 0; ns < statp->_u._ext.nscount; ns++) { + if (statp->_u._ext.nssocks[ns] != -1) { + (void) close(statp->_u._ext.nssocks[ns]); + statp->_u._ext.nssocks[ns] = -1; + } + } +} + +void +res_ndestroy(res_state statp) { + res_nclose(statp); + if (statp->_u._ext.ext != NULL) + free(statp->_u._ext.ext); + statp->options &= ~RES_INIT; + statp->_u._ext.ext = NULL; +} + +const char * +res_get_nibblesuffix(res_state statp) { + if (statp->_u._ext.ext) + return (statp->_u._ext.ext->nsuffix); + return ("ip6.arpa"); +} + +const char * +res_get_nibblesuffix2(res_state statp) { + if (statp->_u._ext.ext) + return (statp->_u._ext.ext->nsuffix2); + return ("ip6.int"); +} + +const char * +res_get_bitstringsuffix(res_state statp) { + if (statp->_u._ext.ext) + return (statp->_u._ext.ext->bsuffix); + return ("ip6.arpa"); +} + +void +res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) { + int i, nserv; + size_t size; + + /* close open servers */ + res_nclose(statp); + + /* cause rtt times to be forgotten */ + statp->_u._ext.nscount = 0; + + nserv = 0; + for (i = 0; i < cnt && nserv < MAXNS; i++) { + switch (set->sin.sin_family) { + case AF_INET: + size = sizeof(set->sin); + if (statp->_u._ext.ext) + memcpy(&statp->_u._ext.ext->nsaddrs[nserv], + &set->sin, size); + if (size <= sizeof(statp->nsaddr_list[nserv])) + memcpy(&statp->nsaddr_list[nserv], + &set->sin, size); + else + statp->nsaddr_list[nserv].sin_family = 0; + nserv++; + break; + +#ifdef HAS_INET6_STRUCTS + case AF_INET6: + size = sizeof(set->sin6); + if (statp->_u._ext.ext) + memcpy(&statp->_u._ext.ext->nsaddrs[nserv], + &set->sin6, size); + if (size <= sizeof(statp->nsaddr_list[nserv])) + memcpy(&statp->nsaddr_list[nserv], + &set->sin6, size); + else + statp->nsaddr_list[nserv].sin_family = 0; + nserv++; + break; +#endif + + default: + break; + } + set++; + } + statp->nscount = nserv; + +} + +int +res_getservers(res_state statp, union res_sockaddr_union *set, int cnt) { + int i; + size_t size; + u_int16_t family; + + for (i = 0; i < statp->nscount && i < cnt; i++) { + if (statp->_u._ext.ext) + family = statp->_u._ext.ext->nsaddrs[i].sin.sin_family; + else + family = statp->nsaddr_list[i].sin_family; + + switch (family) { + case AF_INET: + size = sizeof(set->sin); + if (statp->_u._ext.ext) + memcpy(&set->sin, + &statp->_u._ext.ext->nsaddrs[i], + size); + else + memcpy(&set->sin, &statp->nsaddr_list[i], + size); + break; + +#ifdef HAS_INET6_STRUCTS + case AF_INET6: + size = sizeof(set->sin6); + if (statp->_u._ext.ext) + memcpy(&set->sin6, + &statp->_u._ext.ext->nsaddrs[i], + size); + else + memcpy(&set->sin6, &statp->nsaddr_list[i], + size); + break; +#endif + + default: + set->sin.sin_family = 0; + break; + } + set++; + } + return (statp->nscount); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_init.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_private.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/resolv/res_private.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/resolv/res_private.h (revision 109985) @@ -0,0 +1,21 @@ +#ifndef res_private_h +#define res_private_h + +struct __res_state_ext { + union res_sockaddr_union nsaddrs[MAXNS]; + struct sort_list { + int af; + union { + struct in_addr ina; + struct in6_addr in6a; + } addr, mask; + } sort_list[MAXRESOLVSORT]; + char nsuffix[64]; + char bsuffix[64]; + char nsuffix2[64]; +}; + +extern int +res_ourserver_p(const res_state statp, const struct sockaddr *sa); + +#endif Property changes on: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_private.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_findzonecut.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/resolv/res_findzonecut.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/resolv/res_findzonecut.c (revision 109985) @@ -0,0 +1,687 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: res_findzonecut.c,v 8.16 2002/04/12 06:27:46 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* Import. */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "port_after.h" + +#include + +/* Data structures. */ + +typedef struct rr_a { + LINK(struct rr_a) link; + union res_sockaddr_union addr; +} rr_a; +typedef LIST(rr_a) rrset_a; + +typedef struct rr_ns { + LINK(struct rr_ns) link; + const char * name; + int have_v4; + int have_v6; + rrset_a addrs; +} rr_ns; +typedef LIST(rr_ns) rrset_ns; + +/* Forward. */ + +static int satisfy(res_state, const char *, rrset_ns *, + union res_sockaddr_union *, int); +static int add_addrs(res_state, rr_ns *, + union res_sockaddr_union *, int); +static int get_soa(res_state, const char *, ns_class, int, + char *, size_t, char *, size_t, + rrset_ns *); +static int get_ns(res_state, const char *, ns_class, int, rrset_ns *); +static int get_glue(res_state, ns_class, int, rrset_ns *); +static int save_ns(res_state, ns_msg *, ns_sect, + const char *, ns_class, int, rrset_ns *); +static int save_a(res_state, ns_msg *, ns_sect, + const char *, ns_class, int, rr_ns *); +static void free_nsrrset(rrset_ns *); +static void free_nsrr(rrset_ns *, rr_ns *); +static rr_ns * find_ns(rrset_ns *, const char *); +static int do_query(res_state, const char *, ns_class, ns_type, + u_char *, ns_msg *); +static void res_dprintf(const char *, ...) ISC_FORMAT_PRINTF(1, 2); + +/* Macros. */ + +#define DPRINTF(x) do {\ + int save_errno = errno; \ + if ((statp->options & RES_DEBUG) != 0) res_dprintf x; \ + errno = save_errno; \ + } while (0) + +/* Public. */ + +/* + * int + * res_findzonecut(res, dname, class, zname, zsize, addrs, naddrs) + * find enclosing zone for a , and some server addresses + * parameters: + * res - resolver context to work within (is modified) + * dname - domain name whose enclosing zone is desired + * class - class of dname (and its enclosing zone) + * zname - found zone name + * zsize - allocated size of zname + * addrs - found server addresses + * naddrs - max number of addrs + * return values: + * < 0 - an error occurred (check errno) + * = 0 - zname is now valid, but addrs[] wasn't changed + * > 0 - zname is now valid, and return value is number of addrs[] found + * notes: + * this function calls res_nsend() which means it depends on correctly + * functioning recursive nameservers (usually defined in /etc/resolv.conf + * or its local equivilent). + * + * we start by asking for an SOA. if we get one as an + * answer, that just means is a zone top, which is fine. + * more than likely we'll be told to go pound sand, in the form of a + * negative answer. + * + * note that we are not prepared to deal with referrals since that would + * only come from authority servers and our correctly functioning local + * recursive server would have followed the referral and got us something + * more definite. + * + * if the authority section contains an SOA, this SOA should also be the + * closest enclosing zone, since any intermediary zone cuts would've been + * returned as referrals and dealt with by our correctly functioning local + * recursive name server. but an SOA in the authority section should NOT + * match our dname (since that would have been returned in the answer + * section). an authority section SOA has to be "above" our dname. + * + * however, since authority section SOA's were once optional, it's + * possible that we'll have to go hunting for the enclosing SOA by + * ripping labels off the front of our dname -- this is known as "doing + * it the hard way." + * + * ultimately we want some server addresses, which are ideally the ones + * pertaining to the SOA.MNAME, but only if there is a matching NS RR. + * so the second phase (after we find an SOA) is to go looking for the + * NS RRset for that SOA's zone. + * + * no answer section processed by this code is allowed to contain CNAME + * or DNAME RR's. for the SOA query this means we strip a label and + * keep going. for the NS and A queries this means we just give up. + */ + +int +res_findzonecut(res_state statp, const char *dname, ns_class class, int opts, + char *zname, size_t zsize, struct in_addr *addrs, int naddrs) { + int result, i; + union res_sockaddr_union *u; + + + opts |= RES_IPV4ONLY; + opts &= ~RES_IPV6ONLY; + + u = calloc(naddrs, sizeof(*u)); + if (u == NULL) + return(-1); + + result = res_findzonecut2(statp, dname, class, opts, zname, zsize, + u, naddrs); + + for (i = 0; i < result; i++) { + addrs[i] = u[i].sin.sin_addr; + } + free(u); + return (result); +} + +int +res_findzonecut2(res_state statp, const char *dname, ns_class class, int opts, + char *zname, size_t zsize, union res_sockaddr_union *addrs, + int naddrs) +{ + char mname[NS_MAXDNAME]; + u_long save_pfcode; + rrset_ns nsrrs; + int n; + + DPRINTF(("START dname='%s' class=%s, zsize=%ld, naddrs=%d", + dname, p_class(class), (long)zsize, naddrs)); + save_pfcode = statp->pfcode; + statp->pfcode |= RES_PRF_HEAD2 | RES_PRF_HEAD1 | RES_PRF_HEADX | + RES_PRF_QUES | RES_PRF_ANS | + RES_PRF_AUTH | RES_PRF_ADD; + INIT_LIST(nsrrs); + + DPRINTF(("get the soa, and see if it has enough glue")); + if ((n = get_soa(statp, dname, class, opts, zname, zsize, + mname, sizeof mname, &nsrrs)) < 0 || + ((opts & RES_EXHAUSTIVE) == 0 && + (n = satisfy(statp, mname, &nsrrs, addrs, naddrs)) > 0)) + goto done; + + DPRINTF(("get the ns rrset and see if it has enough glue")); + if ((n = get_ns(statp, zname, class, opts, &nsrrs)) < 0 || + ((opts & RES_EXHAUSTIVE) == 0 && + (n = satisfy(statp, mname, &nsrrs, addrs, naddrs)) > 0)) + goto done; + + DPRINTF(("get the missing glue and see if it's finally enough")); + if ((n = get_glue(statp, class, opts, &nsrrs)) >= 0) + n = satisfy(statp, mname, &nsrrs, addrs, naddrs); + + done: + DPRINTF(("FINISH n=%d (%s)", n, (n < 0) ? strerror(errno) : "OK")); + free_nsrrset(&nsrrs); + statp->pfcode = save_pfcode; + return (n); +} + +/* Private. */ + +static int +satisfy(res_state statp, const char *mname, rrset_ns *nsrrsp, + union res_sockaddr_union *addrs, int naddrs) +{ + rr_ns *nsrr; + int n, x; + + n = 0; + nsrr = find_ns(nsrrsp, mname); + if (nsrr != NULL) { + x = add_addrs(statp, nsrr, addrs, naddrs); + addrs += x; + naddrs -= x; + n += x; + } + for (nsrr = HEAD(*nsrrsp); + nsrr != NULL && naddrs > 0; + nsrr = NEXT(nsrr, link)) + if (ns_samename(nsrr->name, mname) != 1) { + x = add_addrs(statp, nsrr, addrs, naddrs); + addrs += x; + naddrs -= x; + n += x; + } + DPRINTF(("satisfy(%s): %d", mname, n)); + return (n); +} + +static int +add_addrs(res_state statp, rr_ns *nsrr, + union res_sockaddr_union *addrs, int naddrs) +{ + rr_a *arr; + int n = 0; + + for (arr = HEAD(nsrr->addrs); arr != NULL; arr = NEXT(arr, link)) { + if (naddrs <= 0) + return (0); + *addrs++ = arr->addr; + naddrs--; + n++; + } + DPRINTF(("add_addrs: %d", n)); + return (n); +} + +static int +get_soa(res_state statp, const char *dname, ns_class class, int opts, + char *zname, size_t zsize, char *mname, size_t msize, + rrset_ns *nsrrsp) +{ + char tname[NS_MAXDNAME]; + u_char resp[NS_PACKETSZ]; + int n, i, ancount, nscount; + ns_sect sect; + ns_msg msg; + u_int rcode; + + /* + * Find closest enclosing SOA, even if it's for the root zone. + */ + + /* First canonicalize dname (exactly one unescaped trailing "."). */ + if (ns_makecanon(dname, tname, sizeof tname) < 0) + return (-1); + dname = tname; + + /* Now grovel the subdomains, hunting for an SOA answer or auth. */ + for (;;) { + /* Leading or inter-label '.' are skipped here. */ + while (*dname == '.') + dname++; + + /* Is there an SOA? */ + n = do_query(statp, dname, class, ns_t_soa, resp, &msg); + if (n < 0) { + DPRINTF(("get_soa: do_query('%s', %s) failed (%d)", + dname, p_class(class), n)); + return (-1); + } + if (n > 0) { + DPRINTF(("get_soa: CNAME or DNAME found")); + sect = ns_s_max, n = 0; + } else { + rcode = ns_msg_getflag(msg, ns_f_rcode); + ancount = ns_msg_count(msg, ns_s_an); + nscount = ns_msg_count(msg, ns_s_ns); + if (ancount > 0 && rcode == ns_r_noerror) + sect = ns_s_an, n = ancount; + else if (nscount > 0) + sect = ns_s_ns, n = nscount; + else + sect = ns_s_max, n = 0; + } + for (i = 0; i < n; i++) { + const char *t; + const u_char *rdata; + int rdlen; + ns_rr rr; + + if (ns_parserr(&msg, sect, i, &rr) < 0) { + DPRINTF(("get_soa: ns_parserr(%s, %d) failed", + p_section(sect, ns_o_query), i)); + return (-1); + } + if (ns_rr_type(rr) == ns_t_cname || + ns_rr_type(rr) == ns_t_dname) + break; + if (ns_rr_type(rr) != ns_t_soa || + ns_rr_class(rr) != class) + continue; + t = ns_rr_name(rr); + switch (sect) { + case ns_s_an: + if (ns_samedomain(dname, t) == 0) { + DPRINTF(("get_soa: ns_samedomain('%s', '%s') == 0", + dname, t)); + errno = EPROTOTYPE; + return (-1); + } + break; + case ns_s_ns: + if (ns_samename(dname, t) == 1 || + ns_samedomain(dname, t) == 0) { + DPRINTF(("get_soa: ns_samename() || !ns_samedomain('%s', '%s')", + dname, t)); + errno = EPROTOTYPE; + return (-1); + } + break; + default: + abort(); + } + if (strlen(t) + 1 > zsize) { + DPRINTF(("get_soa: zname(%d) too small (%d)", + zsize, strlen(t) + 1)); + errno = EMSGSIZE; + return (-1); + } + strcpy(zname, t); + rdata = ns_rr_rdata(rr); + rdlen = ns_rr_rdlen(rr); + if (ns_name_uncompress(resp, ns_msg_end(msg), rdata, + mname, msize) < 0) { + DPRINTF(("get_soa: ns_name_uncompress failed")); + return (-1); + } + if (save_ns(statp, &msg, ns_s_ns, + zname, class, opts, nsrrsp) < 0) { + DPRINTF(("get_soa: save_ns failed")); + return (-1); + } + return (0); + } + + /* If we're out of labels, then not even "." has an SOA! */ + if (*dname == '\0') + break; + + /* Find label-terminating "."; top of loop will skip it. */ + while (*dname != '.') { + if (*dname == '\\') + if (*++dname == '\0') { + errno = EMSGSIZE; + return (-1); + } + dname++; + } + } + DPRINTF(("get_soa: out of labels")); + errno = EDESTADDRREQ; + return (-1); +} + +static int +get_ns(res_state statp, const char *zname, ns_class class, int opts, + rrset_ns *nsrrsp) +{ + u_char resp[NS_PACKETSZ]; + ns_msg msg; + int n; + + /* Go and get the NS RRs for this zone. */ + n = do_query(statp, zname, class, ns_t_ns, resp, &msg); + if (n != 0) { + DPRINTF(("get_ns: do_query('%s', %s) failed (%d)", + zname, p_class(class), n)); + return (-1); + } + + /* Remember the NS RRs and associated A RRs that came back. */ + if (save_ns(statp, &msg, ns_s_an, zname, class, opts, nsrrsp) < 0) { + DPRINTF(("get_ns save_ns('%s', %s) failed", + zname, p_class(class))); + return (-1); + } + + return (0); +} + +static int +get_glue(res_state statp, ns_class class, int opts, rrset_ns *nsrrsp) { + rr_ns *nsrr, *nsrr_n; + + /* Go and get the A RRs for each empty NS RR on our list. */ + for (nsrr = HEAD(*nsrrsp); nsrr != NULL; nsrr = nsrr_n) { + u_char resp[NS_PACKETSZ]; + ns_msg msg; + int n; + + nsrr_n = NEXT(nsrr, link); + + if (!nsrr->have_v4) { + n = do_query(statp, nsrr->name, class, ns_t_a, + resp, &msg); + if (n < 0) { + DPRINTF(("get_glue: do_query('%s', %s') failed", + nsrr->name, p_class(class))); + return (-1); + } + if (n > 0) { + DPRINTF(( + "get_glue: do_query('%s', %s') CNAME or DNAME found", + nsrr->name, p_class(class))); + } + if (save_a(statp, &msg, ns_s_an, nsrr->name, class, + opts, nsrr) < 0) { + DPRINTF(("get_glue: save_r('%s', %s) failed", + nsrr->name, p_class(class))); + return (-1); + } + } + + if (!nsrr->have_v6) { + n = do_query(statp, nsrr->name, class, ns_t_aaaa, + resp, &msg); + if (n < 0) { + DPRINTF(("get_glue: do_query('%s', %s') failed", + nsrr->name, p_class(class))); + return (-1); + } + if (n > 0) { + DPRINTF(( + "get_glue: do_query('%s', %s') CNAME or DNAME found", + nsrr->name, p_class(class))); + } + if (save_a(statp, &msg, ns_s_an, nsrr->name, class, + opts, nsrr) < 0) { + DPRINTF(("get_glue: save_r('%s', %s) failed", + nsrr->name, p_class(class))); + return (-1); + } + } + + /* If it's still empty, it's just chaff. */ + if (EMPTY(nsrr->addrs)) { + DPRINTF(("get_glue: removing empty '%s' NS", + nsrr->name)); + free_nsrr(nsrrsp, nsrr); + } + } + return (0); +} + +static int +save_ns(res_state statp, ns_msg *msg, ns_sect sect, + const char *owner, ns_class class, int opts, + rrset_ns *nsrrsp) +{ + int i; + + for (i = 0; i < ns_msg_count(*msg, sect); i++) { + char tname[MAXDNAME]; + const u_char *rdata; + rr_ns *nsrr; + ns_rr rr; + int rdlen; + + if (ns_parserr(msg, sect, i, &rr) < 0) { + DPRINTF(("save_ns: ns_parserr(%s, %d) failed", + p_section(sect, ns_o_query), i)); + return (-1); + } + if (ns_rr_type(rr) != ns_t_ns || + ns_rr_class(rr) != class || + ns_samename(ns_rr_name(rr), owner) != 1) + continue; + nsrr = find_ns(nsrrsp, ns_rr_name(rr)); + if (nsrr == NULL) { + nsrr = malloc(sizeof *nsrr); + if (nsrr == NULL) { + DPRINTF(("save_ns: malloc failed")); + return (-1); + } + rdata = ns_rr_rdata(rr); + rdlen = ns_rr_rdlen(rr); + if (ns_name_uncompress(ns_msg_base(*msg), + ns_msg_end(*msg), rdata, + tname, sizeof tname) < 0) { + DPRINTF(("save_ns: ns_name_uncompress failed")); + free(nsrr); + return (-1); + } + nsrr->name = strdup(tname); + if (nsrr->name == NULL) { + DPRINTF(("save_ns: strdup failed")); + free(nsrr); + return (-1); + } + INIT_LINK(nsrr, link); + INIT_LIST(nsrr->addrs); + nsrr->have_v4 = 0; + nsrr->have_v6 = 0; + APPEND(*nsrrsp, nsrr, link); + } + if (save_a(statp, msg, ns_s_ar, + nsrr->name, class, opts, nsrr) < 0) { + DPRINTF(("save_ns: save_r('%s', %s) failed", + nsrr->name, p_class(class))); + return (-1); + } + } + return (0); +} + +static int +save_a(res_state statp, ns_msg *msg, ns_sect sect, + const char *owner, ns_class class, int opts, + rr_ns *nsrr) +{ + int i; + + for (i = 0; i < ns_msg_count(*msg, sect); i++) { + ns_rr rr; + rr_a *arr; + + if (ns_parserr(msg, sect, i, &rr) < 0) { + DPRINTF(("save_a: ns_parserr(%s, %d) failed", + p_section(sect, ns_o_query), i)); + return (-1); + } + if ((ns_rr_type(rr) != ns_t_a && ns_rr_type(rr) != ns_t_aaaa) || + ns_rr_class(rr) != class || + ns_samename(ns_rr_name(rr), owner) != 1 || + ns_rr_rdlen(rr) != NS_INADDRSZ) + continue; + if ((opts & RES_IPV6ONLY) != 0 && ns_rr_type(rr) != ns_t_aaaa) + continue; + if ((opts & RES_IPV4ONLY) != 0 && ns_rr_type(rr) != ns_t_a) + continue; + arr = malloc(sizeof *arr); + if (arr == NULL) { + DPRINTF(("save_a: malloc failed")); + return (-1); + } + INIT_LINK(arr, link); + memset(&arr->addr, 0, sizeof(arr->addr)); + switch (ns_rr_type(rr)) { + case ns_t_a: + arr->addr.sin.sin_family = AF_INET; +#ifdef HAVE_SA_LEN + arr->addr.sin.sin_len = sizeof(arr->addr.sin); +#endif + memcpy(&arr->addr.sin.sin_addr, ns_rr_rdata(rr), + NS_INADDRSZ); + arr->addr.sin.sin_port = htons(NAMESERVER_PORT); + nsrr->have_v4 = 1; + break; + case ns_t_aaaa: + arr->addr.sin6.sin6_family = AF_INET6; +#ifdef HAVE_SA_LEN + arr->addr.sin6.sin6_len = sizeof(arr->addr.sin6); +#endif + memcpy(&arr->addr.sin6.sin6_addr, ns_rr_rdata(rr), 16); + arr->addr.sin.sin_port = htons(NAMESERVER_PORT); + nsrr->have_v6 = 1; + break; + default: + abort(); + } + APPEND(nsrr->addrs, arr, link); + } + return (0); +} + +static void +free_nsrrset(rrset_ns *nsrrsp) { + rr_ns *nsrr; + + while ((nsrr = HEAD(*nsrrsp)) != NULL) + free_nsrr(nsrrsp, nsrr); +} + +static void +free_nsrr(rrset_ns *nsrrsp, rr_ns *nsrr) { + rr_a *arr; + char *tmp; + + while ((arr = HEAD(nsrr->addrs)) != NULL) { + UNLINK(nsrr->addrs, arr, link); + free(arr); + } + DE_CONST(nsrr->name, tmp); + free(tmp); + UNLINK(*nsrrsp, nsrr, link); + free(nsrr); +} + +static rr_ns * +find_ns(rrset_ns *nsrrsp, const char *dname) { + rr_ns *nsrr; + + for (nsrr = HEAD(*nsrrsp); nsrr != NULL; nsrr = NEXT(nsrr, link)) + if (ns_samename(nsrr->name, dname) == 1) + return (nsrr); + return (NULL); +} + +static int +do_query(res_state statp, const char *dname, ns_class class, ns_type qtype, + u_char *resp, ns_msg *msg) +{ + u_char req[NS_PACKETSZ]; + int i, n; + + n = res_nmkquery(statp, ns_o_query, dname, class, qtype, + NULL, 0, NULL, req, NS_PACKETSZ); + if (n < 0) { + DPRINTF(("do_query: res_nmkquery failed")); + return (-1); + } + n = res_nsend(statp, req, n, resp, NS_PACKETSZ); + if (n < 0) { + DPRINTF(("do_query: res_nsend failed")); + return (-1); + } + if (n == 0) { + DPRINTF(("do_query: res_nsend returned 0")); + errno = EMSGSIZE; + return (-1); + } + if (ns_initparse(resp, n, msg) < 0) { + DPRINTF(("do_query: ns_initparse failed")); + return (-1); + } + n = 0; + for (i = 0; i < ns_msg_count(*msg, ns_s_an); i++) { + ns_rr rr; + + if (ns_parserr(msg, ns_s_an, i, &rr) < 0) { + DPRINTF(("do_query: ns_parserr failed")); + return (-1); + } + n += (ns_rr_class(rr) == class && + (ns_rr_type(rr) == ns_t_cname || + ns_rr_type(rr) == ns_t_dname)); + } + return (n); +} + +static void +res_dprintf(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + fputs(";; res_findzonecut: ", stderr); + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); + va_end(ap); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_findzonecut.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_send.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/resolv/res_send.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/resolv/res_send.c (revision 109985) @@ -0,0 +1,1026 @@ +/* + * Copyright (c) 1985, 1989, 1993 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: res_send.c,v 8.49 2002/03/29 21:50:51 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Send query to name server and wait for reply. + */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "port_after.h" + +/* Options. Leave them on. */ +#define DEBUG +#include "res_debug.h" +#include "res_private.h" + +#define EXT(res) ((res)->_u._ext) + +static const int highestFD = FD_SETSIZE - 1; + +/* Forward. */ + +static int get_salen __P((const struct sockaddr *)); +static struct sockaddr * get_nsaddr __P((res_state, size_t)); +static int send_vc(res_state, const u_char *, int, + u_char *, int, int *, int); +static int send_dg(res_state, const u_char *, int, + u_char *, int, int *, int, + int *, int *); +static void Aerror(const res_state, FILE *, const char *, int, + const struct sockaddr *, int); +static void Perror(const res_state, FILE *, const char *, int); +static int sock_eq(struct sockaddr *, struct sockaddr *); +#ifdef NEED_PSELECT +static int pselect(int, void *, void *, void *, + struct timespec *, + const sigset_t *); +#endif +void res_pquery(const res_state, const u_char *, int, FILE *); + +static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; + +/* Public. */ + +/* int + * res_isourserver(ina) + * looks up "ina" in _res.ns_addr_list[] + * returns: + * 0 : not found + * >0 : found + * author: + * paul vixie, 29may94 + */ +int +res_ourserver_p(const res_state statp, const struct sockaddr *sa) { + const struct sockaddr_in *inp, *srv; + const struct sockaddr_in6 *in6p, *srv6; + int ns; + + switch (sa->sa_family) { + case AF_INET: + inp = (const struct sockaddr_in *)sa; + for (ns = 0; ns < statp->nscount; ns++) { + srv = (struct sockaddr_in *)get_nsaddr(statp, ns); + if (srv->sin_family == inp->sin_family && + srv->sin_port == inp->sin_port && + (srv->sin_addr.s_addr == INADDR_ANY || + srv->sin_addr.s_addr == inp->sin_addr.s_addr)) + return (1); + } + break; + case AF_INET6: + if (EXT(statp).ext == NULL) + break; + in6p = (const struct sockaddr_in6 *)sa; + for (ns = 0; ns < statp->nscount; ns++) { + srv6 = (struct sockaddr_in6 *)get_nsaddr(statp, ns); + if (srv6->sin6_family == in6p->sin6_family && + srv6->sin6_port == in6p->sin6_port && + (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) || + IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr))) + return (1); + } + break; + default: + break; + } + return (0); +} + +/* int + * res_nameinquery(name, type, class, buf, eom) + * look for (name,type,class) in the query section of packet (buf,eom) + * requires: + * buf + HFIXEDSZ <= eom + * returns: + * -1 : format error + * 0 : not found + * >0 : found + * author: + * paul vixie, 29may94 + */ +int +res_nameinquery(const char *name, int type, int class, + const u_char *buf, const u_char *eom) +{ + const u_char *cp = buf + HFIXEDSZ; + int qdcount = ntohs(((const HEADER*)buf)->qdcount); + + while (qdcount-- > 0) { + char tname[MAXDNAME+1]; + int n, ttype, tclass; + + n = dn_expand(buf, eom, cp, tname, sizeof tname); + if (n < 0) + return (-1); + cp += n; + if (cp + 2 * INT16SZ > eom) + return (-1); + ttype = ns_get16(cp); cp += INT16SZ; + tclass = ns_get16(cp); cp += INT16SZ; + if (ttype == type && tclass == class && + ns_samename(tname, name) == 1) + return (1); + } + return (0); +} + +/* int + * res_queriesmatch(buf1, eom1, buf2, eom2) + * is there a 1:1 mapping of (name,type,class) + * in (buf1,eom1) and (buf2,eom2)? + * returns: + * -1 : format error + * 0 : not a 1:1 mapping + * >0 : is a 1:1 mapping + * author: + * paul vixie, 29may94 + */ +int +res_queriesmatch(const u_char *buf1, const u_char *eom1, + const u_char *buf2, const u_char *eom2) +{ + const u_char *cp = buf1 + HFIXEDSZ; + int qdcount = ntohs(((const HEADER*)buf1)->qdcount); + + if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2) + return (-1); + + /* + * Only header section present in replies to + * dynamic update packets. + */ + if ((((const HEADER *)buf1)->opcode == ns_o_update) && + (((const HEADER *)buf2)->opcode == ns_o_update)) + return (1); + + if (qdcount != ntohs(((const HEADER*)buf2)->qdcount)) + return (0); + while (qdcount-- > 0) { + char tname[MAXDNAME+1]; + int n, ttype, tclass; + + n = dn_expand(buf1, eom1, cp, tname, sizeof tname); + if (n < 0) + return (-1); + cp += n; + if (cp + 2 * INT16SZ > eom1) + return (-1); + ttype = ns_get16(cp); cp += INT16SZ; + tclass = ns_get16(cp); cp += INT16SZ; + if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) + return (0); + } + return (1); +} + +int +res_nsend(res_state statp, + const u_char *buf, int buflen, u_char *ans, int anssiz) +{ + int gotsomewhere, terrno, try, v_circuit, resplen, ns, n; + char abuf[NI_MAXHOST]; + + if (statp->nscount == 0) { + errno = ESRCH; + return (-1); + } + if (anssiz < HFIXEDSZ) { + errno = EINVAL; + return (-1); + } + DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY), + (stdout, ";; res_send()\n"), buf, buflen); + v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ; + gotsomewhere = 0; + terrno = ETIMEDOUT; + + /* + * If the ns_addr_list in the resolver context has changed, then + * invalidate our cached copy and the associated timing data. + */ + if (EXT(statp).nscount != 0) { + int needclose = 0; + struct sockaddr_storage peer; + ISC_SOCKLEN_T peerlen; + + if (EXT(statp).nscount != statp->nscount) + needclose++; + else + for (ns = 0; ns < statp->nscount; ns++) { + if (statp->nsaddr_list[ns].sin_family && + !sock_eq((struct sockaddr *)&statp->nsaddr_list[ns], + (struct sockaddr *)&EXT(statp).ext->nsaddrs[ns])) { + needclose++; + break; + } + + if (EXT(statp).nssocks[ns] == -1) + continue; + peerlen = sizeof(peer); + if (getsockname(EXT(statp).nssocks[ns], + (struct sockaddr *)&peer, &peerlen) < 0) { + needclose++; + break; + } + if (!sock_eq((struct sockaddr *)&peer, + get_nsaddr(statp, ns))) { + needclose++; + break; + } + } + if (needclose) { + res_nclose(statp); + EXT(statp).nscount = 0; + } + } + + /* + * Maybe initialize our private copy of the ns_addr_list. + */ + if (EXT(statp).nscount == 0) { + for (ns = 0; ns < statp->nscount; ns++) { + EXT(statp).nstimes[ns] = RES_MAXTIME; + EXT(statp).nssocks[ns] = -1; + if (!statp->nsaddr_list[ns].sin_family) + continue; + EXT(statp).ext->nsaddrs[ns].sin = + statp->nsaddr_list[ns]; + } + EXT(statp).nscount = statp->nscount; + } + + /* + * Some resolvers want to even out the load on their nameservers. + * Note that RES_BLAST overrides RES_ROTATE. + */ + if ((statp->options & RES_ROTATE) != 0 && + (statp->options & RES_BLAST) == 0) { + union res_sockaddr_union inu; + struct sockaddr_in ina; + int lastns = statp->nscount - 1; + int fd; + u_int16_t nstime; + + if (EXT(statp).ext != NULL) + inu = EXT(statp).ext->nsaddrs[0]; + ina = statp->nsaddr_list[0]; + fd = EXT(statp).nssocks[0]; + nstime = EXT(statp).nstimes[0]; + for (ns = 0; ns < lastns; ns++) { + if (EXT(statp).ext != NULL) + EXT(statp).ext->nsaddrs[ns] = + EXT(statp).ext->nsaddrs[ns + 1]; + statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1]; + EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1]; + EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1]; + } + if (EXT(statp).ext != NULL) + EXT(statp).ext->nsaddrs[lastns] = inu; + statp->nsaddr_list[lastns] = ina; + EXT(statp).nssocks[lastns] = fd; + EXT(statp).nstimes[lastns] = nstime; + } + + /* + * Send request, RETRY times, or until successful. + */ + for (try = 0; try < statp->retry; try++) { + for (ns = 0; ns < statp->nscount; ns++) { + struct sockaddr *nsap; + int nsaplen; + nsap = get_nsaddr(statp, ns); + nsaplen = get_salen(nsap); + same_ns: + if (statp->qhook) { + int done = 0, loops = 0; + + do { + res_sendhookact act; + + act = (*statp->qhook)(&nsap, &buf, &buflen, + ans, anssiz, &resplen); + switch (act) { + case res_goahead: + done = 1; + break; + case res_nextns: + res_nclose(statp); + goto next_ns; + case res_done: + return (resplen); + case res_modified: + /* give the hook another try */ + if (++loops < 42) /*doug adams*/ + break; + /*FALLTHROUGH*/ + case res_error: + /*FALLTHROUGH*/ + default: + goto fail; + } + } while (!done); + } + + Dprint(((statp->options & RES_DEBUG) && + getnameinfo(nsap, nsaplen, abuf, sizeof(abuf), + NULL, 0, niflags) == 0), + (stdout, ";; Querying server (# %d) address = %s\n", + ns + 1, abuf)); + + + if (v_circuit) { + /* Use VC; at most one attempt per server. */ + try = statp->retry; + n = send_vc(statp, buf, buflen, ans, anssiz, &terrno, + ns); + if (n < 0) + goto fail; + if (n == 0) + goto next_ns; + resplen = n; + } else { + /* Use datagrams. */ + n = send_dg(statp, buf, buflen, ans, anssiz, &terrno, + ns, &v_circuit, &gotsomewhere); + if (n < 0) + goto fail; + if (n == 0) + goto next_ns; + if (v_circuit) + goto same_ns; + resplen = n; + } + + Dprint((statp->options & RES_DEBUG) || + ((statp->pfcode & RES_PRF_REPLY) && + (statp->pfcode & RES_PRF_HEAD1)), + (stdout, ";; got answer:\n")); + + DprintQ((statp->options & RES_DEBUG) || + (statp->pfcode & RES_PRF_REPLY), + (stdout, "%s", ""), + ans, (resplen > anssiz) ? anssiz : resplen); + + /* + * If we have temporarily opened a virtual circuit, + * or if we haven't been asked to keep a socket open, + * close the socket. + */ + if ((v_circuit && (statp->options & RES_USEVC) == 0) || + (statp->options & RES_STAYOPEN) == 0) { + res_nclose(statp); + } + if (statp->rhook) { + int done = 0, loops = 0; + + do { + res_sendhookact act; + + act = (*statp->rhook)(nsap, buf, buflen, + ans, anssiz, &resplen); + switch (act) { + case res_goahead: + case res_done: + done = 1; + break; + case res_nextns: + res_nclose(statp); + goto next_ns; + case res_modified: + /* give the hook another try */ + if (++loops < 42) /*doug adams*/ + break; + /*FALLTHROUGH*/ + case res_error: + /*FALLTHROUGH*/ + default: + goto fail; + } + } while (!done); + + } + return (resplen); + next_ns: ; + } /*foreach ns*/ + } /*foreach retry*/ + res_nclose(statp); + if (!v_circuit) { + if (!gotsomewhere) + errno = ECONNREFUSED; /* no nameservers found */ + else + errno = ETIMEDOUT; /* no answer obtained */ + } else + errno = terrno; + return (-1); + fail: + res_nclose(statp); + return (-1); +} + +/* Private */ + +static int +get_salen(sa) + const struct sockaddr *sa; +{ + +#ifdef HAVE_SA_LEN + /* There are people do not set sa_len. Be forgiving to them. */ + if (sa->sa_len) + return (sa->sa_len); +#endif + + if (sa->sa_family == AF_INET) + return (sizeof(struct sockaddr_in)); + else if (sa->sa_family == AF_INET6) + return (sizeof(struct sockaddr_in6)); + else + return (0); /* unknown, die on connect */ +} + +/* + * pick appropriate nsaddr_list for use. see res_init() for initialization. + */ +static struct sockaddr * +get_nsaddr(statp, n) + res_state statp; + size_t n; +{ + + if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) { + /* + * - EXT(statp).ext->nsaddrs[n] holds an address that is larger + * than struct sockaddr, and + * - user code did not update statp->nsaddr_list[n]. + */ + return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n]; + } else { + /* + * - user code updated statp->nsaddr_list[n], or + * - statp->nsaddr_list[n] has the same content as + * EXT(statp).ext->nsaddrs[n]. + */ + return (struct sockaddr *)(void *)&statp->nsaddr_list[n]; + } +} + +static int +send_vc(res_state statp, + const u_char *buf, int buflen, u_char *ans, int anssiz, + int *terrno, int ns) +{ + const HEADER *hp = (const HEADER *) buf; + HEADER *anhp = (HEADER *) ans; + struct sockaddr *nsap; + int nsaplen; + int truncating, connreset, resplen, n; + struct iovec iov[2]; + u_short len; + u_char *cp; + void *tmp; + + nsap = get_nsaddr(statp, ns); + nsaplen = get_salen(nsap); + + connreset = 0; + same_ns: + truncating = 0; + + /* Are we still talking to whom we want to talk to? */ + if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) { + struct sockaddr_storage peer; + ISC_SOCKLEN_T size = sizeof peer; + + if (getpeername(statp->_vcsock, + (struct sockaddr *)&peer, &size) < 0 || + !sock_eq((struct sockaddr *)&peer, nsap)) { + res_nclose(statp); + statp->_flags &= ~RES_F_VC; + } + } + + if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) { + if (statp->_vcsock >= 0) + res_nclose(statp); + + statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0); + if (statp->_vcsock > highestFD) { + res_nclose(statp); + errno = ENOTSOCK; + } + if (statp->_vcsock < 0) { + *terrno = errno; + Perror(statp, stderr, "socket(vc)", errno); + return (-1); + } + errno = 0; + if (connect(statp->_vcsock, nsap, nsaplen) < 0) { + *terrno = errno; + Aerror(statp, stderr, "connect/vc", errno, nsap, + nsaplen); + res_nclose(statp); + return (0); + } + statp->_flags |= RES_F_VC; + } + + /* + * Send length & message + */ + putshort((u_short)buflen, (u_char*)&len); + iov[0] = evConsIovec(&len, INT16SZ); + DE_CONST(buf, tmp); + iov[1] = evConsIovec(tmp, buflen); + if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) { + *terrno = errno; + Perror(statp, stderr, "write failed", errno); + res_nclose(statp); + return (0); + } + /* + * Receive length & response + */ + read_len: + cp = ans; + len = INT16SZ; + while ((n = read(statp->_vcsock, (char *)cp, (int)len)) > 0) { + cp += n; + if ((len -= n) <= 0) + break; + } + if (n <= 0) { + *terrno = errno; + Perror(statp, stderr, "read failed", errno); + res_nclose(statp); + /* + * A long running process might get its TCP + * connection reset if the remote server was + * restarted. Requery the server instead of + * trying a new one. When there is only one + * server, this means that a query might work + * instead of failing. We only allow one reset + * per query to prevent looping. + */ + if (*terrno == ECONNRESET && !connreset) { + connreset = 1; + res_nclose(statp); + goto same_ns; + } + res_nclose(statp); + return (0); + } + resplen = ns_get16(ans); + if (resplen > anssiz) { + Dprint(statp->options & RES_DEBUG, + (stdout, ";; response truncated\n") + ); + truncating = 1; + len = anssiz; + } else + len = resplen; + if (len < HFIXEDSZ) { + /* + * Undersized message. + */ + Dprint(statp->options & RES_DEBUG, + (stdout, ";; undersized: %d\n", len)); + *terrno = EMSGSIZE; + res_nclose(statp); + return (0); + } + cp = ans; + while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){ + cp += n; + len -= n; + } + if (n <= 0) { + *terrno = errno; + Perror(statp, stderr, "read(vc)", errno); + res_nclose(statp); + return (0); + } + if (truncating) { + /* + * Flush rest of answer so connection stays in synch. + */ + anhp->tc = 1; + len = resplen - anssiz; + while (len != 0) { + char junk[PACKETSZ]; + + n = read(statp->_vcsock, junk, + (len > sizeof junk) ? sizeof junk : len); + if (n > 0) + len -= n; + else + break; + } + } + /* + * If the calling applicating has bailed out of + * a previous call and failed to arrange to have + * the circuit closed or the server has got + * itself confused, then drop the packet and + * wait for the correct one. + */ + if (hp->id != anhp->id) { + DprintQ((statp->options & RES_DEBUG) || + (statp->pfcode & RES_PRF_REPLY), + (stdout, ";; old answer (unexpected):\n"), + ans, (resplen > anssiz) ? anssiz: resplen); + goto read_len; + } + + /* + * All is well, or the error is fatal. Signal that the + * next nameserver ought not be tried. + */ + return (resplen); +} + +static int +send_dg(res_state statp, + const u_char *buf, int buflen, u_char *ans, int anssiz, + int *terrno, int ns, int *v_circuit, int *gotsomewhere) +{ + const HEADER *hp = (const HEADER *) buf; + HEADER *anhp = (HEADER *) ans; + const struct sockaddr *nsap; + int nsaplen; + struct timespec now, timeout, finish; + fd_set dsmask; + struct sockaddr_storage from; + ISC_SOCKLEN_T fromlen; + int resplen, seconds, n, s; + + nsap = get_nsaddr(statp, ns); + nsaplen = get_salen(nsap); + if (EXT(statp).nssocks[ns] == -1) { + EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0); + if (EXT(statp).nssocks[ns] > highestFD) { + res_nclose(statp); + errno = ENOTSOCK; + } + if (EXT(statp).nssocks[ns] < 0) { + *terrno = errno; + Perror(statp, stderr, "socket(dg)", errno); + return (-1); + } +#ifndef CANNOT_CONNECT_DGRAM + /* + * On a 4.3BSD+ machine (client and server, + * actually), sending to a nameserver datagram + * port with no nameserver will cause an + * ICMP port unreachable message to be returned. + * If our datagram socket is "connected" to the + * server, we get an ECONNREFUSED error on the next + * socket operation, and select returns if the + * error message is received. We can thus detect + * the absence of a nameserver without timing out. + */ + if (connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) { + Aerror(statp, stderr, "connect(dg)", errno, nsap, + nsaplen); + res_nclose(statp); + return (0); + } +#endif /* !CANNOT_CONNECT_DGRAM */ + Dprint(statp->options & RES_DEBUG, + (stdout, ";; new DG socket\n")) + } + s = EXT(statp).nssocks[ns]; +#ifndef CANNOT_CONNECT_DGRAM + if (send(s, (const char*)buf, buflen, 0) != buflen) { + Perror(statp, stderr, "send", errno); + res_nclose(statp); + return (0); + } +#else /* !CANNOT_CONNECT_DGRAM */ + if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) + { + Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); + res_nclose(statp); + return (0); + } +#endif /* !CANNOT_CONNECT_DGRAM */ + + /* + * Wait for reply. + */ + seconds = (statp->retrans << ns); + if (ns > 0) + seconds /= statp->nscount; + if (seconds <= 0) + seconds = 1; + now = evNowTime(); + timeout = evConsTime(seconds, 0); + finish = evAddTime(now, timeout); + goto nonow; + wait: + now = evNowTime(); + nonow: + FD_ZERO(&dsmask); + FD_SET(s, &dsmask); + if (evCmpTime(finish, now) > 0) + timeout = evSubTime(finish, now); + else + timeout = evConsTime(0, 0); + n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL); + if (n == 0) { + Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n")); + *gotsomewhere = 1; + return (0); + } + if (n < 0) { + if (errno == EINTR) + goto wait; + Perror(statp, stderr, "select", errno); + res_nclose(statp); + return (0); + } + errno = 0; + fromlen = sizeof(from); + resplen = recvfrom(s, (char*)ans, anssiz,0, + (struct sockaddr *)&from, &fromlen); + if (resplen <= 0) { + Perror(statp, stderr, "recvfrom", errno); + res_nclose(statp); + return (0); + } + *gotsomewhere = 1; + if (resplen < HFIXEDSZ) { + /* + * Undersized message. + */ + Dprint(statp->options & RES_DEBUG, + (stdout, ";; undersized: %d\n", + resplen)); + *terrno = EMSGSIZE; + res_nclose(statp); + return (0); + } + if (hp->id != anhp->id) { + /* + * response from old query, ignore it. + * XXX - potential security hazard could + * be detected here. + */ + DprintQ((statp->options & RES_DEBUG) || + (statp->pfcode & RES_PRF_REPLY), + (stdout, ";; old answer:\n"), + ans, (resplen > anssiz) ? anssiz : resplen); + goto wait; + } + if (!(statp->options & RES_INSECURE1) && + !res_ourserver_p(statp, (struct sockaddr *)&from)) { + /* + * response from wrong server? ignore it. + * XXX - potential security hazard could + * be detected here. + */ + DprintQ((statp->options & RES_DEBUG) || + (statp->pfcode & RES_PRF_REPLY), + (stdout, ";; not our server:\n"), + ans, (resplen > anssiz) ? anssiz : resplen); + goto wait; + } +#ifdef RES_USE_EDNS0 + if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0) { + /* + * Do not retry if the server do not understand EDNS0. + * The case has to be captured here, as FORMERR packet do not + * carry query section, hence res_queriesmatch() returns 0. + */ + DprintQ(statp->options & RES_DEBUG, + (stdout, "server rejected query with EDNS0:\n"), + ans, (resplen > anssiz) ? anssiz : resplen); + /* record the error */ + statp->_flags |= RES_F_EDNS0ERR; + res_nclose(statp); + return (0); + } +#endif + if (!(statp->options & RES_INSECURE2) && + !res_queriesmatch(buf, buf + buflen, + ans, ans + anssiz)) { + /* + * response contains wrong query? ignore it. + * XXX - potential security hazard could + * be detected here. + */ + DprintQ((statp->options & RES_DEBUG) || + (statp->pfcode & RES_PRF_REPLY), + (stdout, ";; wrong query name:\n"), + ans, (resplen > anssiz) ? anssiz : resplen); + goto wait; + } + if (anhp->rcode == SERVFAIL || + anhp->rcode == NOTIMP || + anhp->rcode == REFUSED) { + DprintQ(statp->options & RES_DEBUG, + (stdout, "server rejected query:\n"), + ans, (resplen > anssiz) ? anssiz : resplen); + res_nclose(statp); + /* don't retry if called from dig */ + if (!statp->pfcode) + return (0); + } + if (!(statp->options & RES_IGNTC) && anhp->tc) { + /* + * To get the rest of answer, + * use TCP with same server. + */ + Dprint(statp->options & RES_DEBUG, + (stdout, ";; truncated answer\n")); + *v_circuit = 1; + res_nclose(statp); + return (1); + } + /* + * All is well, or the error is fatal. Signal that the + * next nameserver ought not be tried. + */ + return (resplen); +} + +static void +Aerror(const res_state statp, FILE *file, const char *string, int error, + const struct sockaddr *address, int alen) +{ + int save = errno; + char hbuf[NI_MAXHOST]; + char sbuf[NI_MAXSERV]; + + alen = alen; + + if ((statp->options & RES_DEBUG) != 0) { + if (getnameinfo(address, alen, hbuf, sizeof(hbuf), + sbuf, sizeof(sbuf), niflags)) { + strncpy(hbuf, "?", sizeof(hbuf) - 1); + hbuf[sizeof(hbuf) - 1] = '\0'; + strncpy(sbuf, "?", sizeof(sbuf) - 1); + sbuf[sizeof(sbuf) - 1] = '\0'; + } + fprintf(file, "res_send: %s ([%s].%s): %s\n", + string, hbuf, sbuf, strerror(error)); + } + errno = save; +} + +static void +Perror(const res_state statp, FILE *file, const char *string, int error) { + int save = errno; + + if ((statp->options & RES_DEBUG) != 0) + fprintf(file, "res_send: %s: %s\n", + string, strerror(error)); + errno = save; +} + +static int +sock_eq(struct sockaddr *a, struct sockaddr *b) { + struct sockaddr_in *a4, *b4; + struct sockaddr_in6 *a6, *b6; + + if (a->sa_family != b->sa_family) + return 0; + switch (a->sa_family) { + case AF_INET: + a4 = (struct sockaddr_in *)a; + b4 = (struct sockaddr_in *)b; + return a4->sin_port == b4->sin_port && + a4->sin_addr.s_addr == b4->sin_addr.s_addr; + case AF_INET6: + a6 = (struct sockaddr_in6 *)a; + b6 = (struct sockaddr_in6 *)b; + return a6->sin6_port == b6->sin6_port && +#ifdef HAVE_SIN6_SCOPE_ID + a6->sin6_scope_id == b6->sin6_scope_id && +#endif + IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr); + default: + return 0; + } +} + +#ifdef NEED_PSELECT +/* XXX needs to move to the porting library. */ +static int +pselect(int nfds, void *rfds, void *wfds, void *efds, + struct timespec *tsp, const sigset_t *sigmask) +{ + struct timeval tv, *tvp; + sigset_t sigs; + int n; + + if (tsp) { + tvp = &tv; + tv = evTimeVal(*tsp); + } else + tvp = NULL; + if (sigmask) + sigprocmask(SIG_SETMASK, sigmask, &sigs); + n = select(nfds, rfds, wfds, efds, tvp); + if (sigmask) + sigprocmask(SIG_SETMASK, &sigs, NULL); + if (tsp) + *tsp = evTimeSpec(tv); + return (n); +} +#endif Property changes on: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_send.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_update.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/resolv/res_update.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/resolv/res_update.c (revision 109985) @@ -0,0 +1,205 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: res_update.c,v 1.34 2002/04/12 06:28:52 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * Based on the Dynamic DNS reference implementation by Viraj Bais + * + */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" +#include "res_private.h" + +/* + * Separate a linked list of records into groups so that all records + * in a group will belong to a single zone on the nameserver. + * Create a dynamic update packet for each zone and send it to the + * nameservers for that zone, and await answer. + * Abort if error occurs in updating any zone. + * Return the number of zones updated on success, < 0 on error. + * + * On error, caller must deal with the unsynchronized zones + * eg. an A record might have been successfully added to the forward + * zone but the corresponding PTR record would be missing if error + * was encountered while updating the reverse zone. + */ + +struct zonegrp { + char z_origin[MAXDNAME]; + ns_class z_class; + union res_sockaddr_union z_nsaddrs[MAXNS]; + int z_nscount; + int z_flags; + LIST(ns_updrec) z_rrlist; + LINK(struct zonegrp) z_link; +}; + +#define ZG_F_ZONESECTADDED 0x0001 + +/* Forward. */ + +static void res_dprintf(const char *, ...); + +/* Macros. */ + +#define DPRINTF(x) do {\ + int save_errno = errno; \ + if ((statp->options & RES_DEBUG) != 0) res_dprintf x; \ + errno = save_errno; \ + } while (0) + +/* Public. */ + +int +res_nupdate(res_state statp, ns_updrec *rrecp_in, ns_tsig_key *key) { + ns_updrec *rrecp; + u_char answer[PACKETSZ], packet[2*PACKETSZ]; + struct zonegrp *zptr, tgrp; + LIST(struct zonegrp) zgrps; + int nzones = 0, nscount = 0, n; + union res_sockaddr_union nsaddrs[MAXNS]; + + /* Thread all of the updates onto a list of groups. */ + INIT_LIST(zgrps); + memset(&tgrp, 0, sizeof (tgrp)); + for (rrecp = rrecp_in; rrecp; + rrecp = LINKED(rrecp, r_link) ? NEXT(rrecp, r_link) : NULL) { + int nscnt; + /* Find the origin for it if there is one. */ + tgrp.z_class = rrecp->r_class; + nscnt = res_findzonecut2(statp, rrecp->r_dname, tgrp.z_class, + RES_EXHAUSTIVE, tgrp.z_origin, + sizeof tgrp.z_origin, + tgrp.z_nsaddrs, MAXNS); + if (nscnt <= 0) { + DPRINTF(("res_findzonecut failed (%d)", nscnt)); + goto done; + } + tgrp.z_nscount = nscnt; + /* Find the group for it if there is one. */ + for (zptr = HEAD(zgrps); zptr != NULL; zptr = NEXT(zptr, z_link)) + if (ns_samename(tgrp.z_origin, zptr->z_origin) == 1 && + tgrp.z_class == zptr->z_class) + break; + /* Make a group for it if there isn't one. */ + if (zptr == NULL) { + zptr = malloc(sizeof *zptr); + if (zptr == NULL) { + DPRINTF(("malloc failed")); + goto done; + } + *zptr = tgrp; + zptr->z_flags = 0; + INIT_LINK(zptr, z_link); + INIT_LIST(zptr->z_rrlist); + APPEND(zgrps, zptr, z_link); + } + /* Thread this rrecp onto the right group. */ + APPEND(zptr->z_rrlist, rrecp, r_glink); + } + + for (zptr = HEAD(zgrps); zptr != NULL; zptr = NEXT(zptr, z_link)) { + /* Construct zone section and prepend it. */ + rrecp = res_mkupdrec(ns_s_zn, zptr->z_origin, + zptr->z_class, ns_t_soa, 0); + if (rrecp == NULL) { + DPRINTF(("res_mkupdrec failed")); + goto done; + } + PREPEND(zptr->z_rrlist, rrecp, r_glink); + zptr->z_flags |= ZG_F_ZONESECTADDED; + + /* Marshall the update message. */ + n = res_nmkupdate(statp, HEAD(zptr->z_rrlist), + packet, sizeof packet); + DPRINTF(("res_mkupdate -> %d", n)); + if (n < 0) + goto done; + + /* Temporarily replace the resolver's nameserver set. */ + nscount = res_getservers(statp, nsaddrs, MAXNS); + res_setservers(statp, zptr->z_nsaddrs, zptr->z_nscount); + + /* Send the update and remember the result. */ + if (key != NULL) + n = res_nsendsigned(statp, packet, n, key, + answer, sizeof answer); + else + n = res_nsend(statp, packet, n, answer, sizeof answer); + if (n < 0) { + DPRINTF(("res_nsend: send error, n=%d (%s)\n", + n, strerror(errno))); + goto done; + } + if (((HEADER *)answer)->rcode == NOERROR) + nzones++; + + /* Restore resolver's nameserver set. */ + res_setservers(statp, nsaddrs, nscount); + nscount = 0; + } + done: + while (!EMPTY(zgrps)) { + zptr = HEAD(zgrps); + if ((zptr->z_flags & ZG_F_ZONESECTADDED) != 0) + res_freeupdrec(HEAD(zptr->z_rrlist)); + UNLINK(zgrps, zptr, z_link); + free(zptr); + } + if (nscount != 0) + res_setservers(statp, nsaddrs, nscount); + + return (nzones); +} + +/* Private. */ + +static void +res_dprintf(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + fputs(";; res_nupdate: ", stderr); + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); + va_end(ap); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_update.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/resolv/Makefile =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/resolv/Makefile (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/resolv/Makefile (revision 109985) @@ -0,0 +1,95 @@ +# Copyright (c) 1996,1999 by Internet Software Consortium +# +# 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. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +# CONSORTIUM 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 +# SOFTWARE. + +# $Id: Makefile,v 8.36 2001/08/14 05:58:11 marka Exp $ + +# these are only appropriate for BSD 4.4 or derivatives, and are used in +# development. normal builds will be done in the top level directory and +# this Makefile will be invoked with a lot of overrides for the following: +SYSTYPE= freebsd +DESTDIR = +DESTLIB = /usr/local/lib +O=o +A=a +CC= cc +LD= ld +SHELL= /bin/sh +CDEBUG= -g -Wall +TOP= ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.${A} +LIBBINDR = ../${TOP}/lib/libbind_r.${A} +CFLAGS= ${CDEBUG} +CPPFLAGS= -I${PORTINCL} -I${INCL} +# -D__BIND_NOSTATIC +LD_LIBFLAGS= -x -r +AR= ar cru +RANLIB= ranlib +INSTALL= install +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin +THREADED= threaded + +SRCS= herror.c res_debug.c res_data.c res_comp.c res_init.c \ + res_mkquery.c res_query.c res_send.c res_sendsigned.c \ + res_mkupdate.c res_update.c \ + res_findzonecut.c + +OBJS= herror.${O} res_debug.${O} res_data.${O} res_comp.${O} res_init.${O} \ + res_mkquery.${O} res_query.${O} res_send.${O} res_sendsigned.${O} \ + res_mkupdate.${O} res_update.${O} \ + res_findzonecut.${O} + +all: ${LIBBIND} + +${LIBBIND}: ${OBJS} + ( cd ${THREADED} ; \ + ${AR} ${LIBBINDR} ${ARPREF} ${OBJS} ${ARSUFF} ; \ + ${RANLIB} ${LIBBINDR} ) + ${AR} ${LIBBIND} ${ARPREF} ${OBJS} ${ARSUFF} + ${RANLIB} ${LIBBIND} + +.c.${O}: + mkdir ${THREADED} 2> /dev/null || test -d ${THREADED} -a -w ${THREADED} + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} ${REENTRANT} -c $*.c \ + -o ${THREADED}/$*.${O} + -${LDS} ${LD} ${LD_LIBFLAGS} ${THREADED}/$*.${O} \ + -o ${THREADED}/$*.out && \ + ${LDS} mv ${THREADED}/$*.out ${THREADED}/$*.${O} + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c + -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} -o $*.out && \ + ${LDS} mv $*.out $*.${O} + +distclean: clean + +clean: FRC + rm -f .depend a.out core ${LIB} tags + rm -f *.${O} *.BAK *.CKP *~ + rm -f ${THREADED}/*.${O} + -if test -d ${THREADED} ; then rmdir ${THREADED}; else true; fi + +depend: FRC + mkdep -I${INCL} -I${PORTINCL} ${CPPFLAGS} ${SRCS} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +install: + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Property changes on: vendor/bind/8.3.4/contrib/bind/lib/resolv/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/resolv/herror.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/resolv/herror.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/resolv/herror.c (revision 109985) @@ -0,0 +1,125 @@ +/* + * Copyright (c) 1987, 1993 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: herror.c,v 8.13 2001/06/18 14:44:06 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "port_after.h" +#undef h_errno + +const char *h_errlist[] = { + "Resolver Error 0 (no error)", + "Unknown host", /* 1 HOST_NOT_FOUND */ + "Host name lookup failure", /* 2 TRY_AGAIN */ + "Unknown server error", /* 3 NO_RECOVERY */ + "No address associated with name", /* 4 NO_ADDRESS */ +}; +int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] }; + +int h_errno; + +/* + * herror -- + * print the error indicated by the h_errno value. + */ +void +herror(const char *s) { + struct iovec iov[4], *v = iov; + char *t; + + if (s != NULL && *s != '\0') { + DE_CONST(s, t); + v->iov_base = t; + v->iov_len = strlen(t); + v++; + DE_CONST(": ", t); + v->iov_base = t; + v->iov_len = 2; + v++; + } + DE_CONST(hstrerror(*__h_errno()), t); + v->iov_base = t; + v->iov_len = strlen(v->iov_base); + v++; + DE_CONST("\n", t); + v->iov_base = t; + v->iov_len = 1; + writev(STDERR_FILENO, iov, (v - iov) + 1); +} + +/* + * hstrerror -- + * return the string associated with a given "host" errno value. + */ +const char * +hstrerror(int err) { + if (err < 0) + return ("Resolver internal error"); + else if (err < h_nerr) + return (h_errlist[err]); + return ("Unknown resolver error"); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/resolv/herror.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_mkquery.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/resolv/res_mkquery.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/resolv/res_mkquery.c (revision 109985) @@ -0,0 +1,258 @@ +/* + * Copyright (c) 1985, 1993 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: res_mkquery.c,v 8.14 2001/09/24 13:50:27 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "port_after.h" + +/* Options. Leave them on. */ +#define DEBUG + +extern const char *_res_opcodes[]; + +/* + * Form all types of queries. + * Returns the size of the result or -1. + */ +int +res_nmkquery(res_state statp, + int op, /* opcode of query */ + const char *dname, /* domain name */ + int class, int type, /* class and type of query */ + const u_char *data, /* resource record data */ + int datalen, /* length of data */ + const u_char *newrr_in, /* new rr for modify or append */ + u_char *buf, /* buffer to put query */ + int buflen) /* size of buffer */ +{ + register HEADER *hp; + register u_char *cp; + register int n; + u_char *dnptrs[20], **dpp, **lastdnptr; + + UNUSED(newrr_in); + +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_nmkquery(%s, %s, %s, %s)\n", + _res_opcodes[op], dname, p_class(class), p_type(type)); +#endif + /* + * Initialize header fields. + */ + if ((buf == NULL) || (buflen < HFIXEDSZ)) + return (-1); + memset(buf, 0, HFIXEDSZ); + hp = (HEADER *) buf; + hp->id = htons(++statp->id); + hp->opcode = op; + hp->rd = (statp->options & RES_RECURSE) != 0; + hp->rcode = NOERROR; + cp = buf + HFIXEDSZ; + buflen -= HFIXEDSZ; + dpp = dnptrs; + *dpp++ = buf; + *dpp++ = NULL; + lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; + /* + * perform opcode specific processing + */ + switch (op) { + case QUERY: /*FALLTHROUGH*/ + case NS_NOTIFY_OP: + if ((buflen -= QFIXEDSZ) < 0) + return (-1); + if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) + return (-1); + cp += n; + buflen -= n; + __putshort(type, cp); + cp += INT16SZ; + __putshort(class, cp); + cp += INT16SZ; + hp->qdcount = htons(1); + if (op == QUERY || data == NULL) + break; + /* + * Make an additional record for completion domain. + */ + buflen -= RRFIXEDSZ; + n = dn_comp((const char *)data, cp, buflen, dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + buflen -= n; + __putshort(T_NULL, cp); + cp += INT16SZ; + __putshort(class, cp); + cp += INT16SZ; + __putlong(0, cp); + cp += INT32SZ; + __putshort(0, cp); + cp += INT16SZ; + hp->arcount = htons(1); + break; + + case IQUERY: + /* + * Initialize answer section + */ + if (buflen < 1 + RRFIXEDSZ + datalen) + return (-1); + *cp++ = '\0'; /* no domain name */ + __putshort(type, cp); + cp += INT16SZ; + __putshort(class, cp); + cp += INT16SZ; + __putlong(0, cp); + cp += INT32SZ; + __putshort(datalen, cp); + cp += INT16SZ; + if (datalen) { + memcpy(cp, data, datalen); + cp += datalen; + } + hp->ancount = htons(1); + break; + + default: + return (-1); + } + return (cp - buf); +} + +#ifdef RES_USE_EDNS0 +/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */ +#ifndef T_OPT +#define T_OPT 41 +#endif + +int +res_nopt(statp, n0, buf, buflen, anslen) + res_state statp; + int n0; + u_char *buf; /* buffer to put query */ + int buflen; /* size of buffer */ + int anslen; /* answer buffer length */ +{ + register HEADER *hp; + register u_char *cp; + u_int16_t flags = 0; + +#ifdef DEBUG + if ((statp->options & RES_DEBUG) != 0) + printf(";; res_nopt()\n"); +#endif + + hp = (HEADER *) buf; + cp = buf + n0; + buflen -= n0; + + if (buflen < 1 + RRFIXEDSZ) + return -1; + + *cp++ = 0; /* "." */ + buflen--; + + __putshort(T_OPT, cp); /* TYPE */ + cp += INT16SZ; + __putshort(anslen & 0xffff, cp); /* CLASS = UDP payload size */ + cp += INT16SZ; + *cp++ = NOERROR; /* extended RCODE */ + *cp++ = 0; /* EDNS version */ + if (statp->options & RES_USE_DNSSEC) { +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_opt()... ENDS0 DNSSEC\n"); +#endif + flags |= NS_OPT_DNSSEC_OK; + } + __putshort(flags, cp); + cp += INT16SZ; + __putshort(0, cp); /* RDLEN */ + cp += INT16SZ; + hp->arcount = htons(ntohs(hp->arcount) + 1); + buflen -= RRFIXEDSZ; + + return cp - buf; +} +#endif Property changes on: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_mkquery.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_mkupdate.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/resolv/res_mkupdate.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/resolv/res_mkupdate.c (revision 109985) @@ -0,0 +1,1100 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +/* + * Based on the Dynamic DNS reference implementation by Viraj Bais + * + */ + +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: res_mkupdate.c,v 1.26 2001/05/29 05:49:47 marka Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +/* Options. Leave them on. */ +#define DEBUG +#define MAXPORT 1024 + +static int getnum_str(u_char **, u_char *); +static int gethexnum_str(u_char **, u_char *); +static int getword_str(char *, int, u_char **, u_char *); +static int getstr_str(char *, int, u_char **, u_char *); + +#define ShrinkBuffer(x) if ((buflen -= x) < 0) return (-2); + +/* Forward. */ + +int res_protocolnumber(const char *); +int res_servicenumber(const char *); + +/* + * Form update packets. + * Returns the size of the resulting packet if no error + * On error, + * returns -1 if error in reading a word/number in rdata + * portion for update packets + * -2 if length of buffer passed is insufficient + * -3 if zone section is not the first section in + * the linked list, or section order has a problem + * -4 on a number overflow + * -5 unknown operation or no records + */ +int +res_nmkupdate(res_state statp, ns_updrec *rrecp_in, u_char *buf, int buflen) { + ns_updrec *rrecp_start = rrecp_in; + HEADER *hp; + u_char *cp, *sp1, *sp2, *startp, *endp; + int n, i, soanum, multiline; + ns_updrec *rrecp; + struct in_addr ina; + struct in6_addr in6a; + char buf2[MAXDNAME]; + u_char buf3[MAXDNAME]; + int section, numrrs = 0, counts[ns_s_max]; + u_int16_t rtype, rclass; + u_int32_t n1, rttl; + u_char *dnptrs[20], **dpp, **lastdnptr; + int siglen, keylen, certlen; + + /* + * Initialize header fields. + */ + if ((buf == NULL) || (buflen < HFIXEDSZ)) + return (-1); + memset(buf, 0, HFIXEDSZ); + hp = (HEADER *) buf; + hp->id = htons(++statp->id); + hp->opcode = ns_o_update; + hp->rcode = NOERROR; + sp1 = buf + 2*INT16SZ; /* save pointer to zocount */ + cp = buf + HFIXEDSZ; + buflen -= HFIXEDSZ; + dpp = dnptrs; + *dpp++ = buf; + *dpp++ = NULL; + lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; + + if (rrecp_start == NULL) + return (-5); + else if (rrecp_start->r_section != S_ZONE) + return (-3); + + memset(counts, 0, sizeof counts); + for (rrecp = rrecp_start; rrecp; rrecp = NEXT(rrecp, r_glink)) { + numrrs++; + section = rrecp->r_section; + if (section < 0 || section >= ns_s_max) + return (-1); + counts[section]++; + for (i = section + 1; i < ns_s_max; i++) + if (counts[i]) + return (-3); + rtype = rrecp->r_type; + rclass = rrecp->r_class; + rttl = rrecp->r_ttl; + /* overload class and type */ + if (section == S_PREREQ) { + rttl = 0; + switch (rrecp->r_opcode) { + case YXDOMAIN: + rclass = C_ANY; + rtype = T_ANY; + rrecp->r_size = 0; + break; + case NXDOMAIN: + rclass = C_NONE; + rtype = T_ANY; + rrecp->r_size = 0; + break; + case NXRRSET: + rclass = C_NONE; + rrecp->r_size = 0; + break; + case YXRRSET: + if (rrecp->r_size == 0) + rclass = C_ANY; + break; + default: + fprintf(stderr, + "res_mkupdate: incorrect opcode: %d\n", + rrecp->r_opcode); + fflush(stderr); + return (-1); + } + } else if (section == S_UPDATE) { + switch (rrecp->r_opcode) { + case DELETE: + rclass = rrecp->r_size == 0 ? C_ANY : C_NONE; + break; + case ADD: + break; + default: + fprintf(stderr, + "res_mkupdate: incorrect opcode: %d\n", + rrecp->r_opcode); + fflush(stderr); + return (-1); + } + } + + /* + * XXX appending default domain to owner name is omitted, + * fqdn must be provided + */ + if ((n = dn_comp(rrecp->r_dname, cp, buflen, dnptrs, + lastdnptr)) < 0) + return (-1); + cp += n; + ShrinkBuffer(n + 2*INT16SZ); + PUTSHORT(rtype, cp); + PUTSHORT(rclass, cp); + if (section == S_ZONE) { + if (numrrs != 1 || rrecp->r_type != T_SOA) + return (-3); + continue; + } + ShrinkBuffer(INT32SZ + INT16SZ); + PUTLONG(rttl, cp); + sp2 = cp; /* save pointer to length byte */ + cp += INT16SZ; + if (rrecp->r_size == 0) { + if (section == S_UPDATE && rclass != C_ANY) + return (-1); + else { + PUTSHORT(0, sp2); + continue; + } + } + startp = rrecp->r_data; + endp = startp + rrecp->r_size - 1; + /* XXX this should be done centrally. */ + switch (rrecp->r_type) { + case T_A: + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + if (!inet_aton(buf2, &ina)) + return (-1); + n1 = ntohl(ina.s_addr); + ShrinkBuffer(INT32SZ); + PUTLONG(n1, cp); + break; + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_NS: + case T_PTR: + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + break; + case T_MINFO: + case T_SOA: + case T_RP: + for (i = 0; i < 2; i++) { + if (!getword_str(buf2, sizeof buf2, &startp, + endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, + dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + } + if (rrecp->r_type == T_SOA) { + ShrinkBuffer(5 * INT32SZ); + while (isspace(*startp) || !*startp) + startp++; + if (*startp == '(') { + multiline = 1; + startp++; + } else + multiline = 0; + /* serial, refresh, retry, expire, minimum */ + for (i = 0; i < 5; i++) { + soanum = getnum_str(&startp, endp); + if (soanum < 0) + return (-1); + PUTLONG(soanum, cp); + } + if (multiline) { + while (isspace(*startp) || !*startp) + startp++; + if (*startp != ')') + return (-1); + } + } + break; + case T_MX: + case T_AFSDB: + case T_RT: + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + break; + case T_SRV: + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + break; + case T_PX: + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + PUTSHORT(n, cp); + ShrinkBuffer(INT16SZ); + for (i = 0; i < 2; i++) { + if (!getword_str(buf2, sizeof buf2, &startp, + endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, dnptrs, + lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + } + break; + case T_WKS: { + char bm[MAXPORT/8]; + unsigned int maxbm = 0; + + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + if (!inet_aton(buf2, &ina)) + return (-1); + n1 = ntohl(ina.s_addr); + ShrinkBuffer(INT32SZ); + PUTLONG(n1, cp); + + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + if ((i = res_protocolnumber(buf2)) < 0) + return (-1); + ShrinkBuffer(1); + *cp++ = i & 0xff; + + for (i = 0; i < MAXPORT/8 ; i++) + bm[i] = 0; + + while (getword_str(buf2, sizeof buf2, &startp, endp)) { + if ((n1 = res_servicenumber(buf2)) <= 0) + return (-1); + + if (n1 < MAXPORT) { + bm[n1/8] |= (0x80>>(n1%8)); + if (n1 > maxbm) + maxbm = n1; + } else + return (-1); + } + maxbm = maxbm/8 + 1; + ShrinkBuffer(maxbm); + memcpy(cp, bm, maxbm); + cp += maxbm; + break; + } + case T_HINFO: + for (i = 0; i < 2; i++) { + if ((n = getstr_str(buf2, sizeof buf2, + &startp, endp)) < 0) + return (-1); + if (n > 255) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + } + break; + case T_TXT: + while (1) { + if ((n = getstr_str(buf2, sizeof buf2, + &startp, endp)) < 0) { + if (cp != (sp2 + INT16SZ)) + break; + return (-1); + } + if (n > 255) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + } + break; + case T_X25: + /* RFC 1183 */ + if ((n = getstr_str(buf2, sizeof buf2, &startp, + endp)) < 0) + return (-1); + if (n > 255) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + break; + case T_ISDN: + /* RFC 1183 */ + if ((n = getstr_str(buf2, sizeof buf2, &startp, + endp)) < 0) + return (-1); + if ((n > 255) || (n == 0)) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + if ((n = getstr_str(buf2, sizeof buf2, &startp, + endp)) < 0) + n = 0; + if (n > 255) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + break; + case T_NSAP: + if ((n = inet_nsap_addr((char *)startp, (u_char *)buf2, sizeof(buf2))) != 0) { + ShrinkBuffer(n); + memcpy(cp, buf2, n); + cp += n; + } else { + return (-1); + } + break; + case T_LOC: + if ((n = loc_aton((char *)startp, (u_char *)buf2)) != 0) { + ShrinkBuffer(n); + memcpy(cp, buf2, n); + cp += n; + } else + return (-1); + break; + case ns_t_sig: + { + int sig_type, success, dateerror; + u_int32_t exptime, timesigned; + + /* type */ + if ((n = getword_str(buf2, sizeof buf2, + &startp, endp)) < 0) + return (-1); + sig_type = sym_ston(__p_type_syms, buf2, &success); + if (!success || sig_type == ns_t_any) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(sig_type, cp); + /* alg */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(1); + *cp++ = n; + /* labels */ + n = getnum_str(&startp, endp); + if (n <= 0 || n > 255) + return (-1); + ShrinkBuffer(1); + *cp++ = n; + /* ottl & expire */ + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + exptime = ns_datetosecs(buf2, &dateerror); + if (!dateerror) { + ShrinkBuffer(INT32SZ); + PUTLONG(rttl, cp); + } + else { + char *ulendp; + u_int32_t ottl; + + ottl = strtoul(buf2, &ulendp, 10); + if (ulendp != NULL && *ulendp != '\0') + return (-1); + ShrinkBuffer(INT32SZ); + PUTLONG(ottl, cp); + if (!getword_str(buf2, sizeof buf2, &startp, + endp)) + return (-1); + exptime = ns_datetosecs(buf2, &dateerror); + if (dateerror) + return (-1); + } + /* expire */ + ShrinkBuffer(INT32SZ); + PUTLONG(exptime, cp); + /* timesigned */ + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + timesigned = ns_datetosecs(buf2, &dateerror); + if (!dateerror) { + ShrinkBuffer(INT32SZ); + PUTLONG(timesigned, cp); + } + else + return (-1); + /* footprint */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + /* signer name */ + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + /* sig */ + if ((n = getword_str(buf2, sizeof buf2, + &startp, endp)) < 0) + return (-1); + siglen = b64_pton(buf2, buf3, sizeof(buf3)); + if (siglen < 0) + return (-1); + ShrinkBuffer(siglen); + memcpy(cp, buf3, siglen); + cp += siglen; + break; + } + case ns_t_key: + /* flags */ + n = gethexnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + /* proto */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(1); + *cp++ = n; + /* alg */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(1); + *cp++ = n; + /* key */ + if ((n = getword_str(buf2, sizeof buf2, + &startp, endp)) < 0) + return (-1); + keylen = b64_pton(buf2, buf3, sizeof(buf3)); + if (keylen < 0) + return (-1); + ShrinkBuffer(keylen); + memcpy(cp, buf3, keylen); + cp += keylen; + break; + case ns_t_nxt: + { + int success, nxt_type; + u_char data[32]; + int maxtype; + + /* next name */ + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + maxtype = 0; + memset(data, 0, sizeof data); + while (1) { + if (!getword_str(buf2, sizeof buf2, &startp, + endp)) + break; + nxt_type = sym_ston(__p_type_syms, buf2, + &success); + if (!success || !ns_t_rr_p(nxt_type)) + return (-1); + NS_NXT_BIT_SET(nxt_type, data); + if (nxt_type > maxtype) + maxtype = nxt_type; + } + n = maxtype/NS_NXT_BITS+1; + ShrinkBuffer(n); + memcpy(cp, data, n); + cp += n; + break; + } + case ns_t_cert: + /* type */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + /* key tag */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + /* alg */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(1); + *cp++ = n; + /* cert */ + if ((n = getword_str(buf2, sizeof buf2, + &startp, endp)) < 0) + return (-1); + certlen = b64_pton(buf2, buf3, sizeof(buf3)); + if (certlen < 0) + return (-1); + ShrinkBuffer(certlen); + memcpy(cp, buf3, certlen); + cp += certlen; + break; + case ns_t_aaaa: + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + if (inet_pton(AF_INET6, buf2, &in6a) <= 0) + return (-1); + ShrinkBuffer(NS_IN6ADDRSZ); + memcpy(cp, &in6a, NS_IN6ADDRSZ); + cp += NS_IN6ADDRSZ; + break; + default: + return (-1); + } /*switch*/ + n = (u_int16_t)((cp - sp2) - INT16SZ); + PUTSHORT(n, sp2); + } /*for*/ + + hp->qdcount = htons(counts[0]); + hp->ancount = htons(counts[1]); + hp->nscount = htons(counts[2]); + hp->arcount = htons(counts[3]); + return (cp - buf); +} + +/* + * Get a whitespace delimited word from a string (not file) + * into buf. modify the start pointer to point after the + * word in the string. + */ +static int +getword_str(char *buf, int size, u_char **startpp, u_char *endp) { + char *cp; + int c; + + for (cp = buf; *startpp <= endp; ) { + c = **startpp; + if (isspace(c) || c == '\0') { + if (cp != buf) /* trailing whitespace */ + break; + else { /* leading whitespace */ + (*startpp)++; + continue; + } + } + (*startpp)++; + if (cp >= buf+size-1) + break; + *cp++ = (u_char)c; + } + *cp = '\0'; + return (cp != buf); +} + +/* + * get a white spae delimited string from memory. Process quoted strings + * and \DDD escapes. Return length or -1 on error. Returned string may + * contain nulls. + */ +static char digits[] = "0123456789"; +static int +getstr_str(char *buf, int size, u_char **startpp, u_char *endp) { + char *cp; + int c, c1 = 0; + int inquote = 0; + int seen_quote = 0; + int escape = 0; + int dig = 0; + + for (cp = buf; *startpp <= endp; ) { + if ((c = **startpp) == '\0') + break; + /* leading white space */ + if ((cp == buf) && !seen_quote && isspace(c)) { + (*startpp)++; + continue; + } + + switch (c) { + case '\\': + if (!escape) { + escape = 1; + dig = 0; + c1 = 0; + (*startpp)++; + continue; + } + goto do_escape; + case '"': + if (!escape) { + inquote = !inquote; + seen_quote = 1; + (*startpp)++; + continue; + } + /* fall through */ + default: + do_escape: + if (escape) { + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + c1 = c1 * 10 + + (strchr(digits, c) - digits); + + if (++dig == 3) { + c = c1 &0xff; + break; + } + (*startpp)++; + continue; + } + escape = 0; + } else if (!inquote && isspace(c)) + goto done; + if (cp >= buf+size-1) + goto done; + *cp++ = (u_char)c; + (*startpp)++; + } + } + done: + *cp = '\0'; + return ((cp == buf)? (seen_quote? 0: -1): (cp - buf)); +} +/* + * Get a whitespace delimited base 16 number from a string (not file) into buf + * update the start pointer to point after the number in the string. + */ +static int +gethexnum_str(u_char **startpp, u_char *endp) { + int c, n; + int seendigit = 0; + int m = 0; + + if (*startpp + 2 >= endp || strncasecmp((char *)*startpp, "0x", 2) != 0) + return getnum_str(startpp, endp); + (*startpp)+=2; + for (n = 0; *startpp <= endp; ) { + c = **startpp; + if (isspace(c) || c == '\0') { + if (seendigit) /* trailing whitespace */ + break; + else { /* leading whitespace */ + (*startpp)++; + continue; + } + } + if (c == ';') { + while ((*startpp <= endp) && + ((c = **startpp) != '\n')) + (*startpp)++; + if (seendigit) + break; + continue; + } + if (!isxdigit(c)) { + if (c == ')' && seendigit) { + (*startpp)--; + break; + } + return (-1); + } + (*startpp)++; + if (isdigit(c)) + n = n * 16 + (c - '0'); + else + n = n * 16 + (tolower(c) - 'a' + 10); + seendigit = 1; + } + return (n + m); +} + +/* + * Get a whitespace delimited base 16 number from a string (not file) into buf + * update the start pointer to point after the number in the string. + */ +static int +getnum_str(u_char **startpp, u_char *endp) { + int c, n; + int seendigit = 0; + int m = 0; + + for (n = 0; *startpp <= endp; ) { + c = **startpp; + if (isspace(c) || c == '\0') { + if (seendigit) /* trailing whitespace */ + break; + else { /* leading whitespace */ + (*startpp)++; + continue; + } + } + if (c == ';') { + while ((*startpp <= endp) && + ((c = **startpp) != '\n')) + (*startpp)++; + if (seendigit) + break; + continue; + } + if (!isdigit(c)) { + if (c == ')' && seendigit) { + (*startpp)--; + break; + } + return (-1); + } + (*startpp)++; + n = n * 10 + (c - '0'); + seendigit = 1; + } + return (n + m); +} + +/* + * Allocate a resource record buffer & save rr info. + */ +ns_updrec * +res_mkupdrec(int section, const char *dname, + u_int class, u_int type, u_long ttl) { + ns_updrec *rrecp = (ns_updrec *)calloc(1, sizeof(ns_updrec)); + + if (!rrecp || !(rrecp->r_dname = strdup(dname))) { + if (rrecp) + free((char *)rrecp); + return (NULL); + } + INIT_LINK(rrecp, r_link); + INIT_LINK(rrecp, r_glink); + rrecp->r_class = class; + rrecp->r_type = type; + rrecp->r_ttl = ttl; + rrecp->r_section = section; + return (rrecp); +} + +/* + * Free a resource record buffer created by res_mkupdrec. + */ +void +res_freeupdrec(ns_updrec *rrecp) { + /* Note: freeing r_dp is the caller's responsibility. */ + if (rrecp->r_dname != NULL) + free(rrecp->r_dname); + free(rrecp); +} + +struct valuelist { + struct valuelist * next; + struct valuelist * prev; + char * name; + char * proto; + int port; +}; +static struct valuelist *servicelist, *protolist; + +static void +res_buildservicelist() { + struct servent *sp; + struct valuelist *slp; + +#ifdef MAYBE_HESIOD + setservent(0); +#else + setservent(1); +#endif + while ((sp = getservent()) != NULL) { + slp = (struct valuelist *)malloc(sizeof(struct valuelist)); + if (!slp) + break; + slp->name = strdup(sp->s_name); + slp->proto = strdup(sp->s_proto); + if ((slp->name == NULL) || (slp->proto == NULL)) { + if (slp->name) free(slp->name); + if (slp->proto) free(slp->proto); + free(slp); + break; + } + slp->port = ntohs((u_int16_t)sp->s_port); /* host byt order */ + slp->next = servicelist; + slp->prev = NULL; + if (servicelist) + servicelist->prev = slp; + servicelist = slp; + } + endservent(); +} + +void +res_destroyservicelist() { + struct valuelist *slp, *slp_next; + + for (slp = servicelist; slp != NULL; slp = slp_next) { + slp_next = slp->next; + free(slp->name); + free(slp->proto); + free(slp); + } + servicelist = (struct valuelist *)0; +} + +void +res_buildprotolist(void) { + struct protoent *pp; + struct valuelist *slp; + +#ifdef MAYBE_HESIOD + setprotoent(0); +#else + setprotoent(1); +#endif + while ((pp = getprotoent()) != NULL) { + slp = (struct valuelist *)malloc(sizeof(struct valuelist)); + if (!slp) + break; + slp->name = strdup(pp->p_name); + if (slp->name == NULL) { + free(slp); + break; + } + slp->port = pp->p_proto; /* host byte order */ + slp->next = protolist; + slp->prev = NULL; + if (protolist) + protolist->prev = slp; + protolist = slp; + } + endprotoent(); +} + +void +res_destroyprotolist(void) { + struct valuelist *plp, *plp_next; + + for (plp = protolist; plp != NULL; plp = plp_next) { + plp_next = plp->next; + free(plp->name); + free(plp); + } + protolist = (struct valuelist *)0; +} + +static int +findservice(const char *s, struct valuelist **list) { + struct valuelist *lp = *list; + int n; + + for (; lp != NULL; lp = lp->next) + if (strcasecmp(lp->name, s) == 0) { + if (lp != *list) { + lp->prev->next = lp->next; + if (lp->next) + lp->next->prev = lp->prev; + (*list)->prev = lp; + lp->next = *list; + *list = lp; + } + return (lp->port); /* host byte order */ + } + if (sscanf(s, "%d", &n) != 1 || n <= 0) + n = -1; + return (n); +} + +/* + * Convert service name or (ascii) number to int. + */ +int +res_servicenumber(const char *p) { + if (servicelist == (struct valuelist *)0) + res_buildservicelist(); + return (findservice(p, &servicelist)); +} + +/* + * Convert protocol name or (ascii) number to int. + */ +int +res_protocolnumber(const char *p) { + if (protolist == (struct valuelist *)0) + res_buildprotolist(); + return (findservice(p, &protolist)); +} + +static struct servent * +cgetservbyport(u_int16_t port, const char *proto) { /* Host byte order. */ + struct valuelist **list = &servicelist; + struct valuelist *lp = *list; + static struct servent serv; + + port = ntohs(port); + for (; lp != NULL; lp = lp->next) { + if (port != (u_int16_t)lp->port) /* Host byte order. */ + continue; + if (strcasecmp(lp->proto, proto) == 0) { + if (lp != *list) { + lp->prev->next = lp->next; + if (lp->next) + lp->next->prev = lp->prev; + (*list)->prev = lp; + lp->next = *list; + *list = lp; + } + serv.s_name = lp->name; + serv.s_port = htons((u_int16_t)lp->port); + serv.s_proto = lp->proto; + return (&serv); + } + } + return (0); +} + +static struct protoent * +cgetprotobynumber(int proto) { /* Host byte order. */ + struct valuelist **list = &protolist; + struct valuelist *lp = *list; + static struct protoent prot; + + for (; lp != NULL; lp = lp->next) + if (lp->port == proto) { /* Host byte order. */ + if (lp != *list) { + lp->prev->next = lp->next; + if (lp->next) + lp->next->prev = lp->prev; + (*list)->prev = lp; + lp->next = *list; + *list = lp; + } + prot.p_name = lp->name; + prot.p_proto = lp->port; /* Host byte order. */ + return (&prot); + } + return (0); +} + +const char * +res_protocolname(int num) { + static char number[8]; + struct protoent *pp; + + if (protolist == (struct valuelist *)0) + res_buildprotolist(); + pp = cgetprotobynumber(num); + if (pp == 0) { + (void) sprintf(number, "%d", num); + return (number); + } + return (pp->p_name); +} + +const char * +res_servicename(u_int16_t port, const char *proto) { /* Host byte order. */ + static char number[8]; + struct servent *ss; + + if (servicelist == (struct valuelist *)0) + res_buildservicelist(); + ss = cgetservbyport(htons(port), proto); + if (ss == 0) { + (void) sprintf(number, "%d", port); + return (number); + } + return (ss->s_name); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_mkupdate.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_query.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/resolv/res_query.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/resolv/res_query.c (revision 109985) @@ -0,0 +1,429 @@ +/* + * Copyright (c) 1988, 1993 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: res_query.c,v 8.23 2001/09/24 13:50:29 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "port_after.h" + +/* Options. Leave them on. */ +#define DEBUG + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +/* + * Formulate a normal query, send, and await answer. + * Returned answer is placed in supplied buffer "answer". + * Perform preliminary check of answer, returning success only + * if no error is indicated and the answer count is nonzero. + * Return the size of the response on success, -1 on error. + * Error number is left in H_ERRNO. + * + * Caller must parse answer and determine whether it answers the question. + */ +int +res_nquery(res_state statp, + const char *name, /* domain name */ + int class, int type, /* class and type of query */ + u_char *answer, /* buffer to put answer */ + int anslen) /* size of answer buffer */ +{ + u_char buf[MAXPACKET]; + HEADER *hp = (HEADER *) answer; + int n; + u_int oflags; + + oflags = statp->_flags; + +again: + hp->rcode = NOERROR; /* default */ + +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_query(%s, %d, %d)\n", name, class, type); +#endif + + n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL, + buf, sizeof(buf)); +#ifdef RES_USE_EDNS0 + if (n > 0 && (statp->_flags & RES_F_EDNS0ERR) == 0 && + (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0) + n = res_nopt(statp, n, buf, sizeof(buf), anslen); +#endif + if (n <= 0) { +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_query: mkquery failed\n"); +#endif + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (n); + } + n = res_nsend(statp, buf, n, answer, anslen); + if (n < 0) { +#ifdef RES_USE_EDNS0 + /* if the query choked with EDNS0, retry without EDNS0 */ + if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0 && + ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) { + statp->_flags |= RES_F_EDNS0ERR; + if (statp->options & RES_DEBUG) + printf(";; res_nquery: retry without EDNS0\n"); + goto again; + } +#endif +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_query: send error\n"); +#endif + RES_SET_H_ERRNO(statp, TRY_AGAIN); + return (n); + } + + if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; rcode = %d, ancount=%d\n", hp->rcode, + ntohs(hp->ancount)); +#endif + switch (hp->rcode) { + case NXDOMAIN: + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); + break; + case SERVFAIL: + RES_SET_H_ERRNO(statp, TRY_AGAIN); + break; + case NOERROR: + RES_SET_H_ERRNO(statp, NO_DATA); + break; + case FORMERR: + case NOTIMP: + case REFUSED: + default: + RES_SET_H_ERRNO(statp, NO_RECOVERY); + break; + } + return (-1); + } + return (n); +} + +/* + * Formulate a normal query, send, and retrieve answer in supplied buffer. + * Return the size of the response on success, -1 on error. + * If enabled, implement search rules until answer or unrecoverable failure + * is detected. Error code, if any, is left in H_ERRNO. + */ +int +res_nsearch(res_state statp, + const char *name, /* domain name */ + int class, int type, /* class and type of query */ + u_char *answer, /* buffer to put answer */ + int anslen) /* size of answer */ +{ + const char *cp, * const *domain; + HEADER *hp = (HEADER *) answer; + char tmp[NS_MAXDNAME]; + u_int dots; + int trailing_dot, ret, saved_herrno; + int got_nodata = 0, got_servfail = 0, root_on_list = 0; + int tried_as_is = 0; + int searched = 0; + + errno = 0; + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /* True if we never query. */ + + dots = 0; + for (cp = name; *cp != '\0'; cp++) + dots += (*cp == '.'); + trailing_dot = 0; + if (cp > name && *--cp == '.') + trailing_dot++; + + /* If there aren't any dots, it could be a user-level alias. */ + if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL) + return (res_nquery(statp, cp, class, type, answer, anslen)); + + /* + * If there are enough dots in the name, let's just give it a + * try 'as is'. The threshold can be set with the "ndots" option. + * Also, query 'as is', if there is a trailing dot in the name. + */ + saved_herrno = -1; + if (dots >= statp->ndots || trailing_dot) { + ret = res_nquerydomain(statp, name, NULL, class, type, + answer, anslen); + if (ret > 0 || trailing_dot) + return (ret); + saved_herrno = h_errno; + tried_as_is++; + } + + /* + * We do at least one level of search if + * - there is no dot and RES_DEFNAME is set, or + * - there is at least one dot, there is no trailing dot, + * and RES_DNSRCH is set. + */ + if ((!dots && (statp->options & RES_DEFNAMES) != 0) || + (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0)) { + int done = 0; + + for (domain = (const char * const *)statp->dnsrch; + *domain && !done; + domain++) { + searched = 1; + + if (domain[0][0] == '\0' || + (domain[0][0] == '.' && domain[0][1] == '\0')) + root_on_list++; + + ret = res_nquerydomain(statp, name, *domain, + class, type, + answer, anslen); + if (ret > 0) + return (ret); + + /* + * If no server present, give up. + * If name isn't found in this domain, + * keep trying higher domains in the search list + * (if that's enabled). + * On a NO_DATA error, keep trying, otherwise + * a wildcard entry of another type could keep us + * from finding this entry higher in the domain. + * If we get some other error (negative answer or + * server failure), then stop searching up, + * but try the input name below in case it's + * fully-qualified. + */ + if (errno == ECONNREFUSED) { + RES_SET_H_ERRNO(statp, TRY_AGAIN); + return (-1); + } + + switch (statp->res_h_errno) { + case NO_DATA: + got_nodata++; + /* FALLTHROUGH */ + case HOST_NOT_FOUND: + /* keep trying */ + break; + case TRY_AGAIN: + if (hp->rcode == SERVFAIL) { + /* try next search element, if any */ + got_servfail++; + break; + } + /* FALLTHROUGH */ + default: + /* anything else implies that we're done */ + done++; + } + + /* if we got here for some reason other than DNSRCH, + * we only wanted one iteration of the loop, so stop. + */ + if ((statp->options & RES_DNSRCH) == 0) + done++; + } + } + + /* + * If the query has not already been tried as is then try it + * unless RES_NOTLDQUERY is set and there were no dots. + */ + if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0) && + !(tried_as_is || root_on_list)) { + ret = res_nquerydomain(statp, name, NULL, class, type, + answer, anslen); + if (ret > 0) + return (ret); + } + + /* if we got here, we didn't satisfy the search. + * if we did an initial full query, return that query's H_ERRNO + * (note that we wouldn't be here if that query had succeeded). + * else if we ever got a nodata, send that back as the reason. + * else send back meaningless H_ERRNO, that being the one from + * the last DNSRCH we did. + */ + if (saved_herrno != -1) + RES_SET_H_ERRNO(statp, saved_herrno); + else if (got_nodata) + RES_SET_H_ERRNO(statp, NO_DATA); + else if (got_servfail) + RES_SET_H_ERRNO(statp, TRY_AGAIN); + return (-1); +} + +/* + * Perform a call on res_query on the concatenation of name and domain, + * removing a trailing dot from name if domain is NULL. + */ +int +res_nquerydomain(res_state statp, + const char *name, + const char *domain, + int class, int type, /* class and type of query */ + u_char *answer, /* buffer to put answer */ + int anslen) /* size of answer */ +{ + char nbuf[MAXDNAME]; + const char *longname = nbuf; + int n, d; + +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_nquerydomain(%s, %s, %d, %d)\n", + name, domain?domain:"", class, type); +#endif + if (domain == NULL) { + /* + * Check for trailing '.'; + * copy without '.' if present. + */ + n = strlen(name); + if (n >= MAXDNAME) { + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); + } + n--; + if (n >= 0 && name[n] == '.') { + strncpy(nbuf, name, n); + nbuf[n] = '\0'; + } else + longname = name; + } else { + n = strlen(name); + d = strlen(domain); + if (n + d + 1 >= MAXDNAME) { + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); + } + sprintf(nbuf, "%s.%s", name, domain); + } + return (res_nquery(statp, longname, class, type, answer, anslen)); +} + +const char * +res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) { + char *file, *cp1, *cp2; + char buf[BUFSIZ]; + FILE *fp; + + if (statp->options & RES_NOALIASES) + return (NULL); + file = getenv("HOSTALIASES"); + if (file == NULL || (fp = fopen(file, "r")) == NULL) + return (NULL); + setbuf(fp, NULL); + buf[sizeof(buf) - 1] = '\0'; + while (fgets(buf, sizeof(buf), fp)) { + for (cp1 = buf; *cp1 && !isspace((unsigned char)*cp1); ++cp1) + ; + if (!*cp1) + break; + *cp1 = '\0'; + if (ns_samename(buf, name) == 1) { + while (isspace((unsigned char)*++cp1)) + ; + if (!*cp1) + break; + for (cp2 = cp1 + 1; *cp2 && + !isspace((unsigned char)*cp2); ++cp2) + ; + *cp2 = '\0'; + strncpy(dst, cp1, siz - 1); + dst[siz - 1] = '\0'; + fclose(fp); + return (dst); + } + } + fclose(fp); + return (NULL); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_query.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_data.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/resolv/res_data.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/resolv/res_data.c (revision 109985) @@ -0,0 +1,291 @@ +/* + * Copyright (c) 1995-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: res_data.c,v 8.18 2000/12/23 08:14:58 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "port_after.h" +#undef _res + +const char *_res_opcodes[] = { + "QUERY", + "IQUERY", + "CQUERYM", + "CQUERYU", /* experimental */ + "NOTIFY", /* experimental */ + "UPDATE", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "ZONEINIT", + "ZONEREF", +}; + +#ifdef BIND_UPDATE +const char *_res_sectioncodes[] = { + "ZONE", + "PREREQUISITES", + "UPDATE", + "ADDITIONAL", +}; +#endif + +#ifndef __BIND_NOSTATIC +struct __res_state _res +# if defined(__BIND_RES_TEXT) + = { RES_TIMEOUT, } /* Motorola, et al. */ +# endif + ; + +/* Proto. */ + +int res_ourserver_p(const res_state, const struct sockaddr_in *); + +int +res_init(void) { + extern int __res_vinit(res_state, int); + + /* + * These three fields used to be statically initialized. This made + * it hard to use this code in a shared library. It is necessary, + * now that we're doing dynamic initialization here, that we preserve + * the old semantics: if an application modifies one of these three + * fields of _res before res_init() is called, res_init() will not + * alter them. Of course, if an application is setting them to + * _zero_ before calling res_init(), hoping to override what used + * to be the static default, we can't detect it and unexpected results + * will follow. Zero for any of these fields would make no sense, + * so one can safely assume that the applications were already getting + * unexpected results. + * + * _res.options is tricky since some apps were known to diddle the bits + * before res_init() was first called. We can't replicate that semantic + * with dynamic initialization (they may have turned bits off that are + * set in RES_DEFAULT). Our solution is to declare such applications + * "broken". They could fool us by setting RES_INIT but none do (yet). + */ + if (!_res.retrans) + _res.retrans = RES_TIMEOUT; + if (!_res.retry) + _res.retry = 4; + if (!(_res.options & RES_INIT)) + _res.options = RES_DEFAULT; + + /* + * This one used to initialize implicitly to zero, so unless the app + * has set it to something in particular, we can randomize it now. + */ + if (!_res.id) + _res.id = res_randomid(); + + return (__res_vinit(&_res, 1)); +} + +void +p_query(const u_char *msg) { + fp_query(msg, stdout); +} + +void +fp_query(const u_char *msg, FILE *file) { + fp_nquery(msg, PACKETSZ, file); +} + +void +fp_nquery(const u_char *msg, int len, FILE *file) { + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return; + + res_pquery(&_res, msg, len, file); +} + +int +res_mkquery(int op, /* opcode of query */ + const char *dname, /* domain name */ + int class, int type, /* class and type of query */ + const u_char *data, /* resource record data */ + int datalen, /* length of data */ + const u_char *newrr_in, /* new rr for modify or append */ + u_char *buf, /* buffer to put query */ + int buflen) /* size of buffer */ +{ + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + return (res_nmkquery(&_res, op, dname, class, type, + data, datalen, + newrr_in, buf, buflen)); +} + +int +res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) { + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + + return (res_nmkupdate(&_res, rrecp_in, buf, buflen)); +} + +int +res_query(const char *name, /* domain name */ + int class, int type, /* class and type of query */ + u_char *answer, /* buffer to put answer */ + int anslen) /* size of answer buffer */ +{ + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + return (res_nquery(&_res, name, class, type, answer, anslen)); +} + +void +res_send_setqhook(res_send_qhook hook) { + _res.qhook = hook; +} + +void +res_send_setrhook(res_send_rhook hook) { + _res.rhook = hook; +} + +int +res_isourserver(const struct sockaddr_in *inp) { + return (res_ourserver_p(&_res, inp)); +} + +int +res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) { + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + /* errno should have been set by res_init() in this case. */ + return (-1); + } + + return (res_nsend(&_res, buf, buflen, ans, anssiz)); +} + +int +res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key, + u_char *ans, int anssiz) +{ + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + /* errno should have been set by res_init() in this case. */ + return (-1); + } + + return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz)); +} + +void +res_close(void) { + res_nclose(&_res); +} + +int +res_update(ns_updrec *rrecp_in) { + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + + return (res_nupdate(&_res, rrecp_in, NULL)); +} + +int +res_search(const char *name, /* domain name */ + int class, int type, /* class and type of query */ + u_char *answer, /* buffer to put answer */ + int anslen) /* size of answer */ +{ + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + + return (res_nsearch(&_res, name, class, type, answer, anslen)); +} + +int +res_querydomain(const char *name, + const char *domain, + int class, int type, /* class and type of query */ + u_char *answer, /* buffer to put answer */ + int anslen) /* size of answer */ +{ + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + + return (res_nquerydomain(&_res, name, domain, + class, type, + answer, anslen)); +} + +const char * +hostalias(const char *name) { + static char abuf[MAXDNAME]; + + return (res_hostalias(&_res, name, abuf, sizeof abuf)); +} + +#ifdef ultrix +int +local_hostname_length(const char *hostname) { + int len_host, len_domain; + + if (!*_res.defdname) + res_init(); + len_host = strlen(hostname); + len_domain = strlen(_res.defdname); + if (len_host > len_domain && + !strcasecmp(hostname + len_host - len_domain, _res.defdname) && + hostname[len_host - len_domain - 1] == '.') + return (len_host - len_domain - 1); + return (0); +} +#endif /*ultrix*/ + +#endif Property changes on: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_data.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_sendsigned.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/resolv/res_sendsigned.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/resolv/res_sendsigned.c (revision 109985) @@ -0,0 +1,134 @@ +#include "port_before.h" +#include "fd_setsize.h" + +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +#define DEBUG +#include "res_debug.h" + + +/* res_nsendsigned */ +int +res_nsendsigned(res_state statp, const u_char *msg, int msglen, + ns_tsig_key *key, u_char *answer, int anslen) +{ + res_state nstatp; + DST_KEY *dstkey; + int usingTCP = 0; + u_char *newmsg; + int newmsglen, bufsize, siglen; + u_char sig[64]; + HEADER *hp; + time_t tsig_time; + int ret; + + dst_init(); + + nstatp = (res_state) malloc(sizeof(*statp)); + if (nstatp == NULL) { + errno = ENOMEM; + return (-1); + } + memcpy(nstatp, statp, sizeof(*statp)); + + bufsize = msglen + 1024; + newmsg = (u_char *) malloc(bufsize); + if (newmsg == NULL) { + errno = ENOMEM; + return (-1); + } + memcpy(newmsg, msg, msglen); + newmsglen = msglen; + + if (ns_samename(key->alg, NS_TSIG_ALG_HMAC_MD5) != 1) + dstkey = NULL; + else + dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5, + NS_KEY_TYPE_AUTH_ONLY, + NS_KEY_PROT_ANY, + key->data, key->len); + if (dstkey == NULL) { + errno = EINVAL; + free(nstatp); + free(newmsg); + return (-1); + } + + nstatp->nscount = 1; + siglen = sizeof(sig); + ret = ns_sign(newmsg, &newmsglen, bufsize, NOERROR, dstkey, NULL, 0, + sig, &siglen, 0); + if (ret < 0) { + free (nstatp); + free (newmsg); + dst_free_key(dstkey); + if (ret == NS_TSIG_ERROR_NO_SPACE) + errno = EMSGSIZE; + else if (ret == -1) + errno = EINVAL; + return (ret); + } + + if (newmsglen > PACKETSZ || (nstatp->options & RES_IGNTC)) + usingTCP = 1; + if (usingTCP == 0) + nstatp->options |= RES_IGNTC; + else + nstatp->options |= RES_USEVC; + +retry: + + ret = res_nsend(nstatp, newmsg, newmsglen, answer, anslen); + if (ret < 0) { + free (nstatp); + free (newmsg); + dst_free_key(dstkey); + return (ret); + } + + anslen = ret; + ret = ns_verify(answer, &anslen, dstkey, sig, siglen, + NULL, NULL, &tsig_time, nstatp->options & RES_KEEPTSIG); + if (ret != 0) { + Dprint(nstatp->pfcode & RES_PRF_REPLY, + (stdout, ";; TSIG invalid (%s)\n", p_rcode(ret))); + free (nstatp); + free (newmsg); + dst_free_key(dstkey); + if (ret == -1) + errno = EINVAL; + else + errno = ENOTTY; + return (-1); + } + Dprint(nstatp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG ok\n")); + + hp = (HEADER *) answer; + if (hp->tc && usingTCP == 0) { + nstatp->options &= ~RES_IGNTC; + usingTCP = 1; + goto retry; + } + + free (nstatp); + free (newmsg); + dst_free_key(dstkey); + return (anslen); +} Property changes on: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_sendsigned.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_debug.h =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/resolv/res_debug.h (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/resolv/res_debug.h (revision 109985) @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#ifndef _RES_DEBUG_H_ +#define _RES_DEBUG_H_ + +#ifndef DEBUG +# define Dprint(cond, args) /*empty*/ +# define DprintQ(cond, args, query, size) /*empty*/ +# define Aerror(statp, file, string, error, address) /*empty*/ +# define Perror(statp, file, string, error) /*empty*/ +#else +# define Dprint(cond, args) if (cond) {fprintf args;} else {} +# define DprintQ(cond, args, query, size) if (cond) {\ + fprintf args;\ + res_pquery(statp, query, size, stdout);\ + } else {} +#endif + +#endif /* _RES_DEBUG_H_ */ Property changes on: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_debug.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.3.4/contrib/bind/lib/resolv/res_comp.c =================================================================== --- vendor/bind/8.3.4/contrib/bind/lib/resolv/res_comp.c (nonexistent) +++ vendor/bind/8.3.4/contrib/bind/lib/resolv/res_comp.c (revision 109985) @@ -0,0 +1,251 @@ +/* + * Copyright (c) 1985, 1993 + * 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 + * are met: + * 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 + * SUCH DAMAGE. + */ + +/* + * 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 + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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 + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: res_comp.c,v 8.15 1999/10/13 16:39:39 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "port_after.h" + +/* + * Expand compressed domain name 'comp_dn' to full domain name. + * 'msg' is a pointer to the begining of the message, + * 'eomorig' points to the first location after the message, + * 'exp_dn' is a pointer to a buffer of size 'length' for the result. + * Return size of compressed name or -1 if there was an error. + */ +int +dn_expand(const u_char *msg, const u_char *eom, const u_char *src, + char *dst, int dstsiz) +{ + int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz); + + if (n > 0 && dst[0] == '.') + dst[0] = '\0'; + return (n); +} + +/* + * Pack domain name 'exp_dn' in presentation form into 'comp_dn'. + * Return the size of the compressed name or -1. + * 'length' is the size of the array pointed to by 'comp_dn'. + */ +int +dn_comp(const char *src, u_char *dst, int dstsiz, + u_char **dnptrs, u_char **lastdnptr) +{ + return (ns_name_compress(src, dst, (size_t)dstsiz, + (const u_char **)dnptrs, + (const u_char **)lastdnptr)); +} + +/* + * Skip over a compressed domain name. Return the size or -1. + */ +int +dn_skipname(const u_char *ptr, const u_char *eom) { + const u_char *saveptr = ptr; + + if (ns_name_skip(&ptr, eom) == -1) + return (-1); + return (ptr - saveptr); +} + +/* + * Verify that a domain name uses an acceptable character set. + */ + +/* + * Note the conspicuous absence of ctype macros in these definitions. On + * non-ASCII hosts, we can't depend on string literals or ctype macros to + * tell us anything about network-format data. The rest of the BIND system + * is not careful about this, but for some reason, we're doing it right here. + */ +#define PERIOD 0x2e +#define hyphenchar(c) ((c) == 0x2d) +#define bslashchar(c) ((c) == 0x5c) +#define periodchar(c) ((c) == PERIOD) +#define asterchar(c) ((c) == 0x2a) +#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \ + || ((c) >= 0x61 && (c) <= 0x7a)) +#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) + +#define borderchar(c) (alphachar(c) || digitchar(c)) +#define middlechar(c) (borderchar(c) || hyphenchar(c)) +#define domainchar(c) ((c) > 0x20 && (c) < 0x7f) + +int +res_hnok(const char *dn) { + int ppch = '\0', pch = PERIOD, ch = *dn++; + + while (ch != '\0') { + int nch = *dn++; + + if (periodchar(ch)) { + (void)NULL; + } else if (periodchar(pch)) { + if (!borderchar(ch)) + return (0); + } else if (periodchar(nch) || nch == '\0') { + if (!borderchar(ch)) + return (0); + } else { + if (!middlechar(ch)) + return (0); + } + ppch = pch, pch = ch, ch = nch; + } + return (1); +} + +/* + * hostname-like (A, MX, WKS) owners can have "*" as their first label + * but must otherwise be as a host name. + */ +int +res_ownok(const char *dn) { + if (asterchar(dn[0])) { + if (periodchar(dn[1])) + return (res_hnok(dn+2)); + if (dn[1] == '\0') + return (1); + } + return (res_hnok(dn)); +} + +/* + * SOA RNAMEs and RP RNAMEs can have any printable character in their first + * label, but the rest of the name has to look like a host name. + */ +int +res_mailok(const char *dn) { + int ch, escaped = 0; + + /* "." is a valid missing representation */ + if (*dn == '\0') + return (1); + + /* otherwise