Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/named/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/Makefile (revision 60942) @@ -0,0 +1,132 @@ +## 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.49 2000/05/09 07:02:22 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +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} -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.2.3.t5b/contrib/bind/bin/named/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_defs.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_defs.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_defs.h (revision 60942) @@ -0,0 +1,313 @@ +/* + * from db.h 4.16 (Berkeley) 6/1/90 + * $Id: db_defs.h,v 8.38 2000/04/21 06:54:01 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 definitions for data base routines. + */ + + /* max length of data in RR data field */ +#define MAXDATA (2*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; +}; + +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; + 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 */ + +/* + * 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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/db_dump.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_dump.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_dump.c (revision 60942) @@ -0,0 +1,677 @@ +#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.43 2000/04/21 06:54:01 vixie 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 "port_after.h" + +#include "named.h" + +static const char *MkCredStr(int); + +/* + * Dump current data base in a format similar to RFC 883. + */ + +void +doadump() +{ + FILE *fp; + + ns_notice(ns_log_db, "dumping nameserver data"); + + if ((fp = write_open(server_options->dump_filename)) == NULL) + return; + gettime(&tt); + 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++) { + char *pre, 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); +} +int +fwd_dump(FILE *fp) { + int i; + fprintf(fp, ";; ++forwarders table++\n"); + for (i=0;ifwdaddr.sin_addr), + fwddata[i]->nsdata->d_nstime); + } + fprintf(fp, ";; --forwarders table--\n"); + return (0); +} + +int +db_dump(struct hashbuf *htp, FILE *fp, int zone, 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); + + if ((n = *cp++) != 0) { + fprintf(fp, "\"%.*s\"", (int)n, cp); + cp += n; + } + if ((n = *cp++) != 0) { + fprintf(fp, "\"%.*s\"", (int)n, cp); + cp += n; + } + if ((n = *cp++) != 0) { + 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, "%s?d_type=%d?", + sep, dp->d_type); + sep = " "; + } + 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=%d", + sep, when - tt.tv_sec); + sep = " "; + } + } + + eoln: + if (dp->d_ns != NULL){ + fprintf(fp, "%s[%s]", + sep, inet_ntoa(dp->d_ns->addr)); + sep = " "; + } + 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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/db_func.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_func.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_func.h (revision 60942) @@ -0,0 +1,213 @@ +/* + * 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.42 2000/04/21 06:54:02 vixie Exp $ + */ + +/* ++from db_update.c++ */ +extern int db_update(const char *name, + struct databuf *odp, + struct databuf *newdp, + struct databuf **savedpp, + int flags, + struct hashbuf *htp, + struct sockaddr_in from), + db_cmp(const struct databuf *, const struct databuf *), + findMyZone(struct namebuf *np, int class); +void fixttl(struct databuf *dp); +/* --from db_update.c-- */ + +/* ++from db_save.c++ */ +extern struct namebuf *savename(const char *, int); +extern struct databuf *savedata(int, int, u_int32_t, u_char *, int); +extern struct hashbuf *savehash(struct hashbuf *); +/* --from db_save.c-- */ + +/* ++from db_dump.c++ */ +extern int db_dump(struct hashbuf *, FILE *, int, char *), + zt_dump(FILE *); +extern void doadump(void); +/* --from db_dump.c-- */ + +/* ++from db_load.c++ */ +extern 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); +extern void endline(FILE *); +extern int getword(char *, size_t, FILE *, int), + getttl(FILE *, const char *, int, u_int32_t *, int *), + getnum(FILE *, const char *, int), + db_load(const char *, const char *, struct zoneinfo *, + const char *, int); +extern int getnonblank(FILE *, const char *), + getservices(int, char *, FILE *, const char *); +extern char getprotocol(FILE *, const char *); +extern int makename(char *, const char *, int); +extern void db_err(int, char *, int, const char *, int); +extern 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, + char **errmsg); +/* --from db_load.c-- */ + +/* ++from db_glue.c++ */ +extern void buildservicelist(void), + destroyservicelist(void), + buildprotolist(void), + destroyprotolist(void), + getname(struct namebuf *, char *, int); +extern int servicenumber(const char *), + protocolnumber(const char *), + get_class(const char *); +extern u_int nhash(const char *); +extern const char *protocolname(int), + *servicename(u_int16_t, const char *); +#ifndef BSD +extern int getdtablesize(void); +#endif +extern struct databuf *rm_datum(struct databuf *, + struct namebuf *, + struct databuf *, + struct databuf **); +extern struct namebuf *rm_name(struct namebuf *, + struct namebuf **, + struct namebuf *); +extern void rm_hash(struct hashbuf *); +extern void db_freedata(struct databuf *); +extern void db_lame_add(char *zone, char *server, time_t when); +extern time_t db_lame_find(char *zone, struct databuf *dp); +extern void db_lame_clean(void); +extern void db_lame_destroy(void); +/* --from db_glue.c-- */ + +/* ++from db_lookup.c++ */ +extern struct namebuf *nlookup(const char *, struct hashbuf **, + const char **, int); +extern struct namebuf *np_parent __P((struct namebuf *)); +extern 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++ */ +extern 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++ */ +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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/db_glob.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_glob.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_glob.h (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/db_glue.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_glue.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_glue.c (revision 60942) @@ -0,0 +1,656 @@ +#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.40 2000/04/21 06:54:02 vixie 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; + freestr(slp->name); + 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; + 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; +#ifdef BIND_UPDATE + if (savedpp != NULL) { + /* mark deleted or pending deletion */ + dp->d_mark |= D_MARK_DELETED; + dp->d_next = *savedpp; + *savedpp = dp; + } else + dp->d_next = NULL; +#else + dp->d_next = NULL; +#endif + dp->d_flags &= ~DB_F_ACTIVE; + DRCNTDEC(dp); + if (dp->d_rcnt) { +#ifdef DEBUG + int32_t ii; +#endif + + switch(dp->d_type) { + case T_NS: + ns_debug(ns_log_db, 3, "rm_datum: %s rcnt = %d", + dp->d_data, dp->d_rcnt); + break; +#ifdef DEBUG + case T_A: + memcpy(&ii, dp->d_data, sizeof ii); + ns_debug(ns_log_db, 3, + "rm_datum: %08.8X rcnt = %d", + ii, dp->d_rcnt); + break; +#endif + default: + ns_debug(ns_log_db, 3, + "rm_datum: rcnt = %d", dp->d_rcnt); + } + } else +#ifdef BIND_UPDATE + if (savedpp == NULL) +#endif + db_freedata(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 && (msg = "data")) + || (np->n_hash && (msg = "hash")) + ) { + ns_panic(ns_log_db, 1, "rm_name(%#x(%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) { + *cp = '\0'; + ns_info(ns_log_db, + "domain name too long: %s...", buf); + 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); +} + +void +db_freedata(struct databuf *dp) { + int bytes = 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; + memput(dp, bytes); +} + +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) + freestr(this->server); + if (this->zone != NULL) + 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) { + freestr(this->zone); + 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; + freestr(last->zone); + 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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/db_ixfr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_ixfr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_ixfr.c (revision 60942) @@ -0,0 +1,925 @@ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: db_ixfr.c,v 8.20 2000/02/29 05:15:03 vixie 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 "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); + 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 ((uprec->r_zone < from_serial) || + (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_freedata(uprec->r_dp); + uprec->r_dp = NULL; + 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_freedata(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) +{ + static int read_soa, read_ns, rrcount; + + char data[MAXDATA], dnbuf[MAXDNAME], sclass[3]; + const char *errtype = "Database"; + char *dname, *cp, *cp1; + char buf[MAXDATA]; + u_int32_t serial, ttl; + 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 databuf *dp; + struct in_addr ina; + struct sockaddr_in empty_from; + 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; + for (;;) { + 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'; + switch (section) { + case S_ZONE: + cp = fgets(buf, sizeof buf, fp); + if (!cp) + *buf = '\0'; + n = sscanf(cp, "origin %s class %s serial %ul", + origin, sclass, &serial); + 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 = sym_ston(__p_class_syms, 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, 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 = sym_ston(__p_class_syms, + 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 = sym_ston(__p_type_syms, + 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); + if (c == '(') { + multiline = 1; + } else { + multiline = 0; + ungetc(c, fp); + } + n = getnum(fp, zp->z_updatelog, GETNUM_SERIAL); + if (getnum_error) { + err++; + break; + } + if (opcode == ADD && i == 0) + *new_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 && + getnonblank(fp, zp->z_updatelog) != ')') + { + 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:{ + 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: + err++; + } + 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) { + 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 == dp->d_type && + arp->r_dp->d_class == dp->d_class && + arp->r_dp->d_ttl == dp->d_ttl && + ns_samename(arp->r_dname, dname) == 1 && + db_cmp(arp->r_dp, dp) == 0) { + db_freedata(dp); + db_freedata(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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/db_load.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_load.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_load.c (revision 60942) @@ -0,0 +1,2614 @@ +#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.103 2000/04/21 06:54:02 vixie 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 "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 , char **); +static int parse_key_rr(char *, int, u_char *, int, FILE *, + struct zoneinfo *, char *, enum context, + enum transport, char **); + +static int parse_cert_rr(char *, int, u_char *, int, FILE *, char **); +static int parse_nxt_rr(char *, int, u_char *, int, FILE *, + struct zoneinfo *, char *, enum context, + enum transport, 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]; + 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; + + 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: + 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; + return (-1); + } + 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 = sym_ston(__p_type_syms, 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"); + for (i = genstart; i <= genend; i += genstep) { + if (genname(genlhs, i, origin, domain, + sizeof domain) == -1) + ERRTOZ("$GENERATE genname LHS failed"); + 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) + errs++; + } + } + 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 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 = sym_ston(__p_class_syms, 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 = sym_ston(__p_type_syms, 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; + default: + escape = 0; + } + 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); + if (c == '(') { + multiline = 1; + } else { + multiline = 0; + ungetc(c, fp); + } + serial = zp->z_serial; + zp->z_serial = getnum(fp, filename, + GETNUM_SERIAL); + 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, + zp->z_serial, 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); + 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); + 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); + if (getnum_error || n > 65536) + ERRTO("SRV RR"); + PUTSHORT((u_int16_t)n, cp); + + n = getnum(fp, filename, GETNUM_NONE); + 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: + 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: { + 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: + goto err; + } + /* + * 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) + errs++; + 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) + 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); + while (filenames) { + fn = filenames; + filenames = filenames->next; + freestr(fn->name); + memput(fn, sizeof *fn); + } + if (errs != 0) + ns_warning(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); + 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) && + (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 '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); + 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 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') + lineno++; + if (seendigit) + break; + continue; + } + if (c == ';') { + while ((c = getc(fp)) != EOF && c != '\n') + ; + if (c == '\n') + lineno++; + 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); +} + +#ifndef BIND_UPDATE +static +#endif +int +getnonblank(FILE *fp, const char *src) { + int c; + + while ((c = getc(fp)) != EOF) { + if (isspace(c)) { + if (c == '\n') + lineno++; + continue; + } + if (c == ';') { + while ((c = getc(fp)) != EOF && c != '\n') + ; + if (c == '\n') + lineno++; + continue; + } + return (c); + } + ns_info(ns_log_db, "%s:%d: unexpected EOF", src, lineno); + return (EOF); +} + +/* + * 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 = sym_ston(__p_type_syms, (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, 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; + 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 = sym_ston(__p_type_syms, 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 (0 >= origTTL || wordtouint32_error || + (origTTL > 0x7fffffff)) + 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, int buf_len, u_char *data, int data_size, + FILE *fp, struct zoneinfo *zp, char *domain, enum context context, + enum transport transport, 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, 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; + 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"); + } + 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"); + + 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"); + } + + 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, sizeof(data) - 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, struct zoneinfo *zp, char *domain, enum context context, + enum transport transport, 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; + 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, 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, zp, + domain, context, transport, errmsg); + break; + case ns_t_nxt: + ret = parse_nxt_rr(buf, buf_len, 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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/db_lookup.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_lookup.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_lookup.c (revision 60942) @@ -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.26 2000/04/21 06:54:03 vixie 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 && 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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/db_save.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_save.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_save.c (revision 60942) @@ -0,0 +1,211 @@ +#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.27 2000/04/21 06:54:03 vixie 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 = 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_ns = NULL; + dp->d_nstime = 0; + 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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/db_sec.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_sec.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_sec.c (revision 60942) @@ -0,0 +1,1097 @@ + +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: db_sec.c,v 8.31 2000/04/21 06:54:04 vixie 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; + + tkey.zpk_name = (char *) 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 < 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 < 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 < 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 < 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 < 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; + } + } +} + +int +verify_set(struct db_rrset *rrset) { + DST_KEY *key = NULL; + struct sig_record *sigdata; + struct dnode *sigdn; + struct databuf *sigdp; + time_t now; + 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; + + 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) + */ + if (ntohl(sigdata->sig_time_n) > now) + continue; + + /* An expired set is dropped, but the data is not. */ + if (ntohl(sigdata->sig_exp_n) < now) { + db_freedata(sigdp); + sigdn->dp = 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_freedata(sigdp); + sigdn->dp = NULL; + } + else + dnssec_succeeded++; + } + +end: + if (dnssec_failed > 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_partial(struct db_rrset *rrset, int free_data, struct dnode *start) { + struct dnode *dnp; + int found_start = 0; + + ns_debug(ns_log_default, 5, "rrset_free(%s)", rrset->rr_name); + + if (start == NULL) + found_start = 1; + + while (rrset->rr_list) { + dnp = rrset->rr_list; + if (dnp == start) + found_start = 1; + rrset->rr_list = rrset->rr_list->dn_next; + if (dnp->dp != NULL && free_data == 1 && found_start == 1) + db_freedata(dnp->dp); + memput(dnp, sizeof(struct dnode)); + } + while (rrset->rr_sigs) { + dnp = rrset->rr_sigs; + if (dnp == start) + found_start = 1; + rrset->rr_sigs = rrset->rr_sigs->dn_next; + if (dnp->dp != NULL && free_data == 1 && found_start == 1) + db_freedata(dnp->dp); + memput(dnp, sizeof(struct dnode)); + } +} + +static void +rrset_free(struct db_rrset *rrset, int free_data) { + rrset_free_partial(rrset, free_data, NULL); +} + +/* + * 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; + struct databuf *dp; + 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, 1); + return (OK); + } + + if (rrset->rr_list != NULL && + verify_set(rrset) == DB_S_FAILED) + { + rrset_free(rrset, 1); + return (OK); + } + } + + for (dnp = rrset->rr_list; dnp != NULL; dnp = dnp->dn_next) { + dp = dnp->dp; + ret = db_update(rrset->rr_name, dp, dp, NULL, + flags, (*htpp), from); + if (ret != OK) { + /* XXX Probably should do rollback. */ + db_err(ret, rrset->rr_name, dp->d_type, + dnp->file, dnp->line); + if (ret != DATAEXISTS) { + rrset_free_partial(rrset, 1, dnp); + return (ret); + } + db_freedata(dp); + } + if (rrcount != NULL) + (*rrcount)++; + dnp->dp = NULL; + } + for (dnp = rrset->rr_sigs; dnp != NULL; dnp = dnp->dn_next) { + dp = dnp->dp; + if (dp == NULL) /* verifyset() can remove sigs */ + continue; + ret = db_update(rrset->rr_name, dp, dp, NULL, + flags, (*htpp), from); + if (ret != OK) { + /* XXX Probably should do rollback. */ + db_err(ret, rrset->rr_name, dp->d_type, + dnp->file, dnp->line); + if (ret != DATAEXISTS) { + rrset_free_partial(rrset, 1, dnp); + return (ret); + } + db_freedata(dp); + } + if (rrcount != NULL) + (*rrcount)++; + dnp->dp = NULL; + } + rrset_free(rrset, 0); + 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 (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))) + { + db_freedata(dp); + 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; + 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 = (char *) 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, 1); + result = DNSSECFAIL; + } + 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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/db_tsig.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_tsig.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_tsig.c (revision 60942) @@ -0,0 +1,158 @@ + +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: db_tsig.c,v 8.6 2000/04/21 06:54:04 vixie 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" + +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 = 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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/db_update.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_update.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/db_update.c (revision 60942) @@ -0,0 +1,989 @@ +#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.42 2000/04/21 06:54:04 vixie 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, (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 (secondary) + * CRL.DEC.COM NS (in secondary) + * 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, %#x, %#x, %#x, 0%o, %#x)%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) { + ns_debug(ns_log_db, 5, + "attempted update child zone %s, %s", + zones[zn].z_origin, name); + 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 %#x freed", dp); + db_freedata(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 secondary 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 %#x", + (newdp->d_flags&DB_F_HINT) ? " hint":"", newdp); + + if (NS_OPTION_P(OPTION_HOSTSTATS) && + newdp->d_zone == DB_Z_CACHE && + (newdp->d_flags & DB_F_HINT) == 0) + newdp->d_ns = nameserFind(from.sin_addr, NS_F_INSERT); + + /* 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((char *)dp1->d_data, (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((char *)dp1->d_data + NS_SIG_SIGNER); + if (ns_samename((char *)dp1->d_data + NS_SIG_SIGNER, + (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((char *)dp1->d_data, (char *)dp2->d_data) != 1) + return (1); + len = strlen((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((char *)++cp1, (char *)++cp2, len)) + return (1); + cp1 += len; + cp2 += len; + len = *cp1; + len2 = *cp2; + if (len != len2) + return (1); + return (strncasecmp((char *)++cp1, (char *)++cp2, len)); + + case T_SOA: + case T_MINFO: + case T_RP: + if (ns_samename((char *)dp1->d_data, (char *)dp2->d_data) != 1) + return (1); + cp1 = dp1->d_data + strlen((char *)dp1->d_data) + 1; + cp2 = dp2->d_data + strlen((char *)dp2->d_data) + 1; + if (ns_samename((char *)cp1, (char *)cp2) != 1) + return (1); + if (dp1->d_type != T_SOA) + return (0); + cp1 += strlen((char *)cp1) + 1; + cp2 += strlen((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 */ + t1 = strlen((char *)cp1); t2 = strlen((char *)cp2); + if (t1 != t2 || memcmp(cp1, cp2, t1)) + return (1); + cp1 += t1 + 1; cp2 += t2 + 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((char *)cp1, (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((char *)cp1, (char *)cp2) != 1) + return (1); + cp1 += strlen((char *)cp1) + 1; + cp2 += strlen((char *)cp2) + 1; + if (ns_samename((char *)cp1, (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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/named.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/named.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/named.h (revision 60942) @@ -0,0 +1,63 @@ +/* + * 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.27 2000/04/21 06:54:04 vixie Exp $ + */ + +/* Options. Change them at your peril. */ +#define DEBUG +#define ADDAUTH +#define STUBS +#define RETURNSOA +#define BOGUSNS +#define TRACEROOT +#define XFRNETS +#define QRYLOG +#define 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 + +#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.2.3.t5b/contrib/bind/bin/named/named.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_config.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_config.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_config.c (revision 60942) @@ -0,0 +1,3126 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_config.c,v 8.114 2000/04/23 02:18:58 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. + */ + +/* + * 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 int initial_configuration = 1; + +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) { + 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) + freestr(zp->z_origin); + zp->z_origin = NULL; + if (zp->z_source != NULL) + freestr(zp->z_source); + zp->z_source = NULL; + if (zp->z_ixfr_base != NULL) + freestr(zp->z_ixfr_base); + zp->z_ixfr_base = NULL; + if (zp->z_ixfr_tmp != NULL) + freestr(zp->z_ixfr_tmp); + zp->z_ixfr_tmp = NULL; + 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) + freestr(zp->z_updatelog); + zp->z_updatelog = NULL; +#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 + 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(int class, int type) { + 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 && + zp->z_type != z_stub) { + ns_error(ns_log_config, + "'allow-query' option for non-{master,slave,stub} zone '%s'", + zp->z_origin); + return (0); + } + } + +#ifdef BIND_NOTIFY + /* Check notify */ + if (zp->z_notify != znotify_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) + 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_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) + 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) { + 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) + 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) + 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) + freestr(zp->z_source); + zp->z_source = new_zp->z_source; + new_zp->z_source = NULL; + + if (zp->z_ixfr_base != NULL) + 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 (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"); + freestr(zp->z_source); + zp->z_source = NULL; + 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) + 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 secondary 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; + 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(new_zp->z_class, new_zp->z_type); + INSIST(zp != NULL); + value.integer = (zp - zones); + define_symbol(zone_symbol_table, savestr(new_zp->z_origin, 1), + new_zp->z_class, value, SYMBOL_FREE_KEY); + } + 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 = znotify_yes; +#endif + } else + zp->z_dialup = zdialup_no; + + return (1); +} + +int +set_zone_notify(zone_config zh, int value) { +#ifdef BIND_NOTIFY + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + if (value) + zp->z_notify = znotify_yes; + else + zp->z_notify = znotify_no; +#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 checknames 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 checknames 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 checknames 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 zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + zp->z_addr[zp->z_addrcnt] = address; + 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; + + op = (options)memget(sizeof (struct options)); + if (op == NULL) + panic("memget failed in new_options()", NULL); + + op->version = savestr(ShortVersion, 1); + 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->lame_ttl = NTTL; + op->heartbeat_interval = 3600; + op->max_log_size_ixfr = 20; + op->minroots = MINROOTS; + return (op); +} + +void +free_options(options op) { + INSIST(op != NULL); + + if (op->version) + freestr(op->version); + if (op->directory) + freestr(op->directory); + if (op->pid_filename) + freestr(op->pid_filename); + if (op->named_xfer) + freestr(op->named_xfer); + if (op->dump_filename) + freestr(op->dump_filename); + if (op->stats_filename) + freestr(op->stats_filename); + if (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) { + case OPTION_NORECURSE: + case OPTION_NOFETCHGLUE: + case OPTION_FORWARD_ONLY: + case OPTION_FAKE_IQUERY: + case OPTION_NONOTIFY: + 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; + 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 (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)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); + freestr(current_pid_filename); + current_pid_filename = NULL; + } + 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) +{ + getnetconf(1); +} + +static void +set_interval_timer(int which_timer, int interval) { + evTimerID *tid = NULL; + evTimerFunc func = NULL; + + switch (which_timer) { + case CLEAN_TIMER: + tid = &clean_timer; + func = ns_cleancache; + break; + case INTERFACE_TIMER: + tid = &interface_timer; + func = periodic_getnetconf; + break; + case STATS_TIMER: + tid = &stats_timer; + func = ns_logstats; + break; + case HEARTBEAT_TIMER: + 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 (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 " }, /* can't match */ + { fixed_order, "fixed" }, + { cyclic_order, "cyclic" }, + { random_order, "random" }, + { unknown_order, 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; + 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; +} + +/* 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)); + } +} + + +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, + char *allow, 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: + 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 databuf *ns, *nsdata; + register int i; + + for (i=0;ifwdaddr.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); + fdp->fwdaddr.sin_family = AF_INET; + fdp->fwdaddr.sin_addr = address; + fdp->fwdaddr.sin_port = ns_port; + ns = fdp->ns = (struct databuf *)memget(sizeof(*ns)); + if (!ns) + panic("memget failed in find_forwarder", NULL); + memset(ns,0,sizeof(*ns)); + nsdata = fdp->nsdata = (struct databuf *)memget(sizeof(*nsdata)); + if (!nsdata) + panic("memget failed in find_forwarder", NULL); + memset(nsdata,0,sizeof(*nsdata)); + ns->d_type = T_NS; + ns->d_class = C_IN; + ns->d_rcnt=1; + nsdata->d_type = T_A; + nsdata->d_class = C_IN; + nsdata->d_nstime = 1 + (int)(25.0*rand()/(RAND_MAX + 1.0)); + nsdata->d_rcnt=1; + fdp->ref_count=1; + + 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; + 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; + + for (ftp = fwdtab; ftp != NULL; ftp = fnext) { + fnext = ftp->next; + if (!--ftp->fwddata->ref_count) { + memput(ftp->fwddata->ns, sizeof *ftp->fwddata->ns); + memput(ftp->fwddata->nsdata, + sizeof *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; + return (si); +} + +static void +free_server(server_info si) { + /* Don't free key; it'll be done when the auth table is freed. */ + 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: + 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; + char *name; + FILE *stream; + + syslog_channel = log_new_syslog_channel(0, log_info, LOG_DAEMON); + 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++) + 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) + freestr(current_pid_filename); + free_nameserver_info(); + free_secretkey_info(); + free_symbol_table(zone_symbol_table); + parser_shutdown(); + config_initialized = 0; +} + +void +load_configuration(const char *filename) { + 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; + + 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(); +} Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_ctl.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_ctl.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_ctl.c (revision 60942) @@ -0,0 +1,937 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_ctl.c,v 8.34 2000/04/21 06:54:05 vixie 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, ...); +static void verb_connect(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, void *, void *); +static void verb_getpid(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, 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, 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, void *, void *); +static void verb_exec(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, void *, void *); +static void verb_reload(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, void *, void *); +static void verb_reconfig(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, void *, void *); +static void verb_dumpdb(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, void *, void *); +static void verb_stats(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, void *, void *); +static void verb_trace(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, 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, void *, void *); +static void verb_querylog(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, void *, void *); +static void verb_help(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, void *, void *); +static void verb_quit(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, + const char *, u_int, 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"}, + { "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"}, + { 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(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); + 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 { + freestr(path); + path = savestr("/", 1); + } + } else { + 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 + 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: 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, void *respctx, void *uctx) +{ + const struct sockaddr *sa = (struct sockaddr *)respctx; + control nsctl = (control)uctx; + + if (sa->sa_family == AF_INET) { + const struct sockaddr_in *in = (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, void *respctx, void *uctx) +{ + char *msg = memget(MAX_STR_LEN); + + 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; + + memput(msg, MAX_STR_LEN); +} + +enum state { + e_version = 0, + e_nzones, + e_debug, + e_xfersrun, + e_xfersdfr, + e_qserials, + e_qrylog, + e_priming, + e_loading, + 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, void *respctx, void *uctx) +{ + struct pvt_status *pvt = ctl_getcsctx(sess); + + 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 = e_version; + (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_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: + sprintf(pvt->text, "server is %s priming", + priming ? "STILL" : "DONE"); + break; + case e_loading: + sprintf(pvt->text, "server %s loading its configuration", + loading ? "IS" : "IS NOT"); + 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); + + 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, void *respctx, void *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, void *respctx, void *uctx) +{ + struct stat sb; + + 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 { + ns_need(main_need_restart); + ctl_response(sess, 250, "Restart initiated.", 0, NULL, + NULL, NULL, NULL, 0); + } +} + +static void +verb_reload(struct ctl_sctx *ctl, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *rest, + u_int respflags, void *respctx, void *uctx) +{ + static const char spaces[] = " \t"; + struct zoneinfo *zp; + char *tmp = NULL, *x; + const char *msg; + int class, code, success; + + /* 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); + } + if (x == NULL || *x == '\0') + x = "in"; + class = sym_ston(__p_class_syms, x, &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) + 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, void *respctx, void *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, void *respctx, void *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, void *respctx, void *uctx) +{ + 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, void *respctx, void *uctx) +{ + int i = atoi(rest); + char *msg = memget(MAX_STR_LEN); + + if (msg == NULL) { + ctl_response(sess, 503, "(out of memory)", 0, + NULL, NULL, NULL, NULL, 0); + return; + } + if (i > 0) + desired_debug = i; + else + desired_debug++; + ns_need(main_need_debug); + 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; + + 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, void *respctx, void *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, void *respctx, void *uctx) +{ + static const char on[] = "Query logging is now on.", + off[] = "Query logging is now off."; + + 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, void *respctx, void *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, void *respctx, void *uctx) +{ + ctl_response(sess, 221, "End of control session.", CTL_EXIT, NULL, + NULL, NULL, NULL, 0); +} Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_defs.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_defs.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_defs.h (revision 60942) @@ -0,0 +1,901 @@ +/* + * from ns.h 4.33 (Berkeley) 8/23/90 + * $Id: ns_defs.h,v 8.96 2000/04/21 06:54:06 vixie 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 /* must be a power of two. */ +#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 secondary */ + /* 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 */ + + /* 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_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_num, /* number of needs, used for array bound. */ + main_need_tick /* tick every second to poll for cleanup (NT)*/ +} main_need; + + /* What global options are set? */ +#define OPTION_NORECURSE 0x0001 /* Don't recurse even if asked. */ +#define OPTION_NOFETCHGLUE 0x0002 /* Don't fetch missing glue. */ +#define OPTION_FORWARD_ONLY 0x0004 /* Don't use NS RR's, just forward. */ +#define OPTION_FAKE_IQUERY 0x0008 /* Fake up bogus response to IQUERY. */ +#ifdef BIND_NOTIFY +#define OPTION_NONOTIFY 0x0010 /* Turn off notify */ +#endif +#define OPTION_NONAUTH_NXDOMAIN 0x0020 /* Generate non-auth NXDOMAINs? */ +#define OPTION_MULTIPLE_CNAMES 0x0040 /* Allow a name to have multiple + * CNAME RRs */ +#define OPTION_HOSTSTATS 0x0080 /* Maintain per-host statistics? */ +#define OPTION_DEALLOC_ON_EXIT 0x0100 /* Deallocate everything on exit? */ +#define OPTION_NODIALUP 0x0200 /* Turn off dialup support */ +#define OPTION_NORFC2308_TYPE1 0x0400 /* Prevent type1 respones (RFC 2308) + * to cached negative respones */ +#define OPTION_USE_ID_POOL 0x0800 /* Use the memory hogging query ID */ +#define OPTION_TREAT_CR_AS_SPACE 0x1000 /* Treat CR in zone files as space */ +#define OPTION_USE_IXFR 0x2000 /* Use by delault ixfr in zone transfer */ +#define OPTION_MAINTAIN_IXFR_BASE 0x4000 /* Part of IXFR file name logic. */ + +#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 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 znotify { znotify_use_default=0, znotify_yes, znotify_no }; +#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 */ + 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 znotify 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 */ + + /* 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_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 nretry:31; /* # 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 */ + 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 + 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 znotify() + * 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_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 */ + 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 */ +#endif + u_int8_t xfers; /* #/xfers running right now */ +}; + +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_int flags; + 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 lame_ttl; + int minroots; +} *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 + +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 */ + 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 { + 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 Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_forw.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_forw.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_forw.c (revision 60942) @@ -0,0 +1,1272 @@ +#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.75 2000/05/09 07:12:58 vixie 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; + u_char *oldqbuf; + u_char *smsg; + int smsglen, smsgsize, 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 = tsig_key_from_addr(nsa->sin_addr); + if (key != NULL) { + smsgsize = qp->q_msglen + TSIG_BUF_SIZE; + 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); + 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; + hp = (HEADER *) qp->q_msg; + has_tsig = 1; + 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 (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 (has_tsig == 1) { + memput(qp->q_msg, 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)) { + 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 (NS_OPTION_P(OPTION_HOSTSTATS)) { + char nsbuf[20], abuf[20]; + + if (nsdp != NULL) { + if (nsdp->d_ns != NULL) { + strcpy(nsbuf, + inet_ntoa(nsdp->d_ns->addr)); + ns = nsbuf; + } else { + ns = zones[nsdp->d_zone].z_origin; + } + } + if (a_rr->d_ns != NULL) { + strcpy(abuf, inet_ntoa(a_rr->d_ns->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; + + ns_debug(ns_log_default, 3, "nslookup(nsp=%#x, qp=%#x, \"%s\")", + nsp, qp, syslogdname); + + 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; + } + } + + 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 %#x", + dname, fname, np); + found_arr = 0; + goto need_sysquery; + } + if (fname != dname) { + found_arr = 0; + goto need_sysquery; + } + found_arr = 0; + 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_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; + qs->ns = nsdp; + qs->nsdata = dp; + qs->forwarder = 0; + 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 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 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) { + potential_ns++; + if (!(qp->q_flags & Q_SYSTEM)) + (void) sysquery(dname, class, T_A, NULL, 0, + ns_port, QUERY); + } + skipserver: + (void)NULL; + } + out: + 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 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 || qs2->nsdata == NULL) { + rtt1 = 0; + rttr1 = 0; + rtt2 = 0; + rttr2 = 0; + } else { + rtt1 = qs1->nsdata->d_nstime; + rttr1 = RTTROUND(rtt1); + 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) %lu (%lu) - %lu (%lu) = %lu", + 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(%#x, %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) { + retry_timer_set = 0; + retry(retryqp); +} + +/* + * Retry is called to retransmit query 'qp'. + */ +void +retry(struct qinfo *qp) { + int n, has_tsig, oldqlen; + HEADER *hp; + struct sockaddr_in *nsa; + int sendto_errno = 0; + u_char *oldqbuf; + u_char *smsg; + int smsglen, smsgsize, 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 (qp->q_naddr > 0) { + ++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 = ((HEADER *)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 = 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; + 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 (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 (has_tsig == 1) { + memput(qp->q_msg, 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, char *where) { + static const char freed[] = "freed", busy[] = "busy"; + const char *result; + struct databuf *dp; + int i; + + for (i = 0 ; i < (int)qp->q_naddr ; i++) { + dp = qp->q_addr[i].ns; + if (dp) { + DRCNTDEC(dp); + result = (dp->d_rcnt) ? busy : freed; + ns_debug(ns_log_default, 3, "%s: ns %s rcnt %d (%s)", + where, dp->d_data, dp->d_rcnt, result); + if (result == freed) + db_freedata(dp); + } + dp = qp->q_addr[i].nsdata; + if (dp) { + DRCNTDEC(dp); + result = (dp->d_rcnt) ? busy : freed; + ns_debug(ns_log_default, 3, + "%s: nsdata %s rcnt %d (%s)", + where, inet_ntoa(ina_get(dp->d_data)), + dp->d_rcnt, result); + if (result == freed) + db_freedata(dp); + } + } +} + +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) + freestr(qp->q_domain); + if (qp->q_name != NULL) + 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, "ns_freeqry"); + 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 < (u_int)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->nretry = 0; + n++; + nextfwd: + fwd = fwd->next; + } + qp->q_naddr = n; + + /* Update the refcounts before the sort. */ + for (i = 0; i < (u_int)n; i++) { + DRCNTINC(qp->q_addr[i].nsdata); + DRCNTINC(qp->q_addr[i].ns); + } + if (n > 1) { + qsort((char *)qp->q_addr, n, sizeof(struct qserv), + (int (*)(const void *, const void *))qcomp); + } +} Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_func.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_func.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_func.h (revision 60942) @@ -0,0 +1,503 @@ +/* + * 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.96 2000/04/21 06:54:06 vixie Exp $ + */ + +/* ++from ns_glue.c++ */ +extern struct in_addr ina_get(const u_char *data); +extern const char *sin_ntoa(struct sockaddr_in); +extern int ns_wouldlog(int category, int level); +extern void ns_debug(int, int, const char *, ...), + ns_info(int, const char *, ...), + ns_notice(int, const char *, ...), + ns_warning(int, const char *, ...), + ns_error(int, const char *, ...), + ns_panic(int, int, const char *, ...), + ns_assertion_failed(char *file, int line, + assertion_type type, char *cond, + int print_errno); +extern void panic(const char *, const void *), + gettime(struct timeval *); +extern int nlabels(const char *), + my_close(int), + my_fclose(FILE *); +extern void __freestr(char *); +extern char *__newstr(size_t, int), + *__savestr(const char *, int), + *checked_ctime(const time_t *t), + *ctimel(long); +extern void __freestr_record(char *, char *, int); +extern char *__newstr_record(size_t, int, char *, int); +extern char *__savestr_record(const char *, int, char *, int); +extern u_char *ina_put(struct in_addr ina, u_char *data), + *savebuf(const u_char *, size_t, int); +extern void dprintf(int level, const char *format, ...); +#ifdef DEBUG_STRINGS +extern char *debug_newstr(size_t, int, const char *, int), + *debug_savestr(const char *, int, const char *, int); +extern 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 */ +int movefile(const char *, const char *); +/* --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++ */ +extern void ns_resp(u_char *, int, struct sockaddr_in, + struct qstream *), + prime_cache(void), + delete_all(struct namebuf *, int, int); +extern int delete_stale(struct namebuf *); +extern struct qinfo *sysquery(const char *, int, int, + struct in_addr *, int, u_int16_t, int); +extern int doupdate(u_char *, u_char *, struct databuf **, + int, int, int, u_int, struct sockaddr_in), + send_msg(u_char *, int, struct qinfo *), + findns(struct namebuf **, int, + struct databuf **, int *, int), + finddata(struct namebuf *, int, int, HEADER *, + char **, int *, int *), + add_data(struct namebuf *, + struct databuf **, + u_char *, int, int *), + trunc_adjust(u_char *, int, int); +/* --from ns_resp.c-- */ + +/* ++from ns_req.c++ */ +extern void ns_req(u_char *, int, int, + struct qstream *, + struct sockaddr_in, + int), + free_addinfo(void), + free_nsp(struct databuf **); +extern int stale(struct databuf *), + make_rr(const char *, struct databuf *, + u_char *, int, int, + u_char **, u_char **, int), + doaddinfo(HEADER *, u_char *, int), + doaddauth(HEADER *, u_char *, int, + struct namebuf *, + struct databuf *); +#ifdef BIND_NOTIFY +extern int findZonePri(const struct zoneinfo *, + const struct sockaddr_in); +#endif +/* --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), + ns_stopxfrs(struct zoneinfo *), + ns_freexfr(struct qstream *), + sx_newmsg(struct qstream *qsp), + sx_sendlev(struct qstream *qsp), + 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 WINNT +control ns_ctl_new_unix(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 *qsp); +/* --from ns_ixfr.c-- */ + +/* ++from ns_forw.c++ */ +extern time_t retrytime(struct qinfo *); +extern 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), + haveComplained(u_long, u_long), + nslookup(struct databuf *nsp[], + struct qinfo *qp, + const char *syslogdname, + const char *sysloginfo), + qcomp(struct qserv *, struct qserv *); +extern void schedretry(struct qinfo *, time_t), + unsched(struct qinfo *), + reset_retrytimer(void), + retrytimer(evContext ctx, void *uap, + struct timespec due, struct timespec ival), + retry(struct qinfo *), + qflush(void), + qremove(struct qinfo *), + ns_freeqns(struct qinfo *, char *), + ns_freeqry(struct qinfo *), + freeComplaints(void), + nsfwdadd(struct qinfo *, struct fwdinfo *); +extern struct qinfo *qfindid(u_int16_t), + *qnew(const char *, int, int, int); +/* --from ns_forw.c-- */ + +/* ++from ns_main.c++ */ +extern struct in_addr net_mask(struct in_addr); +extern void sq_remove(struct qstream *), + sq_flushw(struct qstream *), + sq_flush(struct qstream *allbut), + dq_remove_gen(time_t gen), + dq_remove_all(), + sq_done(struct qstream *), + ns_setproctitle(char *, int), + getnetconf(int), + nsid_init(void), + ns_setoption(int option), + writestream(struct qstream *, const u_char *, int), + ns_need_unsafe(enum need), + ns_need(enum need), + opensocket_f(void), + nsid_hash(u_char *, size_t); +extern u_int16_t nsid_next(void); +extern int sq_openw(struct qstream *, int), + sq_writeh(struct qstream *, sq_closure), + sq_write(struct qstream *, const u_char *, int), + tcp_send(struct qinfo *), + aIsUs(struct in_addr); +/* --from ns_main.c-- */ + +/* ++from ns_maint.c++ */ +extern void zone_maint(struct zoneinfo *), + sched_zone_maint(struct zoneinfo *), + ns_cleancache(evContext ctx, void *uap, + struct timespec due, + struct timespec inter), + clean_cache_from(char *dname, struct hashbuf *htp), + remove_zone(struct zoneinfo *, const char *), + purge_zone(const char *, struct hashbuf *, int), + loadxfer(void), + qserial_retrytime(struct zoneinfo *, time_t), + qserial_query(struct zoneinfo *), + qserial_answer(struct qinfo *), +#ifdef DEBUG + printzoneinfo(int, int, int), +#endif + endxfer(void), + addxfer(struct zoneinfo *), + ns_zreload(void), + ns_reload(void), + ns_reconfig(void), + ns_noexpired(void); +#if 0 +extern int reload_all_unsafe(void); +#endif +extern int zonefile_changed_p(struct zoneinfo *); +int reload_master(struct zoneinfo *); +extern const char * deferred_reload_unsafe(struct zoneinfo *); +extern struct namebuf * purge_node(struct hashbuf *htp, struct namebuf *np); +extern int clean_cache(struct hashbuf *, int); +extern void reapchild(void); +extern const char * zoneTypeString(unsigned int); +extern void ns_heartbeat(evContext ctx, void *uap, + struct timespec, struct timespec); +extern void make_new_zones(void); +extern void free_zone(struct zoneinfo *); +extern struct zoneinfo *find_auth_zone(const char *, ns_class); +extern int purge_nonglue(const char *dname, struct hashbuf *htp, + int class); +/* --from ns_maint.c-- */ + +/* ++from ns_sort.c++ */ +extern void sort_response(u_char *, u_char *, int, + struct sockaddr_in *); +/* --from ns_sort.c-- */ + +/* ++from ns_init.c++ */ +extern void ns_refreshtime(struct zoneinfo *, time_t); +extern void ns_retrytime(struct zoneinfo *, time_t); +extern void ns_init(const char *); +extern void purgeandload(struct zoneinfo *zp); +extern enum context ns_ptrcontext(const char *owner); +extern enum context ns_ownercontext(int type, enum transport); +extern 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); +extern int ns_wildcard(const char *name); +extern void zoneinit(struct zoneinfo *); +extern void do_reload(const char *, int, int, int); +extern void ns_shutdown(void); +/* --from ns_init.c-- */ + +/* ++from ns_ncache.c++ */ +extern void cache_n_resp(u_char *, int, struct sockaddr_in, + const char *, int, int); +/* --from ns_ncache.c-- */ + +/* ++from ns_udp.c++ */ +extern void ns_udp(void); +/* --from ns_udp.c-- */ + +/* ++from ns_stats.c++ */ +extern void ns_stats(void), + ns_freestats(void); +extern void ns_logstats(evContext ctx, void *uap, + struct timespec, struct timespec); +extern void qtypeIncr(int qtype); +extern 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++ */ +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 qstream *qsp, + int dfd, 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 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, int 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); +#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, char *, + 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); +void load_configuration(const char *); +/* --from ns_config.c-- */ +/* ++from parser.y++ */ +ip_match_list lookup_acl(char *); +void define_acl(char *, ip_match_list); +struct dst_key *lookup_key(char *); +void define_key(char *, struct dst_key *); +void 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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_glob.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_glob.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_glob.h (revision 60942) @@ -0,0 +1,342 @@ +/* + * from ns.h 4.33 (Berkeley) 8/23/90 + * $Id: ns_glob.h,v 8.54 2000/04/21 06:54:07 vixie 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; + + /* default configuration file */ +DECL char *conffile; + + /* 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 int main_needs_exit INIT(0); +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 int loading INIT(0); + +DECL int xfers_running INIT(0); +DECL int xfers_deferred INIT(0); +DECL int qserials_running INIT(0); Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_glue.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_glue.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_glue.c (revision 60942) @@ -0,0 +1,463 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_glue.c,v 8.16 2000/04/21 06:50:18 vixie 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_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(char *file, int line, assertion_type type, 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); + + if (s < 0 && errno != EBADF) + 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__); +} + +#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; +} +#endif /* DEBUG_STRINGS */ + +/* + * Return a counted string buffer big enough for a string of length 'len'. + */ +char * +__newstr_record(size_t len, int needpanic, 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, 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, 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); +} + +char * +checked_ctime(const time_t *t) { + 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. + */ +char * +ctimel(long l) { + time_t t = (time_t)l; + + return (checked_ctime(&t)); +} + +/* + * rename() is lame (can't overwrite an existing file) on some systems. + * use movefile() instead, and let lame OS ports do what they need to. + */ +#ifndef HAVE_MOVEFILE +int +movefile(const char *oldname, const char *newname) { + return (rename(oldname, newname)); +} +#endif + +#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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_init.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_init.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_init.c (revision 60942) @@ -0,0 +1,579 @@ +#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.68 2000/04/21 06:54:07 vixie 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; + + zp->z_time = timebase + half + (rand() % half); +} + +/* + * Set new retry time for zone. + */ +void +ns_retrytime(struct zoneinfo *zp, time_t timebase) { + zp->z_time = timebase + zp->z_retry; +} + +/* + * Read configuration file and save it as internal state. + */ +void +ns_init(const char *conffile) { + struct zoneinfo *zp; + static int loads = 0; /* number of times loaded */ + + 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 + + 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++; +} + +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); + 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) + if ( (transport == response_trans) && + (qry != NULL) ) { + + if ( qry->q_flags & Q_PRIMING ) { + sprintf(s, "%s from [%s] for priming", + transport_strings[transport], + inet_ntoa(source)); + } else if ( qry->q_flags & Q_ZSERIAL ) { + sprintf(s, "%s from [%s] for soacheck", + transport_strings[transport], + inet_ntoa(source)); + } else if ( qry->q_flags & Q_SYSTEM ) { + 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_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) + freestr(s); + if (o != NULL) + 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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_ixfr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_ixfr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_ixfr.c (revision 60942) @@ -0,0 +1,612 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_ixfr.c,v 8.19 2000/04/18 20:47:27 vixie 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 "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; + struct databuf *dp; + const char * fname; + u_char ** edp = qsp->xfr.ptrs + + sizeof qsp->xfr.ptrs / sizeof(u_char *); + + 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; + foreach_rr(dp, np, T_SOA, qsp->xfr.class, qsp->xfr.zone) { + n = make_rr(zp->z_origin, dp, qsp->xfr.cp, qsp->xfr.eom - qsp->xfr.cp, 0, qsp->xfr.ptrs, edp, 0); + qsp->xfr.cp += n; + hp->ancount = htons(ntohs(hp->ancount) + 1); + } + } +} + +/* + * 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; + u_int32_t serial = 0; + struct zoneinfo *zp = NULL; + struct databuf *soa_dp; + struct databuf *old_soadp; + ns_delta *dp; + ns_updrec *rp; + ns_updrec *trp; + 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(DATASIZE(soa_dp->d_size)); + memcpy(old_soadp, soa_dp, 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); + /* + * The current SOA has been emited already. + * It would be cleaner if the first one was emited here... + * + * 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_freedata(rp->r_dp); + rp->r_dp = NULL; + 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_freedata(rp->r_dp); + rp->r_dp = NULL; + } + 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_freedata(rp->r_dp); + rp->r_dp = NULL; + 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_freedata(rp->r_dp); + rp->r_dp = NULL; + } + 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_freedata(rp->r_dp); + rp->r_dp = NULL; + } + 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; + } + 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); + cleanup: + 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_freedata(rp->r_dp); + rp->r_dp = NULL; + res_freeupdrec(rp); + } + memput(dp, sizeof *dp); + } + } + memput(qsp->xfr.top.ixfr, sizeof *qsp->xfr.top.ixfr); + qsp->xfr.top.ixfr = NULL; + } + memput(old_soadp, 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 + * fast_trim - is used to denote that this is not called on the regular + * maintaince cycle. + * + */ +int ixfr_log_maint(struct zoneinfo *zp, int fast_trim) { + int fd, rcount, wcount; + int found = 0; + int error = 0; + long seek = 0; + FILE *to_fp, *from_fp, *db_fp; + static char *tmpname; + 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 %d blk %d", + zp->z_source, db_sb.st_size, + 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 %d max %d\n", + zp->z_ixfr_base, + sb.st_size, + zp->z_max_log_size_ixfr); + if (zp->z_max_log_size_ixfr) { + if (sb.st_size > zp->z_max_log_size_ixfr) + seek = (signed)sb.st_size - + (signed)(zp->z_max_log_size_ixfr + + (zp->z_max_log_size_ixfr * .10) ); + else + seek = 0; + } else { + if (sb.st_size > (db_sb.st_size * .50)) + seek = (signed)sb.st_size - (signed)((db_sb.st_size * .50) + + ((db_sb.st_size * zp->z_max_log_size_ixfr) *.10)); + else + seek = 0; + } + ns_debug(ns_log_default, 3, "seek: %d", 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); + } + + if ((fast_trim) && seek < (zp->z_max_log_size_ixfr + 100000)) { + (void) my_fclose(from_fp); + return (0); + } + + tmpname = memget(strlen(zp->z_ixfr_base) + sizeof(".XXXXXX") + 1); + 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", + strerror(errno)); + memput(tmpname, (strlen(zp->z_ixfr_base) + sizeof(".XXXXXX") + 1)); + return (-1); + } + if ((to_fp = fdopen(fd, "r+")) == NULL) { + ns_warning(ns_log_db, "%s: %s", + tmpname, strerror(errno)); + (void) unlink(tmpname); + memput(tmpname, (strlen(zp->z_ixfr_base) + sizeof(".XXXXXX") + 1)); + (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) close(fd); + (void) my_fclose(from_fp); + if (error == 0) { + if (rename(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)); + 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); + } + 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) unlink(tmpname); + memput(tmpname, (strlen(zp->z_ixfr_base) + sizeof(".XXXXXX") + 1)); + (void) my_fclose(from_fp); + + zp->z_serial_ixfr_start = 0; /* signal to read for lowest serial number */ + + ns_debug(ns_log_default, 3, "%s, size %d max %d\n", + zp->z_ixfr_base, + sb.st_size, + zp->z_max_log_size_ixfr); + + if (error) + return(-1); + else + return (0); +} + Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_lexer.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_lexer.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_lexer.c (revision 60942) @@ -0,0 +1,809 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_lexer.c,v 8.20 2000/04/21 06:54:07 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 "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 { + const 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) +{ + 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, message); +} + +/* + * Keywords + */ + +struct keyword { + 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}, + {"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}, + {"host-statistics", T_HOSTSTATS}, + {"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}, + {"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}, + {"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 = filename; /* note copy by reference */ + 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); + 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; + } + } +} + +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); +} + +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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_lexer.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_lexer.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_lexer.h (revision 60942) @@ -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 *, ...); +int parser_error(int, const char *, ...); +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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_main.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_main.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_main.c (revision 60942) @@ -0,0 +1,2759 @@ +#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.125 2000/04/21 06:54:08 vixie 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 +# include +#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" + +#ifdef HAVE_GETRUSAGE /* XXX */ +#include +#endif + +#define MAIN_PROGRAM +#include "named.h" +#undef MAIN_PROGRAM + + /* 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; + +typedef void (*handler)(void); +static int needs = 0; +static handler handlers[main_need_num]; + +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 int sq_here(struct qstream *); + +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_need(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 char bad_p_option[] = +"-p remote/local obsolete; use 'listen-on' in config file to specify local"; + +static char bad_directory[] = "chdir failed for directory '%s': %s"; + +/*ARGSUSED*/ +int +main(int argc, char *argv[], char *envp[]) { + 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) + 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': + if (chdir(optarg) < 0) { + syslog(LOG_CRIT, bad_directory, optarg, + strerror(errno)); + fprintf(stderr, bad_directory, optarg, + strerror(errno)); + fputc('\n', stderr); + exit(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) + 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) + 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"); + freestr(chroot_dir); + chroot_dir = NULL; +#endif + } + + /* 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, LOG_DAEMON); +#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", Version); + + /* + * Initialize and load database. + */ + gettime(&tt); + buildservicelist(); + buildprotolist(); + 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 (!main_needs_exit) { + evEvent event; + + ns_debug(ns_log_default, 15, "main loop"); + if (needs != 0) { + /* Drain outstanding events; handlers ~block~. */ + while (evGetNext(ev, &event, EV_POLL) != -1) + INSIST_ERR(evDispatch(ev, event) != -1); + INSIST_ERR(errno == EINTR || errno == EWOULDBLOCK); + handle_need(); + } else if (evGetNext(ev, &event, EV_WAIT) != -1) { + INSIST_ERR(evDispatch(ev, event) != -1); + } else { + INSIST_ERR(errno == EINTR); + } + } + 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(); + + /* Cleanup for system-dependent stuff */ + custom_shutdown(); + + return (0); +} + +#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; + int len, n; + const int on = 1; +#ifdef IP_OPTIONS /* XXX */ + u_char ip_opts[IP_OPT_BUF_SIZE]; +#endif + const struct sockaddr_in *la, *ra; + + la = (const struct sockaddr_in *)lav; + ra = (const struct sockaddr_in *)rav; + + INSIST(ifp != NULL); + + 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) { + struct qstream *nextsp; + struct qstream *candidate = NULL; + time_t lasttime, maxctime = 0; + + for (sp = streamq; sp; sp = nextsp) { + nextsp = sp->s_next; + if (sp->s_refcnt) + continue; + gettime(&tt); + lasttime = tt.tv_sec - sp->s_time; + if (lasttime >= VQEXPIRY) + sq_remove(sp); + else if (lasttime > maxctime) { + candidate = sp; + maxctime = lasttime; + } + } + if (candidate) + sq_remove(candidate); + 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, + (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, + (char *)&on, sizeof on) < 0) { + ns_info(ns_log_default, "setsockopt(rfd, KEEPALIVE): %s", + strerror(errno)); + (void) close(rfd); + return; + } + + 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; + } + + /* + * 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; +#ifdef DEBUG + if (debug) + ns_info(ns_log_default, "IP/TCP connection from %s (fd %d)", + sin_ntoa(sp->s_from), rfd); +#endif +} + +int +tcp_send(struct qinfo *qp) { + struct qstream *sp; + int on = 1; + + ns_debug(ns_log_default, 1, "tcp_send"); + if ((sp = sq_add()) == NULL) { + return (SERVFAIL); + } + if ((sp->s_rfd = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) == -1) { + sq_remove(sp); + return (SERVFAIL); + } + if (sp->s_rfd > evHighestFD(ev)) { + sq_remove(sp); + return (SERVFAIL); + } + if (fcntl(sp->s_rfd, F_SETFD, 1) < 0) { + sq_remove(sp); + return (SERVFAIL); + } + 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(rfd, 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; + + 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; + + 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", + (void *)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; + + 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 %#x rfd %d size %d time %d next %#x", + sp, sp->s_rfd, sp->s_size, 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; + int from_len = sizeof from; + int n, nudp; + union { + HEADER h; /* Force alignment of 'buf'. */ + u_char buf[PACKETSZ+1]; + } u; + + 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 > PACKETSZ) { + /* + * 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, PACKETSZ, PACKETSZ); + ns_debug(ns_log_default, 1, "truncated oversize UDP packet"); + } + + dispatch_message(u.buf, n, PACKETSZ, NULL, from, fd, ifp); + if (++nudp < nudptrans) + goto more; +} + +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)", NULL); + 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(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)", NULL); + memset(ifp, 0, sizeof *ifp); + 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; + int m, n; + int fd; + + memset(&nsa, 0, sizeof nsa); + nsa.sin_family = AF_INET; + nsa.sin_addr = ifp->addr; + nsa.sin_port = ifp->port; + + if ((ifp->dfd = 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); + } + 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); + } +#ifdef F_DUPFD /* XXX */ + /* + * Leave a space for stdio to work in. + */ + if ((fd = fcntl(ifp->dfd, F_DUPFD, 20)) != -1) { + close(ifp->dfd); + ifp->dfd = fd; + } else + ns_notice(ns_log_default, "fcntl(dfd, F_DUPFD, 20): %s", + strerror(errno)); +#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, + (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, + (char *)&drbufsize, sizeof drbufsize); + } +#endif /* SO_RCVBUF */ +#ifndef CANNOT_SET_SNDBUF + if (setsockopt(ifp->dfd, SOL_SOCKET, SO_SNDBUF, + (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 + 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); +} + +/* 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; + int fd; + + 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 = 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); + } +#ifdef F_DUPFD /* XXX */ + /* + * Leave a space for stdio to work in. + */ + if ((fd = fcntl(ifp->sfd, F_DUPFD, 20)) != -1) { + close(ifp->sfd); + ifp->sfd = fd; + } else + ns_notice(ns_log_default, "fcntl(sfd, F_DUPFD, 20): %s", + strerror(errno)); +#endif + 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, + (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; + int n, 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, + (char *)&on, sizeof on) != 0) { + ns_notice(ns_log_default, "setsockopt(REUSEADDR): %s", + strerror(errno)); + /* XXX press on regardless, this is not too serious. */ + } + 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", + (void *)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); + 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; + + 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); +} + +/* int + * sq_here(sp) + * determine whether stream 'sp' is still on the streamq + * return: + * boolean: is it here? + */ +static int +sq_here(struct qstream *sp) { + struct qstream *t; + + for (t = streamq; t != NULL; t = t->s_next) + if (t == sp) + return (1); + 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", + (void *)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) { + 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)", + NULL); + 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)", NULL); + 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 + ns_panic(ns_log_default, 1, "Unknown ID algorithm", NULL); + + /* 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 (nsid_pool != NULL) + memput(nsid_pool, 0x10000 * (sizeof(u_int16_t))); + nsid_pool = NULL; + irs_destroy(); + if (f != NULL) { + memstats(f); + (void)fclose(f); + } +} + +static void +ns_exit(void) { + main_needs_exit++; +} + +static void +ns_restart(void) { + ns_info(ns_log_default, "named restarting"); +#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(); + execvp(saved_argv[0], saved_argv); + abort(); +} + +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", NULL); +} + +/* + * 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_exit] = ns_exit; + 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; +} + +static void +handle_need(void) { + int need; + + ns_debug(ns_log_default, 15, "handle_need()"); + for (need = 0; need < main_need_num; need++) + if ((needs & (1 << need)) != 0) { + /* Turn off flag first, handlers ~turn~ it back on. */ + block_signals(); + needs &= ~(1 << need); + unblock_signals(); + (handlers[need])(); + return; + } + ns_panic(ns_log_default, 1, "handle_need() found no needs", NULL); +} + +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); +} + +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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_maint.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_maint.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_maint.c (revision 60942) @@ -0,0 +1,1935 @@ +#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.103 2000/04/23 02:18:58 vixie 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 "port_after.h" + +#include "named.h" + +static int nxfers(struct zoneinfo *, int), + bottom_of_zone(struct databuf *, int); + +static void startxfer(struct zoneinfo *), + abortxfer(struct zoneinfo *), + tryxfer(void), + purge_z_2(struct hashbuf *, int); +static int purge_nonglue_2(const char *, struct hashbuf *, + int, int); + +#ifndef HAVE_SPAWNXFER +static pid_t spawnxfer(char **, struct zoneinfo *); +#endif + +static time_t stats_time; /* Redundant ??? XXX ogud */ + + /* State of all running zone transfers */ +static struct { + pid_t xfer_pid; + int xfer_state; /* see below */ + WAIT_T xfer_status; +} 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; + } + + /* + * It is essential that we never try to set a timer in the past + * or for now because doing so could cause an infinite loop. + */ + INSIST(zp->z_time == 0 || 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; + + 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; + + 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; + + 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 == znotify_yes) || + ((zp->z_notify == znotify_use_default) && + !NS_OPTION_P(OPTION_NONOTIFY))) && + (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_addrcnt, + ntohs(zp->z_port) ? zp->z_port : ns_port, + QUERY); + 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), + 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), + qs->serial, + inet_ntoa(qs->ns_addr.sin_addr), + 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), + 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. + */ +static int +write_tsig_info(struct in_addr addr, char *name, int *fd, int creat_failed) { + server_info si; + DST_KEY *dst_key; + int tsig_fd = *fd; + char tsig_str[1024], secret_buf64[172]; + u_char secret_buf[128]; + int secret_len; + + 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 < 0 && creat_failed == 0) { + *fd = tsig_fd = creat(name, S_IRUSR); + if (tsig_fd < 0) { + ns_warning(ns_log_default, + "write_tsig_info: creat(%s) for TSIG info failed", + name); + return(-1); + } + (void) fchown(tsig_fd, user_id, group_id); + } + if (creat_failed != 0) + return(-1); + memset(secret_buf, 0, sizeof(secret_buf)); + secret_len = dst_key_to_buffer(dst_key, secret_buf, sizeof(secret_buf)); + b64_ntop(secret_buf, secret_len, secret_buf64, sizeof(secret_buf64)); + 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); + write(tsig_fd, tsig_str, strlen(tsig_str)); + return (0); +} + +/* + * 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], 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]; + int tsig_fd = -1; + char tsig_name[MAXPATHLEN+1], *s; + 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; + argv[argc++] = "-z"; + argv[argc++] = zp->z_origin; + argv[argc++] = "-f"; + argv[argc++] = zp->z_source; +#ifdef BIND_IXFR + if (zp->z_ixfr_tmp) { + argv[argc++] = "-i"; + argv[argc++] = zp->z_ixfr_tmp; + } +#endif + if (zp->z_serial != 0) { + argv[argc++] = "-s"; + 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) { + argv[argc++] = "-x"; + argv[argc++] = strcpy(src_str, inet_ntoa( + (zp->z_axfr_src.s_addr != 0) ? zp->z_axfr_src : + server_options->axfr_src)); + } + argv[argc++] = "-C"; + sprintf(class_str, "%d", zp->z_class); + argv[argc++] = class_str; + if (zp->z_flags & Z_SYSLOGGED) + argv[argc++] = "-q"; + argv[argc++] = "-P"; + sprintf(port_str, "%d", ntohs(zp->z_port) != 0 ? zp->z_port : ns_port); + argv[argc++] = port_str; + argv[argc++] = "-T"; + sprintf(tsig_name, "%s.%d", zp->z_origin, getpid()); + s = tsig_name; + while ((s = strchr(s, '/')) != NULL) + *s = '_'; + argv[argc++] = tsig_name; +#ifdef STUBS + if (zp->z_type == Z_STUB) + argv[argc++] = "-S"; +#endif +#ifdef DEBUG + if (debug) { + argv[argc++] = "-d"; + sprintf(debug_str, "%d", debug); + argv[argc++] = debug_str; + argv[argc++] = "-l"; + argv[argc++] = _PATH_XFERDDT; + if (debug > 5) { + argv[argc++] = "-t"; + argv[argc++] = _PATH_XFERTRACE; + } + } +#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]; + } + /* + * 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) + argv[argc++] = "ixfr"; + else + argv[argc++] = "axfr"; + } +#endif + tsig_ret = write_tsig_info(a, tsig_name, &tsig_fd, tsig_ret); + } + if (tsig_fd > 0) + close(tsig_fd); + + 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, 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; + (void)nxfers(zp, -1); + return; + } + + if ((pid = spawnxfer(argv, zp)) == -1) + unlink(tsig_name); + + xferstatus[i].xfer_state = XFER_RUNNING; + xferstatus[i].xfer_pid = pid; /* XXX - small race condition here if we + * can't hold signals */ + 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++; + 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", + zp->z_dumpintvl, zp->z_soaincrintvl, + 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); + ns_stopxfrs(zp); + 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); + free_zone(zp); +} + +int +purge_nonglue(const char *dname, struct hashbuf *htp, int class) { + 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); + 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); + + /* NOKEY is in parent zone otherwise child zone */ + if (dp->d_type == T_KEY && dp->d_size == 4 && + (dp->d_data[0] & 0xc6) == 0xc2) + 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) +{ + 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)) { + ns_error(ns_log_db, + "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); + 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); + + /* 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, int delta) { + struct in_addr nsa; + struct nameser *nsp; + int ret; + + 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); + + if (!(nsp = nameserFind(nsa, NS_F_INSERT))) + return (-1); /* probably ENOMEM */ + + ret = nsp->xfers; + if (delta < 0 && -delta > ret) + return (-1); /* taking more than we have */ + + nsp->xfers += delta; + 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--; + (void)nxfers(zp, -1); + 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--; + (void) nxfers(zp, -1); + 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; + } + 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_flags |= Z_XFER_RUNNING; + 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); + 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); + } else + ns_notice(ns_log_default, + "IXFR Merge failed %s", + zp->z_ixfr_tmp); + zp->z_flags &= + ~(Z_XFER_RUNNING|Z_XFER_ABORTED|Z_XFER_GONE); + break; + + case XFER_TIMEOUT: + if (!(zp->z_flags & Z_SYSLOGGED)) { + zp->z_flags |= Z_SYSLOGGED; + ns_notice(ns_log_default, + "zoneref: Masters for secondary zone \"%s\" unreachable", + 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) + */ +static 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, 0)) != -1 && + xfers < server_options->transfers_per_ns && + (zp->z_flags & Z_NEED_XFER)) { + nxfers(zp, 1); + xfers_deferred--; + 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 secondary and backing up. */ + 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; + + 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); + 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)); + (void)nxfers(zp, -1); + _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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_ncache.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_ncache.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_ncache.c (revision 60942) @@ -0,0 +1,270 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_ncache.c,v 8.27 2000/04/21 06:54:09 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 "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]; + size_t len = 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; + u_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, len); + if (n < 0) { + ns_debug(ns_log_ncache, 3, + "ncache: origin form error"); + return; + } + cp += n; + n = strlen((char*)data) + 1; + cp1 = data + n; + len -= n; + /* mail */ + n = dn_expand(msg, msg + msglen, cp, (char*)cp1, len); + if (n < 0) { + ns_debug(ns_log_ncache, 3, "ncache: mail form error"); + return; + } + cp += n; + n = strlen((char*)cp1) + 1; + cp1 += n; + len -= n; + n = 5 * INT32SZ; + BOUNDS_CHECK(cp, n); + memcpy(cp1, cp, n); + /* serial, refresh, retry, expire, min */ + cp1 += n; + len -= 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, len); + 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; + } + + if ((n = db_update(dname, dp, dp, NULL, flags, hashtab, from)) != OK) { + ns_debug(ns_log_ncache, 1, + "db_update failed (%d), cache_n_resp()", n); + db_freedata(dp); + return; + } + 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)); +} Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_notify.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_notify.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_notify.c (revision 60942) @@ -0,0 +1,424 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_notify.c,v 8.10 2000/04/21 06:54:09 vixie 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 notify { + char * name; + ns_class class; + ns_type type; + evTimerID timer; + LINK(struct notify) 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 notify *); +static void notify_timer(evContext, void *, + struct timespec, struct timespec); + +/* Local. */ + +static LIST(struct notify) pending_notifies; +static LIST(struct notify) 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 notify *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; + 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/5, 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)); + 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 notify *ni; + + INSIST(loading == 0); + while ((ni = HEAD(loading_notifies)) != NULL) { + UNLINK(loading_notifies, ni, link); + ns_notify(ni->name, ni->class, ni->type); + 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 notify *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 notify *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, *fname; + 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 == znotify_no || + (zp->z_notify == znotify_use_default && + NS_OPTION_P(OPTION_NONOTIFY))) + 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; + 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, 1, ns_port, + NS_NOTIFY_OP); + 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, + 1, ns_port, ns_o_notify); + 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; + + htp = hashtab; + anp = nlookup(aname, &htp, &fname, 0); + nsc = 0; + is_us = 0; + if (anp != NULL) + for (adp = anp->n_data; adp; adp = adp->d_next) { + struct in_addr ina; + + if (!match(adp, class, T_A)) + 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 && !NS_OPTION_P(OPTION_NOFETCHGLUE)) { + struct qinfo *qp; + + qp = sysquery(aname, class, ns_t_a, 0, 0, ns_port, + ns_o_query); + if (qp != NULL) + qp->q_notifyzone = zn; + } + return; + } + sysquery(dname, class, type, nss, nsc, ns_port, ns_o_notify); + (*nns)++; + *na += nsc; +} + +static void +free_notify(struct notify *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); + } + freestr(ni->name); + memput(ni, sizeof *ni); +} + +static void +notify_timer(evContext ctx, void *uap, + struct timespec due, + struct timespec inter) +{ + struct notify *ni = uap; + + 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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_parser.y =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_parser.y (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_parser.y (revision 60942) @@ -0,0 +1,1970 @@ +%{ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: ns_parser.y,v 8.55 2000/04/23 02:18:59 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. + */ + +/* 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 "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 zone_config current_zone; +static int should_install; + +static options current_options; +static int seen_options; + +static controls current_controls; + +static topology_config current_topology; +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(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_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 +%token T_HOSTSTATS 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_AUTH_NXDOMAIN T_MULTIPLE_CNAMES T_USE_IXFR T_MAINTAIN_IXFR_BASE +%token T_CLEAN_INTERVAL T_INTERFACE_INTERVAL T_STATS_INTERVAL 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 + +/* 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); } + ; + +/* + * 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_VERSION L_QSTRING + { + if (current_options->version != NULL) + freestr(current_options->version); + current_options->version = $2; + } + | T_DIRECTORY L_QSTRING + { + if (current_options->directory != NULL) + freestr(current_options->directory); + current_options->directory = $2; + } + | T_NAMED_XFER L_QSTRING + { + if (current_options->named_xfer != NULL) + freestr(current_options->named_xfer); + current_options->named_xfer = $2; + } + | T_PIDFILE L_QSTRING + { + if (current_options->pid_filename != NULL) + freestr(current_options->pid_filename); + current_options->pid_filename = $2; + } + | T_STATS_FILE L_QSTRING + { + if (current_options->stats_filename != NULL) + freestr(current_options->stats_filename); + current_options->stats_filename = $2; + } + | T_MEMSTATS_FILE L_QSTRING + { + if (current_options->memstats_filename != NULL) + freestr(current_options->memstats_filename); + current_options->memstats_filename = $2; + } + | T_DUMP_FILE L_QSTRING + { + if (current_options->dump_filename != NULL) + freestr(current_options->dump_filename); + current_options->dump_filename = $2; + } + | 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_NOTIFY yea_or_nay + { + set_global_boolean_option(current_options, + OPTION_NONOTIFY, !$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, savestr(port_string, 1), + SYM_PORT, value, SYMBOL_FREE_KEY); + } + + } + | 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_MAX_LOG_SIZE_IXFR L_NUMBER + { + 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_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 + } + | 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; + } + 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); + } + } + freestr($2); + } + +ordering_name: /* nothing */ + { + $$ = savestr("*", 1); + } + | T_NAME L_QSTRING + { + if (strcmp(".",$2) == 0 || strcmp("*.",$2) == 0) { + $$ = savestr("*", 1); + 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)); + } + + 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; + } + 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); + freestr($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); + freestr(chan_name); + chan_name = NULL; + 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); + } + } + ; + +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); + } + 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; + } + 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; + symbol_value value; + + 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); + } + 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; + } + 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, savestr(ip_printable, 1), + SYM_SERVER, value, + SYMBOL_FREE_KEY); + 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 '}' + | 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); + } + ; + +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(savestr(name, 1), $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); + 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; + freestr(key_name); + } + 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 + ; + +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); + freestr(key_name); + } else { + if (current_algorithm == NULL || + current_secret == NULL) { + parser_error(0, "skipping bad key '%s'", + key_name); + freestr(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); + } + } + } + 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); + freestr($2); + } else + define_acl($2, $4); + } + ; + +/* + * Zones + */ + +zone_stmt: T_ZONE L_QSTRING optional_class + { + int sym_type; + symbol_value value; + char *zone_name; + + if (!seen_options) + parser_error(0, + "no options statement before first zone; using previous/default"); + 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, savestr(zone_name, 1), + sym_type, value, + SYMBOL_FREE_KEY); + } + } + 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; + } + 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 L_NUMBER + { + set_zone_max_log_size_ixfr(current_zone, $2); + } + | T_NOTIFY yea_or_nay + { + set_zone_notify(current_zone, $2); + } + | 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); + } + ; + +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", + $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(savestr("any", 1), 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(savestr("none", 1), iml); + + /* ACL "localhost" */ + ime = new_ip_match_localhost(); + iml = new_ip_match_list(); + add_to_ip_match_list(iml, ime); + define_acl(savestr("localhost", 1), iml); + + /* ACL "localnets" */ + ime = new_ip_match_localnets(); + iml = new_ip_match_list(); + add_to_ip_match_list(iml, ime); + define_acl(savestr("localnets", 1), 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; + 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(symtab, name, SYM_CHANNEL, &value)) + return ((log_channel)(value.pointer)); + return (NULL); +} + +static void +define_channel(char *name, log_channel channel) { + symbol_value value; + + value.pointer = channel; + define_symbol(symtab, name, SYM_CHANNEL, value, SYMBOL_FREE_KEY); +} + +static void +define_builtin_channels() { + define_channel(savestr("default_syslog", 1), syslog_channel); + define_channel(savestr("default_debug", 1), debug_channel); + define_channel(savestr("default_stderr", 1), stderr_channel); + define_channel(savestr("null", 1), null_channel); +} + +static void +parser_setup() { + seen_options = 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); + 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(char *name) { + symbol_value value; + + if (lookup_symbol(authtab, name, SYM_ACL, &value)) + return ((ip_match_list)(value.pointer)); + return (NULL); +} + +void +define_acl(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_KEY|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(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); +} + +void +parse_configuration(const char *filename) { + FILE *config_stream; + + config_stream = fopen(filename, "r"); + if (config_stream == NULL) + ns_panic(ns_log_parser, 0, "can't open '%s'", filename); + + lexer_setup(); + parser_setup(); + lexer_begin_file(filename, config_stream); + (void)yyparse(); + lexer_end_file(); + parser_cleanup(); +} + +void +parser_initialize(void) { + lexer_initialize(); +} + +void +parser_shutdown(void) { + if (authtab != NULL) + free_symbol_table(authtab); + lexer_shutdown(); +} Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_parseutil.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_parseutil.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_parseutil.c (revision 60942) @@ -0,0 +1,244 @@ +/* + * 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) { + if (ste->flags & SYMBOL_FREE_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, 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 = key; + 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 = key; + 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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_parseutil.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_parseutil.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_parseutil.h (revision 60942) @@ -0,0 +1,65 @@ +/* + * 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_KEY 0x01 +#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, 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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_req.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_req.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_req.c (revision 60942) @@ -0,0 +1,2146 @@ +#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.113 2000/04/21 06:54:11 vixie 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); + +static enum req_action req_iquery(HEADER *hp, u_char **cpp, u_char *eom, + int *buflenp, u_char *msg, + 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 + +/* + * 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; + int n, ra, has_tsig, msglen_orig, tsig_size, siglen, sig2len; + u_char *tsigstart; + u_char sig[TSIG_SIG_SIZE], sig2[TSIG_SIG_SIZE]; + struct tsig_record *in_tsig = NULL; + int error = NOERROR; + DST_KEY *key; + time_t tsig_time; + +#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 + msglen_orig = msglen; + siglen = sizeof(sig); + + tsigstart = ns_find_tsig(msg, msg + msglen); + if (tsigstart == NULL) + has_tsig = 0; + else { + char buf[MAXDNAME]; + + has_tsig = 1; + n = dn_expand(msg, msg + msglen, tsigstart, buf, sizeof(buf)); + if (n < 0) { + ns_debug(ns_log_default, 1, + "ns_req: bad TSIG key name", + buf); + key = NULL; + } + key = find_key(buf, NULL); + if (key == NULL) { + error = ns_r_badkey; + ns_debug(ns_log_default, 1, + "ns_req: TSIG verify failed - unknown key %s", + buf); + } + } + 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; + } 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; + 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); + + /* + * 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. + */ + hp->aa = hp->ra = 0; + ra = (NS_OPTION_P(OPTION_NORECURSE) == 0); + + if (error == NOERROR) + hp->rcode = ns_r_noerror; + cp = msg + HFIXEDSZ; + eom = msg + msglen; + buflen -= HFIXEDSZ; + + free_addinfo(); /* sets addcount to zero */ + dnptrs[0] = NULL; + + if (error == NOERROR) { + switch (hp->opcode) { + case ns_o_query: + action = req_query(hp, &cp, eom, qsp, + &buflen, &msglen, + msg, dfd, &ra, from, in_tsig); + break; + + case ns_o_iquery: + action = req_iquery(hp, &cp, eom, &buflen, msg, 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, qsp, dfd, 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; + } + } + + if (in_tsig != NULL) { + memput(in_tsig, sizeof(struct tsig_record)); + in_tsig = NULL; + } + + /* + * Vector via internal opcode. + */ + switch (action) { + case Return: + return; + case Refuse: + 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 && buflen < tsig_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) { + hp->qdcount = htons(0); + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); + } + + /* + * If the query had a TSIG and the message is truncated or there was + * a TSIG error, build a new message with no data and a TSIG. + */ + if ((hp->tc || error != NOERROR) && has_tsig > 0) { + 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)); + sig2len = sizeof(sig2); + buflen += (msglen - (cp - msg)); + msglen = cp - msg; + n = ns_sign(msg, &msglen, msglen + buflen, error, key, + sig, siglen, sig2, &sig2len, tsig_time); + if (n != 0) { + INSIST(0); + } + cp = msg + msglen; + + } + /* Either the message is not truncated or there was no TSIG */ + else { + if (has_tsig > 0) + buflen -= tsig_size; + n = doaddinfo(hp, cp, buflen); + cp += n; + buflen -= n; + if (has_tsig > 0) { + buflen += tsig_size; + sig2len = sizeof(sig2); + msglen = cp - msg; + n = ns_sign(msg, &msglen, msglen + buflen, error, key, + sig, siglen, sig2, &sig2len, tsig_time); + if (n != 0) { + INSIST(0); + } + cp = msg + msglen; + } + } + +#ifdef DEBUG + 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, zn; + char dnbuf[MAXDNAME]; + struct zoneinfo *zp; + + /* 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. + */ + /* 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-secondary name (%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); + 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; + return (Finish); + refuse: + hp->rcode = ns_r_refused; + return (Finish); +} +#endif /*BIND_NOTIFY*/ + + +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) +{ + int n, class, type, count, zone, foundname, founddata, omsglen, cname; + int recursion_blocked_by_acl; + u_int16_t id; + u_int32_t serial_ixfr; + 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; + + + + + 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 + || ntohs(hp->arcount) != 0) { + ns_debug(ns_log_default, 1, + "FORMERR Query header counts wrong"); + hp->rcode = ns_r_formerr; + return (Finish); + } + + /* + * 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) { + 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) + 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; + 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); + + + 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*/ + + /* + * Begin Access Control Point + */ + + zone = DB_Z_CACHE; + if (np) { + 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 != class) + dp = dp->d_next; + if (dp != NULL) { + zone = dp->d_zone; + break; + } + } + } + + 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 != 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; + } + } + ns_notice(ns_log_security, + "denied query from %s for \"%s\"", + sin_ntoa(from), *dname ? dname : "."); + nameserIncr(from.sin_addr, nssRcvdUQ); + return (Refuse); + } + } 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\" (acl)", + p_type(type), sin_ntoa(from), + *dname ? dname : "."); + nameserIncr(from.sin_addr, nssRcvdUXFR); + 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); + return (Refuse); + } + + /* Are we authoritative? */ + + if ((zp->z_flags & Z_AUTH) == 0) { + ns_notice(ns_log_security, + "denied %s from %s for \"%s\" (not authoritative)", + p_type(type), sin_ntoa(from), + *dname ? dname : "."); + nameserIncr(from.sin_addr, nssRcvdUXFR); + 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\" (not zone top)", + p_type(type), sin_ntoa(from), + *dname ? dname : "."); + nameserIncr(from.sin_addr, nssRcvdUXFR); + 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) { + 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, "VERSION"); /* 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, server_options->version); + PUTSHORT((*cpp) - (tp + INT16SZ), tp); /* Real RdLength */ + *msglenp = *cpp - msg; /* Total message length */ + return (Finish); + } + + /* + * 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) { + 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", + sin_ntoa(from), *dname ? dname : "."); + 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); + 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) { + memput(omsg, omsglen); + omsg = NULL; + } + switch (n) { + case FW_OK: + if (cname) { + qp->q_cname = cname; + qp->q_cmsg = omsg; + qp->q_cmsglen = omsglen; + qp->q_id = id; + } + 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, + u_char *msg, struct sockaddr_in from) +{ + int dlen, alen, n, type, class, count; + char dnbuf[MAXDNAME], anbuf[PACKETSZ], *data, *fname; + + 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. + */ + if ((n = dn_skipname(*cpp, eom)) < 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); + *cpp += dlen; + if (*cpp != eom) { + ns_debug(ns_log_default, 1, + "FORMERR IQuery message length off"); + hp->rcode = ns_r_formerr; + return (Finish); + } + + /* + * not all inverse queries are handled. + */ + switch (type) { + case T_A: + if (!NS_OPTION_P(OPTION_FAKE_IQUERY) || dlen != INT32SZ) { + if (dlen != INT32SZ) + ns_warning(ns_log_security, + "bad iquery from %s", + inet_ntoa(from.sin_addr)); + return (Refuse); + } + break; + default: + ns_warning(ns_log_security, + "unsupported iquery type from %s", + inet_ntoa(from.sin_addr)); + return (Refuse); + } + ns_debug(ns_log_default, 1, + "req: IQuery class %d type %d", class, type); + + fname = (char *)msg + HFIXEDSZ; + alen = (char *)*cpp - fname; + if ((size_t)alen > sizeof anbuf) { + ns_warning(ns_log_security, + "bad iquery from %s", + inet_ntoa(from.sin_addr)); + return (Refuse); + } + memcpy(anbuf, fname, alen); + data = anbuf + alen - dlen; + *cpp = (u_char *)fname; + *buflenp -= HFIXEDSZ; + count = 0; + +#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((u_char *)data)), + 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((u_char *)data))); + *buflenp -= QFIXEDSZ; + n = dn_comp(dnbuf, *cpp, *buflenp, NULL, NULL); + if (n < 0) { + hp->tc = 1; + return (Finish); + } + *cpp += n; + PUTSHORT((u_int16_t)type, *cpp); + PUTSHORT((u_int16_t)class, *cpp); + *buflenp -= n; + count++; + + ns_debug(ns_log_default, 1, "req: IQuery %d records", count); + hp->qdcount = htons((u_int16_t)count); + if (alen > *buflenp) { + hp->tc = 1; + return (Finish); + } + memcpy(*cpp, anbuf, alen); + *cpp += 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]; + + 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 secondary 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: secondary zone %s expired", + zp->z_origin); + if (!haveComplained((u_long)zp, (u_long)stale)) { + ns_notice(ns_log_default, + "secondary 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, + "secondary 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; + + 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; + *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, dnptrs, edp); + ns_debug(ns_log_default, 1, "dn_comp's n = %u", n); + if (n < 0) + goto cleanup; + cp += n; + + /* 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 ((dp->d_size - 18) > buflen) + 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 finishedA = 0; + int save_addcount = addcount; + + 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; --addcount >= 0; ap++) { + int foundany = 0, + foundcname = 0, + save_count = count, + save_msglen = msglen; + u_char *save_cp = cp; + + if ((finishedA == 1 && ap->a_type == T_A) || + (finishedA == 0 && 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_rcode) + continue; + if ((match(dp, (int)ap->a_class, T_CNAME) && + dp->d_type == T_CNAME) || + (match(dp, C_IN, T_CNAME) && + dp->d_type == T_CNAME)) { + foundcname++; + break; + } + if (ap->a_type == T_A && + !match(dp, (int)ap->a_class, T_A) && + !match(dp, C_IN, T_A) && + !match(dp, (int)ap->a_class, T_AAAA) && + !match(dp, C_IN, T_AAAA) && + !match(dp, (int)ap->a_class, ns_t_a6) && + !match(dp, C_IN, ns_t_a6)) { + continue; + } + if (ap->a_type == T_KEY && + !match(dp, (int)ap->a_class, T_KEY) && + !match(dp, C_IN, T_KEY)) + continue; + + foundany++; + /* + * Should be smart and eliminate duplicate + * data here. XXX + */ + if ((n = make_rr(ap->a_dname, dp, cp, msglen, 0, + 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 && !foundany && + (ap->a_type == T_A || ap->a_type == T_AAAA)) { + /* ask a real server for this info */ + (void) sysquery(ap->a_dname, (int)ap->a_class, + ap->a_type, NULL, 0, ns_port, QUERY); + } + 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); + } + } + freestr(ap->a_dname); + freestr(ap->a_rname); + } + if (finishedA == 0) { + finishedA = 1; + addcount = save_addcount; + goto loop; /* now do the KEYs... */ + } + hp->arcount = htons((u_int16_t)count); + 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++) { + freestr(ap->a_dname); + freestr(ap->a_rname); + } + addcount = 0; +} + +void +free_nsp(struct databuf **nsp) { + while (*nsp) { + DRCNTDEC(*nsp); + if ((*nsp)->d_rcnt) + ns_debug(ns_log_default, 3, "free_nsp: %s rcnt %d", + (*nsp)->d_data, (*nsp)->d_rcnt); + else { + ns_debug(ns_log_default, 3, + "free_nsp: %s rcnt %d delayed", + (*nsp)->d_data, (*nsp)->d_rcnt); + db_freedata(*nsp); /* delayed free */ + } + *nsp++ = NULL; + } +} + +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; +} Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_resp.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_resp.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_resp.c (revision 60942) @@ -0,0 +1,4003 @@ +#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.143 2000/05/09 07:38:38 vixie 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 void fast_retry(struct qinfo *qp, struct sockaddr_in from); +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; + char *a, *ns, *na; + struct databuf *db; + int i; + + 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 (NS_OPTION_P(OPTION_HOSTSTATS)) { + char nsbuf[20]; + + if (db->d_ns != NULL) { + strcpy(nsbuf, + inet_ntoa(db->d_ns->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; + } + + if (NS_OPTION_P(OPTION_HOSTSTATS)) { + char abuf[20]; + + db = qp->q_addr[i].nsdata; + if (db != NULL) { + if (db->d_ns != NULL) { + strcpy(abuf, + inet_ntoa(db->d_ns->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 = "\".\""; + + if (NS_OPTION_P(OPTION_HOSTSTATS)) { + static const char fmt[] = " '%s': learnt (A=%s,NS=%s)"; + + buf = newstr(sizeof fmt + strlen(na) + strlen(a) + strlen(ns), + 0); + if (buf == NULL) + return (NULL); + sprintf(buf, fmt, na, a, ns); + } else { + static const char fmt[] = " '%s'"; + + buf = newstr(sizeof fmt + strlen(na), 0); + if (buf == NULL) + return (NULL); + sprintf(buf, fmt, na); + } + + 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[PACKETSZ]; + u_char **dpp, *tp; + time_t rtrip; + struct hashbuf *htp; + struct namebuf *np; + struct fwdinfo *fwd; + struct databuf *dp; + int forcecmsg = 0; + char *tname = NULL; + int sendto_errno = 0; + int has_tsig, oldqlen; + u_char *oldqbuf; + u_char *smsg; + int smsglen, smsgsize, siglen; + u_char sig[TSIG_SIG_SIZE]; + time_t tsig_time; + DST_KEY *key; + + 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 + )) { + 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); + break; + case FORMERR: + nameserIncr(from.sin_addr, nssRcvdFErr); + break; + default: + nameserIncr(from.sin_addr, nssRcvdErr); + break; + } + if (ns_samename(qp->q_name, qp->q_domain) == 1 && + hp->rcode == SERVFAIL && hp->opcode == QUERY) + mark_lame(qp, from); + mark_bad(qp, from); + fast_retry(qp, from); + 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)", + sin_ntoa(from)); + } + /* + * 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; + 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); + else + t = ns2->d_nstime * BETA + + + (1 - ALPHA) * rtrip; + } else + t = ns2->d_nstime * GAMMA; + if (t > 65535) + t = 65535; + 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 from %s for \"%s %s %s\"", + 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); + 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, 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) + 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); + 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 = 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; + 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); + + 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); + return; + } + + tp = cp; + + restart = 0; + validanswer = 0; + 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; + + 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. */ + 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_freedata(dp); + 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 { + 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_freedata(dp); + 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_freedata(dp); + continue; + } else if (fwd == NULL && + !ns_samedomain(name, + qp->q_domain)) { + if (!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_freedata(dp); + 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_freedata(dp); + 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 T_AAAA: + 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_freedata(dp); + 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_freedata(dp); + continue; + } + 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; + 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_freedata(dp); + continue; + } + dp->d_cred = (qp->q_flags & Q_PRIMING) + ? DB_C_ANSWER + : DB_C_ADDITIONAL; + } + } + rrsetadd(flushset, name, 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); + 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) { + /* + * 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) { + ns_debug(ns_log_default, 3, + "resp: leaving NO: auth = %d", hp->aa); + goto return_msg; + } + forcecmsg = 1; + } + + /* + * 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(PACKETSZ, qp->q_cmsglen); + memcpy(newmsg, qp->q_cmsg, newmsglen); + } else { + newmsglen = MIN(PACKETSZ, 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, "ns_resp"); + qp->q_naddr = 0; + qp->q_curaddr = 0; + nsfwdadd(qp, NS_ZFWDTAB(qp->q_fzone)); + + if (qp->q_domain != NULL) + 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) + 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 = 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; + 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 (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_resp: sendto(%s): %s", + sin_ntoa(*nsa), strerror(errno)); + nameserIncr(nsa->sin_addr, nssSendtoErr); + } + if (has_tsig == 1) { + memput(qp->q_msg, 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); + 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 (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: + 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; + 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; + + /* 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; + 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_long 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 %d to origTTL %d", + ttl, origTTL); + ttl = origTTL; + } + + /* Don't let bogus signers "sign" in the future. */ + if (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 (exptime <= now) { + 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 > 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 > (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 >= 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 > 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: + ns_debug(ns_log_default, 3, "unknown type %d", type); + return ((cp - rrp) + dlen); + } + + 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; + *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; + int msgsize; + int ret; + + if (qp->q_flags & Q_SYSTEM) + return (1); + if (!qp->q_stream && (msglen > PACKETSZ)) + msglen = trunc_adjust(msg, msglen, PACKETSZ); + 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); + } + } + if (debug >= 6) + res_pquery(&res, msg, msglen, log_get_stream(packet_channel)); +#endif /* DEBUG */ + + if (qp->q_tsig != NULL) { + u_char sig[TSIG_SIG_SIZE]; + int siglen = sizeof(sig); + + oldmsg = msg; + oldlen = msglen; + + msgsize = msglen + TSIG_BUF_SIZE; + msg = memget(msgsize); + memcpy(msg, oldmsg, oldlen); + + 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); + } + } + + if (qp->q_stream == NULL) { + /* + * Don't send FORMERR to these well known ports + * (loop avoidance). + */ + switch (ntohs(qp->q_from.sin_port)) { + case 7: /* echo */ + case 13: /* daytime */ + case 19: /* chargen */ + case 37: /* time */ + if (hp->rcode == FORMERR) + return (-1); + default: + break; + } + 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 (qp->q_tsig != NULL) + memput(msg, oldlen + TSIG_BUF_SIZE); + + 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, 0, ns_port, ns_o_query); + + 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, int nsc, u_int16_t port, int opcode) +{ + 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; + int oldqlen, has_tsig; + u_char *smsg; + int smsglen, smsgsize, siglen; + u_char sig[TSIG_SIG_SIZE]; + DST_KEY *key; + + nsp[0] = NULL; + ns_debug(ns_log_default, 3, "sysquery(%s, %d, %d, %#x, %d, %d)", + dname, class, type, nss, nsc, ntohs(port)); + qp = qnew(dname, class, type, (nss != NULL && nsc != 0) ? 0 : 1); + + 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); + + /* 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; + qs->ns = NULL; + qs->nsdata = NULL; + qs->stime = tt; + qs->forwarder = 0; + 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) + 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); + + 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 = 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; + qp->q_nstsig = new_tsig(key, sig, siglen); /* BEW? */ + + } + 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 (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 (has_tsig == 1) { + memput(qp->q_msg, 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, + 0, ns_port, QUERY); + 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, + 0, ns_port, QUERY); + } + } + + 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 %#x '%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 secondary 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]) { + nspp--; + DRCNTDEC(*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; + } + } + + /* 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 ; idx >= 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(%#x, %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(%#x, %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; + 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; + 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_freedata(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_freedata(dp); +} + +static void +free_flushset(struct flush_set *flushset, int flushset_size) { + struct flush_set *fs; + + for (fs = flushset; fs->fs_name != NULL; fs++) + freestr(fs->fs_name); + 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(%#x:\"%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 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) { + if (ina_equal(qp->q_addr[qp->q_curaddr].ns_addr.sin_addr, + from.sin_addr)) + retry(qp); +} + +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) { + freestr(name); + return; + } + related[num_related++] = name; +} + +static void +free_related_additional() { + int i; + + for (i = 0; i < num_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; + freestr(*tname); + *tname = NULL; +} + +/* + * 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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_signal.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_signal.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_signal.c (revision 60942) @@ -0,0 +1,264 @@ +#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.12 2000/04/21 06:54:12 vixie 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 +# include +#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) { + ns_need_unsafe(main_need_reload); +} + +static SIG_FN +onintr(int sig) { + ns_need_unsafe(main_need_exit); +} + +static SIG_FN +setdumpflg(int sig) { + ns_need_unsafe(main_need_dump); +} + +#ifdef DEBUG +static SIG_FN +setIncrDbgFlg(int sig) { + desired_debug++; + ns_need_unsafe(main_need_debug); +} + +static SIG_FN +setNoDbgFlg(int sig) { + desired_debug = 0; + ns_need_unsafe(main_need_debug); +} +#endif /*DEBUG*/ + +#if defined(QRYLOG) && defined(SIGWINCH) +static SIG_FN +setQrylogFlg(int sig) { + ns_need_unsafe(main_need_qrylog); +} +#endif /*QRYLOG && SIGWINCH*/ + +static SIG_FN +setstatsflg(int 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; + + 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; +#endif +} + +static SIG_FN +setreapflg(int sig) { + ns_need_unsafe(main_need_reap); +} + +/* Public. */ + +void +init_signals(void) { + int 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)); + } +} + +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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_sort.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_sort.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_sort.c (revision 60942) @@ -0,0 +1,410 @@ +#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.6 2000/04/21 06:54:13 vixie 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 "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: + 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: + 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; + struct in_addr inaddr; + u_char *rr1 = NULL, *rrbest, *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: + 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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_stats.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_stats.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_stats.c (revision 60942) @@ -0,0 +1,402 @@ +#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.30 2000/04/23 02:18:59 vixie 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 *); + +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++; + } + + dummy.addr = addr; + ns = (struct nameser *)tree_srch(&nameserTree, nameserCompar, + (tree_t)&dummy); + if (ns == NULL && (flags & NS_F_INSERT) != 0) { + 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; + } + } + 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); + 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[64]; + 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)) + + getrusage(RUSAGE_SELF, &usage); + getrusage(RUSAGE_CHILDREN, &childu); + + sprintf(buffer, "CPU=%gu/%gs CHILDCPU=%gu/%gs", + tv_float(usage.ru_utime), tv_float(usage.ru_stime), + tv_float(childu.ru_utime), tv_float(childu.ru_stime)); + ns_info(ns_log_statistics, "USAGE %lu %lu %s", (u_long)timenow, + (u_long)boottime, buffer); +# 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, buffer); + strcpy(buffer, header); + } + strcat(buffer, buffer2); + } + } + ns_info(ns_log_statistics, 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, buffer); + strcpy(buffer, header); + } + strcat(buffer, buffer2); + } + ns_info(ns_log_statistics, 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; +} Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_udp.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_udp.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_udp.c (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_update.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_update.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_update.c (revision 60942) @@ -0,0 +1,3019 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_update.c,v 8.78 2000/04/23 02:19:00 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. + */ + +/* + * 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 "port_after.h" + +#include "named.h" + +static ns_updque curupd; + +#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 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; + struct map *mp; + ns_updrec *rrecp; + int opcode; + char time[25]; + FILE *fp, *ifp; + + if (EMPTY(*updlist)) + return; + + fp = open_transaction_log(zp); + if (fp == NULL) + return; + + ifp = open_ixfr_log(zp); + if (ifp == NULL) { + (void) close_transaction_log(zp, fp); + return; + } + 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()); + 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); + fprintf(ifp, "zone:\torigin %s class %s serial %u\n", + zp->z_origin, p_class(zp->z_class), + 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)) { + 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)) { + 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)) { + 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); + (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 *dname = ur->r_dname; + 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; + + int ret = 1; + + /* We don't care about deletes */ + if (ur->r_class != zclass) + return (1); + + context = ns_ownercontext(type, primary_trans); + if (!ns_nameok(NULL, owner, class, zp, primary_trans, context, owner, + inaddr_any)) + goto refused; + + switch (type) { + case ns_t_soa: + context = hostname_ctx; + if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner, + inaddr_any)) + goto refused; + cp += strlen(cp) + 1; + context = mailname_ctx; + if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner, + inaddr_any)) + goto refused; + break; + case ns_t_rp: + context = mailname_ctx; + if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner, + inaddr_any)) + goto refused; + cp += strlen(cp) + 1; + context = domain_ctx; + if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner, + inaddr_any)) + goto refused; + break; + case ns_t_minfo: + context = mailname_ctx; + if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner, + inaddr_any)) + goto refused; + cp += strlen(cp) + 1; + context = mailname_ctx; + if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner, + inaddr_any)) + goto refused; + break; + case ns_t_ns: + context = hostname_ctx; + if (!ns_nameok(NULL, cp, class, zp, primary_trans, 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, primary_trans, context, owner, + inaddr_any)) + goto refused; + break; + case ns_t_ptr: + context = ns_ptrcontext(owner); + if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner, + inaddr_any)) + goto refused; + break; + case ns_t_naptr: + /* + * Order (2) + * Preference (2) + * Flags (1) + */ + cp += 5; + /* Service (txt) */ + cp += strlen(cp) + 1; + /* Pattern (txt) */ + cp += strlen(cp) + 1; + context = domain_ctx; + if (!ns_nameok(NULL, cp, class, zp, primary_trans, 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, primary_trans, context, owner, + inaddr_any)) + goto refused; + break; + case ns_t_px: + cp += 2; + context = domain_ctx; + if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner, + inaddr_any)) + goto refused; + cp += strlen(cp) + 1; + if (!ns_nameok(NULL, cp, class, zp, primary_trans, 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, primary_trans, context, owner, + inaddr_any)) + goto refused; + break; + case ns_t_nxt: + context = domain_ctx; + if (!ns_nameok(NULL, cp, class, zp, primary_trans, 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) { + 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; + + 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 i, j, n, dbflags, matches, zonenum; + int numupdated = 0, soaupdated = 0, schedmaint = 0; + u_int16_t zclass; + ns_updrec *ur; + const char *fname; + 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=0x%0x", + 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 0x%0x", + 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 qstream *qsp, int dfd, struct sockaddr_in from, + struct tsig_record *in_tsig) +{ + char dnbuf[MAXDNAME], *dname; + u_int zocount, prcount, upcount, adcount, class, type, dlen; + u_int32_t ttl; + int i, n, cnt, found, matches, zonenum, numupdated = 0; + int rcode = NOERROR; + u_int c, section; + u_char rdata[MAXDATA]; + struct qinfo *qp; + struct databuf *dp, *nsp[NSMAX]; + struct databuf **nspp = &nsp[0]; + struct zoneinfo *zp; + ns_updrec *rrecp; + int zonelist[MAXDNAME]; + int should_use_tcp; + u_int32_t old_serial; + int unapproved_ip = 0; + int tsig_len; + 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", + sin_ntoa(from), *dname ? dname : "."); + 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, *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, 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); + if (rrecp->r_section != S_UPDATE) { + if (rrecp->r_dp) + db_freedata(rrecp->r_dp); + res_freeupdrec(rrecp); + continue; + } + dname = rrecp->r_dname; + dp = rrecp->r_dp; + 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 0x%0x", + dp); + /* + * XXXRTH + * + * We used to db_freedata() here, + * but I removed it because 'dp' was + * part of a hashtab before we called + * db_update(), and since our delete + * has succeeded, it should have been + * freed. + */ + } + } + } else { + /* + * Databuf's matching this were deleted by this + * update, or were never executed (because we bailed + * out early). + */ + db_freedata(dp); + } + + /* Process deleted databuf's. */ + dp = rrecp->r_deldp; + while (dp != NULL) { + tmpdp = dp; + dp = dp->d_next; + if (rcode == NOERROR) { + if (tmpdp->d_rcnt) + ns_debug(ns_log_update, 1, + "free_rrecp: type = %d, rcnt = %d", + p_type(tmpdp->d_type), + tmpdp->d_rcnt); + else { + tmpdp->d_next = NULL; + db_freedata(tmpdp); + } + } else { + /* 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 0x%0x", + tmpdp); + } + } + } + res_freeupdrec(rrecp); + } + INIT_LIST(*updlist); +} + +enum req_action +req_update(HEADER *hp, u_char *cp, u_char *eom, u_char *msg, + struct qstream *qsp, int dfd, struct sockaddr_in from, + struct tsig_record *in_tsig) +{ + enum req_action ret; + + INIT_LIST(curupd); + ret = req_update_private(hp, cp, eom, msg, qsp, dfd, from, in_tsig); + 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 > dlen) + return (0); + cp += n; + n1 = dlen - n - SIG_HDR_SIZE; + n = strlen((char *)cp1) + 1; + cp1 += n; + if (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 > size) + return (0); + memcpy(cp1, cp, n1); + cp1 += n1; + return (cp1 - cp1init); + default: + ns_debug(ns_log_update, 3, "unknown type %d", type); + return (0); + } +} + +/* + * 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, "\\%03.3d", *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, "\t;?d_type=%d?", dp->d_type); + } +} + +/* + * 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, *cp; + 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=0x%x, 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], buf2[100]; + 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, 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; + u_char *serialp; + struct sockaddr_in empty_from; + int datasize; + unsigned long l; + + 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 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 movefile that was interrupted. */ + ns_info(ns_log_update, + "completing interrupted dump movefile for %s", + zp->z_source); + fclose(fp); + if (movefile(logname, zp->z_source) < 0) { + ns_error(ns_log_update, "movefile(%s,%s) failed: %s :1", + logname, zp->z_source, + strerror(errno)); + fclose(fp); + 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; + 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); + 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); + return(-1); + } + free_rrecp(&curupd, rcode, empty_from); + } + 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 %ul", + origin, sclass, &serial); + 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 = sym_ston(__p_class_syms, 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, 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 = sym_ston(__p_class_syms, + 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 = sym_ston(__p_type_syms, + 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); + if (c == '(') { + multiline = 1; + } else { + multiline = 0; + ungetc(c, fp); + } + n = getnum(fp, logname, GETNUM_SERIAL); + 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 && + (getnonblank(fp, logname) + != ')')) { + 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: + { + 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: + err++; + } + 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) { + inside_next = 0; + 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); + continue; + } + 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 (;;) */ + + 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 (movefile(tmp_name, zp->z_ixfr_tmp) < 0) { + ns_error(ns_log_update, "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 (movefile(zp->z_ixfr_tmp, zp->z_source) < 0) { + ns_error(ns_log_update, "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 (movefile(tmp_name, zp->z_updatelog) < 0) { + ns_error(ns_log_update, "movefile(%s,%s) failed: %s :4", + tmp_name, zp->z_updatelog, strerror(errno)); + return (-1); + } + if (movefile(zp->z_updatelog, zp->z_source) < 0) { + ns_error(ns_log_update, "movefile(%s,%s) failed: %s:5", + zp->z_updatelog, zp->z_source, + strerror(errno)); + return (-1); + } + } else { + if (movefile(tmp_name, zp->z_source) < 0) { + ns_error(ns_log_update, "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); + ifp = open_ixfr_log(zp); + if (ifp == NULL) + return (-1); + dp = findzonesoa(zp); + if (dp) { + olddp = memget(DATASIZE(dp->d_size)); + if (olddp != NULL) { + memcpy(olddp, dp, 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, 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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/ns_xfr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_xfr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/ns_xfr.c (revision 60942) @@ -0,0 +1,860 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ns_xfr.c,v 8.62 2000/04/24 05:20:51 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 + +#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_axfr: /*FALLTHROUGH*/ + case ns_t_ixfr: +#ifdef BIND_ZXFR + case ns_t_zxfr: +#endif + ns_info(ns_log_xfer_out, + "zone transfer (%s) of \"%s\" (%s) to %s", + p_type(type), zones[zone].z_origin, p_class(class), + sin_ntoa(qsp->s_from)); + 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, + (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, + (char *)&sndlowat, sizeof sndlowat); +#endif + if (sq_openw(qsp, 64*1024) == -1) + 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) + 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; + 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; + } + + if (type == ns_t_ixfr) { + changes = ixfr_get_change_list(&zones[zone], serial_ixfr, + zones[zone].z_serial); + ixfr_log_maint(&zones[zone], 1); + 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) { + 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_freedata(rp->r_dp); + rp->r_dp = NULL; + 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); + 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, + 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, + 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. + */ +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) { + DRCNTDEC(lev->dp); + if (lev->dp->d_rcnt == 0) + db_freedata(lev->dp); + } + memput(lev, sizeof *lev); + return (next); +} + +static struct databuf * +db_next(struct databuf *dp) { + struct databuf *next = dp->d_next; + + DRCNTDEC(dp); + if (dp->d_rcnt == 0) + db_freedata(dp); + + if (next) + DRCNTINC(next); + + return (next); +} + Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/pathtemplate.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/pathtemplate.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/pathtemplate.h (revision 60942) @@ -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.2.3.t5b/contrib/bind/bin/named/pathtemplate.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/named/named.conf =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/named.conf (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/named.conf (revision 60942) @@ -0,0 +1,456 @@ +/* + * 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! + +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) + max-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. + 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; + }; + 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; + }; +}; + +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"; +}; + +acl key_acl { key sample_key; }; // a request signed with sample_key + +server 1.2.3.4 { + 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.2.3.t5b/contrib/bind/bin/named/named.conf ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/named/test/named.conf =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/test/named.conf (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/test/named.conf (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/test/127.0.0.zone =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/test/127.0.0.zone (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/test/127.0.0.zone (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/test/localhost.zone =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/test/localhost.zone (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/test/localhost.zone (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/test/root.hint =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/test/root.hint (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/test/root.hint (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named/version.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named/version.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named/version.c (revision 60942) @@ -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.2.3.t5b/contrib/bind/bin/named/version.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/ndc/ndc.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/ndc/ndc.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/ndc/ndc.c (revision 60942) @@ -0,0 +1,709 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ndc.c,v 1.14 2000/02/04 08:28:32 vixie 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 "port_after.h" +#include "pathnames.h" + +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 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(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, ...); +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(char *, sockaddr_t *); +static size_t impute_addrlen(const struct sockaddr *); +static void vtrace(const char *, va_list); +static void trace(const char *, ...); +static void result(const char *, ...); +static void fatal(const char *, ...); +static void verror(const char *, va_list); +static void error(const char *, ...); + +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 *envp[]) { + char *p; + int ch; + + if ((program = strrchr(argv[0], '/')) != 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)"); +} + +static int +builtincmd(void) { + static const char spaces[] = " \t"; + char *rest, *syscmd; + pid_t pid; + int save_quiet = quiet; + int len; + + quiet = 1; + + len = strcspn(cmd, spaces); + rest = cmd + len; + if (*rest != '\0') { + rest++; + rest += strspn(rest, spaces); + } + 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 (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) { + printf(helpfmt, "start", "start the server"); + printf(helpfmt, "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; + channel_loop(cmd, !quiet, NULL, NULL); + quiet = save_quiet; +} + +struct args { + const char *cmd; + closure cl; + void *ua; +}; + +static void +channel_loop(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; + 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; + + 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: + 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 } +}; + +static void +command_signals(void) { + struct cmdsig *cmdsig; + pid_t pid; + int sig; + + 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)", pidfile, try + 1); + if ((fp = fopen(pidfile, "r")) == NULL) + trace("pid file (%s) unavailable - %s", + pidfile, strerror(errno)); + else if (fscanf(fp, "%ld\n", &t) != 1) + trace("pid file (%s) format is bad", pidfile); + else if (*pid = (pid_t)t, fclose(fp), kill(*pid, 0) < 0) + trace("pid file (%s) contains unusable pid (%d) - %s", + pidfile, *pid, strerror(errno)); + else { + trace("pid is %ld", (long)*pid); + return (1); + } + sleep(1); + } + trace("pid not found"); + return (0); +} + +static int +get_sockaddr(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 == 0) + 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(); + } +} + +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.2.3.t5b/contrib/bind/bin/ndc/ndc.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/ndc/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/ndc/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/ndc/Makefile (revision 60942) @@ -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 1.15 1999/08/08 17:51:02 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +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} -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.2.3.t5b/contrib/bind/bin/ndc/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/commands.l =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/commands.l (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/commands.l (revision 60942) @@ -0,0 +1,218 @@ +%{ + +/* + * 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 "port_after.h" +#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(yytext, 0); + return(1); + } +^{WS}*lserver{WS}+{LET}{NAME}*{WS}*$ { + SetDefaultServer(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(yytext, 1); + return(1); + } +^{WS}*finger({WS}+{LET}{NAME}*)?{WS}*$ { + Finger(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(yytext, 1); + return(1); + } +^{WS}*ls{WS}+(("-a"|"-d"|"-h"|"-m"|"-s"){WS}+)?{LET}{NAME}*{WS}*$ { + ListHosts(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(yytext, 1); + return(1); + } +^{WS}*ls{WS}+-t{WS}+({LET}{NAME}*{WS}+)?{LET}{NAME}*{WS}*$ { + ListHostsByType(yytext, 0); + return(1); + } +^{WS}*set{WS}+{NAME}+{WS}*$ { + SetOption(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(yytext, 1); + return(1); + } +^{WS}*{FLET}{NAME}*{WS}*$ { + LookupHost(yytext, 0); + return(1); + } +^{WS}*{FLET}{NAME}*{WS}+{LET}{NAME}*{WS}+>>?{WS}*{NAME}+{WS}*$ { + /* + * 0 == output to stdout + * 1 == output to file + */ + LookupHostWithServer(yytext, 1); + return(1); + } +^{WS}*{FLET}{NAME}*{WS}+{LET}{NAME}*{WS}*$ { + LookupHostWithServer(yytext, 0); + return(1); + } +^{WS}*\n { + return(1); + } +^.*\n { + printf("Unrecognized command: %s", + yytext); + return(1); + } +\n { ; } +%% Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/commands.l ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/list.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/list.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/list.c (revision 60942) @@ -0,0 +1,650 @@ +/* + * 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.23 2000/03/30 23:25:34 vixie 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 "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_in sin; + HEADER *headerPtr; + int msglen, amtToRead, numRead, n, count, 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; + + /* + * 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); + } + + memset(&sin, 0, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(nsport); + + /* + * 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) + sin.sin_addr = *(struct in_addr *) defaultPtr->addrList[0]; + else + sin.sin_addr = *(struct in_addr *) + defaultPtr->servers[0]->addrList[0]; + + /* + * Set up a virtual circuit to the server. + */ + sockFD = socket(AF_INET, SOCK_STREAM, 0); + if (sockFD < 0) { + perror("ls: socket"); + return (ERROR); + } + if (connect(sockFD, (struct sockaddr *)&sin, sizeof(sin)) < 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); + if (write(sockFD, (char *)tmp, INT16SZ) != INT16SZ || + write(sockFD, (char *)buf.qb2, msglen) != 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 || 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. + * + ******************************************************************************* + */ + +Finger(string, putToFile) + char *string; + int putToFile; +{ + struct servent *sp; + struct sockaddr_in sin; + FILE *f; + int c; + int lastc; + char name[NAME_LEN]; + char file[PATH_MAX]; + int i; + + /* + * 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(&sin, 0, sizeof sin); + sin.sin_family = curHostInfo.addrType; + sin.sin_port = sp->s_port; + memcpy(&sin.sin_addr, curHostInfo.addrList[0], curHostInfo.addrLen); + + /* + * Set up a virtual circuit to the host. + */ + + sockFD = socket(curHostInfo.addrType, SOCK_STREAM, 0); + if (sockFD < 0) { + fflush(stdout); + perror("finger: socket"); + return (ERROR); + } + + if (connect(sockFD, (struct sockaddr *)&sin, sizeof (sin)) < 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() +{ + if (sockFD != -1) { + (void) close(sockFD); + sockFD = -1; + } +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/list.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/main.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/main.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/main.c (revision 60942) @@ -0,0 +1,1214 @@ +/* + * 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.14 2000/03/30 23:25:34 vixie 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 "res.h" +#include "pathnames.h" + +/* + * Name of a top-level name server. Can be changed with + * the "set root" command. + */ + +#ifndef ROOT_SERVER +#define ROOT_SERVER "a.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]; +struct in_addr 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(); +FILE *filePtr; +jmp_buf env; + + +/* + * Browser command for help. + */ +char *pager; + +static void CvtAddrToPtr(); +static void ReadRC(); + +/* + * Forward declarations. + */ +void LocalServer(HostInfo *defaultPtr); +void res_re_init(void); +void res_dnsrch(char *cp); + + +/* + ****************************************************************************** + * + * main -- + * + * Initializes the resolver library and determines the address + * of the initial name server. The yylex routine is used to + * read and perform commands. + * + ****************************************************************************** + */ + +main(argc, argv) + int argc; + char **argv; +{ + char *wantedHost = NULL; + Boolean useLocalServer; + int result; + int i; + struct hostent *hp; + + /* + * 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) { + struct in_addr addr; + + /* + * Use an explicit name server. If the hostname lookup fails, + * default to the server(s) in resolv.conf. + */ + + if (inet_aton(*++argv, &addr)) { + res.nscount = 1; + res.nsaddr.sin_addr = addr; + } else { + hp = gethostbyname(*argv); + if (hp == NULL) { + fprintf(stderr, "*** Can't find server address for '%s': ", + *argv); + herror((char *)NULL); + fputc('\n', stderr); + } else { + for (i = 0; i < MAXNS && hp->h_addr_list[i] != NULL; i++) { + memcpy(&res.nsaddr_list[i].sin_addr, hp->h_addr_list[i], + hp->h_length); + } + res.nscount = i; + } + } + } + + + if (res.nscount == 0 || useLocalServer) { + LocalServer(defaultPtr); + } else { + for (i = 0; i < res.nscount; i++) { + if (res.nsaddr_list[i].sin_addr.s_addr == INADDR_ANY) { + LocalServer(defaultPtr); + break; + } else { + result = GetHostInfoByAddr(&(res.nsaddr_list[i].sin_addr), + &(res.nsaddr_list[i].sin_addr), + defaultPtr); + if (result != SUCCESS) { + fprintf(stderr, + "*** Can't find server name for address %s: %s\n", + inet_ntoa(res.nsaddr_list[i].sin_addr), + DecodeError(result)); + } else { + defaultAddr = res.nsaddr_list[i].sin_addr; + 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); +} + + +void +LocalServer(defaultPtr) + HostInfo *defaultPtr; +{ + char hostName[NAME_LEN]; + + (void) gethostname(hostName, sizeof(hostName)); + + defaultAddr.s_addr = htonl(INADDR_ANY); + (void) GetHostInfoByName(&defaultAddr, C_IN, T_A, + "0.0.0.0", defaultPtr, 1); + 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. + * + ****************************************************************************** + */ + +Usage() +{ + 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) + char *host; + struct in_addr *addrPtr; /* If return TRUE, contains IP address */ +{ + register char *cp; + + if (isdigit(host[0])) { + /* Make sure it has only digits and dots. */ + for (cp = host; *cp; ++cp) { + if (!isdigit(*cp) && *cp != '.') + return FALSE; + } + /* If it has a trailing dot, don't treat it as an address. */ + if (*--cp != '.') { + return inet_aton(host, addrPtr); + } + } + return FALSE; +} + + +/* + ****************************************************************************** + * + * 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; + struct in_addr *servAddrPtr; + struct in_addr addr; + char newServer[NAME_LEN]; + int result; + 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) { + servAddrPtr = &defaultAddr; + } else if (defaultPtr->addrList != NULL) { + servAddrPtr = (struct in_addr *) defaultPtr->addrList[0]; + } else { + servAddrPtr = (struct in_addr *) defaultPtr->servers[0]->addrList[0]; + } + + result = ERROR; + if (IsAddr(newServer, &addr)) { + result = GetHostInfoByAddr(servAddrPtr, &addr, newDefPtr); + /* If we can't get the name, fall through... */ + } + if (result != SUCCESS && result != NONAUTH) { + result = GetHostInfoByName(servAddrPtr, C_IN, T_A, + newServer, newDefPtr, 1); + } + + /* 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; + struct in_addr *servAddrPtr; + struct in_addr 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) { + servAddrPtr = (struct in_addr *) servPtr->addrList[0]; + } else { + servAddrPtr = (struct in_addr *) servPtr->servers[0]->addrList[0]; + } + + /* + * RFC1123 says we "SHOULD check the string syntactically for a + * dotted-decimal number before looking it up [...]" (p. 13). + */ + if (queryType == T_A && IsAddr(host, &addr)) { + result = GetHostInfoByAddr(servAddrPtr, &addr, &curHostInfo); + } else { + if (queryType == T_PTR) { + CvtAddrToPtr(host); + } + result = GetHostInfoByName(servAddrPtr, queryClass, queryType, host, + &curHostInfo, 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) { + 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(string, putToFile) + 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; + + 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); + } + + result = GetHostInfoByName( + defaultPtr->addrList ? + (struct in_addr *) defaultPtr->addrList[0] : + (struct in_addr *) defaultPtr->servers[0]->addrList[0], + C_IN, T_A, server, &serverInfo, 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); + } + + queryType = StringToType(type, queryType, stderr); + } + } 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. + */ +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 '/' + +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. + * + ****************************************************************************** + */ + +void +ShowOptions() +{ + 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() +{ + 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]; + struct in_addr addr; + + if (IsAddr(name, &addr)) { + p = inet_ntoa(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]); + } + } +} + +/* + ****************************************************************************** + * + * ReadRC -- + * + * Use the contents of ~/.nslookuprc as options. + * + ****************************************************************************** + */ + +static void +ReadRC() +{ + 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.2.3.t5b/contrib/bind/bin/nslookup/main.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/nslookup.help =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/nslookup.help (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/nslookup.help (revision 60942) @@ -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.2.3.t5b/contrib/bind/bin/nslookup/nslookup.help ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/Makefile (revision 60942) @@ -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 8.24 1999/10/13 01:14:46 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +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= +DEFS= -D_PATH_HELPFILE=\"${DESTHELP}/nslookup.help\" +CFLAGS= ${CDEBUG} -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} ${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.2.3.t5b/contrib/bind/bin/nslookup/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/debug.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/debug.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/debug.c (revision 60942) @@ -0,0 +1,646 @@ +/* + * 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.15 1999/10/13 16:39:16 vixie 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 "port_after.h" + +#include "res.h" + +/* + * Imported from res_debug.c + */ +extern char *_res_opcodes[]; + +/* + * 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; + + /* + * Print header fields. + */ + hp = (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((u_char*)cp); + cp += INT16SZ; + class = ns_get16((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"); +} + +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((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((u_char*)cp)); + cp += INT16SZ; + fprintf(file,", preference = %u\n", ns_get16((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((u_char*)cp)); + cp += INT16SZ; + fprintf(file,", weight = %u", ns_get16((u_char*)cp)); + cp += INT16SZ; + fprintf(file,", port= %u\n", ns_get16((u_char*)cp)); + cp += INT16SZ; + + fprintf(file,"\thost = "); + goto doname; + + case T_PX: + BOUNDS_CHECK(cp, INT16SZ); + fprintf(file,"\tpreference = %u",ns_get16((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((u_char*)cp)); + cp += INT16SZ; + fprintf(file,", router = "); + goto doname; + + case T_AFSDB: + BOUNDS_CHECK(cp, INT16SZ); + fprintf(file,"\tsubtype = %d",ns_get16((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((u_char*)cp)); + cp += INT32SZ; + ttl = ns_get32((u_char*)cp); + fprintf(file,"\n\trefresh = %lu (%s)", ttl, p_time(ttl)); + cp += INT32SZ; + ttl = ns_get32((u_char*)cp); + fprintf(file,"\n\tretry = %lu (%s)", ttl, p_time(ttl)); + cp += INT32SZ; + ttl = ns_get32((u_char*)cp); + fprintf(file,"\n\texpire = %lu (%s)", ttl, p_time(ttl)); + cp += INT32SZ; + ttl = ns_get32((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. */ + + if (ns_sprintrrf(msg, eom - msg, "?", (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.2.3.t5b/contrib/bind/bin/nslookup/debug.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/getinfo.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/getinfo.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/getinfo.c (revision 60942) @@ -0,0 +1,874 @@ +/* + * 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.15 1999/10/13 16:39:16 vixie 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 + +#include "port_after.h" + +#include "res.h" + +extern char *res_skip(); + +static char *addr_list[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]; + 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(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isServer) + struct in_addr *nsAddrPtr; + char *msg; + int queryType; + int msglen; + Boolean iquery; + register HostInfo *hostPtr; + Boolean isServer; +{ + register HEADER *headerPtr; + register u_char *cp; + querybuf answer; + char **aliasPtr; + u_char *eom, *bp; + char **addrPtr; + char *namePtr; + char *dnamePtr; + int type, class; + int qdcount, ancount, arcount, nscount, buflen; + int origClass; + int numAliases = 0; + int numAddresses = 0; + int n, i, j; + int dlen; + int status; + int numServers; + size_t s; + Boolean haveAnswer; + Boolean printedAnswers = FALSE; + + + /* + * If the hostPtr was used before, free up the calloc'd areas. + */ + FreeHostInfoPtr(hostPtr); + + status = SendRequest(nsAddrPtr, 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; + 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 && !(iquery && queryType == T_PTR)) { + while (--ancount >= 0 && cp < eom) { + if ((cp = (u_char *)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) { + cp += dlen; + continue; + } + if (dlen != INADDRSZ) + return (ERROR); + if (haveAnswer) { + /* + * If we've already got 1 address, we aren't interested + * in addresses with a different length or class. + */ + if (dlen != hostPtr->addrLen) { + cp += dlen; + continue; + } + if (class != origClass) { + cp += dlen; + continue; + } + } else { + /* + * First address: record its length and class so we + * only save additonal ones with the same attributes. + */ + hostPtr->addrLen = dlen; + origClass = class; + hostPtr->addrType = (class == C_IN) ? AF_INET : AF_UNSPEC; + 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); + bp += dlen; + cp += dlen; + numAddresses++; + haveAnswer = TRUE; + } + } + } + + if ((queryType == T_A || queryType == T_PTR) && haveAnswer) { + + /* + * Go through the alias and address lists and return them + * in the hostPtr variable. + */ + + if (numAliases > 0) { + hostPtr->aliases = + (char **) Calloc(1 + numAliases, sizeof(char *)); + for (i = 0; i < numAliases; i++) { + hostPtr->aliases[i] = Calloc(1, host_aliases_len[i]); + memcpy(hostPtr->aliases[i], host_aliases[i], + host_aliases_len[i]); + } + hostPtr->aliases[i] = NULL; + } + if (numAddresses > 0) { + hostPtr->addrList = + (char **)Calloc(1+numAddresses, sizeof(char *)); + for (i = 0; i < numAddresses; i++) { + hostPtr->addrList[i] = Calloc(1, hostPtr->addrLen); + memcpy(hostPtr->addrList[i], addr_list[i], hostPtr->addrLen); + } + hostPtr->addrList[i] = 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) && (nscount > 0 || arcount > 0)) { + if (printedAnswers) { + putchar('\n'); + } + printf("Authoritative answers can be found from:\n"); + } + + cp = (u_char *)res_skip((char *) &answer, 2, eom); + + numServers = 0; + if (queryType != T_A) { + /* + * If we don't need to save the record, just print it. + */ + while (--nscount >= 0 && cp < eom) { + if ((cp = (u_char *)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 (strcmp(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 = (u_char *)res_skip((char *) &answer, 3, eom); + + if (queryType != T_A) { + /* + * If we don't need to save the record, just print it. + */ + while (--arcount >= 0 && cp < eom) { + if ((cp = (u_char *)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) { + cp += dlen; + continue; + } else { + if (dlen != INADDRSZ) + return (ERROR); + for (j = 0; j < numServers; j++) { + if (strcmp((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); + break; + } + } + } + cp += dlen; + } + } + } + + /* + * If we are returning name server info, transfer it to the hostPtr. + */ + if (numServers > 0) { + hostPtr->servers = (ServerInfo **) + Calloc(numServers+1, sizeof(ServerInfo *)); + + for (i = 0; i < numServers; i++) { + hostPtr->servers[i] = (ServerInfo *) Calloc(1, sizeof(ServerInfo)); + hostPtr->servers[i]->name = server[i].name; + + + hostPtr->servers[i]->domains = (char **) + Calloc(server[i].numDomains+1,sizeof(char *)); + for (j = 0; j < server[i].numDomains; j++) { + hostPtr->servers[i]->domains[j] = server[i].domain[j]; + } + hostPtr->servers[i]->domains[j] = NULL; + + + hostPtr->servers[i]->addrList = (char **) + Calloc(server[i].numAddresses+1,sizeof(char *)); + for (j = 0; j < server[i].numAddresses; j++) { + hostPtr->servers[i]->addrList[j] = server[i].address[j]; + } + hostPtr->servers[i]->addrList[j] = NULL; + + } + hostPtr->servers[i] = NULL; + } + + switch (queryType) { + 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) + struct in_addr *nsAddrPtr; + int queryClass; + int queryType; + char *name; + HostInfo *hostPtr; + Boolean isServer; +{ + int n; + register int result; + register char **domain; + const char *cp; + Boolean got_nodata = FALSE; + struct in_addr 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); + hostPtr->aliases = NULL; + hostPtr->servers = NULL; + hostPtr->addrType = AF_INET; + hostPtr->addrLen = INADDRSZ; + hostPtr->addrList = (char **)Calloc(2, sizeof(char *)); + hostPtr->addrList[0] = Calloc(INT32SZ, sizeof(char)); + memcpy(hostPtr->addrList[0], &ina, INADDRSZ); + hostPtr->addrList[1] = NULL; + 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)); + } + + /* + * 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); + 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) || + (n != 0 && *--cp != '.' && res.options & RES_DNSRCH)) + for (domain = res.dnsrch; *domain; domain++) { + result = GetHostDomain(nsAddrPtr, queryClass, queryType, + name, *domain, hostPtr, isServer); + /* + * 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) + ) == 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. + */ +GetHostDomain(nsAddrPtr, queryClass, queryType, name, domain, hostPtr, isServer) + struct in_addr *nsAddrPtr; + int queryClass; + int queryType; + char *name, *domain; + HostInfo *hostPtr; + Boolean isServer; +{ + querybuf buf; + char nbuf[2*MAXDNAME+2]; + char *longname = nbuf; + int n; + + if (domain == NULL) { + /* + * Check for trailing '.'; + * copy without '.' if present. + */ + n = strlen(name) - 1; + if (name[n] == '.' && n < 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); + + /* + * 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(nsAddrPtr, address, hostPtr) + struct in_addr *nsAddrPtr; + struct in_addr *address; + HostInfo *hostPtr; +{ + int n; + querybuf buf; + char qbuf[MAXDNAME]; + char *p = (char *) &address->s_addr; + + (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", + ((unsigned)p[3] & 0xff), + ((unsigned)p[2] & 0xff), + ((unsigned)p[1] & 0xff), + ((unsigned)p[0] & 0xff)); + 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); + if (n == SUCCESS) { + hostPtr->addrType = AF_INET; + hostPtr->addrLen = 4; + hostPtr->addrList = (char **)Calloc(2, sizeof(char *)); + hostPtr->addrList[0] = Calloc(INT32SZ, sizeof(char)); + memcpy(hostPtr->addrList[0], p, INADDRSZ); + 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]); + 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]); + 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.2.3.t5b/contrib/bind/bin/nslookup/getinfo.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/res.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/res.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/res.h (revision 60942) @@ -0,0 +1,188 @@ +/* + * ++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.5 1998/09/16 17:03:17 vixie 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. + * + */ + +#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 { + char *name; /* official name of host */ + char **domains; /* domains it serves */ + char **addrList; /* list of addresses from name server */ +} ServerInfo; + +typedef struct { + char *name; /* official name of host */ + char **aliases; /* alias list */ + char **addrList; /* list of addresses from name server */ + int addrType; /* host address type */ + int addrLen; /* length of address */ + 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 */ +extern Boolean IsAddr(); +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 ShowOptions(); +extern void FreeHostInfoPtr(); +extern FILE *OpenFile(); +extern char *res_skip(); Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/res.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/send.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/send.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/send.c (revision 60942) @@ -0,0 +1,402 @@ +/* + * 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.9 1999/10/13 16:39:19 vixie 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 "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(struct in_addr *nsAddrPtr, const u_char *buf, int buflen, + u_char *answer, u_int anslen, int *trueLenPtr) +{ + int n, try, v_circuit, resplen, 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 = (HEADER *) buf; + HEADER *anhp = (HEADER *) answer; + struct iovec iov[2]; + int terrno = ETIMEDOUT; + char junk[512]; + struct sockaddr_in sin, sa; + + if (res.options & RES_DEBUG2) { + printf("------------\nSendRequest(), len %d\n", buflen); + Print_query(buf, buf + buflen, 1); + } + sin.sin_family = AF_INET; + sin.sin_port = htons(nsport); + sin.sin_addr = *nsAddrPtr; + 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(AF_INET, SOCK_STREAM, 0); + if (s < 0) { + terrno = errno; + if (res.options & RES_DEBUG) + perror("socket (vc) failed"); + continue; + } + if (connect(s, (struct sockaddr *)&sin, + sizeof(struct sockaddr)) < 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; + iov[1].iov_base = (caddr_t)buf; + 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)) > 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(AF_INET, 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 *)&sin, + sizeof sin) < 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 *) &sin, + sizeof sin) != 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() +{ + if (s != -1) { + (void) close(s); + s = -1; + } +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/send.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/skip.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/skip.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/skip.c (revision 60942) @@ -0,0 +1,218 @@ +/* + * 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.5 1999/10/13 16:39:20 vixie 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" + +char *res_skip_rr(); + + +/* + ******************************************************************************* + * + * 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. + * + ******************************************************************************* + */ + +char * +res_skip(msg, numFieldsToSkip, eom) + char *msg; + int numFieldsToSkip; + char *eom; +{ + register 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((u_char *)cp, (u_char *)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. + ******************************************************************************* + */ + +char * +res_skip_rr(cp, eom) + char *cp; + char *eom; +{ + int tmp; + int dlen; + + if ((tmp = dn_skipname((u_char *)cp, (u_char *)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((u_char*)cp); + cp += INT16SZ; /* dlen */ + cp += dlen; + if (cp > eom) + return (NULL); + return (cp); +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/skip.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/subr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/subr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/subr.c (revision 60942) @@ -0,0 +1,591 @@ +/* + * 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.13 1999/10/13 16:39:20 vixie 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 "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() +{ + 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); + + 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; + char *title; + register HostInfo *hp; +{ + register char **cp; + register ServerInfo **sp; + char comma; + int i; + + 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 (cp = hp->addrList; cp && *cp; cp++) { + i++; + if (i > 4) { + fprintf(file, "\n\t"); + comma = ' '; + i = 0; + } + fprintf(file,"%c %s", comma, inet_ntoa(*(struct in_addr *)*cp)); + 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 (cp = (*sp)->addrList; cp && *cp && **cp; cp++) { + i++; + if (i > 4) { + fprintf(file, "\n\t"); + comma = ' '; + i = 0; + } + fprintf(file, + "%c %s", comma, inet_ntoa(*(struct in_addr *)*cp)); + 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" }, + { FORMERR, "Format error" }, + { SERVFAIL, "Server failed" }, + { NXDOMAIN, "Non-existent host/domain" }, + { NOTIMP, "Not implemented" }, + { REFUSED, "Query refused" }, +#ifdef NOCHANGE + { NOCHANGE, "No change" }, +#endif + { TIME_OUT, "Timed out" }, + { NO_INFO, "No information" }, + { ERROR, "Unspecified error" }, + { NONAUTH, "Non-authoritative answer" }, + { NO_RESPONSE, "No response from server" }, + { 0, 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.2.3.t5b/contrib/bind/bin/nslookup/subr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/pathnames.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/pathnames.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/nslookup/pathnames.h (revision 60942) @@ -0,0 +1,71 @@ +/* + * ++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.1 1994/12/15 06:24:31 vixie Exp $ + */ + +#define _PATH_NSLOOKUPRC "/.nslookuprc" +#define _PATH_PAGERCMD "more" + +#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.2.3.t5b/contrib/bind/bin/nslookup/pathnames.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/dig/dig.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/dig/dig.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/dig/dig.c (revision 60942) @@ -0,0 +1,1656 @@ +#ifndef lint +static const char rcsid[] = "$Id: dig.c,v 8.41 2000/04/20 07:36:04 vixie 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 "../nslookup/res.h" + +/* Global. */ + +#define VERSION 83 +#define VSTRING "8.3" + +#define PRF_DEF 0x2ff9 +#define PRF_MIN 0xA930 +#define PRF_ZONE 0x24f9 + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif + +#define SAVEENV "DiG.env" +#define DIG_MAXARGS 30 + +static int eecode = 0; +static FILE * qfp; +static int sockFD; +static char *defsrv, *srvmsg; +static char defbuf[40] = "default -- "; +static char srvbuf[60]; +static char myhostname[MAXHOSTNAMELEN]; +static struct sockaddr_in myaddress; +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) { } +#endif +char *pager = NULL; +/* end of nslookup stuff */ + +/* Forward. */ + +static void Usage(void); +static int SetOption(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 **); + +/* Public. */ + +int +main(int argc, char **argv) { + struct hostent *hp; + short port = htons(NAMESERVER_PORT); + /* 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], *msgptr; + char **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; + char *pp; + + 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*/; + 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 == '+') { + SetOption(*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': + wait = atoi(*++argv); + break; + case 'c': + 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 ((tmp = atoi(*++argv)) + || *argv[0]=='0') { + queryType = tmp; + qtypeSet++; + } else if ((tmp = StringToType(*argv, + 0, NULL) + ) != 0) { + queryType = tmp; + qtypeSet++; + } else { + printf( + "; invalid type specified\n" + ); + } + break; + case 'x': + if (!qtypeSet) { + queryType = T_ANY; + qtypeSet++; + } + if (!(addrc = *++argv)) { + printf( + "; no arg for -x?\n" + ); + 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 = ntohs(atoi(argv[0]+2)); + 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 + res.ndots = atoi(*++argv); + break; + case 'b': { + char *a, *p; + + if (argv[0][2] != '\0') + a = argv[0]+2; + else + a = *++argv; + if ((p = strchr(a, ':')) != NULL) { + *p++ = '\0'; + myaddress.sin_port = + ntohs(atoi(p)); + } + if (!inet_aton(a,&myaddress.sin_addr)){ + fprintf(stderr, + ";; bad -b addr\n"); + exit(1); + } + } + break; + case 'k': + /* -k keydir:keyname */ + + if (argv[0][2] != '\0') + keyfile = argv[0]+2; + 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) { + struct in_addr addr; + + if (inet_aton(srv, &addr)) { + res.nscount = 1; + res.nsaddr.sin_addr = addr; + srvmsg = strcat(srvbuf, srv); + } else { + res_t = res; + res_ninit(&res); + res.pfcode = 0; + res.options = RES_DEFAULT; + hp = gethostbyname(srv); + res = res_t; + if (hp == NULL + || hp->h_addr_list == NULL + || *hp->h_addr_list == NULL) { + fflush(stdout); + fprintf(stderr, + "; Bad server: %s -- using default server and timer opts\n", + srv); + fflush(stderr); + srvmsg = defsrv; + srv = NULL; + } else { + u_int32_t **addr; + + res.nscount = 0; + for (addr = (u_int32_t**)hp->h_addr_list; + *addr && (res.nscount < MAXNS); + addr++) { + res.nsaddr_list[ + res.nscount++ + ].sin_addr.s_addr = **addr; + } + + srvmsg = strcat(srvbuf,srv); + strcat(srvbuf, " "); + strcat(srvmsg, + inet_ntoa(res.nsaddr.sin_addr)); + } + } + printf("; (%d server%s found)\n", + res.nscount, (res.nscount==1)?"":"s"); + res.id += res.retry; + } + + { + int i; + + for (i = 0; i < res.nscount; i++) { + res.nsaddr_list[i].sin_family = AF_INET; + res.nsaddr_list[i].sin_port = port; + } + res.id += res.retry; + } + + if (ns_t_xfr_p(xfr)) { + int i; + + for (i = 0; i < res.nscount; i++) { + int x; + + if (keyfile) + x = printZone(xfr, domain, + &res.nsaddr_list[i], + &key); + else + x = printZone(xfr, domain, + &res.nsaddr_list[i], + NULL); + if (res.pfcode & RES_PRF_STATS) { + exectime = time(NULL); + printf(";; FROM: %s to SERVER: %s\n", + myhostname, + inet_ntoa(res.nsaddr_list[i] + .sin_addr)); + 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"); + 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; + }; + + 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) { + time_t t; + + 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); + } + } + 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\n\ + [no]ttlid [no]cl [no]qr [no]reply [no]ques [no]answer\n\ + [no]author [no]addit pfdef pfmin 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.41 2000/04/20 07:36:04 vixie Exp $\n\ +", stderr); +} + +static int +SetOption(const char *string) { + char option[NAME_LEN], type[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, "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, "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; + HEADER *headerPtr; + int msglen, amtToRead, numRead, result = 0, sockFD, len; + int count, type, class, rlen, done, n; + int numAnswers = 0, numRecords = 0, soacnt = 0; + u_char *cp, tmp[NS_INT16SZ]; + char dname[2][NS_MAXDNAME], file[NAME_LEN]; + enum { NO_ERRORS, ERR_READING_LEN, ERR_READING_MSG, ERR_PRINTING } + error = NO_ERRORS; + pid_t zpid; + 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); + } + 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, (struct sockaddr *)sin, sizeof *sin) < 0) { + int e = errno; + + perror(";; connect"); + (void) close(sockFD); + sockFD = -1; + return (e); + } + + /* + * 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); + } + + /* + * 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; + if (key) + free (newmsg); + + perror(";; pipe"); + (void) close(sockFD); + sockFD = -1; + return (e); + } + zpid = vfork(); + if (zpid < 0) { + int e = errno; + if (key) + free (newmsg); + + 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]); + } + + 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", + pid, WEXITSTATUS(status), + WIFSIGNALED(status) ? WTERMSIG(status) : 0, + WCOREDUMP(status) ? 't' : 'f'); + } + + /* XXX This should probably happen sooner than here */ + if (key) + free (newmsg); + + 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); + strcpy(name_ctx, "@"); + } + if (ns_sprintrr(&handle, &rr, name_ctx, origin, + 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; + } + } +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/bin/dig/dig.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/dig/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/dig/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/dig/Makefile (revision 60942) @@ -0,0 +1,88 @@ +## 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.25 1999/08/08 17:51:01 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +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} -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.2.3.t5b/contrib/bind/bin/dig/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/host/host.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/host/host.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/host/host.c (revision 60942) @@ -0,0 +1,1954 @@ +#ifndef lint +static const char rcsid[] = "$Id: host.c,v 8.36 2000/01/25 00:20:21 cyarnell 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 + +#include "port_after.h" + +/* Global. */ + +#define SIG_RDATA_BY_NAME 18 +#define NS_HEADERDATA_SIZE 10 + +#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 +#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, orig; +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 char getdomain[NS_MAXDNAME]; + +/* Forward. */ + +static int parsetype(const char *s); +static int parseclass(const char *s); +static void printanswer(const struct hostent *hp); +static void hperror(int errnum); +static int addrinfo(struct in_addr 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); +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 in_addr addr; + struct hostent *hp; + char *s; + int inverse = 0, waitmode = 0; + int ncnames, ch; + int nkeychains, i; + + dst_init(); + + if ((progname = strrchr(argv[0], '/')) == 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; + gettype = 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': + gettype = 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 ((gettype == 0) && (sigchase)) { + if (verbose) + printf ("Forcing `-t a' for signature trace.\n"); + gettype = 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) { + s = *argv++; + argc--; + server_specified++; + + if (!inet_aton(s, &addr)) { + hp = gethostbyname(s); + if (hp == NULL) { + fprintf(stderr, + "Error in looking up server name:\n"); + hperror(res.res_h_errno); + exit(1); + } + memcpy(&res.nsaddr.sin_addr, hp->h_addr, NS_INADDRSZ); + printf("Using domain server:\n"); + printanswer(hp); + } else { + res.nsaddr.sin_family = AF_INET; + res.nsaddr.sin_addr = addr; + res.nsaddr.sin_port = htons(NAMESERVER_PORT); + printf("Using domain server %s:\n", + inet_ntoa(res.nsaddr.sin_addr)); + } + res.nscount = 1; + res.retry = 2; + } + if (strcmp(getdomain, ".") == 0 || !inet_aton(getdomain, &addr)) + addr.s_addr = INADDR_NONE; + hp = NULL; + res.res_h_errno = TRY_AGAIN; +/* + * We handle default domains ourselves, thank you. + */ + res.options &= ~RES_DEFNAMES; + + if (list) + exit(ListHosts(getdomain, gettype ? gettype : ns_t_a)); + ncnames = 5; nkeychains = 18; + while (hp == NULL && res.res_h_errno == TRY_AGAIN) { + if (addr.s_addr == INADDR_NONE) { + 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, "."); + gettype = ns_t_key; + } else if (!(chase_step & SD_BADSIG)) { + /* start new query, for SIG */ + strcpy (getdomain, chase_domain); + strcat (getdomain, "."); + gettype = 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_domain, + chase_lastgoodkey ? 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 +printanswer(const struct hostent *hp) { + struct in_addr **hptr; + char **cp; + + printf("Name: %s\n", hp->h_name); + printf("Address:"); + for (hptr = (struct in_addr **)hp->h_addr_list; *hptr; hptr++) + printf(" %s", inet_ntoa(**hptr)); + printf("\nAliases:"); + for (cp = hp->h_aliases; cp && *cp && **cp; cp++) + printf(" %s", *cp); + printf("\n\n"); +} + +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 in_addr addr) { + u_int32_t ha = ntohl(addr.s_addr); + char name[NS_MAXDNAME]; + + sprintf(name, "%u.%u.%u.%u.IN-ADDR.ARPA.", + (ha) & 0xff, + (ha >> 8) & 0xff, + (ha >> 16) & 0xff, + (ha >> 24) & 0xff); + return (getinfo(name, NULL, ns_t_ptr)); +} + +static int +gethostinfo(char *name) { + char *cp, **domain; + char tmp[NS_MAXDNAME]; + const char *tp; + int hp, nDomain; + 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; + + if (gettype) + return (getinfo(name, domain, gettype)); + else { + val1 = getinfo(name, domain, gettype=ns_t_a); + if (cname || verbose) + return (val1); + val2 = getinfo(name, domain, gettype=ns_t_mx); + return (val1 || val2); + } +} + +static int +getinfo(const char *name, const char *domain, int type) { + HEADER *hp; + u_char *eom, *bp, *cp; + querybuf buf, answer; + int n, n1, i, j, nmx, ancount, nscount, arcount, qdcount, buflen; + u_short pref, class; + char host[NS_MAXDNAME]; + + if (domain == NULL) + 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)); +} + +static int +printinfo(const querybuf *answer, const u_char *eom, int filter, int isls) { + int n, n1, i, j, nmx, ancount, nscount, arcount, qdcount, buflen, savesigchase; + u_short pref, class; + const u_char *bp, *cp; + const HEADER *hp; + + /* + * Find first satisfactory answer. + */ + hp = (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); + } + 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 = (u_char *)pr_rr(cp, answer->qb2, stdout, filter); + } + if (arcount) { + printf("Additional information:\n"); + while (--arcount >= 0 && cp && cp < eom) + cp = (u_char *)pr_rr(cp, answer->qb2, stdout, filter); + } + + /* restore sigchase value */ + + sigchase = savesigchase; + + return (1); +} + +void print_hex_field (u_int8_t field[], int length, int width, 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 = (u_char *)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 = (u_char *)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 = (u_char *)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%ld\t;serial (version)", + ns_get32(cp)); + cp += INT32SZ; + if (doprint) + fprintf(file, "\n\t\t\t%ld\t;refresh period", + ns_get32(cp)); + cp += INT32SZ; + if (doprint) + fprintf(file, + "\n\t\t\t%ld\t;retry refresh this often", + ns_get32(cp)); + cp += INT32SZ; + if (doprint) + fprintf(file, "\n\t\t\t%ld\t;expiration period", + ns_get32(cp)); + cp += INT32SZ; + if (doprint) + fprintf(file, "\n\t\t\t%ld\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 = (u_char *)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 = (u_char *)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 = (u_char *)pr_cdname(cp, msg, name, sizeof(name)); + if (doprint) + fprintf(file, "%s", name); + break; + + case ns_t_minfo: + case ns_t_rp: + cp = (u_char *)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 = (u_char *)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 = (u_char *) 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, " %d", ns_get32(cp)); + cp += INT32SZ; + /* signature expiration */ + if (doprint && verbose) + fprintf(file, " %d", ns_get32(cp)); + cp += INT32SZ; + /* time signed */ + if (doprint && verbose) + fprintf(file, " %d", ns_get32(cp)); + cp += INT32SZ; + /* key footprint */ + if (doprint && verbose) + fprintf(file, " %d", ns_get16(cp)); + cp += sizeof(u_short); + /* signer's name */ + cp = (u_char *)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; i < 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) { + 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)", sigchase-1); + + /* 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: + 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 int +ListHosts(char *namePtr, int queryType) { + querybuf buf, answer; + struct sockaddr_in sin; + const HEADER *headerPtr; + const struct hostent *hp; + 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]; + struct in_addr nsipaddr[NUMNSADDR]; + int numns, numnsaddr, thisns; + + /* + * 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) { + memcpy(&nsipaddr[0], &res.nsaddr.sin_addr, NS_INADDRSZ); + numnsaddr = 1; + } 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; + if (ntohs(answer.qb1.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) { + if (numnsaddr < NUMNSADDR) + for (i = 0; i < numns; i++) { + if (ns_samename(nsname[i], + (char *)domain) + == 1) { + nshaveaddr[i]++; + memcpy( + &nsipaddr[numnsaddr], + cp, NS_INADDRSZ); + numnsaddr++; + 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++) { + if (nshaveaddr[i] == 0) { + struct in_addr **hptr; + int numaddrs = 0; + + hp = gethostbyname(nsname[i]); + if (hp) { + for (hptr = (struct in_addr **) + hp->h_addr_list; + *hptr != NULL; + hptr++) + if (numnsaddr < NUMNSADDR) { + memcpy( + &nsipaddr[numnsaddr], + *hptr, NS_INADDRSZ); + numnsaddr++; + numaddrs++; + } + } + if (res.options & RES_DEBUG || verbose) + printf( + "Found %d addresses for %s by extra query\n", + numaddrs, nsname[i]); + } 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(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("ListHosts"); + return (ERROR); + } + memcpy(&sin.sin_addr, &nsipaddr[thisns], NS_INADDRSZ); + if (res.options & RES_DEBUG || verbose) + printf("Trying %s\n", inet_ntoa(sin.sin_addr)); + if (connect(sockFD, (struct sockaddr *)&sin, sizeof(sin)) >= 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); + if (! result) { + error = ERR_PRINTING; + break; + } + numAnswers++; + cp = buf.qb2 + HFIXEDSZ; + if (ntohs(buf.qb1.qdcount) > 0) { + n = dn_skipname(cp, buf.qb2 + len); + if (n < 0) { + error = ERR_PRINTING; + break; + } + cp += n + QFIXEDSZ; + } + 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; + } + if ((ns_get16(cp) == 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) + break; + } else + soacnt++; + } + } + + (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.2.3.t5b/contrib/bind/bin/host/host.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/host/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/host/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/host/Makefile (revision 60942) @@ -0,0 +1,84 @@ +## 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 1999/08/08 17:51:01 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +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} -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.2.3.t5b/contrib/bind/bin/host/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/irpd/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/irpd/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/irpd/Makefile (revision 60942) @@ -0,0 +1,98 @@ +## 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.4 2000/05/09 07:02:22 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +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} -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} + +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.2.3.t5b/contrib/bind/bin/irpd/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/irpd/irpd.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/irpd/irpd.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/irpd/irpd.c (revision 60942) @@ -0,0 +1,2259 @@ +/* + * 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.8 2000/02/04 08:28:27 vixie 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) { \ + 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 int is_all_digits(char *p); +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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, void *respctx, void *uctx); + +static void irpd_done(struct ctl_sctx *ctx, struct ctl_sess *sess, + void *param); +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 }, + { "gethostbyname2", irpd_gethostbyname2 }, + { "gethostbyaddr", irpd_gethostbyaddr }, + { "gethostent", irpd_gethostent }, + { "sethostent", irpd_sethostent }, +#ifdef WANT_IRS_PW + { "getpwnam", irpd_getpwnam }, + { "getpwuid", irpd_getpwuid }, + { "getpwent", irpd_getpwent }, + { "setpwent", irpd_setpwent }, +#endif + { "getnetbyname", irpd_getnetbyname }, + { "getnetbyaddr", irpd_getnetbyaddr }, + { "getnetent", irpd_getnetent }, + { "setnetent", irpd_setnetent }, +#ifdef WANT_IRS_GR + { "getgrnam", irpd_getgrnam }, + { "getgrgid", irpd_getgrgid }, + { "getgrent", irpd_getgrent }, + { "setgrent", irpd_setgrent }, +#endif + { "getservbyname", irpd_getservbyname }, + { "getservbyport", irpd_getservbyport }, + { "getservent", irpd_getservent }, + { "setservent", irpd_setservent }, + + { "getprotobyname", irpd_getprotobyname }, + { "getprotobynumber", irpd_getprotobynumber }, + { "getprotoent", irpd_getprotoent }, + { "setprotoent", irpd_setprotoent }, + + { "getnetgrent", irpd_getnetgrent }, + { "innetgr", irpd_innetgr }, + { "setnetgrent", irpd_setnetgrent }, + { "endnetgrent", irpd_endnetgrent }, + { "quit", irpd_quit }, + { "help", irpd_help }, + + { "", irpd_accept }, /* 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 } +}; + +/* + * An empty string causes the library to use the compiled in + * defaults and to ignore any external files. + */ +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; + log_channel chan; + short port = IRPD_PORT; + char *prog = argv[0]; + char *sockname = IRPD_PATH; + char *p; + int ch; + size_t socksize; + + addr = (struct sockaddr *)&iaddr; + socksize = sizeof iaddr; + + openlog("iprd", LOG_CONS|LOG_PID, LOG_DAEMON); + 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, char *msg); + * Send back a simple, one-line response to the client. + */ +static void +simple_response(struct ctl_sess *sess, u_int code, 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 { + size_t need; + 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, 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, void *respctx, void *uctx) +{ + char hname[MAXHOSTNAMELEN]; + struct arg_s *args; + int i; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + char hname[MAXHOSTNAMELEN]; + struct arg_s *args; + int i; + int af; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct hostent *ho; + char haddr[MAXHOSTNAMELEN]; + char tmpaddr[NS_IN6ADDRSZ]; + struct arg_s *args; + int i; + int af; + int addrlen; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct hostent *ho; + size_t need; + size_t need_total = 0; + struct response_buff *b; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct hostent *ho; + size_t need; + size_t need_total = 0; + struct response_buff *b; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct arg_s *args; + struct passwd *pw; + char username[64]; + struct response_buff *b; + size_t need; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct arg_s *args; + struct passwd *pw; + char userid[64]; + struct response_buff *b; + size_t need; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct passwd *pw; + size_t need; + size_t need_total = 0; + struct response_buff *b; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct passwd *pw; + size_t need; + size_t need_total = 0; + struct response_buff *b; + struct net_data *netdata = get_net_data(sess); + + 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 + * send_netent(struct ctl_sess *sess, struct netent *ne); + * Sends a NETENT structure over the wire, or "No such + * Network" error if NE is NULL. + */ +static void +send_netent(struct ctl_sess *sess, struct netent *ne) { + if (ne == NULL) { + simple_response(sess, IRPD_GETNET_NONE, "No such net"); + } else { + struct response_buff *b = newbuffer(0); + + if (irp_marshall_ne(ne, &b->buff, + &b->bufflen) != 0) { + simple_response(sess, IRPD_GETNET_ERROR, + "Internal error"); + logger(ctl_warning, "Cant marshall ne\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, 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, void *respctx, void *uctx) +{ + struct arg_s *args; + struct netent *ne; + struct nwent *nw; + char netname[MAXNETNAMELEN]; + struct response_buff *b; + size_t need; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct netent *ne; + struct nwent *nw; + char haddr[MAXHOSTNAMELEN]; + long tmpaddr; + struct arg_s *args; + int i; + int af; + int addrlen; + int bits; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct netent *ne; + struct nwent *nw; + size_t need; + size_t need_total = 0; + struct response_buff *b; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct netent *ne; + struct nwent *nw; + size_t need; + size_t need_total = 0; + struct response_buff *b; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct arg_s *args; + struct group *gr; + char groupname[64]; + struct response_buff *b; + size_t need; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct arg_s *args; + struct group *gr; + char groupid[64]; + struct response_buff *b; + size_t need; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct group *gr; + size_t need; + size_t need_total = 0; + struct response_buff *b; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct group *gr; + size_t need; + size_t need_total = 0; + struct response_buff *b; + struct net_data *netdata = get_net_data(sess); + + 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, void *respctx, void *uctx) +{ + struct arg_s *args; + struct servent *serv; + char servicename[64]; + char protoname[10]; + struct response_buff *b; + size_t need; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct arg_s *args; + struct servent *sv; + char portnum[64]; + char protoname[10]; + struct response_buff *b; + size_t need; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct servent *sv; + size_t need; + size_t need_total = 0; + struct response_buff *b; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct servent *sv; + size_t need; + size_t need_total = 0; + struct response_buff *b; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct arg_s *args; + struct protoent *pr; + char protoname[64]; + struct response_buff *b; + size_t need; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct arg_s *args; + struct protoent *pr; + char protonum[64]; + struct response_buff *b; + size_t need; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct protoent *pr; + size_t need; + size_t need_total = 0; + struct response_buff *b; + struct net_data *netdata = get_net_data(sess); + + 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, 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, void *respctx, void *uctx) +{ + struct protoent *pr; + size_t need; + size_t need_total = 0; + struct response_buff *b; + struct net_data *netdata = get_net_data(sess); + + 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, char *host, char *user, 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, 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, void *respctx, void *uctx) +{ + char netgroupname[64]; + struct response_buff *b = NULL; + size_t need; + struct net_data *netdata = get_net_data(sess); + + 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 { + 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, 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, void *respctx, void *uctx) +{ + struct arg_s *args; + struct response_buff *b; + size_t need; + struct net_data *netdata = get_net_data(sess); + char *host; + char *user; + char *domain; + + 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); + } + + untimely: + 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, 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, void *respctx, void *uctx) +{ + struct arg_s *args; + struct net_data *netdata = get_net_data(sess); + + 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"); + } + + untimely: + 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, 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, void *respctx, void *uctx) +{ + struct arg_s *args; + struct net_data *netdata = get_net_data(sess); + + 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_done(struct ctl_sctx *ctx, struct ctl_sess *sess, void *param) + * Callback for when QUIT respnse is sent out. + */ +static void +irpd_done(struct ctl_sctx *ctx, struct ctl_sess *sess, void *param) { + struct net_data *netdata = get_net_data(sess); + + INSIST(netdata != NULL); + + net_data_destroy(netdata); +} + +/* + * static void + * irpd_quit(struct ctl_sctx *ctx, struct ctl_sess *sess, + * const struct ctl_verb *verb, const char *rest, + * u_int respflags, 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, void *respctx, void *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, 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, void *respctx, void *uctx) +{ + /* XXX should make this do something better (like include required + * arguments. + */ + 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, 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, void *respctx, void *uctx) +{ + struct sockaddr *sa = respctx; + char raddr[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; + int reject = 1; + int response; + char *respmsg = NULL; + + if (sa->sa_family == AF_UNIX) { + syslog (LOG_INFO, "New AF_UNIX connection"); + reject = 0; + } else if (sa->sa_family == AF_INET) { + struct sockaddr_in *sin = respctx; + static long localhost; + static 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, 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, void *respctx, void *uctx) +{ + struct net_data *netdata = get_net_data(sess); + + 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) { + 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) > (sizeof (buffer) - 1)) { + syslog(LOG_CRIT, "Buffer overrun in logger"); + 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; + + iovs[c].iov_base = (void *)p; + + 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 void +release_cli_ctx(struct client_ctx *ctx) { + INSIST(ctx != NULL); + INSIST(ctx->net_data != NULL); + + net_data_destroy(ctx->net_data); + memput(ctx, sizeof *ctx); +} + +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.2.3.t5b/contrib/bind/bin/irpd/irpd.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/irpd/irs-irpd.conf =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/irpd/irs-irpd.conf (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/irpd/irs-irpd.conf (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/irpd/version.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/irpd/version.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/irpd/version.c (revision 60942) @@ -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.2.3.t5b/contrib/bind/bin/irpd/version.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/named-xfer/named-xfer.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named-xfer/named-xfer.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named-xfer/named-xfer.c (revision 60942) @@ -0,0 +1,3195 @@ +/* + * 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.93 2000/04/20 07:33:47 vixie 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 +/* This still uses malloc/free, but the tsig routines allocate memory with + * memget, and we free it with memput. + */ +#include + +#include + +#include "port_after.h" + + +#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 *), + 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, + char *domain, 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, LOG_DAEMON); + 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); +} + +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; + u_int32_t new_serial_no = 0; + int dbfd, ddtd, result, c, fd, ixfd; + 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; + long num_files; + +#ifdef _AUX_SOURCE + set42sig(); +#endif + memset(&axfr_src, 0, sizeof axfr_src); + ProgName = strrchr(argv[0], '/'); + 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, LOG_DAEMON); +#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)); + exit(XFER_FAIL); + } + if ((dbfp = fdopen(dbfd, "r+")) == NULL) { + perror(tmpname); + if (!quiet) + syslog(LOG_ERR, "can't fdopen tmpfile (%s)", 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); + debug = 0; + } else if ((ddt = fdopen(ddtd, "w")) == NULL) { + perror(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); + + buildservicelist(); + buildprotolist(); + + tsig_init(tsigfile); + + /* 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 (movefile(tmpname, ixfrfile) == -1) { + perror("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 (movefile(tmpname, dbfile) == -1) { + perror("movefile"); + if (!quiet) + syslog(LOG_ERR, "movefile %s to %s: %m", + tmpname, dbfile); + cleanup_for_exit(); + exit(XFER_FAIL); + } + exit(XFER_SUCCESSAXFR); + + case XFER_SUCCESSIXFR: + unlink(tmpname); + if (movefile(tmpiname, ixfrfile) == -1) { + perror("movefile"); + if (!quiet) + syslog(LOG_ERR, "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_TIMEOUT: + case XFER_FAIL: + (void) unlink(tmpname); + cleanup_for_exit(); + exit(result); /* error or timeout */ + } + /*NOTREACHED*/ + return (0); /* Make gcc happy. */ +} + +static 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) { + char * const *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 void +tsig_init(const char *file) { + char buf[1024]; + int n; + FILE *fp; + char *s; + + if (file == NULL) + return; + fp = fopen(file, "r"); + if (fp == NULL) + return; + dst_init(); + INIT_LIST(tsig_list); + while (1) { + tsig_node *n = malloc(sizeof(tsig_node)); + int alg, secret_len; + char *address, *name; + char *cp; + u_char secret[128]; + + 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); + + 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); + APPEND(tsig_list, n, link); + } + fclose(fp); + unlink(file); +} + +#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; +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 */ + +static int +getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { + HEADER *hp; + u_int len; + u_int32_t serial; + int s, n, l, error = 0; + int was_ixfr = 0; + u_int cnt; + u_char *cp, *nmp, *eom, *tmp ; + u_char *buf = NULL, *cpp = NULL; + u_char *bp; + u_int bufsize = 0; + char name[MAXDNAME], name2[MAXDNAME]; + struct sockaddr_in sin; + struct sockaddr_in local; + int locallen; +#ifdef POSIX_SIGNALS + struct sigaction sv, osv; +#else + struct sigvec sv, osv; +#endif + int qdcount, ancount, aucount, arcount, class, type; + int first_serial; + const char *badsoa_msg = "Nil"; + struct sockaddr_in my_addr; + char my_addr_text[30]; + int alen, ret, tsig_req; + DST_KEY *tsig_key; + ns_tcp_tsig_state tsig_state; + int tsig_signed = 0; + u_char sig[64]; + int siglen; + int ixfr_first = 1; + int loop_cnt = 0; + time_t timesigned; + u_int32_t query_serial = serial_no; + +#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,"secondary\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; + if (buf == NULL) { + if ((buf = (u_char *)malloc(2 * PACKETSZ)) == NULL) { + syslog(LOG_INFO, "malloc(%u) failed", + 2 * PACKETSZ); + error++; + break; + } + bufsize = 2 * PACKETSZ; + } + try_again: + if ((s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) { + syslog(LOG_INFO, "socket: %m"); + error++; + break; + } + if (zp->z_axfr_src.s_addr != 0) { + memset(&sin, 0, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_port = 0; /* "ANY" */ + sin.sin_addr = zp->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 (zp->z_axfr_src.s_addr != 0) { + dprintf(2, "connect failed, trying w/o -x"); + zp->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; + } + if (methode == ISIXFR && was_ixfr == 0) { + hp = (HEADER *) buf; + cpp = buf; + n = res_nmkquery(&res, QUERY, zp->z_origin, curclass, + T_IXFR, NULL, 0, NULL, buf, bufsize); + dprintf(1, "len = %d\n", n); + if (n < 0) { + if (!quiet) + syslog(LOG_INFO, + "zone %s: dn_comp for ixfr failed", + zp->z_origin); + (void) my_close(s); +#ifdef POSIX_SIGNALS + sigaction(SIGALRM, + &osv, + (struct sigaction*)0); +#else + sigvec(SIGALRM, + &osv, + (struct sigvec *)0); +#endif + return (XFER_FAIL); + } + hp->nscount = htons(1+ntohs(hp->nscount)); + cpp += n; + n = dn_comp(zp->z_origin, cpp, bufsize-(cpp-buf), + NULL, NULL); + if (n > 0) + 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(serial_no, cpp); + PUTLONG(0xDEAD, cpp); /* Refresh */ + PUTLONG(0xBEEF, cpp); /* Retry */ + PUTLONG(0xABCD, cpp); /* Expire */ + PUTLONG(0x1776, cpp); /* Min TTL */ + n = cpp-buf; + dprintf(1, "len = %d\n", cpp-buf); + if (debug) + res_pquery(&res, buf, n, ddt); + } + else { + n = res_nmkquery(&res, QUERY, zp->z_origin, curclass, + T_SOA, NULL, 0, NULL, buf, bufsize); + if (n < 0) { + if (!quiet) + syslog(LOG_INFO, + "zone %s: res_nmkquery T_SOA failed", + zp->z_origin); + (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); + } + } + /* + * Append TSIG to SOA query if desired + */ + tsig_key = tsig_key_from_addr(sin.sin_addr); + if (tsig_key != NULL) { + siglen = sizeof(sig); + ret = ns_sign(buf, &n, bufsize, NOERROR, tsig_key, + NULL, 0, sig, &siglen, timesigned); + if (ret == 0) + tsig_signed = 1; + } + + /* + * Send length & message for SOA query + */ + if (writemsg(s, buf, n) < 0) { + syslog(LOG_INFO, "writemsg: %m"); + error++; + (void) my_close(s); + continue; + } + /* + * Get out your butterfly net and catch the SOA + */ + + if (netread(s, (char *)buf, INT16SZ, + (soa_cnt == 0) ?400 :XFER_TIMER) < 0) { + (void) my_close(s); + error++; + continue; + } + if ((len = ns_get16(buf)) == 0) { + (void) my_close(s); + continue; + } + if (len > bufsize) { + if ((buf = (u_char *)realloc(buf, len)) == NULL) { + syslog(LOG_INFO, + "malloc(%u) failed for SOA from server [%s], zone %s\n", + len, + inet_ntoa(sin.sin_addr), + zp->z_origin); + (void) my_close(s); + continue; + } + bufsize = len; + } + if (netread(s, (char *)buf, len, XFER_TIMER) < 0) { + error++; + (void) my_close(s); + continue; + } + /* + * Verify the TSIG if expected + */ + if (tsig_signed != 0) { + ret = ns_verify(buf, (int *)&len, tsig_key, sig, siglen, + NULL, NULL, ×igned, 0); + if (ret != 0) { + syslog(LOG_NOTICE, + "SOA TSIG verification from server [%s], zone %s: %s (%d)\n", + inet_ntoa(sin.sin_addr), zp->z_origin, + tsig_rcode(ret), ret); + error++; + continue; + } + } + +#ifdef DEBUG + if (debug >= 3) { + (void)fprintf(ddt,"len = %d\n", len); + res_pquery(&res, buf, len, ddt); + } +#endif + if (((methode == ISIXFR) && (ixfp == NULL)) && was_ixfr == 0) { + delete_soa = 1; + ixfr_soa = 0; + if ((ixfp = fopen(tmpiname, "w+")) == NULL) { + perror(tmpiname); + if (!quiet) + syslog(LOG_ERR, + "can't fdopen 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 || !hp->aa || qdcount != 1 || + (ancount < 1 && aucount < 1)) { +#ifndef SYSLOG_42BSD + syslog(LOG_NOTICE, + "[%s] %s for %s, SOA 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 : ".", + 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 SOA from [%s], zone %s: %s", + 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; + do { + u_char *cp4; + u_short type, class, dlen; + u_int32_t ttl; + n = dn_expand(buf, eom, tmp, name2, sizeof name2); + if (n < 0) { + badsoa_msg = "aname error"; + goto badsoa; + } + tmp += n; + + /* 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)) { + bp = tmp; + soa_cnt++; + badsoa_msg = soa_zinfo(&zp_finish, tmp, eom); + if (badsoa_msg) + goto badsoa; + if (ixfp) + if (ixfr_log(buf, len, &delete_soa, ixfp, + &sin, domain, &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 >= ancount) { + tmp = bp; + check_serial = 0; + break; + } + } while (1); + + 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; + } + 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) { + const char *l, *nl, *t; + + if (soa_cnt) { + goto axfr_response; + } + dprintf(1, "need update, serial %u\n", + zp_start.z_serial); + soa_cnt = 0; + hp = (HEADER *) buf; + ns_cnt = 0; + 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); + t = strdup(inet_ntoa(sin.sin_addr)); + fprintf(dbfp, "; from %s:%d (local %s) using %s at %s", + t, ntohs(sin.sin_port), + inet_ntoa(local.sin_addr), + (methode == ISIXFR) ? "IXFR":"AXFR", + ctimel(tt.tv_sec)); + free((void *)t); + 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 = res_nmkquery(&res, QUERY, + zp->z_origin, + curclass, query_type, + NULL, 0, + NULL, buf, bufsize); + syslog(LOG_INFO, + "send %s query %d to %s", + (query_type == T_IXFR) ? "IXFR" : + (query_type == T_AXFR) ? "AXFR" : + (query_type == ns_t_zxfr) ? "ZXFR" : + (query_type == T_SOA) ? "SOA" : "NS", + cnt, inet_ntoa(sin.sin_addr)); + dprintf(1, + "send %s query to %s\n", + (query_type == T_IXFR) ? "IXFR" : + (query_type == T_AXFR) ? "AXFR" : + (query_type == ns_t_zxfr) ? "ZXFR" : + (query_type == T_SOA) ? "SOA" : "NS", + 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, + (query_type == T_SOA) + ? "zone %s: res_nmkquery T_SOA failed" + : "zone %s: res_nmkquery T_NS failed", + 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); + } + cpp = buf + n; + /* + * Append TSIG to AXFR query if desired + */ + if (tsig_signed != 0) { + siglen = sizeof(sig); + ns_sign(buf, &n, bufsize, + NOERROR, tsig_key, + NULL, 0, sig, &siglen, + timesigned); + cpp = buf + n; + ns_verify_tcp_init(tsig_key, + sig, siglen, + &tsig_state); + } + /* + * Send length & msg for zone transfer + */ + if (writemsg(s, buf, cpp - buf) < 0) { + syslog(LOG_INFO, + "writemsg: %m"); + error++; + (void) my_close(s); + break; + } + } +/*XXX ZXFR*/ +receive: + /* + * Receive length & response + */ + if (netread(s, (char *)buf, INT16SZ, + (soa_cnt == 0) ?300 :XFER_TIMER) + < 0) { + error++; + break; + } + if ((len = ns_get16(buf)) == 0) + break; + if (len > bufsize) { + buf = (u_char *)realloc(buf, len); + if (buf == NULL) { + syslog(LOG_INFO, + "malloc(%u) failed for packet from server [%s], zone %s\n", + len, + inet_ntoa(sin.sin_addr), + zp->z_origin); + error++; + break; + } + bufsize = len; + } + hp = (HEADER *)buf; + eom = buf + len; + if (netread(s, (char *)buf, len, XFER_TIMER) + < 0) { + error++; + break; + } +#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 + /* + * Verify the TSIG if expected + */ + if (tsig_signed != 0) { + tsig_req = (soa_cnt == 0); + ret = ns_verify_tcp(buf, (int *)&len, + &tsig_state, + tsig_req); + eom = buf + len; + + if (ret != 0) { + syslog(LOG_NOTICE, + "TSIG verification from server [%s], zone %s: %s (%d)\n", + inet_ntoa(sin.sin_addr), + zp->z_origin, + tsig_rcode(ret), ret); + error++; + break; + } + } + 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 ((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); + } 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, + was_ixfr); + 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, + was_ixfr); + 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, + was_ixfr); + 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) { + if (ixfr_log(buf, len, + &delete_soa, ixfp, + &sin, domain, + &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, + was_ixfr); + 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) unlink (tmpiname); + (void) fclose(ixfp); + 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) unlink (tmpiname); + (void) fclose(ixfp); + 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); + ixfp = NULL; + (void) unlink (tmpiname); + } + if (was_ixfr == 0) { + was_ixfr++; + n = res_nmkquery(&res, QUERY, + zp->z_origin, + curclass, T_AXFR, + NULL, 0, + NULL, buf, bufsize); + if (n < 0) { + if (!quiet) + syslog(LOG_INFO, + "zone %s: res_nmkquery T_SOA failed", + zp->z_origin); + (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); + } + /* + * Append TSIG to SOA query if desired + */ + tsig_key = tsig_key_from_addr(sin.sin_addr); + if (tsig_key != NULL) { + siglen = sizeof(sig); + ret = ns_sign(buf, &n, bufsize, + NOERROR, + tsig_key, NULL, + 0, sig, &siglen, + timesigned); + if (ret == 0) + tsig_signed = 1; + } + + /* + * Send length & message for AXFR query + */ + if (writemsg(s, buf, n) < 0) + syslog(LOG_INFO, + "writemsg: %m"); + else { + methode = ISNOTIXFR; + check_serial = 0; + soa_cnt = 0; + was_ixfr = 0; + goto receive; + } + } + (void) my_close(s); + return (XFER_FAIL); + } + if (ancount == 1) { + methode = ISNOTIXFR; + check_serial = 0; + soa_cnt = 0; + goto axfr_response; + } + dprintf(1, "We have an IXFR\n"); + while (SEQ_GT(zp_finish.z_serial, serial_no)) { + /* + * Receive length & response + */ + if (netread(s, (char *)buf, INT16SZ, + (soa_cnt == 0) ?300 :XFER_TIMER) + < 0) { + error++; + break; + } + if ((len = ns_get16(buf)) == 0) + break; + if (len > bufsize) { + buf = (u_char *)realloc(buf, len); + if (buf == NULL) { + syslog(LOG_INFO, + "malloc(%u) failed for packet from server [%s], zone %s\n", + len, + inet_ntoa(sin.sin_addr), + zp->z_origin); + error++; + break; + } + bufsize = len; + } + hp = (HEADER *)buf; + eom = buf + len; + if (netread(s, (char *)buf, len, XFER_TIMER) + < 0) { + error++; + break; + } +#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 + /* + * Verify the TSIG if expected + */ + if (tsig_signed != 0) { + tsig_req = (soa_cnt == 0); + ret = ns_verify_tcp(buf, (int *)&len, + &tsig_state, + tsig_req); + eom = buf + len; + + if (ret != 0) { + syslog(LOG_NOTICE, + "TSIG verification from server [%s], zone %s: %s (%d)\n", + inet_ntoa(sin.sin_addr), + zp->z_origin, + tsig_rcode(ret), ret); + error++; + break; + } + } + 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); + } 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) + if (ixfr_log(buf, len, &delete_soa, ixfp, + &sin, domain, &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) unlink (tmpiname); + (void) my_fclose(ixfp); + ixfp = 0; + } + if (!error) + return (XFER_TIMEOUT); + 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, 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 WINNT + 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; + } +#ifndef WINNT + 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; + iov[1].iov_base = (char *)msg; + iov[1].iov_len = msglen; + ret = writev(rfd, iov, 2); + if (ret != INT16SZ + msglen) { + syslog(LOG_DEBUG, "writemsg(%d,%#x,%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 was_ixfr) { + u_char *cp; + HEADER *hp = (HEADER *) msg; + u_int32_t addr, ttl, tmpnum; + int i, j, tab, 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: + syslog(LOG_INFO, "\"%s %s %s\" - unknown type (%d)", + dname, p_class(class), p_type(type), type); + hp->rcode = NOTIMP; + return (-1); + } + + 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; + } 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) && (was_ixfr == 0)) + 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) { + 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 != 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); + } + tab = 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 { + char *backslash; + backslash = (*dname == '@' || *dname == '$') ? + "\\" : ""; + (void) fprintf(dbfp, "%s%s%s\t", ignore, + backslash, dname); + } + if (strlen(dname) < (size_t)8) + tab = 1; + } else { + (void) fprintf(dbfp, "%s\t", ignore); + tab = 1; + } + + (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 */ + if ((n = *cp++) != 0) { + fprintf(dbfp, " \"%.*s\"", (int)n, cp); + cp += n; + } + + /* Service */ + if ((n = *cp++) != 0) { + fprintf(dbfp, " \"%.*s\"", (int)n, cp); + cp += n; + } + + /* Regexp */ + if ((n = *cp++) != 0) { + 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: + cp1 = cp + n; + while (cp < cp1) + fprintf(dbfp, "0x%02.2X ", *cp++ & 0xFF); + (void) fprintf(dbfp, "???\n"); + } + 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; + 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; + serial = -1; + 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); + return (serial); + } + 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, char *domain, 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, n; + char time[25]; + ns_rr rr; + char *cp; + HEADER *hp; + + 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)++; + } + *serial_no = do_section(&handle, ns_s_an, RES_PRF_ANS, file, delete); + 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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named-xfer/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named-xfer/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named-xfer/Makefile (revision 60942) @@ -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.29 1999/08/08 17:51:02 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +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} -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.2.3.t5b/contrib/bind/bin/named-xfer/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/nsupdate/nsupdate.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/nsupdate/nsupdate.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/nsupdate/nsupdate.c (revision 60942) @@ -0,0 +1,691 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: nsupdate.c,v 8.23 2000/02/04 07:51:04 vixie 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(argc, argv) + int argc; + char **argv; +{ + FILE *fp = NULL; + char buf[BUFSIZ], buf2[BUFSIZ], hostbuf[100], filebuf[100]; + char dnbuf[MAXDNAME], data[MAXDATA]; + u_char packet[PACKETSZ], answer[PACKETSZ]; + char *host = hostbuf, *batchfile = filebuf; + 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; + struct in_addr hostaddr; + extern int getopt(); + extern char *optarg; + extern int optind, opterr, optopt; + ns_tsig_key key; + char *keyfile=NULL, *keyname=NULL, *p, *pp; + int file_major, file_minor, alg; + + + + 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) ? -1 : 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: %ul\n", + 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 == -1) { + 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.2.3.t5b/contrib/bind/bin/nsupdate/nsupdate.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/nsupdate/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/nsupdate/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/nsupdate/Makefile (revision 60942) @@ -0,0 +1,84 @@ +## 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 1999/08/08 17:51:02 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +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} -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.2.3.t5b/contrib/bind/bin/nsupdate/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/Makefile (revision 60942) @@ -0,0 +1,93 @@ +## 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 1999/08/08 17:13:24 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +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}" "CPPFLAGS=${CPPFLAGS}" "TOP=../${TOP}" \ + "VER=${VER}" "STRIP=${STRIP}" "PS=${PS}" "INSTALL_LIB=${INSTALL_LIB}" \ + "INSTALL_EXEC=${INSTALL_EXEC}" "BOUNDS=${BOUNDS}" + +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} + +SUBDIRS = addr nslookup dig dnsquery host named named-xfer ndc nsupdate \ + mkservdb irpd dnskeygen named-bootconf + +all: ${SUBDIRS} + +${SUBDIRS}: FRC + @(cd $@; pwd; ${MAKE} ${MARGS}) + +install depend tags clean distclean:: + @for x in ${SUBDIRS}; do \ + (cd $$x; pwd; ${MAKE} ${MARGS} $@); \ + 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; \ + ); \ + 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.2.3.t5b/contrib/bind/bin/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/addr/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/addr/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/addr/Makefile (revision 60942) @@ -0,0 +1,84 @@ +## 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.25 1999/08/08 17:51:00 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +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} -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.2.3.t5b/contrib/bind/bin/addr/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/addr/addr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/addr/addr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/addr/addr.c (revision 60942) @@ -0,0 +1,177 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: addr.c,v 8.8 1999/10/13 16:38:55 vixie 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(src, dst, len) + 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(input, af, addr, len) + 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.2.3.t5b/contrib/bind/bin/addr/addr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/dnskeygen/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/dnskeygen/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/dnskeygen/Makefile (revision 60942) @@ -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 1.5 1999/08/08 17:51:01 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +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} -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.2.3.t5b/contrib/bind/bin/dnskeygen/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/dnskeygen/dnskeygen.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/dnskeygen/dnskeygen.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/dnskeygen/dnskeygen.c (revision 60942) @@ -0,0 +1,318 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: dnskeygen.c,v 1.9 1999/10/13 16:38:59 vixie 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 + +static void usage(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, n; + extern char *optarg; + char array[1024]; + + dst_init(); + if ((prog = strrchr(argv[0],'/')) == 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); + + 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(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.2.3.t5b/contrib/bind/bin/dnskeygen/dnskeygen.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/dnsquery/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/dnsquery/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/dnsquery/Makefile (revision 60942) @@ -0,0 +1,84 @@ +## 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 1999/08/08 17:51:01 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +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} -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.2.3.t5b/contrib/bind/bin/dnsquery/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/dnsquery/dnsquery.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/dnsquery/dnsquery.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/dnsquery/dnsquery.c (revision 60942) @@ -0,0 +1,210 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: dnsquery.c,v 8.13 1999/10/13 16:38:59 vixie 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 "port_after.h" + +extern int errno; +extern int h_errno; +extern char *h_errlist[]; + +struct __res_state res; + +int +main(int argc, char *argv[]) { + char name[MAXDNAME]; + u_char answer[8*1024]; + int c, n, i = 0; + u_int32_t ul; + int nameservers = 0, class, type, len; + struct in_addr q_nsaddr[MAXNS]; + struct hostent *q_nsname; + extern int optind, opterr; + extern char *optarg; + HEADER *hp; + 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' : 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); + } + if (nameservers >= MAXNS) break; + (void) inet_aton(optarg, + &q_nsaddr[nameservers]); + if (!inet_aton(optarg, (struct in_addr *)&ul)){ + q_nsname = gethostbyname(optarg); + if (q_nsname == 0) { + fprintf(stderr, + "Bad nameserver (%s)\n", + optarg); + exit(-1); + } + memcpy(&q_nsaddr[nameservers], + q_nsname->h_addr, INADDRSZ); + } + else + q_nsaddr[nameservers].s_addr = ul; + nameservers++; + 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) + 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.nscount = nameservers; + for (i = nameservers - 1; i >= 0; i--) { + res.nsaddr_list[i].sin_addr.s_addr = q_nsaddr[i].s_addr; + res.nsaddr_list[i].sin_family = AF_INET; + res.nsaddr_list[i].sin_port = htons(NAMESERVER_PORT); + } + } + + /* + * 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.2.3.t5b/contrib/bind/bin/dnsquery/dnsquery.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/mkservdb/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/mkservdb/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/mkservdb/Makefile (revision 60942) @@ -0,0 +1,83 @@ +## 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.6 1999/08/08 17:51:01 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +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} -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.2.3.t5b/contrib/bind/bin/mkservdb/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/mkservdb/mkservdb.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/mkservdb/mkservdb.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/mkservdb/mkservdb.c (revision 60942) @@ -0,0 +1,169 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: mkservdb.c,v 1.6 1999/10/13 16:39:00 vixie 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 +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "../../include/irs.h" +#include "../../lib/irs/irs_p.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 *); + +main(int argc, char **argv) { + DB *db; + DBT key; + DBT data; + char *filename = _PATH_SERVICES; + char *tmpdatabase = _PATH_SERVICES_DB_TMP; + 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", key.data); + else + warnx("will not overwrite %s", 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", + key.data); + else + warnx("will not overwrite %s", + 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 + <= 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 (rename(tmpdatabase, database)) + err(1, "rename %s -> %s", tmpdatabase, database); + exit(0); +} + +#endif Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/bin/mkservdb/mkservdb.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/named-bootconf/Grot/named-bootconf.pl =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named-bootconf/Grot/named-bootconf.pl (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named-bootconf/Grot/named-bootconf.pl (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/bin/named-bootconf/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named-bootconf/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named-bootconf/Makefile (revision 60942) @@ -0,0 +1,76 @@ +## 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.1 1999/01/07 02:09:37 vixie Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +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} -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.2.3.t5b/contrib/bind/bin/named-bootconf/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/bin/named-bootconf/named-bootconf.sh =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/bin/named-bootconf/named-bootconf.sh (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/bin/named-bootconf/named-bootconf.sh (revision 60942) @@ -0,0 +1,306 @@ +#!/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 + ;; + 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 2 ]; then + ZONE=$1 + shift + PRIMARIES=$1 + while [ $# -gt 2 ]; do + shift + PRIMARIES="$PRIMARIES $1" + done + (echo "" + cat $COMMENTFILE + echo "zone \"$ZONE\" ${class}{" + echo " type slave;" + echo " file \"$2\";" + 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 2 ]; then + ZONE=$1 + shift + PRIMARIES=$1 + while [ $# -gt 2 ]; do + shift + PRIMARIES="$PRIMARIES $1" + done + (echo "" + cat $COMMENTFILE + echo "zone \"$ZONE\" ${class}{" + echo " type stub;" + echo " file \"$2\";" + 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/inet/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/Makefile (revision 60942) @@ -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.19 2000/02/29 03:38:22 vixie 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= bsdos +DESTDIR = +DESTLIB = /usr/local/lib +O=o +A=a +CC= cc +LD= ld +SHELL= /bin/sh +CDEBUG= -g +TOP= ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.${A} +LIBBINDR = ../${TOP}/lib/libbind_r.${A} +CFLAGS= ${CDEBUG} -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 + +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} + +all: ${LIBBIND} + +${LIBBIND}: ${OBJS} + ( cd ${THREADED} ; \ + ${AR} ${LIBBINDR} ${ARPREF} ${OBJS} ${ARSUFF} ; \ + ${RANLIB} ${LIBBINDR} ) + ${AR} ${LIBBIND} ${ARPREF} ${OBJS} ${ARSUFF} + ${RANLIB} ${LIBBIND} + +.c.${O}: + if test ! -d ${THREADED} ; then mkdir ${THREADED} ; else true ; fi + ${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.2.3.t5b/contrib/bind/lib/inet/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_addr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_addr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_addr.c (revision 60942) @@ -0,0 +1,205 @@ +/* + * 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.11 1999/10/13 16:39:25 vixie 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(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(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(c)) { + val = (val << 4) | + (c + 10 - (islower(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(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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/inet/inet_cidr_ntop.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_cidr_ntop.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_cidr_ntop.c (revision 60942) @@ -0,0 +1,129 @@ +/* + * 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.4 1999/10/07 20:44:02 vixie 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_cidr_ntop_ipv4 __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)); + default: + errno = EAFNOSUPPORT; + return (NULL); + } +} + +/* + * 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; + char *t; + size_t len = 4; + int b, tb; + + if ((bits < -1) || (bits > 32)) { + errno = EINVAL; + return (NULL); + } + + /* Find number of significant bytes in address. */ + if (bits == -1) + len = 3; + else + for (len = 0,b = 1 ; b < 4; b++) + if (*(src + b)) + len = b; + + /* Format whole octets plus nonzero trailing octets. */ + tb = (bits <= 0) ? 1 : (bits - 1); + for (b = 0; b <= (tb / 8) || (b <= len); b++) { + if (size < sizeof "255.") + goto emsgsize; + t = dst; + dst += SPRINTF((dst, "%u", *src++)); + if (b + 1 <= (tb / 8) || (b + 1 <= len)) { + *dst++ = '.'; + *dst = '\0'; + } + size -= (size_t)(dst - t); + } + + if (bits != -1) { + /* Format CIDR /width. */ + if (size < sizeof "/32") + goto emsgsize; + dst += SPRINTF((dst, "/%u", bits)); + } + + return (odst); + + emsgsize: + errno = EMSGSIZE; + return (NULL); +} Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/inet/inet_cidr_pton.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_cidr_pton.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_cidr_pton.c (revision 60942) @@ -0,0 +1,153 @@ +/* + * 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.3 1999/01/08 19:23:41 vixie Exp $"; +#endif + +#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 + +static int inet_cidr_pton_ipv4 __P((const char *src, u_char *dst, + int *bits)); + +/* + * 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)); + default: + errno = EAFNOSUPPORT; + return (-1); + } +} + +static int +inet_cidr_pton_ipv4(const char *src, u_char *dst, int *pbits) { + static const char digits[] = "0123456789"; + 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 == '/' && isascii(src[0]) && isdigit(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; + + /* Prefix length can default to /32 only if all four octets spec'd. */ + if (bits == -1) + if (dst - odst == 4) + bits = 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 / 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); +} Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/inet/inet_lnaof.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_lnaof.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_lnaof.c (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/inet/inet_makeaddr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_makeaddr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_makeaddr.c (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/inet/inet_net_ntop.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_net_ntop.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_net_ntop.c (revision 60942) @@ -0,0 +1,144 @@ +/* + * 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.6 1999/01/08 19:23:42 vixie 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)); + +/* + * 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)); + 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); +} Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/inet/inet_net_pton.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_net_pton.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_net_pton.c (revision 60942) @@ -0,0 +1,215 @@ +/* + * 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.11 1999/01/08 19:23:44 vixie Exp $"; +#endif + +#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 + +static int inet_net_pton_ipv4 __P((const char *src, u_char *dst, + size_t size)); + +/* + * static 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(af, src, dst, size) + int af; + const char *src; + void *dst; + size_t size; +{ + switch (af) { + case AF_INET: + return (inet_net_pton_ipv4(src, dst, size)); + default: + errno = EAFNOSUPPORT; + return (-1); + } +} + +/* + * 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(src, dst, size) + const char *src; + u_char *dst; + size_t size; +{ + static const char + xdigits[] = "0123456789abcdef", + digits[] = "0123456789"; + int n, ch, tmp, dirty, bits; + const u_char *odst = dst; + + ch = *src++; + if (ch == '0' && (src[0] == 'x' || src[0] == 'X') + && isascii(src[1]) && isxdigit(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(src[0]) && isdigit(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); +} Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/inet/inet_neta.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_neta.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_neta.c (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/inet/inet_netof.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_netof.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_netof.c (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/inet/inet_network.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_network.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_network.c (revision 60942) @@ -0,0 +1,103 @@ +/* + * 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(c)) { + if (base == 8 && (c == '8' || c == '9')) + return (INADDR_NONE); + val = (val * base) + (c - '0'); + cp++; + digit = 1; + continue; + } + if (base == 16 && isxdigit(c)) { + val = (val << 4) + (c + 10 - (islower(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)) + 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/inet/inet_ntoa.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_ntoa.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_ntoa.c (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/inet/inet_ntop.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_ntop.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_ntop.c (revision 60942) @@ -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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_ntop.c,v 1.8 1999/10/13 16:39:28 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" + +#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 == 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/inet/inet_pton.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_pton.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/inet_pton.c (revision 60942) @@ -0,0 +1,220 @@ +/* + * 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.7 1999/10/13 16:39:28 vixie 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 (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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/inet/nsap_addr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/nsap_addr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/inet/nsap_addr.c (revision 60942) @@ -0,0 +1,101 @@ +/* + * 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.10 1999/10/13 16:39:28 vixie 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; + + 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[255*3]; + char *start; + + if (ascii) + start = ascii; + else { + ascii = tmpbuf; + start = tmpbuf; + } + + 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/Makefile (revision 60942) @@ -0,0 +1,109 @@ +# 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 1999/06/08 01:42:57 vixie Exp $ + +SUBDIRS = resolv irs isc bsd inet nameser dst cylink dnssafe + +# 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= bsdos +SHELL= /bin/sh +O=o +A=a +DESTDIR= +DESTINC= /usr/local/bind/include +DESTLIB= /usr/local/bind/lib +TOP= .. +INCL= ${TOP}/include +PORTINCL= ${TOP}/port/${SYSTYPE}/include +LIBBIND= ${TOP}/lib/libbind.${A} +LIBBINDR= ${TOP}/lib/libbind_r.${A} +LIBPORT= ${TOP}/port/libport.${A} +RANLIB= ranlib +AR= ar cru +INSTALL= install +CDEBUG= -g +REENTRANT=-D_REENTRANT +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin + +# Warning: this MARGS has RANLIB=: to prevent submakes from running ranlib +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}" "DESTHELP=${DESTHELP}" \ + "RANLIB=:" "AR=${AR}" "ARPREF=${ARPREF}" "ARSUFF=${ARSUFF}" \ + "INCL=../${INCL}" "PORTINCL=../${PORTINCL}" "EXE=${EXE}" \ + "LIBBIND=../${LIBBIND}" "LIBPORT=../${LIBPORT}" \ + "INSTALL=${INSTALL}" "CPPFLAGS=${CPPFLAGS}" "TOP=../${TOP}" \ + "REENTRANT=${REENTRANT}" "INSTALL_LIB=${INSTALL_LIB}" \ + "INSTALL_EXEC=${INSTALL_EXEC}" "BOUNDS=${BOUNDS}" + +LIB = libbind.${A} +LIBTS = ${TOP}/lib/libbind.ts +LIBR = libbind_r.${A} +LIBRTS = ${TOP}/lib/libbindr.ts + +all depend clean install distclean:: + @for x in ${SUBDIRS}; do \ + (cd $$x; pwd; ${MAKE} ${MARGS} $@); \ + done + +all:: ${LIBTS} ${LIBRTS} + +${LIBRTS}: ${LIBBINDR} + ${RANLIB} ${LIBBINDR} + sleep 1 && touch ${LIBRTS} + +${LIBTS}: ${LIBBIND} + ${RANLIB} ${LIBBIND} + sleep 1 && touch ${LIBTS} + +distclean:: clean + +clean:: FRC + rm -f *~ *.BAK *.CKP *.orig + rm -f ${LIBBIND} ${LIBTS} + rm -f ${LIBBINDR} ${LIBRTS} + +install:: ${DESTDIR}${DESTLIB} ${DESTDIR}${DESTLIB}/${LIB} +install:: ${DESTDIR}${DESTLIB} ${DESTDIR}${DESTLIB}/${LIBR} + +${DESTDIR}${DESTLIB}: + mkdir -p ${DESTDIR}${DESTLIB} + +${DESTDIR}${DESTLIB}/${LIBR}: ${LIBBINDR} + ${INSTALL} -c ${INSTALL_LIB} -m 644 ${LIBBINDR} \ + ${DESTDIR}${DESTLIB}/${LIBR} + ( cd ${DESTDIR}${DESTLIB} ; ${RANLIB} ${LIBR} ) + +${DESTDIR}${DESTLIB}/${LIB}: ${LIBBIND} + ${INSTALL} -c ${INSTALL_LIB} -m 644 ${LIBBIND} \ + ${DESTDIR}${DESTLIB}/${LIB} + ( cd ${DESTDIR}${DESTLIB} ; ${RANLIB} ${LIB} ) + +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; \ + ); \ + done + +FRC: Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/Makefile (revision 60942) @@ -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 1.16 2000/02/29 03:38:21 vixie 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= bsdos +DESTDIR = +DESTLIB = /usr/local/lib +O=o +A=a +CC= cc +LD= ld +SHELL= /bin/sh +CDEBUG= -g +TOP= ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.${A} +LIBBINDR = ../${TOP}/lib/libbind_r.${A} +CFLAGS= ${CDEBUG} -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 + +HDRS= md5.h md5_locl.h + +SRCS= dst_api.c prandom.c rsaref_link.c support.c bsafe_link.c \ + cylink_link.c hmac_link.c md5_dgst.c eay_dss_link.c + +OBJS= dst_api.${O} prandom.${O} rsaref_link.${O} support.${O} \ + bsafe_link.${O} cylink_link.${O} hmac_link.${O} md5_dgst.${O} \ + eay_dss_link.${O} + +CRYPTINCL= -I../cylink -I../dnssafe +CRYPTFLAGS= -DCYLINK_DSS -DHMAC_MD5 -DUSE_MD5 -DDNSSAFE + +all: ${LIBBIND} + +${LIBBIND}: ${OBJS} + ( cd ${THREADED} ; \ + ${AR} ${LIBBINDR} ${ARPREF} ${OBJS} ${ARSUFF} ; \ + ${RANLIB} ${LIBBINDR} ) + ${AR} ${LIBBIND} ${ARPREF} ${OBJS} ${ARSUFF} + ${RANLIB} ${LIBBIND} + +.c.${O}: + if test ! -d ${THREADED} ; then mkdir ${THREADED} ; else true ; fi + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} ${REENTRANT} ${CRYPTINCL} ${CRYPTFLAGS} -c $*.c -o ${THREADED}/$*.${O} + -${LDS} ${LD} ${LD_LIBFLAGS} ${THREADED}/$*.${O} \ + -o ${THREADED}/$*.out && \ + ${LDS} mv ${THREADED}/$*.out ${THREADED}/$*.${O} + ${CC} ${CPPFLAGS} ${CFLAGS} ${CRYPTINCL} ${CRYPTFLAGS} -c $*.c + -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} -o $*.out && \ + ${LDS} mv $*.out $*.${O} + +$(SRCS):: $(HDRS) + +distclean: clean + +clean: FRC + rm -f .depend a.out core ${LIB} tags + rm -f *.${O} *.BAK *.CKP *~ + rm -f prand_conf.h + 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] SRC/*.pl . + +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.2.3.t5b/contrib/bind/lib/dst/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/dst_api.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/dst_api.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/dst_api.c (revision 60942) @@ -0,0 +1,1068 @@ +#ifndef LINT +static const char rcsid[] = "$Header: /proj/cvs/isc/bind/src/lib/dst/dst_api.c,v 1.14 2000/02/28 07:51:50 vixie Exp $"; +#endif + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, 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 TRUSTED INFORMATION SYSTEMS + * 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. + */ +/* + * This file contains the interface between the DST API and the crypto API. + * This is the only file that needs to be changed if the crypto system is + * changed. Exported functions are: + * void dst_init() Initialize the toolkit + * int dst_check_algorithm() Function to determines if alg is suppored. + * int dst_compare_keys() Function to compare two keys for equality. + * int dst_sign_data() Incremental signing routine. + * int dst_verify_data() Incremental verify routine. + * int dst_generate_key() Function to generate new KEY + * DST_KEY *dst_read_key() Function to retrieve private/public KEY. + * void dst_write_key() Function to write out a key. + * DST_KEY *dst_dnskey_to_key() Function to convert DNS KEY RR to a DST + * KEY structure. + * int dst_key_to_dnskey() Function to return a public key in DNS + * format binary + * DST_KEY *dst_buffer_to_key() Converst a data in buffer to KEY + * int *dst_key_to_buffer() Writes out DST_KEY key matterial in buffer + * void dst_free_key() Releases all memory referenced by key structure + */ + +#include "port_before.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dst_internal.h" +#include "port_after.h" + +/* static variables */ +static int done_init = 0; +dst_func *dst_t_func[DST_MAX_ALGS]; +char *key_file_fmt_str = "Private-key-format: v%s\nAlgorithm: %d (%s)\n"; +char *dst_path = ""; + +/* internal I/O functions */ +static DST_KEY *dst_s_read_public_key(const char *in_name, + const u_int16_t in_id, int in_alg); +static int dst_s_read_private_key_file(char *name, DST_KEY *pk_key, + u_int16_t in_id, int in_alg); +static int dst_s_write_public_key(const DST_KEY *key); +static int dst_s_write_private_key(const DST_KEY *key); + +/* internal function to set up data structure */ +static DST_KEY *dst_s_get_key_struct(const char *name, const int alg, + const int flags, const int protocol, + const int bits); + +/* + * dst_init + * This function initializes the Digital Signature Toolkit. + * Right now, it just checks the DSTKEYPATH environment variable. + * Parameters + * none + * Returns + * none + */ +void +dst_init() +{ + char *s; + int len; + + if (done_init != 0) + return; + done_init = 1; + + s = getenv("DSTKEYPATH"); + len = 0; + if (s) { + struct stat statbuf; + + len = strlen(s); + if (len > PATH_MAX) { + EREPORT(("%s is longer than %d characters, ignoring\n", + s, PATH_MAX)); + } else if (stat(s, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) { + EREPORT(("%s is not a valid directory\n", s)); + } else { + dst_path = (char *) malloc(len + 2); + memcpy(dst_path, s, len + 1); + if (dst_path[strlen(dst_path) - 1] != '/') { + dst_path[strlen(dst_path) + 1] = 0; + dst_path[strlen(dst_path)] = '/'; + } + } + } + memset(dst_t_func, 0, sizeof(dst_t_func)); + /* first one is selected */ + dst_bsafe_init(); + dst_rsaref_init(); + dst_hmac_md5_init(); + dst_eay_dss_init(); + dst_cylink_init(); +} + +/* + * dst_check_algorithm + * This function determines if the crypto system for the specified + * algorithm is present. + * Parameters + * alg 1 KEY_RSA + * 3 KEY_DSA + * 157 KEY_HMAC_MD5 + * future algorithms TBD and registered with IANA. + * Returns + * 1 - The algorithm is available. + * 0 - The algorithm is not available. + */ +int +dst_check_algorithm(const int alg) +{ + return (dst_t_func[alg] != NULL); +} + +/* + * dst_s_get_key_struct + * This function allocates key structure and fills in some of the + * fields of the structure. + * Parameters: + * name: the name of the key + * alg: the algorithm number + * flags: the dns flags of the key + * protocol: the dns protocol of the key + * bits: the size of the key + * Returns: + * NULL if error + * valid pointer otherwise + */ +static DST_KEY * +dst_s_get_key_struct(const char *name, const int alg, const int flags, + const int protocol, const int bits) +{ + DST_KEY *new_key = NULL; + + if (dst_check_algorithm(alg)) /* make sure alg is available */ + new_key = (DST_KEY *) malloc(sizeof(*new_key)); + if (new_key == NULL) + return (NULL); + + memset(new_key, 0, sizeof(*new_key)); + new_key->dk_key_name = strdup(name); + new_key->dk_alg = alg; + new_key->dk_flags = flags; + new_key->dk_proto = protocol; + new_key->dk_KEY_struct = NULL; + new_key->dk_key_size = bits; + new_key->dk_func = dst_t_func[alg]; + return (new_key); +} + +/* + * dst_compare_keys + * Compares two keys for equality. + * Parameters + * key1, key2 Two keys to be compared. + * Returns + * 0 The keys are equal. + * non-zero The keys are not equal. + */ + +int +dst_compare_keys(const DST_KEY *key1, const DST_KEY *key2) +{ + if (key1 == key2) + return (0); + if (key1 == NULL || key2 == NULL) + return (4); + if (key1->dk_alg != key2->dk_alg) + return (1); + if (key1->dk_key_size != key2->dk_key_size) + return (2); + if (key1->dk_id != key2->dk_id) + return (3); + return (key1->dk_func->compare(key1, key2)); +} + + +/* + * dst_sign_data + * An incremental signing function. Data is signed in steps. + * First the context must be initialized (SIG_MODE_INIT). + * Then data is hashed (SIG_MODE_UPDATE). Finally the signature + * itself is created (SIG_MODE_FINAL). This function can be called + * once with INIT, UPDATE and FINAL modes all set, or it can be + + * called separately with a different mode set for each step. The + * UPDATE step can be repeated. + * Parameters + * mode A bit mask used to specify operation(s) to be performed. + * SIG_MODE_INIT 1 Initialize digest + * SIG_MODE_UPDATE 2 Add data to digest + * SIG_MODE_FINAL 4 Generate signature + * from signature + * SIG_MODE_ALL (SIG_MODE_INIT,SIG_MODE_UPDATE,SIG_MODE_FINAL + * data Data to be signed. + * len The length in bytes of data to be signed. + * in_key Contains a private key to sign with. + * KEY structures should be handled (created, converted, + * compared, stored, freed) by the DST. + * signature + * The location to which the signature will be written. + * sig_len Length of the signature field in bytes. + * Return + * 0 Successfull INIT or Update operation + * >0 success FINAL (sign) operation + * <0 failure + */ + +int +dst_sign_data(const int mode, DST_KEY *in_key, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len) +{ + DUMP(data, mode, len, "dst_sign_data()"); + + if (mode & SIG_MODE_FINAL && + (in_key->dk_KEY_struct == NULL || signature == NULL)) + return (MISSING_KEY_OR_SIGNATURE); + + if (in_key->dk_func && in_key->dk_func->sign) + return (in_key->dk_func->sign(mode, in_key, context, data, len, + signature, sig_len)); + return (UNKNOWN_KEYALG); +} + + +/* + * dst_verify_data + * An incremental verify function. Data is verified in steps. + * First the context must be initialized (SIG_MODE_INIT). + * Then data is hashed (SIG_MODE_UPDATE). Finally the signature + * is verified (SIG_MODE_FINAL). This function can be called + * once with INIT, UPDATE and FINAL modes all set, or it can be + * called separately with a different mode set for each step. The + * UPDATE step can be repeated. + * Parameters + * mode Operations to perform this time. + * SIG_MODE_INIT 1 Initialize digest + * SIG_MODE_UPDATE 2 add data to digest + * SIG_MODE_FINAL 4 verify signature + * SIG_MODE_ALL + * (SIG_MODE_INIT,SIG_MODE_UPDATE,SIG_MODE_FINAL) + * data Data to pass through the hash function. + * len Length of the data in bytes. + * in_key Key for verification. + * signature Location of signature. + * sig_len Length of the signature in bytes. + * Returns + * 0 Verify success + * Non-Zero Verify Failure + */ + +int +dst_verify_data(const int mode, DST_KEY *in_key, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len) +{ + DUMP(data, mode, len, "dst_verify_data()"); + if (mode & SIG_MODE_FINAL && + (in_key->dk_KEY_struct == NULL || signature == NULL)) + return (MISSING_KEY_OR_SIGNATURE); + + if (in_key->dk_func == NULL || in_key->dk_func->verify == NULL) + return (UNSUPPORTED_KEYALG); + return (in_key->dk_func->verify(mode, in_key, context, data, len, + signature, sig_len)); +} + + +/* + * dst_read_private_key + * Access a private key. First the list of private keys that have + * already been read in is searched, then the key accessed on disk. + * If the private key can be found, it is returned. If the key cannot + * be found, a null pointer is returned. The options specify required + * key characteristics. If the private key requested does not have + * these characteristics, it will not be read. + * Parameters + * in_keyname The private key name. + * in_id The id of the private key. + * options DST_FORCE_READ Read from disk - don't use a previously + * read key. + * DST_CAN_SIGN The key must be useable for signing. + * DST_NO_AUTHEN The key must be useable for authentication. + * DST_STANDARD Return any key + * Returns + * NULL If there is no key found in the current directory or + * this key has not been loaded before. + * !NULL Success - KEY structure returned. + */ + +DST_KEY * +dst_read_key(const char *in_keyname, const u_int16_t in_id, + const int in_alg, const int type) +{ + char keyname[PATH_MAX]; + DST_KEY *dg_key = NULL, *pubkey = NULL; + + if (!dst_check_algorithm(in_alg)) { /* make sure alg is available */ + EREPORT(("dst_read_private_key(): Algorithm %d not suppored\n", + in_alg)); + return (NULL); + } + if ((type & (DST_PUBLIC | DST_PRIVATE)) == 0) + return (NULL); + if (in_keyname == NULL) { + EREPORT(("dst_read_private_key(): Null key name passed in\n")); + return (NULL); + } else + strcpy(keyname, in_keyname); + + /* before I read in the public key, check if it is allowed to sign */ + if ((pubkey = dst_s_read_public_key(keyname, in_id, in_alg)) == NULL) + return (NULL); + + if (type == DST_PUBLIC) + return pubkey; + + if (!(dg_key = dst_s_get_key_struct(keyname, pubkey->dk_alg, + pubkey->dk_flags, pubkey->dk_proto, + 0))) + return (dg_key); + /* Fill in private key and some fields in the general key structure */ + if (dst_s_read_private_key_file(keyname, dg_key, pubkey->dk_id, + pubkey->dk_alg) == 0) + dg_key = dst_free_key(dg_key); + + pubkey = dst_free_key(pubkey); + return (dg_key); +} + +int +dst_write_key(const DST_KEY *key, const int type) +{ + int pub = 0, priv = 0; + + if (key == NULL) + return (0); + if (!dst_check_algorithm(key->dk_alg)) { /* make sure alg is available */ + EREPORT(("dst_write_key(): Algorithm %d not suppored\n", + key->dk_alg)); + return (UNSUPPORTED_KEYALG); + } + if ((type & (DST_PRIVATE|DST_PUBLIC)) == 0) + return (0); + + if (type & DST_PUBLIC) + if ((pub = dst_s_write_public_key(key)) < 0) + return (pub); + if (type & DST_PRIVATE) + if ((priv = dst_s_write_private_key(key)) < 0) + return (priv); + return (priv+pub); +} + +/* + * dst_write_private_key + * Write a private key to disk. The filename will be of the form: + * Kdk_name>+dk_alg>+dk_id>.. + * If there is already a file with this name, an error is returned. + * + * Parameters + * key A DST managed key structure that contains + * all information needed about a key. + * Return + * >= 0 Correct behavior. Returns length of encoded key value + * written to disk. + * < 0 error. + */ + +static int +dst_s_write_private_key(const DST_KEY *key) +{ + u_char encoded_block[RAW_KEY_SIZE]; + char file[PATH_MAX]; + int len; + FILE *fp; + + /* First encode the key into the portable key format */ + if (key == NULL) + return (-1); + if (key->dk_KEY_struct == NULL) + return (0); /* null key has no private key */ + + if (key->dk_func == NULL || key->dk_func->to_file_fmt == NULL) { + EREPORT(("dst_write_private_key(): Unsupported operation %d\n", + key->dk_alg)); + return (-5); + } else if ((len = key->dk_func->to_file_fmt(key, (char *)encoded_block, + sizeof(encoded_block))) <= 0) { + EREPORT(("dst_write_private_key(): Failed encoding private RSA bsafe key %d\n", len)); + return (-8); + } + /* Now I can create the file I want to use */ + dst_s_build_filename(file, key->dk_key_name, key->dk_id, key->dk_alg, + PRIVATE_KEY, PATH_MAX); + + /* Do not overwrite an existing file */ + if ((fp = dst_s_fopen(file, "w", 0600)) != NULL) { + int nn; + if ((nn = fwrite(encoded_block, 1, len, fp)) != len) { + EREPORT(("dst_write_private_key(): Write failure on %s %d != %d errno=%d\n", + file, out_len, nn, errno)); + return (-5); + } + fclose(fp); + } else { + EREPORT(("dst_write_private_key(): Can not create file %s\n" + ,file)); + return (-6); + } + memset(encoded_block, 0, len); + return (len); +} + +/* +* + * dst_read_public_key + * Read a public key from disk and store in a DST key structure. + * Parameters + * in_name K. is the + * filename of the key file to be read. + * Returns + * NULL If the key does not exist or no name is supplied. + * NON-NULL Initalized key structure if the key exists. + */ + +static DST_KEY * +dst_s_read_public_key(const char *in_name, const u_int16_t in_id, int in_alg) +{ + int flags, proto, alg, len, dlen; + int c; + char name[PATH_MAX], enckey[RAW_KEY_SIZE], *notspace; + u_char deckey[RAW_KEY_SIZE]; + FILE *fp; + + if (in_name == NULL) { + EREPORT(("dst_read_public_key(): No key name given\n")); + return (NULL); + } + if (dst_s_build_filename(name, in_name, in_id, in_alg, PUBLIC_KEY, + PATH_MAX) == -1) { + EREPORT(("dst_read_public_key(): Cannot make filename from %s, %d, and %s\n", + in_name, in_id, PUBLIC_KEY)); + return (NULL); + } + /* + * Open the file and read it's formatted contents up to key + * File format: + * domain.name [ttl] [IN] KEY + * flags, proto, alg stored as decimal (or hex numbers FIXME). + * (FIXME: handle parentheses for line continuation.) + */ + if ((fp = dst_s_fopen(name, "r", 0)) == NULL) { + EREPORT(("dst_read_public_key(): Public Key not found %s\n", + name)); + return (NULL); + } + /* Skip domain name, which ends at first blank */ + while ((c = getc(fp)) != EOF) + if (isspace(c)) + break; + /* Skip blank to get to next field */ + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + + /* Skip optional TTL -- if initial digit, skip whole word. */ + if (isdigit(c)) { + while ((c = getc(fp)) != EOF) + if (isspace(c)) + break; + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + } + /* Skip optional "IN" */ + if (c == 'I' || c == 'i') { + while ((c = getc(fp)) != EOF) + if (isspace(c)) + break; + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + } + /* Locate and skip "KEY" */ + if (c != 'K' && c != 'k') { + EREPORT(("\"KEY\" doesn't appear in file: %s", name)); + return NULL; + } + while ((c = getc(fp)) != EOF) + if (isspace(c)) + break; + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + ungetc(c, fp); /* return the charcter to the input field */ + /* Handle hex!! FIXME. */ + + if (fscanf(fp, "%d %d %d", &flags, &proto, &alg) != 3) { + EREPORT(("dst_read_public_key(): Can not read flag/proto/alg field from %s\n" + ,name)); + return (NULL); + } + /* read in the key string */ + fgets(enckey, sizeof(enckey), fp); + + /* If we aren't at end-of-file, something is wrong. */ + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + if (!feof(fp)) { + EREPORT(("Key too long in file: %s", name)); + return NULL; + } + fclose(fp); + + if ((len = strlen(enckey)) <= 0) + return (NULL); + + /* discard \n */ + enckey[--len] = '\0'; + + /* remove leading spaces */ + for (notspace = (char *) enckey; isspace(*notspace); len--) + notspace++; + + dlen = b64_pton(notspace, deckey, sizeof(deckey)); + if (dlen < 0) { + EREPORT(("dst_read_public_key: bad return from b64_pton = %d", + dlen)); + return (NULL); + } + /* store key and info in a key structure that is returned */ +/* return dst_store_public_key(in_name, alg, proto, 666, flags, deckey, + dlen);*/ + return dst_buffer_to_key(in_name, alg, flags, proto, deckey, dlen); +} + + +/* + * dst_write_public_key + * Write a key to disk in DNS format. + * Parameters + * key Pointer to a DST key structure. + * Returns + * 0 Failure + * 1 Success + */ + +static int +dst_s_write_public_key(const DST_KEY *key) +{ + FILE *fp; + char filename[PATH_MAX]; + u_char out_key[RAW_KEY_SIZE]; + char enc_key[RAW_KEY_SIZE]; + int len = 0; + + memset(out_key, 0, sizeof(out_key)); + if (key == NULL) { + EREPORT(("dst_write_public_key(): No key specified \n")); + return (0); + } else if ((len = dst_key_to_dnskey(key, out_key, sizeof(out_key)))< 0) + return (0); + + /* Make the filename */ + if (dst_s_build_filename(filename, key->dk_key_name, key->dk_id, + key->dk_alg, PUBLIC_KEY, PATH_MAX) == -1) { + EREPORT(("dst_write_public_key(): Cannot make filename from %s, %d, and %s\n", + key->dk_key_name, key->dk_id, PUBLIC_KEY)); + return (0); + } + /* create public key file */ + if ((fp = dst_s_fopen(filename, "w+", 0644)) == NULL) { + EREPORT(("DST_write_public_key: open of file:%s failed (errno=%d)\n", + filename, errno)); + return (0); + } + /*write out key first base64 the key data */ + if (key->dk_flags & DST_EXTEND_FLAG) + b64_ntop(&out_key[6], len - 6, enc_key, sizeof(enc_key)); + else + b64_ntop(&out_key[4], len - 4, enc_key, sizeof(enc_key)); + fprintf(fp, "%s IN KEY %d %d %d %s\n", + key->dk_key_name, + key->dk_flags, key->dk_proto, key->dk_alg, enc_key); + fclose(fp); + return (1); +} + + +/* + * dst_dnskey_to_public_key + * This function converts the contents of a DNS KEY RR into a DST + * key structure. + * Paramters + * len Length of the RDATA of the KEY RR RDATA + * rdata A pointer to the the KEY RR RDATA. + * in_name Key name to be stored in key structure. + * Returns + * NULL Failure + * NON-NULL Success. Pointer to key structure. + * Caller's responsibility to free() it. + */ + +DST_KEY * +dst_dnskey_to_key(const char *in_name, const u_char *rdata, const int len) +{ + DST_KEY *key_st; + int alg ; + int start = DST_KEY_START; + + if (rdata == NULL || len <= DST_KEY_ALG) /* no data */ + return (NULL); + alg = (u_int8_t) rdata[DST_KEY_ALG]; + if (!dst_check_algorithm(alg)) { /* make sure alg is available */ + EREPORT(("dst_dnskey_to_key(): Algorithm %d not suppored\n", + alg)); + return (NULL); + } + if ((key_st = dst_s_get_key_struct(in_name, alg, 0, 0, 0)) == NULL) + return (NULL); + + if (in_name == NULL) + return (NULL); + key_st->dk_flags = dst_s_get_int16(rdata); + key_st->dk_proto = (u_int16_t) rdata[DST_KEY_PROT]; + if (key_st->dk_flags & DST_EXTEND_FLAG) { + u_int32_t ext_flags; + ext_flags = (u_int32_t) dst_s_get_int16(&rdata[DST_EXT_FLAG]); + key_st->dk_flags = key_st->dk_flags | (ext_flags << 16); + start += 2; + } + /* + * now point to the begining of the data representing the encoding + * of the key + */ + if (key_st->dk_func && key_st->dk_func->from_dns_key) { + if (key_st->dk_func->from_dns_key(key_st, &rdata[start], + len - start) > 0) + return (key_st); + } else + EREPORT(("dst_dnskey_to_public_key(): unsuppored alg %d\n", + alg)); + + SAFE_FREE(key_st); + return (key_st); +} + + +/* + * dst_public_key_to_dnskey + * Function to encode a public key into DNS KEY wire format + * Parameters + * key Key structure to encode. + * out_storage Location to write the encoded key to. + * out_len Size of the output array. + * Returns + * <0 Failure + * >=0 Number of bytes written to out_storage + */ + +int +dst_key_to_dnskey(const DST_KEY *key, u_char *out_storage, + const int out_len) +{ + u_int16_t val; + int loc = 0; + int enc_len = 0; + if (key == NULL) + return (-1); + + if (!dst_check_algorithm(key->dk_alg)) { /* make sure alg is available */ + EREPORT(("dst_key_to_dnskey(): Algorithm %d not suppored\n", + key->dk_alg)); + return (UNSUPPORTED_KEYALG); + } + memset(out_storage, 0, out_len); + val = (u_int16_t)(key->dk_flags & 0xffff); + dst_s_put_int16(out_storage, val); + loc += 2; + + out_storage[loc++] = (u_char) key->dk_proto; + out_storage[loc++] = (u_char) key->dk_alg; + + if (key->dk_flags > 0xffff) { /* Extended flags */ + val = (u_int16_t)((key->dk_flags >> 16) & 0xffff); + dst_s_put_int16(&out_storage[loc], val); + loc += 2; + } + if (key->dk_KEY_struct == NULL) + return (loc); + if (key->dk_func && key->dk_func->to_dns_key) { + enc_len = key->dk_func->to_dns_key(key, + (u_char *) &out_storage[loc], + out_len - loc); + if (enc_len > 0) + return (enc_len + loc); + else + return (-1); + } else + EREPORT(("dst_key_to_dnskey(): Unsupported ALG %d\n", + key->dk_alg)); + return (-1); +} + + +/* + * dst_buffer_to_key + * Function to encode a string of raw data into a DST key + * Parameters + * alg The algorithm (HMAC only) + * key A pointer to the data + * keylen The length of the data + * Returns + * NULL an error occurred + * NON-NULL the DST key + */ +DST_KEY * +dst_buffer_to_key(const char *key_name, /* name of the key */ + const int alg, /* algorithm */ + const int flags, /* dns flags */ + const int protocol, /* dns protocol */ + const u_char *key_buf, /* key in dns wire fmt */ + const int key_len) /* size of key */ +{ + + DST_KEY *dkey = NULL; + + if (!dst_check_algorithm(alg)) { /* make sure alg is available */ + EREPORT(("dst_buffer_to_key(): Algorithm %d not suppored\n", alg)); + return (NULL); + } + + dkey = dst_s_get_key_struct(key_name, alg, flags, + protocol, -1); + + if (dkey == NULL) + return (NULL); + if (dkey->dk_func != NULL && + dkey->dk_func->from_dns_key != NULL) { + if (dkey->dk_func->from_dns_key(dkey, key_buf, key_len) < 0) { + EREPORT(("dst_buffer_to_key(): dst_buffer_to_hmac failed\n")); + return (dst_free_key(dkey)); + } + return (dkey); + } + return (NULL); +} + +int +dst_key_to_buffer(DST_KEY *key, u_char *out_buff, int buf_len) +{ + int len; + /* this function will extrac the secret of HMAC into a buffer */ + if(key == NULL) + return (0); + if(key->dk_func != NULL && key->dk_func != NULL) { + len = key->dk_func->to_dns_key(key, out_buff, buf_len); + if (len < 0) + return (0); + return (len); + } + return (0); +} + + +/* + * dst_s_read_private_key_file + * Function reads in private key from a file. + * Fills out the KEY structure. + * Parameters + * name Name of the key to be read. + * pk_key Structure that the key is returned in. + * in_id Key identifier (tag) + * Return + * 1 if everthing works + * 0 if there is any problem + */ + +static int +dst_s_read_private_key_file(char *name, DST_KEY *pk_key, u_int16_t in_id, + int in_alg) +{ + int cnt, alg, len, major, minor, file_major, file_minor; + int id; + char filename[PATH_MAX]; + u_char in_buff[RAW_KEY_SIZE], *p; + FILE *fp; + + if (name == NULL || pk_key == NULL) { + EREPORT(("dst_read_private_key_file(): No key name given\n")); + return (0); + } + /* Make the filename */ + if (dst_s_build_filename(filename, name, in_id, in_alg, PRIVATE_KEY, + PATH_MAX) == -1) { + EREPORT(("dst_read_private_key(): Cannot make filename from %s, %d, and %s\n", + name, in_id, PRIVATE_KEY)); + return (0); + } + /* first check if we can find the key file */ + if ((fp = dst_s_fopen(filename, "r", 0)) == NULL) { + EREPORT(("dst_s_read_private_key_file: Could not open file %s in directory %s\n", + filename, dst_path[0] ? dst_path : + (char *) getcwd(NULL, PATH_MAX - 1))); + return (0); + } + /* now read the header info from the file */ + if ((cnt = fread(in_buff, 1, sizeof(in_buff), fp)) < 5) { + fclose(fp); + EREPORT(("dst_s_read_private_key_file: error reading file %s (empty file)\n", + filename)); + return (0); + } + /* decrypt key */ + fclose(fp); + if (memcmp(in_buff, "Private-key-format: v", 20) != 0) + goto fail; + len = cnt; + p = in_buff; + + if (!dst_s_verify_str((const char **) &p, "Private-key-format: v")) { + EREPORT(("dst_s_read_private_key_file(): Not a Key file/Decrypt failed %s\n", name)); + goto fail; + } + /* read in file format */ + sscanf((char *)p, "%d.%d", &file_major, &file_minor); + sscanf(KEY_FILE_FORMAT, "%d.%d", &major, &minor); + if (file_major < 1) { + EREPORT(("dst_s_read_private_key_file(): Unknown keyfile %d.%d version for %s\n", + file_major, file_minor, name)); + goto fail; + } else if (file_major > major || file_minor > minor) + EREPORT(( + "dst_s_read_private_key_file(): Keyfile %s version higher than mine %d.%d MAY FAIL\n", + name, file_major, file_minor)); + + while (*p++ != '\n') ; /* skip to end of line */ + + if (!dst_s_verify_str((const char **) &p, "Algorithm: ")) + goto fail; + + if (sscanf((char *)p, "%d", &alg) != 1) + goto fail; + while (*p++ != '\n') ; /* skip to end of line */ + + if (pk_key->dk_key_name && !strcmp(pk_key->dk_key_name, name)) + SAFE_FREE2(pk_key->dk_key_name, strlen(pk_key->dk_key_name)); + pk_key->dk_key_name = (char *) strdup(name); + + /* allocate and fill in key structure */ + if (pk_key->dk_func == NULL || pk_key->dk_func->from_file_fmt == NULL) + goto fail; + + id = pk_key->dk_func->from_file_fmt(pk_key, (char *)p, &in_buff[len] - p); + if (id < 0) + goto fail; + + /* Make sure the actual key tag matches the input tag used in the filename + */ + if (id != in_id) { + EREPORT(("dst_s_read_private_key_file(): actual tag of key read %d != input tag used to build filename %d.\n", id, in_id)); + goto fail; + } + pk_key->dk_id = (u_int16_t) id; + pk_key->dk_alg = alg; + memset(in_buff, 0, cnt); + return (1); + + fail: + memset(in_buff, 0, cnt); + return (0); +} + + +/* + * dst_generate_key + * Generate and store a public/private keypair. + * Keys will be stored in formatted files. + * Parameters + * name Name of the new key. Used to create key files + * K++.public and K++.private. + * bits Size of the new key in bits. + * exp What exponent to use: + * 0 use exponent 3 + * non-zero use Fermant4 + * flags The default value of the DNS Key flags. + * The DNS Key RR Flag field is defined in RFC 2065, + * section 3.3. The field has 16 bits. + * protocol + * Default value of the DNS Key protocol field. + * The DNS Key protocol field is defined in RFC 2065, + * section 3.4. The field has 8 bits. + * alg What algorithm to use. Currently defined: + * KEY_RSA 1 + * KEY_DSA 3 + * KEY_HMAC 157 + * out_id The key tag is returned. + * + * Return + * NULL Failure + * non-NULL the generated key pair + * Caller frees the result, and its dk_name pointer. + */ +DST_KEY * +dst_generate_key(const char *name, const int bits, const int exp, + const int flags, const int protocol, const int alg) +{ + DST_KEY *new_key = NULL; + int res; + if (name == NULL) + return (NULL); + + if (!dst_check_algorithm(alg)) { /* make sure alg is available */ + EREPORT(("dst_generate_key(): Algorithm %d not suppored\n", alg)); + return (NULL); + } + + new_key = dst_s_get_key_struct(name, alg, flags, protocol, bits); + if (new_key == NULL) + return (NULL); + if (bits == 0) /* null key we are done */ + return (new_key); + if (new_key->dk_func == NULL || new_key->dk_func->generate == NULL) { + EREPORT(("dst_generate_key_pair():Unsupported algorithm %d\n", + alg)); + return (dst_free_key(new_key)); + } + if ((res = new_key->dk_func->generate(new_key, exp)) <= 0) { + EREPORT(("dst_generate_key_pair(): Key generation failure %s %d %d %d\n", + new_key->dk_key_name, new_key->dk_alg, + new_key->dk_key_size, exp)); + return (dst_free_key(new_key)); + } + return (new_key); +} + + +/* + * dst_free_key + * Release all data structures pointed to by a key structure. + * Parameters + * f_key Key structure to be freed. + */ + +DST_KEY * +dst_free_key(DST_KEY *f_key) +{ + + if (f_key == NULL) + return (f_key); + if (f_key->dk_func && f_key->dk_func->destroy) + f_key->dk_KEY_struct = + f_key->dk_func->destroy(f_key->dk_KEY_struct); + else { + EREPORT(("dst_free_key(): Unknown key alg %d\n", + f_key->dk_alg)); + free(f_key->dk_KEY_struct); /* SHOULD NOT happen */ + } + if (f_key->dk_KEY_struct) { + free(f_key->dk_KEY_struct); + f_key->dk_KEY_struct = NULL; + } + if (f_key->dk_key_name) + SAFE_FREE(f_key->dk_key_name); + SAFE_FREE(f_key); + return (NULL); +} + +/* + * dst_sig_size + * Return the maximim size of signature from the key specified in bytes + * Parameters + * key + * Returns + * bytes + */ +int +dst_sig_size(DST_KEY *key) { + switch (key->dk_alg) { + case KEY_HMAC_MD5: + return (16); + case KEY_HMAC_SHA1: + return (20); + case KEY_RSA: + return (key->dk_key_size + 7) / 8; + case KEY_DSA: + return (40); + default: + EREPORT(("dst_sig_size(): Unknown key alg %d\n", key->dk_alg)); + return -1; + } +} + +/* + * dst_random + * function that multiplexes number of random number generators + * Parameters + * mode: select the random number generator + * wanted is how many bytes of random data are requested + * outran is a buffer of size at least wanted for the output data + * + * Returns + * number of bytes written to outran + */ +int +dst_random(const int mode, int wanted, u_char *outran) +{ + u_int32_t *buff = NULL, *bp = NULL; + int i; + if (wanted <= 0 || outran == NULL) + return (0); + + switch (mode) { + case DST_RAND_SEMI: + bp = buff = (u_int32_t *) malloc(wanted+sizeof(u_int32_t)); + for (i = 0; i < wanted; i+= sizeof(u_int32_t), bp++) { + *bp = dst_s_quick_random(i); + } + memcpy(outran, buff, wanted); + SAFE_FREE(buff); + return (wanted); + case DST_RAND_STD: + return (dst_s_semi_random(outran, wanted)); + case DST_RAND_KEY: + return (dst_s_random(outran, wanted)); + case DST_RAND_DSS: + default: + /* need error case here XXX OG */ + return (0); + } +} + Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/dst_api.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/README =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/README (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/README (revision 60942) @@ -0,0 +1,27 @@ +This directory in BIND contains the Domain Signature Tools (dst) +library. It was written by Trusted Information Systems, Inc. and +integrated into BIND by John Gilmore. It is used as a generic +crypto library interface by the DNS Security code in BIND. + + Installing Domain Signature Tools Library - dst + +1. Assess available crypto libraries: + + if you have DNSSAFE (the default) + CRYPTFLAGS must include -DDNSSAFE + CRYPTINCL must include -I../dnssafe + + if you have RSAREF + CRYPTFLAGS must include -DRSAREF + CRYPTINCL must include -I + + if you have BSAFE + CRYPTFLAGS must include -DBSAFE + CRYPTINCL must include -I + + if you want HMAC-MD5 support + CRYPTFLAGs must include -DHMAC + +2. Building BIND as usual will include the dst library routines into + libbind.a, and link them into the BIND programs that use crypto + support. Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/README ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/bsafe_link.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/bsafe_link.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/bsafe_link.c (revision 60942) @@ -0,0 +1,1125 @@ +#if defined(BSAFE) || defined(DNSSAFE) +static const char rcsid[] = "$Header: /proj/cvs/isc/bind/src/lib/dst/bsafe_link.c,v 1.11 1999/10/13 16:39:22 vixie Exp $"; + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, 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 TRUSTED INFORMATION SYSTEMS + * 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. + */ +/* + * This file contains two components + * 1. Interface to the BSAFE library to allow compilation of Bind + * with TIS/DNSSEC when BSAFE is not available + * all calls to BSAFE are contained inside this file. + * 2. The glue to connvert RSA KEYS to and from external formats + */ +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dst_internal.h" + +# ifdef __STDC__ +# define PROTOTYPES 1 +# else +# define PROTOTYPES 0 +# endif + +# ifdef BSAFE +# include +# include +# else +# include +# include +# include +# endif + +#include "port_after.h" + +typedef struct bsafekey { + char *rk_signer; + B_KEY_OBJ rk_Private_Key; + B_KEY_OBJ rk_Public_Key; +} RSA_Key; + +#ifndef MAX_RSA_MODULUS_BITS +#define MAX_RSA_MODULUS_BITS 4096 +#define MAX_RSA_MODULUS_LEN (MAX_RSA_MODULUS_BITS/8) +#define MAX_RSA_PRIME_LEN (MAX_RSA_MODULUS_LEN/2) +#endif + +#define NULL_SURRENDER (A_SURRENDER_CTX *)NULL_PTR +#define NULL_RANDOM (B_ALGORITHM_OBJ)NULL_PTR + +B_ALGORITHM_METHOD *CHOOSER[] = +{ + &AM_MD5, + &AM_MD5_RANDOM, + &AM_RSA_KEY_GEN, + &AM_RSA_ENCRYPT, + &AM_RSA_DECRYPT, + &AM_RSA_CRT_ENCRYPT, + &AM_RSA_CRT_DECRYPT, + (B_ALGORITHM_METHOD *) NULL_PTR +}; + +static u_char pkcs1[] = +{ + 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, + 0x04, 0x10 +}; + +static int dst_bsafe_md5digest(const int mode, B_ALGORITHM_OBJ *digest_obj, + const u_char *data, const int len, + u_char *digest, const int digest_len); + +static int dst_bsafe_key_size(RSA_Key *r_key); + +static int dst_bsafe_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len); +static int dst_bsafe_verify(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len); +static int dst_bsafe_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len); +static int dst_bsafe_from_dns_key(DST_KEY *s_key, const u_char *key, + const int len); +static int dst_bsafe_key_to_file_format(const DST_KEY *key, char *buff, + const int buff_len); +static int dst_bsafe_key_from_file_format(DST_KEY *d_key, + const char *buff, + const int buff_len); +static int dst_bsafe_generate_keypair(DST_KEY *key, int exp); +static int dst_bsafe_compare_keys(const DST_KEY *key1, const DST_KEY *key2); +static void *dst_bsafe_free_key_structure(void *key); + +/* + * dst_bsafe_init() Function to answer set up function pointers for + * BSAFE/DNSSAFE related functions + */ +int +dst_bsafe_init() +{ + if (dst_t_func[KEY_RSA] != NULL) + return (1); + dst_t_func[KEY_RSA] = malloc(sizeof(struct dst_func)); + if (dst_t_func[KEY_RSA] == NULL) + return (0); + memset(dst_t_func[KEY_RSA], 0, sizeof(struct dst_func)); + dst_t_func[KEY_RSA]->sign = dst_bsafe_sign; + dst_t_func[KEY_RSA]->verify = dst_bsafe_verify; + dst_t_func[KEY_RSA]->compare = dst_bsafe_compare_keys; + dst_t_func[KEY_RSA]->generate = dst_bsafe_generate_keypair; + dst_t_func[KEY_RSA]->destroy = dst_bsafe_free_key_structure; + dst_t_func[KEY_RSA]->from_dns_key = dst_bsafe_from_dns_key; + dst_t_func[KEY_RSA]->to_dns_key = dst_bsafe_to_dns_key; + dst_t_func[KEY_RSA]->from_file_fmt = dst_bsafe_key_from_file_format; + dst_t_func[KEY_RSA]->to_file_fmt = dst_bsafe_key_to_file_format; + return (1); +} + +/* + * dst_bsafe_sign + * Call BSAFE signing functions to sign a block of data. + * There are three steps to signing, INIT (initialize structures), + * UPDATE (hash (more) data), FINAL (generate a signature). This + * routine performs one or more of these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * dkey structure holds context for a sign done in multiple calls. + * context the context to use for this computation + * data data to be signed. + * len length in bytes of data. + * priv_key key to use for signing. + * signature location to store signature. + * sig_len size in bytes of signature field. + * returns + * N Success on SIG_MODE_FINAL = returns signature length in bytes + * 0 Success on SIG_MODE_INIT and UPDATE + * <0 Failure + */ + +static int +dst_bsafe_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len) +{ + u_int sign_len = 0; + int status = 0; + B_ALGORITHM_OBJ *md5_ctx = NULL; + int w_bytes = 0; + u_int u_bytes = 0; + u_char work_area[NS_MD5RSA_MAX_SIZE]; + + if (mode & SIG_MODE_INIT) { + md5_ctx = (B_ALGORITHM_OBJ *) malloc(sizeof(B_ALGORITHM_OBJ)); + if ((status = B_CreateAlgorithmObject(md5_ctx))) + return (-1); + if ((status = B_SetAlgorithmInfo(*md5_ctx, AI_MD5, NULL))) + return (-1); + } + else if (context) + md5_ctx = (B_ALGORITHM_OBJ *) *context; + if (md5_ctx == NULL) + return (-1); + + w_bytes = dst_bsafe_md5digest(mode, md5_ctx, + data, len,work_area, sizeof(work_area)); + if (w_bytes < 0 || (mode & SIG_MODE_FINAL)) { + B_DestroyAlgorithmObject(md5_ctx); + SAFE_FREE(md5_ctx); + if (w_bytes < 0) + return (w_bytes); + } + + if (mode & SIG_MODE_FINAL) { + RSA_Key *key; + int ret = 0; + B_ALGORITHM_OBJ rsaEncryptor = (B_ALGORITHM_OBJ) NULL_PTR; + + if (dkey == NULL || dkey->dk_KEY_struct == NULL) + return (-1); + key = (RSA_Key *) dkey->dk_KEY_struct; + if (key == NULL || key->rk_Private_Key == NULL) + return (-1); + + if ((status = B_CreateAlgorithmObject(&rsaEncryptor))) + return (SIGN_FINAL_FAILURE); + if ((status = B_SetAlgorithmInfo(rsaEncryptor, + AI_PKCS_RSAPrivate, + NULL_PTR))) + + ret = SIGN_FINAL_FAILURE; + if (ret == 0 && + (status = B_EncryptInit(rsaEncryptor, + key->rk_Private_Key, + CHOOSER, NULL_SURRENDER))) + ret = SIGN_FINAL_FAILURE; + if (ret == 0 && + (status = B_EncryptUpdate(rsaEncryptor, signature, + &u_bytes, sig_len, pkcs1, + sizeof(pkcs1), NULL_PTR, + NULL_SURRENDER))) + ret = SIGN_FINAL_FAILURE; + if (ret == 0 && + (status = B_EncryptUpdate(rsaEncryptor, signature, + &u_bytes, sig_len, work_area, + w_bytes, NULL_PTR, + NULL_SURRENDER))) + ret = SIGN_FINAL_FAILURE; + + if (ret == 0 && + (status = B_EncryptFinal(rsaEncryptor, signature + u_bytes, + &sign_len, sig_len - u_bytes, + NULL_PTR, NULL_SURRENDER))) + ret = SIGN_FINAL_FAILURE; + B_DestroyAlgorithmObject(&rsaEncryptor); + if (ret != 0) + return (ret); + + } + else { + if (context == NULL) + return (-1); + *context = (void *) md5_ctx; + } + return (sign_len); +} + + +/* + * Dst_bsafe_verify + * Calls BSAFE verification routines. There are three steps to + * verification, INIT (initialize structures), UPDATE (hash (more) data), + * FINAL (generate a signature). This routine performs one or more of + * these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * dkey structure holds context for a verify done in multiple calls. + * context the context to use for this computation + * data data signed. + * len length in bytes of data. + * pub_key key to use for verify. + * signature signature. + * sig_len length in bytes of signature. + * returns + * 0 Success + * <0 Failure + */ + +static int +dst_bsafe_verify(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len) +{ + B_ALGORITHM_OBJ *md5_ctx = NULL; + u_char digest[DST_HASH_SIZE]; + u_char work_area[DST_HASH_SIZE + sizeof(pkcs1)]; + int status = 0, w_bytes = 0; + u_int u_bytes = 0; + + if (mode & SIG_MODE_INIT) { + md5_ctx = (B_ALGORITHM_OBJ *) malloc(sizeof(B_ALGORITHM_OBJ)); + if ((status = B_CreateAlgorithmObject(md5_ctx))) + return (-1); + if ((status = B_SetAlgorithmInfo(*md5_ctx, AI_MD5, NULL))) + return (-1); + } + else if (context) + md5_ctx = (B_ALGORITHM_OBJ *) *context; + if (md5_ctx == NULL) + return (-1); + + w_bytes = dst_bsafe_md5digest(mode, md5_ctx, data, len, + digest, sizeof(digest)); + + if (w_bytes < 0 || (mode & SIG_MODE_FINAL)) { + B_DestroyAlgorithmObject(md5_ctx); + SAFE_FREE(md5_ctx); + if (w_bytes < 0) + return (-1); + } + + if (mode & SIG_MODE_FINAL) { + RSA_Key *key; + int ret = 0; + B_ALGORITHM_OBJ rsaEncryptor = (B_ALGORITHM_OBJ) NULL_PTR; + + if (dkey == NULL || dkey->dk_KEY_struct == NULL) + return (-1); + key = (RSA_Key *) dkey->dk_KEY_struct; + if (key->rk_Public_Key == NULL) + return (-2); + if (rsaEncryptor == NULL_PTR) { + if ((status = B_CreateAlgorithmObject(&rsaEncryptor))) + ret = SIGN_FINAL_FAILURE; + if (ret == 0 && + (status = B_SetAlgorithmInfo(rsaEncryptor, + AI_PKCS_RSAPublic, + NULL_PTR))) + ret = VERIFY_FINAL_FAILURE; + } + if (ret == 0 && + (status = B_DecryptInit(rsaEncryptor, key->rk_Public_Key, + CHOOSER, NULL_SURRENDER))) + ret = VERIFY_FINAL_FAILURE; + + if (ret == 0 && + (status = B_DecryptUpdate(rsaEncryptor, work_area, + &u_bytes, 0, + (u_char *) signature, sig_len, + NULL_PTR, NULL_SURRENDER))) + ret = VERIFY_FINAL_FAILURE; + + if (ret == 0 && + (status = B_DecryptFinal(rsaEncryptor, work_area + u_bytes, + &u_bytes, + sizeof(work_area) - u_bytes, + NULL_PTR, NULL_SURRENDER))) + ret = VERIFY_FINAL_FAILURE; + B_DestroyAlgorithmObject(&rsaEncryptor); + /* skip PKCS#1 header in output from Decrypt function */ + if (ret) + return (ret); + ret = memcmp(digest, &work_area[sizeof(pkcs1)], w_bytes); + if (ret == 0) + return(0); + else + return(VERIFY_FINAL_FAILURE); + } + else { + if (context == NULL) + return (-1); + *context = (void *) md5_ctx; + } + return (0); +} + + +/* + * dst_bsafe_to_dns_key + * Converts key from RSA to DNS distribution format + * This function gets in a pointer to the public key and a work area + * to write the key into. + * Parameters + * public KEY structure + * out_str buffer to write encoded key into + * out_len size of out_str + * Return + * N >= 0 length of encoded key + * n < 0 error + */ + +static int +dst_bsafe_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len) +{ + B_KEY_OBJ public; + A_RSA_KEY *pub = NULL; + u_char *op = out_str; + int n = 0; + + if (in_key == NULL || in_key->dk_KEY_struct == NULL || + out_len <= 0 || out_str == NULL) + return (-1); + public = (B_KEY_OBJ)((RSA_Key *) in_key->dk_KEY_struct)->rk_Public_Key; + + n = B_GetKeyInfo((POINTER *) &pub, public, KI_RSAPublic); + + if (out_len < pub->exponent.len) /* not enough space */ + return (-1); + if (pub->exponent.len < 256) /* key exponent is <= 2040 bits */ + *op++ = (u_int8_t) pub->exponent.len; + else { /* key exponent is > 2040 bits */ + u_int16_t e = (u_int16_t) pub->exponent.len; + *op++ = 0; /* 3 byte lenght field */ + dst_s_put_int16(op, e); + op += sizeof(e); + n = 2; + } + n += pub->exponent.len; + memcpy(op, pub->exponent.data, n); + op += n; + n++; + + if ((out_len - n) > pub->modulus.len) { + /*copy exponent */ + memcpy(op, pub->modulus.data, pub->modulus.len); + n += pub->modulus.len; + } + else + n = -1; + return (n); +} + + +/* + * dst_bsafe_from_dns_key + * Converts from a DNS KEY RR format to an RSA KEY. + * Parameters + * len Length in bytes of DNS key + * key DNS key + * name Key name + * s_key DST structure that will point to the RSA key this routine + * will build. + * Return + * 0 The input key, s_key or name was null. + * 1 Success + */ +static int +dst_bsafe_from_dns_key(DST_KEY *s_key, const u_char *key, const int len) +{ + int bytes; + const u_char *key_ptr; + RSA_Key *r_key; + A_RSA_KEY *public; + + if (s_key == NULL || len < 0 || key == NULL) + return (0); + + r_key = (RSA_Key *) s_key->dk_KEY_struct; + if (r_key != NULL) /* do not reuse */ + s_key->dk_func->destroy(r_key); + + if (len == 0) + return (1); + + if ((r_key = (RSA_Key *) malloc(sizeof(RSA_Key))) == NULL) { + EREPORT(("dst_bsafe_from_dns_key(): Memory allocation error 1")); + return (0); + } + memset(r_key, 0, sizeof(RSA_Key)); + s_key->dk_KEY_struct = (void *) r_key; + r_key->rk_signer = strdup(s_key->dk_key_name); + + if (B_CreateKeyObject(&r_key->rk_Public_Key) != 0) { + EREPORT(("dst_bsafe_from_dns_key(): Memory allocation error 3")); + s_key->dk_func->destroy(r_key); + return (0); + } + key_ptr = key; + bytes = (int) *key_ptr++; /* length of exponent in bytes */ + if (bytes == 0) { /* special case for long exponents */ + bytes = (int) dst_s_get_int16(key_ptr); + key_ptr += sizeof(u_int16_t); + } + if (bytes > MAX_RSA_MODULUS_LEN) { + dst_bsafe_free_key_structure(r_key); + return (-1); + } + if ((public = (A_RSA_KEY *) malloc(sizeof(A_RSA_KEY))) == NULL) + return (0); + memset(public, 0, sizeof(*public)); + public->exponent.len = bytes; + if ((public->exponent.data = (u_char *) malloc(bytes)) == NULL) + return (0); + memcpy(public->exponent.data, key_ptr, bytes); + + key_ptr += bytes; /* beginning of modulus */ + bytes = len - bytes - 1; /* length of modulus */ + + if (bytes > MAX_RSA_MODULUS_LEN) { + dst_bsafe_free_key_structure(r_key); + return (-1); + } + public->modulus.len = bytes; + if ((public->modulus.data = (u_char *) malloc(bytes)) == NULL) + return (0); + memcpy(public->modulus.data, key_ptr, bytes); + + B_SetKeyInfo(r_key->rk_Public_Key, KI_RSAPublic, (POINTER) public); + + s_key->dk_id = (u_int16_t) + dst_s_get_int16(&public->modulus.data[public->modulus.len - 3]); + s_key->dk_key_size = dst_bsafe_key_size(r_key); + SAFE_FREE(public->modulus.data); + SAFE_FREE(public->exponent.data); + SAFE_FREE(public); + return (1); +} + + +/* + * dst_bsafe_key_to_file_format + * Encodes an RSA Key into the portable file format. + * Parameters + * rkey RSA KEY structure + * buff output buffer + * buff_len size of output buffer + * Return + * 0 Failure - null input rkey + * -1 Failure - not enough space in output area + * N Success - Length of data returned in buff + */ + +static int +dst_bsafe_key_to_file_format(const DST_KEY *key, char *buff, + const int buff_len) +{ + char *bp; + int len, b_len; + B_KEY_OBJ rkey; + A_PKCS_RSA_PRIVATE_KEY *private = NULL; + + if (key == NULL || key->dk_KEY_struct == NULL) /* no output */ + return (0); + if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str)) + return (-1); /* no OR not enough space in output area */ + + rkey = (B_KEY_OBJ)((RSA_Key *) key->dk_KEY_struct)->rk_Private_Key; + + B_GetKeyInfo((POINTER *) &private, rkey, KI_PKCS_RSAPrivate); + + memset(buff, 0, buff_len); /* just in case */ + /* write file header */ + sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_RSA, "RSA"); + + bp = strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Modulus: ", + private->modulus.data, + private->modulus.len)) <= 0) + return (-1); + + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "PublicExponent: ", + private->publicExponent.data, + private->publicExponent.len)) <= 0) + return (-2); + + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "PrivateExponent: ", + private->privateExponent.data, + private->privateExponent.len)) <= 0) + return (-3); + bp += len; + b_len -= len; + + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime1: ", + private->prime[0].data, + private->prime[0].len)) < 0) + return (-4); + bp += len; + b_len -= len; + + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime2: ", + private->prime[1].data, + private->prime[1].len)) < 0) + return (-5); + bp += len; + b_len -= len; + + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Exponent1: ", + private->primeExponent[0].data, + private->primeExponent[0].len)) < 0) + return (-6); + bp += len; + b_len -= len; + + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Exponent2: ", + private->primeExponent[1].data, + private->primeExponent[1].len)) < 0) + return (-7); + bp += len; + b_len -= len; + + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Coefficient: ", + private->coefficient.data, + private->coefficient.len)) < 0) + return (-8); + bp += len; + b_len -= len; + return (buff_len - b_len); +} + + +/* + * dst_bsafe_key_from_file_format + * Converts contents of a private key file into a private RSA key. + * Parameters + * RSA_Key structure to put key into + * buff buffer containing the encoded key + * buff_len the length of the buffer + * Return + * n >= 0 Foot print of the key converted + * n < 0 Error in conversion + */ + +static int +dst_bsafe_key_from_file_format(DST_KEY *d_key, const char *buff, + const int buff_len) +{ + int status; + char s[RAW_KEY_SIZE]; + int len, s_len = sizeof(s); + int tag = -1; + const char *p = buff; + RSA_Key *b_key; + A_RSA_KEY *public; + A_PKCS_RSA_PRIVATE_KEY *private; + + if (d_key == NULL || buff == NULL || buff_len <= 0) + return (-1); + + b_key = (RSA_Key *) malloc(sizeof(RSA_Key)); + public = (A_RSA_KEY *) malloc(sizeof(A_RSA_KEY)); + private = (A_PKCS_RSA_PRIVATE_KEY *) + malloc(sizeof(A_PKCS_RSA_PRIVATE_KEY)); + if (b_key == NULL || private == NULL || public == NULL) { + SAFE_FREE(b_key); + SAFE_FREE(public); + SAFE_FREE(private); + return (-2); + } + memset(b_key, 0, sizeof(*b_key)); + memset(public, 0, sizeof(A_RSA_KEY)); + memset(private, 0, sizeof(A_PKCS_RSA_PRIVATE_KEY)); + d_key->dk_KEY_struct = (void *) b_key; + if (!dst_s_verify_str(&p, "Modulus: ")) + return (-3); + memset(s, 0, s_len); + if ((len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, s_len)) == 0) + return (-4); + + private->modulus.len = len; + if ((private->modulus.data = malloc(len)) == NULL) + return (-5); + memcpy(private->modulus.data, s + s_len - len, len); + + while (*(++p) && p < (const char *) &buff[buff_len]) { + if (dst_s_verify_str(&p, "PublicExponent: ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, s_len))) + return (-5); + private->publicExponent.len = len; + if ((private->publicExponent.data = malloc(len)) + == NULL) + return (-6); + memcpy(private->publicExponent.data, + s + s_len - len, len); + } else if (dst_s_verify_str(&p, "PrivateExponent: ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, s_len))) + return (-6); + private->privateExponent.len = len; + if ((private->privateExponent.data = malloc(len)) + == NULL) + return (-7); + memcpy(private->privateExponent.data, s + s_len - len, + len); + } else if (dst_s_verify_str(&p, "Prime1: ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, + MAX_RSA_PRIME_LEN))) + return (-7); + private->prime[0].len = len; + if ((private->prime[0].data = malloc(len)) == NULL) + return (-8); + memcpy(private->prime[0].data, + s + MAX_RSA_PRIME_LEN - len, len); + } else if (dst_s_verify_str(&p, "Prime2: ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, + MAX_RSA_PRIME_LEN))) + return (-8); + private->prime[1].len = len; + if ((private->prime[1].data = malloc(len)) == NULL) + return (-9); + memcpy(private->prime[1].data, + s + MAX_RSA_PRIME_LEN - len, len); + } else if (dst_s_verify_str(&p, "Exponent1: ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, + MAX_RSA_PRIME_LEN))) + return (-9); + private->primeExponent[0].len = len; + if ((private->primeExponent[0].data = malloc(len)) + == NULL) + return (-10); + memcpy(private->primeExponent[0].data, + s + MAX_RSA_PRIME_LEN - len, len); + } else if (dst_s_verify_str(&p, "Exponent2: ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, + MAX_RSA_PRIME_LEN))) + return (-10); + private->primeExponent[1].len = len; + if ((private->primeExponent[1].data = malloc(len)) + == NULL) + return (-11); + memcpy(private->primeExponent[1].data, + s + MAX_RSA_PRIME_LEN - len, len); + } else if (dst_s_verify_str(&p, "Coefficient: ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, + MAX_RSA_PRIME_LEN))) + return (-11); + private->coefficient.len = len; + if ((private->coefficient.data = malloc(len)) == NULL) + return (-12); + memcpy(private->coefficient.data, + s + MAX_RSA_PRIME_LEN - len, len); + } else { + EREPORT(("Decode_RSAKey(): Bad keyword %s\n", p)); + return (-12); + } + } /* while p */ + + public->modulus.len = private->modulus.len; + if ((public->modulus.data = (u_char *) malloc(public->modulus.len)) == + NULL) + return (-13); + memcpy(public->modulus.data, private->modulus.data, + private->modulus.len); + + public->exponent.len = private->publicExponent.len; + if ((public->exponent.data = (u_char *) malloc(public->exponent.len)) + == NULL) + return (-14); + memcpy(public->exponent.data, private->publicExponent.data, + private->publicExponent.len); + + status = B_CreateKeyObject(&(b_key->rk_Public_Key)); + if (status) + return (-1); + status = B_SetKeyInfo(b_key->rk_Public_Key, KI_RSAPublic, + (POINTER) public); + if (status) + return (-1); + + status = B_CreateKeyObject(&b_key->rk_Private_Key); + if (status) + return (-1); + status = B_SetKeyInfo(b_key->rk_Private_Key, KI_PKCS_RSAPrivate, + (POINTER) private); + if (status) + return (-1); + + tag = (int)(u_int16_t) + dst_s_get_int16(&public->modulus.data[public->modulus.len - 3]); + d_key->dk_key_size = dst_bsafe_key_size(b_key); + + SAFE_FREE(private->modulus.data); + SAFE_FREE(private->publicExponent.data); + SAFE_FREE(private->privateExponent.data); + SAFE_FREE(private->prime[0].data); + SAFE_FREE(private->prime[1].data); + SAFE_FREE(private->primeExponent[0].data); + SAFE_FREE(private->primeExponent[1].data); + SAFE_FREE(private->coefficient.data); + SAFE_FREE(private); /* is this the right thing to do ??? XXXX */ + SAFE_FREE(public->modulus.data); + SAFE_FREE(public->exponent.data); + SAFE_FREE(public); + return (tag); +} + + +/* + * dst_bsafe_free_key_structure + * Frees all dynamicly allocated structures in RSA_Key. + */ + +static void * +dst_bsafe_free_key_structure(void *key) +{ + RSA_Key *r_key = (RSA_Key *) key; + if (r_key != NULL) { + if (r_key->rk_Private_Key) + B_DestroyKeyObject(&r_key->rk_Private_Key); + if (r_key->rk_Public_Key) + B_DestroyKeyObject(&r_key->rk_Public_Key); + SAFE_FREE2(r_key->rk_signer, strlen(r_key->rk_signer)); + SAFE_FREE(r_key); + } + return (NULL); +} + + +/* + * dst_bsafe_generate_keypair + * Generates unique keys that are hard to predict. + * Parameters + * key generic Key structure + * exp the public exponent + * Return + * 0 Failure + * 1 Success + */ + +static int +dst_bsafe_generate_keypair(DST_KEY *key, int exp) +{ + int i, status; + B_KEY_OBJ private; + B_KEY_OBJ public; + B_ALGORITHM_OBJ keypairGenerator; + B_ALGORITHM_OBJ randomAlgorithm; + A_RSA_KEY_GEN_PARAMS keygenParams; + char exponent[4]; + int exponent_len; + RSA_Key *rsa; + POINTER randomSeed = NULL_PTR; + int randomSeedLen; + A_RSA_KEY *pk_access = NULL; + + if (key == NULL || key->dk_alg != KEY_RSA) + return (0); + + if ((rsa = (RSA_Key *) malloc(sizeof(RSA_Key))) == NULL) { + EREPORT(("dst_bsafe_generate_keypair: Memory allocation error 3")); + return (0); + } + memset(rsa, 0, sizeof(*rsa)); + + if ((status = B_CreateAlgorithmObject(&keypairGenerator)) != 0) + return (0); + + keygenParams.modulusBits = key->dk_key_size; + + /* exp = 0 or 1 are special (mean 3 or F4) */ + if (exp == 0) + exp = 3; + else if (exp == 1) + exp = 65537; + + /* Now encode the exponent and its length */ + if (exp < 256) { + exponent_len = 1; + exponent[0] = exp; + } else if (exp < (1 << 16)) { + exponent_len = 2; + exponent[0] = exp >> 8; + exponent[1] = exp; + } else if (exp < (1 << 24)) { + exponent_len = 3; + exponent[0] = exp >> 16; + exponent[1] = exp >> 8; + exponent[2] = exp; + } else { + exponent_len = 4; + exponent[0] = exp >> 24; + exponent[1] = exp >> 16; + exponent[2] = exp >> 8; + exponent[3] = exp; + } + + if ((keygenParams.publicExponent.data = (u_char *) malloc(exponent_len)) + == NULL) + return (0); + memcpy(keygenParams.publicExponent.data, exponent, exponent_len); + keygenParams.publicExponent.len = exponent_len; + if ((status = B_SetAlgorithmInfo + (keypairGenerator, AI_RSAKeyGen, (POINTER) &keygenParams)) != 0) + return (0); + + if ((status = B_GenerateInit(keypairGenerator, CHOOSER, + NULL_SURRENDER)) != 0) + return (0); + + if ((status = B_CreateKeyObject(&public)) != 0) + return (0); + + if ((status = B_CreateKeyObject(&private)) != 0) + return (0); + + if ((status = B_CreateAlgorithmObject(&randomAlgorithm)) != 0) + return (0); + + if ((status = B_SetAlgorithmInfo(randomAlgorithm, AI_MD5Random, + NULL_PTR)) + != 0) + return (0); + + if ((status = B_RandomInit(randomAlgorithm, CHOOSER, + NULL_SURRENDER)) != 0) + return (0); + + randomSeedLen = 256; + if ((randomSeed = malloc(randomSeedLen)) == NULL) + return (0); + if ((status = (randomSeed == NULL_PTR)) != 0) + return (0); + + /* gets random seed from /dev/random if present, generates random + * values if it is not present. + * first fill the buffer with semi random data + * then fill as much as possible with good random data + */ + i = dst_random(DST_RAND_SEMI, randomSeedLen, randomSeed); + i += dst_random(DST_RAND_KEY, randomSeedLen, randomSeed); + + if (i <= randomSeedLen) { + SAFE_FREE(rsa); + return(0); + } + if ((status = B_RandomUpdate(randomAlgorithm, randomSeed, + randomSeedLen, NULL_SURRENDER)) != 0) { + SAFE_FREE(rsa); + return (0); + } + SAFE_FREE2(randomSeed, randomSeedLen); + if ((status = B_GenerateKeypair(keypairGenerator, public, private, + randomAlgorithm, NULL_SURRENDER)) + != 0) { + SAFE_FREE(rsa); + return (0); + } + rsa->rk_signer = strdup(key->dk_key_name); + rsa->rk_Private_Key = private; + rsa->rk_Public_Key = public; + key->dk_KEY_struct = (void *) rsa; + + /* fill in the footprint on generate key */ + B_GetKeyInfo((POINTER *) &pk_access, public, KI_RSAPublic); + key->dk_id = (u_int16_t) + dst_s_get_int16(&pk_access->modulus.data[pk_access->modulus.len - 3]); + return (1); +} + + +/************************************************************************** + * dst_bsafe_compare_keys + * Compare two keys for equality. + * Return + * 0 The keys are equal + * NON-ZERO The keys are not equal + */ + +static int +dst_s_bsafe_itemcmp(ITEM i1, ITEM i2) +{ + if (i1.len != i2.len || memcmp (i1.data, i2.data, i1.len)) + return (1); + else + return (0); +} + +static int +dst_bsafe_compare_keys(const DST_KEY *key1, const DST_KEY *key2) +{ + int status, s1 = 0, s2 = 0; + RSA_Key *rkey1 = (RSA_Key *) key1->dk_KEY_struct; + RSA_Key *rkey2 = (RSA_Key *) key2->dk_KEY_struct; + A_RSA_KEY *public1 = NULL, *public2 = NULL; + A_PKCS_RSA_PRIVATE_KEY *p1 = NULL, *p2 = NULL; + + if (rkey1 == NULL && rkey2 == NULL) + return(0); + else if (rkey1 == NULL) + return (1); + else if (rkey2 == NULL) + return (2); + + if (rkey1->rk_Public_Key) + B_GetKeyInfo((POINTER *) &public1, rkey1->rk_Public_Key, + KI_RSAPublic); + if (rkey2->rk_Public_Key) + B_GetKeyInfo((POINTER *) &public2, rkey2->rk_Public_Key, + KI_RSAPublic); + if (public1 == NULL && public2 == NULL) + return (0); + else if (public1 == NULL || public2 == NULL) + return (1); + + status = dst_s_bsafe_itemcmp(public1->modulus, public2->modulus) || + dst_s_bsafe_itemcmp(public1->exponent, public2->exponent); + + if (status) + return (status); + + if (rkey1->rk_Private_Key == NULL || rkey2->rk_Private_Key == NULL) + /* if neither or only one is private key consider identical */ + return (status); + if (rkey1->rk_Private_Key) + s1 = B_GetKeyInfo((POINTER *) &p1, rkey1->rk_Private_Key, + KI_PKCS_RSAPrivate); + if (rkey2->rk_Private_Key) + s2 = B_GetKeyInfo((POINTER *) &p2, rkey2->rk_Private_Key, + KI_PKCS_RSAPrivate); + if (p1 == NULL || p2 == NULL) + return (0); + + status = dst_s_bsafe_itemcmp(p1->modulus, p2->modulus) || + dst_s_bsafe_itemcmp (p1->publicExponent, + p2->publicExponent) || + dst_s_bsafe_itemcmp (p1->privateExponent, + p2->privateExponent) || + dst_s_bsafe_itemcmp (p1->prime[0], p2->prime[0]) || + dst_s_bsafe_itemcmp (p1->prime[1], p2->prime[1]) || + dst_s_bsafe_itemcmp (p1->primeExponent[0], + p2->primeExponent[0])|| + dst_s_bsafe_itemcmp (p1->primeExponent[1], + p2->primeExponent[1])|| + dst_s_bsafe_itemcmp (p1->coefficient, p2->coefficient); + return (status); +} + + +/* + * dst_bsafe_key_size() + * Function to calculate how the size of the key in bits + */ +static int +dst_bsafe_key_size(RSA_Key *r_key) +{ + int size; + A_PKCS_RSA_PRIVATE_KEY *private = NULL; + + if (r_key == NULL) + return (-1); + if (r_key->rk_Private_Key) + B_GetKeyInfo((POINTER *) &private, r_key->rk_Private_Key, + KI_PKCS_RSAPrivate); + else if (r_key->rk_Public_Key) + B_GetKeyInfo((POINTER *) &private, r_key->rk_Public_Key, + KI_RSAPublic); + size = dst_s_calculate_bits(private->modulus.data, + private->modulus.len * 8); + return (size); +} + +/* + * dst_bsafe_md5digest(): function to digest data using MD5 digest function + * if needed + */ +static int +dst_bsafe_md5digest(const int mode, B_ALGORITHM_OBJ *digest_obj, + const u_char *data, const int len, + u_char *digest, const int digest_len) +{ + int status = 0; + u_int work_size = 0; + + if (digest_obj == NULL || *digest_obj == NULL) { + printf("NO digest obj\n"); + exit(-33); + } + + if ((mode & SIG_MODE_INIT) && + (status = B_DigestInit(*digest_obj, (B_KEY_OBJ) NULL, + CHOOSER, NULL_SURRENDER))) + return (SIGN_INIT_FAILURE); + + if ((mode & SIG_MODE_UPDATE) && data && (len > 0) && + (status = B_DigestUpdate(*digest_obj, (u_char *) data, len, + NULL_SURRENDER))) + return (SIGN_UPDATE_FAILURE); + + if (mode & SIG_MODE_FINAL) { + if (digest == NULL || + (status = B_DigestFinal(*digest_obj, digest, &work_size, + digest_len, NULL_SURRENDER))) + return (SIGN_FINAL_FAILURE); + return (work_size); + } + return (0); +} + +/* + * just use the standard memory functions for bsafe + */ +void +T_free(POINTER block) +{ + free(block); +} + +POINTER +T_malloc(unsigned int len) +{ + return (malloc(len)); +} + +int +T_memcmp(POINTER firstBlock, POINTER secondBlock, unsigned int len) +{ + return (memcmp(firstBlock, secondBlock, len)); +} + +void +T_memcpy(POINTER output, POINTER input, unsigned int len) +{ + memcpy(output, input, len); +} + +void +T_memmove(POINTER output, POINTER input, unsigned int len) +{ + memmove(output, input, len); +} + +void +T_memset(POINTER output, int value, unsigned int len) +{ + memset(output, value, len); +} + +POINTER +T_realloc(POINTER block, unsigned int len) +{ + return (realloc(block, len)); +} + +#else /* BSAFE NOT available */ +int +dst_bsafe_init() +{ + return (0); +} +#endif /* BSAFE */ Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/bsafe_link.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/cylink_link.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/cylink_link.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/cylink_link.c (revision 60942) @@ -0,0 +1,676 @@ +#ifdef CYLINK_DSS +static const char rcsid[] = "$Header: /proj/cvs/isc/bind/src/lib/dst/cylink_link.c,v 1.7 1999/10/13 16:39:22 vixie Exp $"; + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, 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 TRUSTED INFORMATION SYSTEMS + * 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. + */ +/* + * This file contains two components + * 1. Interface to the CYLINK library to allow compilation of Bind + * with TIS/DNSSEC when CYLINK is not available + * all calls to CYLINK are contained inside this file. + * 2. The glue to connvert DSA KEYS to and from external formats + */ +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dst_internal.h" +#include + +#include "port_after.h" + +typedef struct cylinkkey { + char *dk_signer; + uchar *dk_p; + uchar *dk_q; + uchar *dk_g; + uchar *dk_x; + uchar *dk_y; + ushort dk_p_bytes; +} DSA_Key; + +#define NULL_PRIV_KEY(k)(k == NULL || k->dk_p == NULL || k->dk_q == NULL || \ + k->dk_g == NULL || k->dk_x == NULL) +#define NULL_PUB_KEY(k)(k == NULL || k->dk_p == NULL || k->dk_q == NULL || \ + k->dk_g == NULL || k->dk_y == NULL) + +static int dst_cylink_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len); + +static int dst_cylink_verify(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len); + +static int dst_cylink_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len); +static int dst_cylink_from_dns_key(DST_KEY *s_key, const u_char *key, + const int len); +static int dst_cylink_key_to_file_format(const DST_KEY *key, char *buff, + const int buff_len); +static int dst_cylink_key_from_file_format(DST_KEY *d_key, + const char *buff, + const int buff_len); +static void *dst_cylink_free_key_structure(void *key); + +static int dst_cylink_generate_keypair(DST_KEY *key, int exp); +static int dst_cylink_compare_keys(const DST_KEY *key1, const DST_KEY *key2); + +static void *memcpyend(void *dest, const void *src, size_t n, size_t size); + +/* + * dst_cylink_init() Function to answer set up function pointers for + * CYLINK related functions + */ +int +dst_cylink_init() +{ + if (dst_t_func[KEY_DSA] != NULL) + return (1); + dst_t_func[KEY_DSA] = malloc(sizeof(struct dst_func)); + if (dst_t_func[KEY_DSA] == NULL) + return (0); + memset(dst_t_func[KEY_DSA], 0, sizeof(struct dst_func)); + dst_t_func[KEY_DSA]->sign = dst_cylink_sign; + dst_t_func[KEY_DSA]->verify = dst_cylink_verify; + dst_t_func[KEY_DSA]->compare = dst_cylink_compare_keys; + dst_t_func[KEY_DSA]->generate = dst_cylink_generate_keypair; + dst_t_func[KEY_DSA]->destroy = dst_cylink_free_key_structure; + dst_t_func[KEY_DSA]->from_dns_key = dst_cylink_from_dns_key; + dst_t_func[KEY_DSA]->to_dns_key = dst_cylink_to_dns_key; + dst_t_func[KEY_DSA]->from_file_fmt = dst_cylink_key_from_file_format; + dst_t_func[KEY_DSA]->to_file_fmt = dst_cylink_key_to_file_format; + SetDataOrder(1); + return (1); +} + +/* + * dst_cylink_sign + * Call CYLINK signing functions to sign a block of data. + * There are three steps to signing, INIT (initialize structures), + * UPDATE (hash (more) data), FINAL (generate a signature). This + * routine performs one or more of these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * algobj structure holds context for a sign done in multiple calls. + * context the context to use for this computation + * data data to be signed. + * len length in bytes of data. + * priv_key key to use for signing. + * signature location to store signature. + * sig_len size in bytes of signature field. + * returns + * N Success on SIG_MODE_FINAL = returns signature length in bytes + * N is 41 for DNS + * 0 Success on SIG_MODE_INIT and UPDATE + * <0 Failure + */ + +static int +dst_cylink_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len) +{ + int sign_len = 0; + int status; + SHA_context *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = (SHA_context *) malloc(sizeof(SHA_context)); + else if (context) + ctx = (SHA_context *) *context; + if (ctx == NULL) + return (-1); + + if (mode & SIG_MODE_INIT) + SHAInit(ctx); + + if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) { + status = SHAUpdate(ctx, (u_char *) data, len); + if (status != SUCCESS) + return (SIGN_UPDATE_FAILURE); + } + if (mode & SIG_MODE_FINAL) { + DSA_Key *key; + uchar digest[SHA_LENGTH]; + uchar rand[SHA_LENGTH]; + uchar r[SHA_LENGTH], s[SHA_LENGTH]; + + if (signature == NULL || sig_len < 2 * SHA_LENGTH) + return (SIGN_FINAL_FAILURE); + if ((status = SHAFinal(ctx, digest)) != SUCCESS) + return (SIGN_FINAL_FAILURE); + SAFE_FREE(ctx); + if (dkey == NULL || dkey->dk_KEY_struct == NULL) + return (-1); + key = (DSA_Key *) dkey->dk_KEY_struct; + if (NULL_PRIV_KEY(key)) + return (-2); + dst_random(DST_RAND_STD, sizeof(rand), rand); + status = GenDSSSignature(key->dk_p_bytes, key->dk_p, + key->dk_q, key->dk_g, key->dk_x, + rand, r, s, digest); + if (status != SUCCESS) + return (SIGN_FINAL_FAILURE); + *signature = (dkey->dk_key_size - 512)/64; + sign_len = 1; + memcpy(signature + sign_len, r, SHA_LENGTH); + sign_len += SHA_LENGTH; + memcpy(signature + sign_len, s, SHA_LENGTH); + sign_len += SHA_LENGTH; + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + return (sign_len); +} + + +/* + * Dst_cylink_verify + * Calls CYLINK verification routines. There are three steps to + * verification, INIT (initialize structures), UPDATE (hash (more) data), + * FINAL (generate a signature). This routine performs one or more of + * these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * dkey structure holds context for a verify done in multiple calls. + * context algorithm specific context for the current context processing + * data data signed. + * len length in bytes of data. + * pub_key key to use for verify. + * signature signature. + * sig_len length in bytes of signature. + * returns + * 0 Success + * <0 Failure + */ + +static int +dst_cylink_verify(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len) +{ + int status; + SHA_context *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = (SHA_context *) malloc(sizeof(SHA_context)); + else if (context) + ctx = (SHA_context *) *context; + if (ctx == NULL) + return (-1); + + if (mode & SIG_MODE_INIT) + SHAInit(ctx); + + if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) { + status = SHAUpdate(ctx, (u_char *) data, len); + if (status != SUCCESS) + return (VERIFY_UPDATE_FAILURE); + } + if (mode & SIG_MODE_FINAL) { + DSA_Key *key; + uchar digest[SHA_LENGTH]; + uchar r[SHA_LENGTH], s[SHA_LENGTH]; + + if (dkey == NULL || dkey->dk_KEY_struct == NULL) + return (-1); + key = (DSA_Key *) dkey->dk_KEY_struct; + if (NULL_PUB_KEY(key)) + return (-2); + if (signature == NULL || sig_len != (2 * SHA_LENGTH +1)) + return (SIGN_FINAL_FAILURE); + status = SHAFinal(ctx, digest); + SAFE_FREE(ctx); + if (status != SUCCESS) + return (SIGN_FINAL_FAILURE); + if (((int)*signature) != ((key->dk_p_bytes -64)/8)) + return(VERIFY_FINAL_FAILURE); + + memcpy(r, signature +1, SHA_LENGTH); + memcpy(s, signature + SHA_LENGTH +1, SHA_LENGTH); + status = VerDSSSignature(key->dk_p_bytes, key->dk_p, + key->dk_q, key->dk_g, key->dk_y, + r, s, digest); + if (status != SUCCESS) + return (VERIFY_FINAL_FAILURE); + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + return (0); +} + + +/* + * dst_cylink_to_dns_key + * Converts key from DSA to DNS distribution format + * This function gets in a pointer to the public key and a work area + * to write the key into. + * Parameters + * public KEY structure + * out_str buffer to write encoded key into + * out_len size of out_str + * Return + * N >= 0 length of encoded key + * n < 0 error + */ + +static int +dst_cylink_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len) +{ + u_char *op = out_str; + int t; + DSA_Key *key; + + if (in_key == NULL || in_key->dk_KEY_struct == NULL || + out_len <= 0 || out_str == NULL) + return (-1); + key = (DSA_Key *) in_key->dk_KEY_struct; + + t = (key->dk_p_bytes - 64) / 8; + + *op++ = t; + memcpy(op, key->dk_q, SHA_LENGTH); + op += SHA_LENGTH; + memcpy(op, key->dk_p, key->dk_p_bytes); + op += key->dk_p_bytes; + memcpy(op, key->dk_g, key->dk_p_bytes); + op += key->dk_p_bytes; + memcpy(op, key->dk_y, key->dk_p_bytes); + op += key->dk_p_bytes; + + return (op - out_str); +} + + +/* + * dst_cylink_from_dns_key + * Converts from a DNS KEY RR format to an RSA KEY. + * Parameters + * len Length in bytes of DNS key + * key DNS key + * name Key name + * s_key DST structure that will point to the RSA key this routine + * will build. + * Return + * 0 The input key, s_key or name was null. + * 1 Success + */ +static int +dst_cylink_from_dns_key(DST_KEY *s_key, const u_char *key, const int len) +{ + int t; + const u_char *key_ptr = key; + DSA_Key *d_key; + + if (s_key == NULL || len < 0 || key == NULL) + return (0); + + if (len == 0) /* process null key */ + return (1); + + if (key_ptr == NULL) + return (0); + t = (int) *key_ptr++; /* length of exponent in bytes */ + + if ((3 * (t * 8 + 64) + SHA_LENGTH + 1) != len) + return (0); + + if ((d_key = (DSA_Key *) malloc(sizeof(DSA_Key))) == NULL) { + EREPORT(("dst_cylink_from_dns_key(): Memory allocation error 1")); + return (0); + } + memset(d_key, 0, sizeof(DSA_Key)); + s_key->dk_KEY_struct = (void *) d_key; + d_key->dk_signer = strdup(s_key->dk_key_name); + d_key->dk_p_bytes = 64 + 8 * t; + + if ((d_key->dk_q = (uchar *) malloc(SHA_LENGTH)) == NULL) + return (0); + memcpy(d_key->dk_q, key_ptr, SHA_LENGTH); + key_ptr += SHA_LENGTH; + + if ((d_key->dk_p = (uchar *) malloc(d_key->dk_p_bytes)) == NULL) + return (0); + memcpy(d_key->dk_p, key_ptr, d_key->dk_p_bytes); + key_ptr += d_key->dk_p_bytes; + + if ((d_key->dk_g = (uchar *) malloc(d_key->dk_p_bytes)) == NULL) + return (0); + memcpy(d_key->dk_g, key_ptr, d_key->dk_p_bytes); + key_ptr += d_key->dk_p_bytes; + + if ((d_key->dk_y = (uchar *) malloc(d_key->dk_p_bytes)) == NULL) + return (0); + memcpy(d_key->dk_y, key_ptr, d_key->dk_p_bytes); + key_ptr += d_key->dk_p_bytes; + + s_key->dk_id = dst_s_id_calc(key, len); + s_key->dk_key_size = d_key->dk_p_bytes * 8; + return (1); +} + + +/************************************************************************** + * dst_cylink_key_to_file_format + * Encodes an DSA Key into the portable file format. + * Parameters + * key DSA KEY structure + * buff output buffer + * buff_len size of output buffer + * Return + * 0 Failure - null input rkey + * -1 Failure - not enough space in output area + * N Success - Length of data returned in buff + */ + +static int +dst_cylink_key_to_file_format(const DST_KEY *key, char *buff, + const int buff_len) +{ + char *bp; + int len, b_len; + DSA_Key *dkey; + u_char num[256]; /* More than long enough for DSA keys */ + + if (key == NULL || key->dk_KEY_struct == NULL) /* no output */ + return (0); + if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str)) + return (-1); /* no OR not enough space in output area */ + + dkey = (DSA_Key *) key->dk_KEY_struct; + + memset(buff, 0, buff_len); /* just in case */ + /* write file header */ + sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_DSA, "DSA"); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->dk_p, dkey->dk_p_bytes); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime(p): ", + num, dkey->dk_p_bytes)) <= 0) + return (-1); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->dk_q, dkey->dk_p_bytes); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Subprime(q): ", + num, SHA_LENGTH)) <= 0) + return (-2); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->dk_g, dkey->dk_p_bytes); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Base(g): ", + num, dkey->dk_p_bytes)) <= 0) + return (-3); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->dk_x, dkey->dk_p_bytes); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Private_value(x): ", + num, SHA_LENGTH)) <= 0) + return (-4); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->dk_y, dkey->dk_p_bytes); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Public_value(y): ", + num, dkey->dk_p_bytes)) <= 0) + return (-4); + + bp += len; + b_len -= len; + return (buff_len - b_len); +} + + +/************************************************************************** + * dst_cylink_key_from_file_format + * Converts contents of a private key file into a private DSA key. + * Parameters + * DSA_Key structure to put key into + * buff buffer containing the encoded key + * buff_len the length of the buffer + * Return + * n >= 0 Foot print of the key converted + * n < 0 Error in conversion + */ + +static int +dst_cylink_key_from_file_format(DST_KEY *d_key, const char *buff, + const int buff_len) +{ + u_char s[DSS_LENGTH_MAX]; + u_char dns[1024]; + int len, s_len = sizeof(s); + int foot = -1, dnslen; + const char *p = buff; + DSA_Key *dsa_key; + + if (d_key == NULL || buff == NULL || buff_len <= 0) + return (-1); + + dsa_key = (DSA_Key *) malloc(sizeof(DSA_Key)); + if (dsa_key == NULL) { + return (-2); + } + memset(dsa_key, 0, sizeof(*dsa_key)); + d_key->dk_KEY_struct = (void *) dsa_key; + + if (!dst_s_verify_str(&p, "Prime(p): ")) + return (-3); + memset(s, 0, s_len); + if ((len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)) == 0) + return (-4); + dsa_key->dk_p_bytes = len; + if ((dsa_key->dk_p = malloc(len)) == NULL) + return (-5); + memcpy(dsa_key->dk_p, s + s_len - len, len); + + while (*++p && p < (const char *) &buff[buff_len]) { + if (dst_s_verify_str(&p, "Subprime(q): ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len))) + return (-6); + if ((dsa_key->dk_q = malloc(SHA_LENGTH)) == NULL) + return (-7); + memcpyend(dsa_key->dk_q, s + s_len - len, len, + SHA_LENGTH); + } else if (dst_s_verify_str(&p, "Base(g): ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len))) + return (-8); + if ((dsa_key->dk_g = malloc(dsa_key->dk_p_bytes)) + == NULL) + return (-9); + memcpyend(dsa_key->dk_g, s + s_len - len, len, + dsa_key->dk_p_bytes); + } else if (dst_s_verify_str(&p, "Private_value(x): ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len))) + return (-10); + if ((dsa_key->dk_x = malloc(SHA_LENGTH)) == NULL) + return (-11); + memcpyend(dsa_key->dk_x, s + s_len - len, len, + SHA_LENGTH); + } else if (dst_s_verify_str(&p, "Public_value(y): ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len))) + return (-10); + if ((dsa_key->dk_y = malloc(dsa_key->dk_p_bytes)) + == NULL) + return (-11); + memcpyend(dsa_key->dk_y, s + s_len - len, len, + dsa_key->dk_p_bytes); + } else { + EREPORT(("Decode_DSAKey(): Bad keyword %s\n", p)); + return (-12); + } + } /* while p */ + + d_key->dk_key_size = dsa_key->dk_p_bytes * 8; + dnslen = d_key->dk_func->to_dns_key(d_key, dns, sizeof(dns)); + foot = dst_s_id_calc(dns, dnslen); + + return (foot); +} + + +/************************************************************************** + * dst_cylink_free_key_structure + * Frees all dynamicly allocated structures in DSA_Key. + */ + +static void * +dst_cylink_free_key_structure(void *key) +{ + DSA_Key *d_key = (DSA_Key *) key; + if (d_key != NULL) { + SAFE_FREE(d_key->dk_signer); + SAFE_FREE(d_key->dk_p); + SAFE_FREE(d_key->dk_q); + SAFE_FREE(d_key->dk_g); + SAFE_FREE(d_key->dk_x); + SAFE_FREE(d_key->dk_y); + SAFE_FREE(d_key); + } + return (NULL); +} + + +/************************************************************************** + * dst_cylink_generate_keypair + * Generates unique keys that are hard to predict. + * Parameters + * key generic Key structure + * exp the public exponent + * Return + * 0 Failure + * 1 Success + */ + +static int +dst_cylink_generate_keypair(DST_KEY *key, int nothing) +{ + int status, dnslen, n; + DSA_Key *dsa; + u_char rand[SHA_LENGTH]; + u_char dns[1024]; + + if (key == NULL || key->dk_alg != KEY_DSA) + return (0); + + if ((dsa = (DSA_Key *) malloc(sizeof(DSA_Key))) == NULL) { + EREPORT(("dst_cylink_generate_keypair: Memory allocation error 3")); + return (0); + } + memset(dsa, 0, sizeof(*dsa)); + + dsa->dk_p_bytes = key->dk_key_size / 8; + dsa->dk_p = (uchar *) malloc(dsa->dk_p_bytes); + dsa->dk_q = (uchar *) malloc(SHA_LENGTH); + dsa->dk_g = (uchar *) malloc(dsa->dk_p_bytes); + dsa->dk_x = (uchar *) malloc(SHA_LENGTH); + dsa->dk_y = (uchar *) malloc(dsa->dk_p_bytes); + if (!dsa->dk_p || !dsa->dk_q || !dsa->dk_g || !dsa->dk_x || !dsa->dk_y) { + EREPORT(("dst_cylink_generate_keypair: Memory allocation error 4")); + return (0); + } + n = dst_random(DST_RAND_KEY, sizeof(rand), rand); + if (n != sizeof(rand)) + return (0); + status = GenDSSParameters(dsa->dk_p_bytes, dsa->dk_p, dsa->dk_q, + dsa->dk_g, rand, NULL); + if (status != SUCCESS) + return (0); + + status = GenDSSKey(dsa->dk_p_bytes, dsa->dk_p, dsa->dk_q, dsa->dk_g, + dsa->dk_x, dsa->dk_y, rand); + if (status != SUCCESS) + return (0); + memset(rand, 0, sizeof(rand)); + key->dk_KEY_struct = (void *) dsa; + dnslen = key->dk_func->to_dns_key(key, dns, sizeof(dns)); + key->dk_id = dst_s_id_calc(dns, dnslen); + return (1); +} + + +/* + * dst_cylink_compare_keys + * Compare two keys for equality. + * Return + * 0 The keys are equal + * NON-ZERO The keys are not equal + */ + +static int +dst_cylink_compare_keys(const DST_KEY *key1, const DST_KEY *key2) +{ + int status; + DSA_Key *dkey1 = (DSA_Key *) key1->dk_KEY_struct; + DSA_Key *dkey2 = (DSA_Key *) key2->dk_KEY_struct; + + if (dkey1 == NULL && dkey2 == NULL) + return (0); + else if (dkey1 == NULL) + return (2); + else if (dkey2 == NULL) + return(1); + + if (dkey1->dk_p_bytes != dkey2->dk_p_bytes) + return (201); + status = memcmp(dkey1->dk_p, dkey2->dk_p, dkey1->dk_p_bytes) || + memcmp(dkey1->dk_q, dkey2->dk_q, SHA_LENGTH) || + memcmp(dkey1->dk_g, dkey2->dk_g, dkey1->dk_p_bytes) || + memcmp(dkey1->dk_y, dkey2->dk_y, dkey1->dk_p_bytes); + if (status) + return (status); + if (dkey1->dk_x || dkey2->dk_x) { + if (dkey1->dk_x == NULL || dkey2->dk_x == NULL) + return (202); + return (memcmp(dkey1->dk_x, dkey2->dk_x, dkey1->dk_p_bytes)); + } else + return (0); +} + +static void * +memcpyend(void *dest, const void *src, size_t n, size_t size) { + if (n < size) + memset(dest, 0, size - n); + memcpy((char *)dest + size - n, src, n); + return dest; +} + +#else +int +dst_cylink_init() +{ + return (0); +} +#endif /* CYLINK */ Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/cylink_link.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/dst_internal.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/dst_internal.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/dst_internal.h (revision 60942) @@ -0,0 +1,163 @@ +#ifndef DST_INTERNAL_H +#define DST_INTERNAL_H + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, 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 TRUSTED INFORMATION SYSTEMS + * 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 +#include +#if (!defined(BSD)) || (BSD < 199306) +# include +#else +# include +#endif + +#ifndef PATH_MAX +# ifdef POSIX_PATH_MAX +# define PATH_MAX POSIX_PATH_MAX +# else +# define PATH_MAX 255 /* this is the value of POSIX_PATH_MAX */ +# endif +#endif + +typedef struct dst_key { + char *dk_key_name; /* name of the key */ + int dk_key_size; /* this is the size of the key in bits */ + int dk_proto; /* what protocols this key can be used for */ + int dk_alg; /* algorithm number from key record */ + u_int32_t dk_flags; /* and the flags of the public key */ + u_int16_t dk_id; /* identifier of the key */ + void *dk_KEY_struct; /* pointer to key in crypto pkg fmt */ + struct dst_func *dk_func; /* point to cryptto pgk specific function table */ +} DST_KEY; +#define HAS_DST_KEY + +#include +/* + * define what crypto systems are supported for RSA, + * BSAFE is prefered over RSAREF; only one can be set at any time + */ +#if defined(BSAFE) && defined(RSAREF) +# error "Cannot have both BSAFE and RSAREF defined" +#endif + +/* Declare dst_lib specific constants */ +#define KEY_FILE_FORMAT "1.2" + +/* suffixes for key file names */ +#define PRIVATE_KEY "private" +#define PUBLIC_KEY "key" + +/* error handling */ +#ifdef REPORT_ERRORS +#define EREPORT(str) printf str +#else +#define EREPORT(str) +#endif + +/* use our own special macro to FRRE memory */ + +#ifndef SAFE_FREE +#define SAFE_FREE(a) if(a != NULL){memset(a,0, sizeof(*a)); free(a); a=NULL;} +#define SAFE_FREE2(a,s) if (a != NULL && s > 0){memset(a,0, s);free(a); a=NULL;} +#endif + +typedef struct dst_func { + int (*sign)(const int mode, DST_KEY *key, void **context, + const u_int8_t *data, const int len, + u_int8_t *signature, const int sig_len); + int (*verify)(const int mode, DST_KEY *key, void **context, + const u_int8_t *data, const int len, + const u_int8_t *signature, const int sig_len); + int (*compare)(const DST_KEY *key1, const DST_KEY *key2); + int (*generate)(DST_KEY *key, int parms); + void *(*destroy)(void *key); + /* conversion functions */ + int (*to_dns_key)(const DST_KEY *key, u_int8_t *out, + const int out_len); + int (*from_dns_key)(DST_KEY *key, const u_int8_t *str, + const int str_len); + int (*to_file_fmt)(const DST_KEY *key, char *out, + const int out_len); + int (*from_file_fmt)(DST_KEY *key, const char *out, + const int out_len); + +} dst_func; + +extern dst_func *dst_t_func[DST_MAX_ALGS]; +extern char *key_file_fmt_str; +extern char *dst_path; + +#ifndef DST_HASH_SIZE +#define DST_HASH_SIZE 20 /* RIPEMD160 and SHA-1 are 20 bytes MD5 is 16 */ +#endif + +int dst_bsafe_init(); + +int dst_rsaref_init(); + +int dst_hmac_md5_init(); + +int dst_cylink_init(); + +int dst_eay_dss_init(); + +/* support functions */ +/* base64 to bignum conversion routines */ +int dst_s_conv_bignum_u8_to_b64( char *out_buf, const int out_len, + const char *header, + const u_int8_t *bin_data, + const int bin_len); +int dst_s_conv_bignum_b64_to_u8( const char **buf, u_int8_t *loc, + const int loclen) ; +/* from higher level support routines */ +int dst_s_calculate_bits( const u_int8_t *str, const int max_bits); +int dst_s_verify_str( const char **buf, const char *str); + + +/* conversion between dns names and key file names */ +size_t dst_s_filename_length( const char *name, const char *suffix); +int dst_s_build_filename( char *filename, const char *name, + u_int16_t id, int alg, const char *suffix, + size_t filename_length); + +FILE *dst_s_fopen (const char *filename, const char *mode, int perm); + +/* from file prandom.c */ +int dst_s_random( u_int8_t *output, int size); +int dst_s_semi_random( u_int8_t *output, int size); +u_int32_t dst_s_quick_random( int inc); +void dst_s_quick_random_set( u_int32_t val, u_int32_t cnt); + +/* + * read and write network byte order into u_int?_t + * all of these should be retired + */ +u_int16_t dst_s_get_int16( const u_int8_t *buf); +void dst_s_put_int16( u_int8_t *buf, const u_int16_t val); + +u_int32_t dst_s_get_int32( const u_int8_t *buf); +void dst_s_put_int32( u_int8_t *buf, const u_int32_t val); + +#ifdef DUMP +# undef DUMP +# define DUMP(a,b,c,d) dst_s_dump(a,b,c,d) +#else +# define DUMP(a,b,c,d) +#endif + + +#endif /* DST_INTERNAL_H */ Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/dst_internal.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/eay_dss_link.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/eay_dss_link.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/eay_dss_link.c (revision 60942) @@ -0,0 +1,624 @@ +#ifdef EAY_DSS +static const char rcsid[] = "$Header: /proj/cvs/isc/bind/src/lib/dst/eay_dss_link.c,v 1.4 1999/10/13 16:39:23 vixie Exp $"; + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, 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 TRUSTED INFORMATION SYSTEMS + * 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. + */ +/* + * This file contains two components + * 1. Interface to the EAY libcrypto library to allow compilation of Bind + * with TIS/DNSSEC when EAY libcrypto is not available + * all calls to libcrypto are contained inside this file. + * 2. The glue to connvert DSA KEYS to and from external formats + */ +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dst_internal.h" + +#include "crypto.h" +#include "bn.h" +#include "dsa.h" +#include "sha.h" + +#include "port_after.h" + +static int dst_eay_dss_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len); + +static int dst_eay_dss_verify(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len); + +static int dst_eay_dss_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len); +static int dst_eay_dss_from_dns_key(DST_KEY *s_key, const u_char *key, + const int len); +static int dst_eay_dss_key_to_file_format(const DST_KEY *key, u_char *buff, + const int buff_len); +static int dst_eay_dss_key_from_file_format(DST_KEY *d_key, + const u_char *buff, + const int buff_len); +static void *dst_eay_dss_free_key_structure(void *key); + +static int dst_eay_dss_generate_keypair(DST_KEY *key, int exp); +static int dst_eay_dss_compare_keys(const DST_KEY *key1, const DST_KEY *key2); + +/* + * dst_eay_dss_init() Function to answer set up function pointers for + * EAY DSS related functions + */ +int +dst_eay_dss_init() +{ + if (dst_t_func[KEY_DSA] != NULL) + return (1); + dst_t_func[KEY_DSA] = malloc(sizeof(struct dst_func)); + if (dst_t_func[KEY_DSA] == NULL) + return (0); + memset(dst_t_func[KEY_DSA], 0, sizeof(struct dst_func)); + dst_t_func[KEY_DSA]->sign = dst_eay_dss_sign; + dst_t_func[KEY_DSA]->verify = dst_eay_dss_verify; + dst_t_func[KEY_DSA]->compare = dst_eay_dss_compare_keys; + dst_t_func[KEY_DSA]->generate = dst_eay_dss_generate_keypair; + dst_t_func[KEY_DSA]->destroy = dst_eay_dss_free_key_structure; + dst_t_func[KEY_DSA]->from_dns_key = dst_eay_dss_from_dns_key; + dst_t_func[KEY_DSA]->to_dns_key = dst_eay_dss_to_dns_key; + dst_t_func[KEY_DSA]->from_file_fmt = dst_eay_dss_key_from_file_format; + dst_t_func[KEY_DSA]->to_file_fmt = dst_eay_dss_key_to_file_format; + return (1); +} + +/* + * dst_eay_dss_sign + * Call EAY DSS signing functions to sign a block of data. + * There are three steps to signing, INIT (initialize structures), + * UPDATE (hash (more) data), FINAL (generate a signature). This + * routine performs one or more of these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * algobj structure holds context for a sign done in multiple calls. + * context the context to use for this computation + * data data to be signed. + * len length in bytes of data. + * priv_key key to use for signing. + * signature location to store signature. + * sig_len size in bytes of signature field. + * returns + * N Success on SIG_MODE_FINAL = returns signature length in bytes + * N is 41 for DNS + * 0 Success on SIG_MODE_INIT and UPDATE + * <0 Failure + */ + +static int +dst_eay_dss_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len) +{ + int sign_len = 0; + int status; + SHA_CTX *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = (SHA_CTX *) malloc(sizeof(SHA_CTX)); + else if (context) + ctx = (SHA_CTX *) *context; + if (ctx == NULL) + return (-1); + + if (mode & SIG_MODE_INIT) + SHA1_Init(ctx); + + if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) { + SHA1_Update(ctx, (u_char *) data, len); + } + if (mode & SIG_MODE_FINAL) { + DSA *key; + u_char digest[SHA_DIGEST_LENGTH]; + u_char rand[SHA_DIGEST_LENGTH]; + u_char r[SHA_DIGEST_LENGTH], s[SHA_DIGEST_LENGTH]; + + if (dkey == NULL || dkey->dk_KEY_struct == NULL) + return (-1); + key = dkey->dk_KEY_struct; + if (key == NULL) + return(-2); + SHA1_Final(digest, ctx); + status = DSA_sign(0, digest, SHA_DIGEST_LENGTH, + signature, &sign_len, key); + if (status != 0) + return (SIGN_FINAL_FAILURE); + + *signature = (dkey->dk_key_size - 512)/64; + sign_len = 1; + memcpy(signature + sign_len, r, SHA_DIGEST_LENGTH); + sign_len += SHA_DIGEST_LENGTH; + memcpy(signature + sign_len, s, SHA_DIGEST_LENGTH); + sign_len += SHA_DIGEST_LENGTH; + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + return (sign_len); +} + + +/* + * dst_eay_dss_verify + * Calls EAY DSS verification routines. There are three steps to + * verification, INIT (initialize structures), UPDATE (hash (more) data), + * FINAL (generate a signature). This routine performs one or more of + * these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * dkey structure holds context for a verify done in multiple calls. + * context algorithm specific context for the current context processing + * data data signed. + * len length in bytes of data. + * pub_key key to use for verify. + * signature signature. + * sig_len length in bytes of signature. + * returns + * 0 Success + * <0 Failure + */ + +static int +dst_eay_dss_verify(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len) +{ + int status; + SHA_CTX *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = (SHA_CTX *) malloc(sizeof(SHA_CTX)); + else if (context) + ctx = (SHA_CTX *) *context; + if (ctx == NULL) + return (-1); + + if (mode & SIG_MODE_INIT) + SHA1_Init(ctx); + + if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) { + SHA1_Update(ctx, (u_char *) data, len); + } + if (mode & SIG_MODE_FINAL) { + DSA *key; + u_char digest[SHA_DIGEST_LENGTH]; + u_char r[SHA_DIGEST_LENGTH], s[SHA_DIGEST_LENGTH]; + + if (dkey == NULL || dkey->dk_KEY_struct == NULL) + return (-1); + key = (DSA *) dkey->dk_KEY_struct; + if (key = NULL) + return (-2); + if (signature == NULL || sig_len != (2 * SHA_DIGEST_LENGTH +1)) + return (SIGN_FINAL_FAILURE); + SHA1_Final(digest, ctx); + SAFE_FREE(ctx); + if (status != 0) + return (SIGN_FINAL_FAILURE); + if (((int)*signature) != ((BN_num_bytes(key->p) -64)/8)) + return(VERIFY_FINAL_FAILURE); + + memcpy(r, signature +1, SHA_DIGEST_LENGTH); + memcpy(s, signature + SHA_DIGEST_LENGTH +1, SHA_DIGEST_LENGTH); + status = DSA_verify(0, digest, SHA_DIGEST_LENGTH, + (u_char *)signature, sig_len, key); + if (status != 0) + return (VERIFY_FINAL_FAILURE); + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + return (0); +} + + +/* + * dst_eay_dss_to_dns_key + * Converts key from DSA to DNS distribution format + * This function gets in a pointer to the public key and a work area + * to write the key into. + * Parameters + * public KEY structure + * out_str buffer to write encoded key into + * out_len size of out_str + * Return + * N >= 0 length of encoded key + * n < 0 error + */ + +static int +dst_eay_dss_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len) +{ + u_char *op = out_str; + int t; + DSA *key; + + if (in_key == NULL || in_key->dk_KEY_struct == NULL || + out_len <= 0 || out_str == NULL) + return (-1); + key = (DSA *) in_key->dk_KEY_struct; + + t = (BN_num_bytes(key->p) - 64) / 8; + + *op++ = t; + BN_bn2bin(key->q, op); + op += BN_num_bytes(key->q); + BN_bn2bin(key->p, op); + op += BN_num_bytes(key->p); + BN_bn2bin(key->g, op); + op += BN_num_bytes(key->g); + BN_bn2bin(key->pub_key, op); + op += BN_num_bytes(key->pub_key); + + return (op - out_str); +} + + +/* + * dst_eay_dss_from_dns_key + * Converts from a DNS KEY RR format to an RSA KEY. + * Parameters + * len Length in bytes of DNS key + * key DNS key + * name Key name + * s_key DST structure that will point to the RSA key this routine + * will build. + * Return + * 0 The input key, s_key or name was null. + * 1 Success + */ +static int +dst_eay_dss_from_dns_key(DST_KEY *s_key, const u_char *key, const int len) +{ + int t; + u_char *key_ptr = (u_char *)key; + DSA *d_key; + int p_bytes; + + if (s_key == NULL || len < 0 || key == NULL) + return (0); + + if (len == 0) /* process null key */ + return (1); + + if (key_ptr == NULL) + return (0); + t = (int) *key_ptr++; /* length of exponent in bytes */ + p_bytes = 64 + 8 * t; + + if ((3 * (t * 8 + 64) + SHA_DIGEST_LENGTH + 1) != len) + return (0); + + if ((d_key = (DSA *) malloc(sizeof(DSA))) == NULL) { + EREPORT(("dst_eay_dss_from_dns_key(): Memory allocation error 1")); + return (0); + } + memset(d_key, 0, sizeof(DSA)); + s_key->dk_KEY_struct = (void *) d_key; + + d_key->q = BN_bin2bn(key_ptr, SHA_DIGEST_LENGTH, NULL); + key_ptr += SHA_DIGEST_LENGTH; + + d_key->p = BN_bin2bn(key_ptr, p_bytes, NULL); + key_ptr += p_bytes; + + d_key->g = BN_bin2bn(key_ptr, p_bytes, NULL); + key_ptr += p_bytes; + + d_key->pub_key = BN_bin2bn(key_ptr, p_bytes, NULL); + key_ptr += p_bytes; + + s_key->dk_id = dst_s_id_calc(key, len); + s_key->dk_key_size = p_bytes * 8; + return (1); +} + + +/************************************************************************** + * dst_eay_dss_key_to_file_format + * Encodes an DSA Key into the portable file format. + * Parameters + * key DSA KEY structure + * buff output buffer + * buff_len size of output buffer + * Return + * 0 Failure - null input rkey + * -1 Failure - not enough space in output area + * N Success - Length of data returned in buff + */ + +static int +dst_eay_dss_key_to_file_format(const DST_KEY *key, u_char *buff, + const int buff_len) +{ + u_char *bp; + int len, b_len; + DSA *dkey; + char num[256]; /* More than long enough for DSA keys */ + + if (key == NULL || key->dk_KEY_struct == NULL) /* no output */ + return (0); + if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str)) + return (-1); /* no OR not enough space in output area */ + + dkey = (DSA *) key->dk_KEY_struct; + + memset(buff, 0, buff_len); /* just in case */ + /* write file header */ + sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_DSA, "DSA"); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->p, BN_num_bytes(dkey->p)); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime(p): ", num, + BN_num_bytes(dkey->p))) <= 0) + return (-1); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->q, BN_num_bytes(dkey->q)); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Subprime(q): ", num, + BN_num_bytes(dkey->q))) <= 0) + return (-2); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->g, BN_num_bytes(dkey->g)); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Base(g): ", num, + BN_num_bytes(dkey->g))) <= 0) + return (-3); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->priv_key, BN_num_bytes(dkey->priv_key)); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Private_value(x): ", + num, + BN_num_bytes(dkey->priv_key))) + <= 0) + return (-4); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->pub_key, BN_num_bytes(dkey->pub_key)); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Public_value(y): ", + num, + BN_num_bytes(dkey->pub_key))) + <= 0) + return (-5); + + bp += len; + b_len -= len; + return (buff_len - b_len); +} + + +/************************************************************************** + * dst_eay_dss_key_from_file_format + * Converts contents of a private key file into a private DSA key. + * Parameters + * d_key structure to put key into + * buff buffer containing the encoded key + * buff_len the length of the buffer + * Return + * n >= 0 Foot print of the key converted + * n < 0 Error in conversion + */ + +static int +dst_eay_dss_key_from_file_format(DST_KEY *d_key, const u_char *buff, + const int buff_len) +{ + char s[128]; + char dns[1024]; + int len, s_len = sizeof(s); + int foot = -1, dnslen; + const char *p = buff; + DSA *dsa_key; + + if (d_key == NULL || buff == NULL || buff_len <= 0) + return (-1); + + dsa_key = (DSA *) malloc(sizeof(DSA)); + if (dsa_key == NULL) { + return (-2); + } + memset(dsa_key, 0, sizeof(*dsa_key)); + d_key->dk_KEY_struct = (void *) dsa_key; + + if (!dst_s_verify_str(&p, "Prime(p): ")) + return (-3); + memset(s, 0, s_len); + if ((len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)) == 0) + return (-4); + dsa_key->p = BN_bin2bn (s, len, NULL); + if (dsa_key->p == NULL) + return(-5); + + while (*++p && p < (const char *) &buff[buff_len]) { + if (dst_s_verify_str(&p, "Subprime(q): ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len))) + return (-6); + dsa_key->q = BN_bin2bn (s, len, NULL); + if (dsa_key->q == NULL) + return (-7); + } else if (dst_s_verify_str(&p, "Base(g): ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len))) + return (-8); + dsa_key->g = BN_bin2bn (s, len, NULL); + if (dsa_key->g == NULL) + return (-9); + } else if (dst_s_verify_str(&p, "Private_value(x): ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len))) + return (-10); + dsa_key->priv_key = BN_bin2bn (s, len, NULL); + if (dsa_key->priv_key == NULL) + return (-11); + } else if (dst_s_verify_str(&p, "Public_value(y): ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len))) + return (-12); + dsa_key->pub_key = BN_bin2bn (s, len, NULL); + if (dsa_key->pub_key == NULL) + return (-13); + } else { + EREPORT(("Decode_DSAKey(): Bad keyword %s\n", p)); + return (-14); + } + } /* while p */ + + d_key->dk_key_size = BN_num_bytes(dsa_key->p); + dnslen = d_key->dk_func->to_dns_key(d_key, dns, sizeof(dns)); + foot = dst_s_id_calc(dns, dnslen); + + return (foot); +} + + +/************************************************************************** + * dst_eay_dss_free_key_structure + * Frees all dynamicly allocated structures in DSA. + */ + +static void * +dst_eay_dss_free_key_structure(void *key) +{ + DSA *d_key = (DSA *) key; + if (d_key != NULL) { + BN_free(d_key->p); + BN_free(d_key->q); + BN_free(d_key->g); + if (d_key->pub_key) + BN_free(d_key->pub_key); + if (d_key->priv_key) + BN_free(d_key->priv_key); + SAFE_FREE(d_key); + } + return (NULL); +} + + +/************************************************************************** + * dst_eay_dss_generate_keypair + * Generates unique keys that are hard to predict. + * Parameters + * key generic Key structure + * exp the public exponent + * Return + * 0 Failure + * 1 Success + */ + +static int +dst_eay_dss_generate_keypair(DST_KEY *key, int nothing) +{ + int status, dnslen, n; + DSA *dsa; + u_char rand[SHA_DIGEST_LENGTH]; + char dns[1024]; + + if (key == NULL || key->dk_alg != KEY_DSA) + return (0); + + if ((dsa = (DSA *) malloc(sizeof(DSA))) == NULL) { + EREPORT(("dst_eay_dss_generate_keypair: Memory allocation error 3")); + return (0); + } + memset(dsa, 0, sizeof(*dsa)); + + n = dst_random(DST_RAND_KEY, sizeof(rand), rand); + if (n != sizeof(rand)) + return (0); + dsa = DSA_generate_parameters(key->dk_key_size, rand, 20, NULL, NULL, + NULL, NULL); + + if (!dsa) { + EREPORT(("dst_eay_dss_generate_keypair: Generate Parameters failed")); + return (0); + } + if (DSA_generate_key(dsa) == 0) { + EREPORT(("dst_eay_dss_generate_keypair: Generate Key failed")); + return(0); + } + key->dk_KEY_struct = (void *) dsa; + dnslen = key->dk_func->to_dns_key(key, dns, sizeof(dns)); + key->dk_id = dst_s_id_calc(dns, dnslen); + return (1); +} + + +/* + * dst_eay_dss_compare_keys + * Compare two keys for equality. + * Return + * 0 The keys are equal + * NON-ZERO The keys are not equal + */ + +static int +dst_eay_dss_compare_keys(const DST_KEY *key1, const DST_KEY *key2) +{ + int status; + DSA *dkey1 = (DSA *) key1->dk_KEY_struct; + DSA *dkey2 = (DSA *) key2->dk_KEY_struct; + + if (dkey1 == NULL && dkey2 == NULL) + return (0); + else if (dkey1 == NULL) + return (2); + else if (dkey2 == NULL) + return(1); + + status = BN_cmp(dkey1->p, dkey2->p) || + BN_cmp(dkey1->q, dkey2->q) || + BN_cmp(dkey1->g, dkey2->g) || + BN_cmp(dkey1->pub_key, dkey2->pub_key); + + if (status) + return (status); + + if (dkey1->priv_key || dkey2->priv_key) { + if (dkey1->priv_key == NULL || dkey2->priv_key == NULL) + return (202); + return (BN_cmp(dkey1->priv_key, dkey2->priv_key)); + } else + return (0); +} +#else +int +dst_eay_dss_init() +{ + return (0); +} +#endif /* EAY_DSS */ Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/eay_dss_link.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/hmac_link.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/hmac_link.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/hmac_link.c (revision 60942) @@ -0,0 +1,493 @@ +#ifdef HMAC_MD5 +#ifndef LINT +static const char rcsid[] = "$Header: /proj/cvs/isc/bind/src/lib/dst/hmac_link.c,v 1.8 1999/10/15 21:30:07 vixie Exp $"; +#endif +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, 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 TRUSTED INFORMATION SYSTEMS + * 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. + */ + +/* + * This file contains an implementation of the HMAC-MD5 algorithm. + */ +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dst_internal.h" +#ifdef USE_MD5 +# include "md5.h" +# ifndef _MD5_H_ +# define _MD5_H_ 1 /* make sure we do not include rsaref md5.h file */ +# endif +#endif + +#include "port_after.h" + + +#define HMAC_LEN 64 +#define HMAC_IPAD 0x36 +#define HMAC_OPAD 0x5c +#define MD5_LEN 16 + + +typedef struct hmackey { + u_char hk_ipad[64], hk_opad[64]; +} HMAC_Key; + + +/************************************************************************** + * dst_hmac_md5_sign + * Call HMAC signing functions to sign a block of data. + * There are three steps to signing, INIT (initialize structures), + * UPDATE (hash (more) data), FINAL (generate a signature). This + * routine performs one or more of these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * priv_key key to use for signing. + * context the context to be used in this digest + * data data to be signed. + * len length in bytes of data. + * signature location to store signature. + * sig_len size of the signature location + * returns + * N Success on SIG_MODE_FINAL = returns signature length in bytes + * 0 Success on SIG_MODE_INIT and UPDATE + * <0 Failure + */ + +static int +dst_hmac_md5_sign(const int mode, DST_KEY *d_key, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len) +{ + HMAC_Key *key; + int sign_len = 0; + MD5_CTX *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = (MD5_CTX *) malloc(sizeof(*ctx)); + else if (context) + ctx = (MD5_CTX *) *context; + if (ctx == NULL) + return (-1); + + if (d_key == NULL || d_key->dk_KEY_struct == NULL) + return (-1); + key = (HMAC_Key *) d_key->dk_KEY_struct; + + if (mode & SIG_MODE_INIT) { + MD5Init(ctx); + MD5Update(ctx, key->hk_ipad, HMAC_LEN); + } + + if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) + MD5Update(ctx, (u_char *)data, len); + + if (mode & SIG_MODE_FINAL) { + if (signature == NULL || sig_len < MD5_LEN) + return (SIGN_FINAL_FAILURE); + MD5Final(signature, ctx); + + /* perform outer MD5 */ + MD5Init(ctx); + MD5Update(ctx, key->hk_opad, HMAC_LEN); + MD5Update(ctx, signature, MD5_LEN); + MD5Final(signature, ctx); + sign_len = MD5_LEN; + SAFE_FREE(ctx); + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + return (sign_len); +} + + +/************************************************************************** + * dst_hmac_md5_verify() + * Calls HMAC verification routines. There are three steps to + * verification, INIT (initialize structures), UPDATE (hash (more) data), + * FINAL (generate a signature). This routine performs one or more of + * these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * dkey key to use for verify. + * data data signed. + * len length in bytes of data. + * signature signature. + * sig_len length in bytes of signature. + * returns + * 0 Success + * <0 Failure + */ + +static int +dst_hmac_md5_verify(const int mode, DST_KEY *d_key, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len) +{ + HMAC_Key *key; + MD5_CTX *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = (MD5_CTX *) malloc(sizeof(*ctx)); + else if (context) + ctx = (MD5_CTX *) *context; + if (ctx == NULL) + return (-1); + + if (d_key == NULL || d_key->dk_KEY_struct == NULL) + return (-1); + + key = (HMAC_Key *) d_key->dk_KEY_struct; + if (mode & SIG_MODE_INIT) { + MD5Init(ctx); + MD5Update(ctx, key->hk_ipad, HMAC_LEN); + } + if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) + MD5Update(ctx, (u_char *)data, len); + + if (mode & SIG_MODE_FINAL) { + u_char digest[MD5_LEN]; + if (signature == NULL || key == NULL || sig_len != MD5_LEN) + return (VERIFY_FINAL_FAILURE); + MD5Final(digest, ctx); + + /* perform outer MD5 */ + MD5Init(ctx); + MD5Update(ctx, key->hk_opad, HMAC_LEN); + MD5Update(ctx, digest, MD5_LEN); + MD5Final(digest, ctx); + + SAFE_FREE(ctx); + if (memcmp(digest, signature, MD5_LEN) != 0) + return (VERIFY_FINAL_FAILURE); + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + return (0); +} + + +/************************************************************************** + * dst_buffer_to_hmac_md5 + * Converts key from raw data to an HMAC Key + * This function gets in a pointer to the data + * Parameters + * hkey the HMAC key to be filled in + * key the key in raw format + * keylen the length of the key + * Return + * 0 Success + * <0 Failure + */ +static int +dst_buffer_to_hmac_md5(DST_KEY *dkey, const u_char *key, const int keylen) +{ + int i; + HMAC_Key *hkey = NULL; + MD5_CTX ctx; + int local_keylen = keylen; + + if (dkey == NULL || key == NULL || keylen < 0) + return (-1); + + if ((hkey = (HMAC_Key *) malloc(sizeof(HMAC_Key))) == NULL) + return (-2); + + memset(hkey->hk_ipad, 0, sizeof(hkey->hk_ipad)); + memset(hkey->hk_opad, 0, sizeof(hkey->hk_opad)); + + /* if key is longer than HMAC_LEN bytes reset it to key=MD5(key) */ + if (keylen > HMAC_LEN) { + u_char tk[MD5_LEN]; + MD5Init(&ctx); + MD5Update(&ctx, (u_char *)key, keylen); + MD5Final(tk, &ctx); + memset((void *) &ctx, 0, sizeof(ctx)); + key = tk; + local_keylen = MD5_LEN; + } + /* start out by storing key in pads */ + memcpy(hkey->hk_ipad, key, local_keylen); + memcpy(hkey->hk_opad, key, local_keylen); + + /* XOR key with hk_ipad and opad values */ + for (i = 0; i < HMAC_LEN; i++) { + hkey->hk_ipad[i] ^= HMAC_IPAD; + hkey->hk_opad[i] ^= HMAC_OPAD; + } + dkey->dk_key_size = local_keylen; + dkey->dk_KEY_struct = (void *) hkey; + return (1); +} + + +/************************************************************************** + * dst_hmac_md5_key_to_file_format + * Encodes an HMAC Key into the portable file format. + * Parameters + * hkey HMAC KEY structure + * buff output buffer + * buff_len size of output buffer + * Return + * 0 Failure - null input hkey + * -1 Failure - not enough space in output area + * N Success - Length of data returned in buff + */ + +static int +dst_hmac_md5_key_to_file_format(const DST_KEY *dkey, char *buff, + const int buff_len) +{ + char *bp; + int len, b_len, i, key_len; + u_char key[HMAC_LEN]; + HMAC_Key *hkey; + + if (dkey == NULL || dkey->dk_KEY_struct == NULL) + return (0); + if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str)) + return (-1); /* no OR not enough space in output area */ + + hkey = (HMAC_Key *) dkey->dk_KEY_struct; + memset(buff, 0, buff_len); /* just in case */ + /* write file header */ + sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_HMAC_MD5, "HMAC"); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + + memset(key, 0, HMAC_LEN); + for (i = 0; i < HMAC_LEN; i++) + key[i] = hkey->hk_ipad[i] ^ HMAC_IPAD; + for (i = HMAC_LEN - 1; i >= 0; i--) + if (key[i] != 0) + break; + key_len = i + 1; + + strcat(bp, "Key: "); + bp += strlen("Key: "); + b_len = buff_len - (bp - buff); + + len = b64_ntop(key, key_len, bp, b_len); + if (len < 0) + return (-1); + bp += len; + *(bp++) = '\n'; + *bp = '\0'; + b_len = buff_len - (bp - buff); + + return (buff_len - b_len); +} + + +/************************************************************************** + * dst_hmac_md5_key_from_file_format + * Converts contents of a key file into an HMAC key. + * Parameters + * hkey structure to put key into + * buff buffer containing the encoded key + * buff_len the length of the buffer + * Return + * n >= 0 Foot print of the key converted + * n < 0 Error in conversion + */ + +static int +dst_hmac_md5_key_from_file_format(DST_KEY *dkey, const char *buff, + const int buff_len) +{ + const char *p = buff, *eol; + u_char key[HMAC_LEN+1]; /* b64_pton needs more than 64 bytes do decode + * it should probably be fixed rather than doing + * this + */ + u_char *tmp; + int key_len, len; + + if (dkey == NULL) + return (-2); + if (buff == NULL || buff_len < 0) + return (-1); + + memset(key, 0, sizeof(key)); + + if (!dst_s_verify_str(&p, "Key: ")) + return (-3); + + eol = strchr(p, '\n'); + if (eol == NULL) + return (-4); + len = eol - p; + tmp = malloc(len + 2); + memcpy(tmp, p, len); + *(tmp + len) = 0x0; + key_len = b64_pton((char *)tmp, key, HMAC_LEN+1); /* see above */ + SAFE_FREE2(tmp, len + 2); + + if (dst_buffer_to_hmac_md5(dkey, key, key_len) < 0) { + return (-6); + } + return (0); +} + +/* + * dst_hmac_md5_to_dns_key() + * function to extract hmac key from DST_KEY structure + * intput: + * in_key: HMAC-MD5 key + * output: + * out_str: buffer to write ot + * out_len: size of output buffer + * returns: + * number of bytes written to output buffer + */ +static int +dst_hmac_md5_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len) +{ + + HMAC_Key *hkey; + int i; + + if (in_key == NULL || in_key->dk_KEY_struct == NULL || + out_len <= in_key->dk_key_size || out_str == NULL) + return (-1); + + hkey = (HMAC_Key *) in_key->dk_KEY_struct; + for (i = 0; i < in_key->dk_key_size; i++) + out_str[i] = hkey->hk_ipad[i] ^ HMAC_IPAD; + return (i); +} + +/************************************************************************** + * dst_hmac_md5_compare_keys + * Compare two keys for equality. + * Return + * 0 The keys are equal + * NON-ZERO The keys are not equal + */ + +static int +dst_hmac_md5_compare_keys(const DST_KEY *key1, const DST_KEY *key2) +{ + HMAC_Key *hkey1 = (HMAC_Key *) key1->dk_KEY_struct; + HMAC_Key *hkey2 = (HMAC_Key *) key2->dk_KEY_struct; + return memcmp(hkey1->hk_ipad, hkey2->hk_ipad, HMAC_LEN); +} + +/************************************************************************** + * dst_hmac_md5_free_key_structure + * Frees all (none) dynamically allocated structures in hkey + */ + +static void * +dst_hmac_md5_free_key_structure(void *key) +{ + HMAC_Key *hkey = key; + SAFE_FREE(hkey); + return (NULL); +} + + +/*************************************************************************** + * dst_hmac_md5_generate_key + * Creates a HMAC key of size size with a maximum size of 63 bytes + * generating a HMAC key larger than 63 bytes makes no sense as that key + * is digested before use. + */ + +static int +dst_hmac_md5_generate_key(DST_KEY *key, const int nothing) +{ + u_char *buff; + int i, n, size; + + if (key == NULL || key->dk_alg != KEY_HMAC_MD5) + return (0); + size = (key->dk_key_size + 7) / 8; /* convert to bytes */ + if (size <= 0) + return(0); + + i = size > 64 ? 64 : size; + buff = malloc(i+8); + + n = dst_random(DST_RAND_SEMI, i, buff); + n += dst_random(DST_RAND_KEY, i, buff); + if (n <= i) { /* failed getting anything */ + SAFE_FREE2(buff, i); + return (-1); + } + n = dst_buffer_to_hmac_md5(key, buff, i); + SAFE_FREE2(buff, i); + if (n <= 0) + return (n); + return (1); +} + +/* + * dst_hmac_md5_init() Function to answer set up function pointers for HMAC + * related functions + */ +int +dst_hmac_md5_init() +{ + if (dst_t_func[KEY_HMAC_MD5] != NULL) + return (1); + dst_t_func[KEY_HMAC_MD5] = malloc(sizeof(struct dst_func)); + if (dst_t_func[KEY_HMAC_MD5] == NULL) + return (0); + memset(dst_t_func[KEY_HMAC_MD5], 0, sizeof(struct dst_func)); + dst_t_func[KEY_HMAC_MD5]->sign = dst_hmac_md5_sign; + dst_t_func[KEY_HMAC_MD5]->verify = dst_hmac_md5_verify; + dst_t_func[KEY_HMAC_MD5]->compare = dst_hmac_md5_compare_keys; + dst_t_func[KEY_HMAC_MD5]->generate = dst_hmac_md5_generate_key; + dst_t_func[KEY_HMAC_MD5]->destroy = dst_hmac_md5_free_key_structure; + dst_t_func[KEY_HMAC_MD5]->to_dns_key = dst_hmac_md5_to_dns_key; + dst_t_func[KEY_HMAC_MD5]->from_dns_key = dst_buffer_to_hmac_md5; + dst_t_func[KEY_HMAC_MD5]->to_file_fmt = dst_hmac_md5_key_to_file_format; + dst_t_func[KEY_HMAC_MD5]->from_file_fmt = dst_hmac_md5_key_from_file_format; + return (1); +} + +#else +int +dst_hmac_md5_init(){ + return (0); +} +#endif + + + + + + + Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/hmac_link.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/md5.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/md5.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/md5.h (revision 60942) @@ -0,0 +1,101 @@ +/* crypto/md/md5.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * 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 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 cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_MD5_H +#define HEADER_MD5_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define MD5_CBLOCK 64 +#define MD5_LBLOCK 16 +#define MD5_BLOCK 16 +#define MD5_LAST_BLOCK 56 +#define MD5_LENGTH_BLOCK 8 +#define MD5_DIGEST_LENGTH 16 + +typedef struct MD5state_st + { + unsigned long A,B,C,D; + unsigned long Nl,Nh; + unsigned long data[MD5_LBLOCK]; + int num; + } MD5_CTX; + +#ifndef NOPROTO +void MD5_Init(MD5_CTX *c); +void MD5_Update(MD5_CTX *c, unsigned char *data, unsigned long len); +void MD5_Final(unsigned char *md, MD5_CTX *c); +unsigned char *MD5(unsigned char *d, unsigned long n, unsigned char *md); +#else +void MD5_Init(); +void MD5_Update(); +void MD5_Final(); +unsigned char *MD5(); +#endif + +/* to provide backward compatabilty to RSAREF calls ogud@tis.com 1997/11/14 */ +#define MD5Init(c) MD5_Init(c) +#define MD5Update(c,data, len) MD5_Update(c,data,len) +#define MD5Final(md, c) MD5_Final(md, c) +#ifdef __cplusplus +} +#endif + +#endif Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/md5.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/md5_dgst.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/md5_dgst.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/md5_dgst.c (revision 60942) @@ -0,0 +1,368 @@ +/* crypto/md/md5_dgst.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * 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 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 cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#ifdef USE_MD5 /* Added by ogud@tis.com 1998/1/26 */ +#include "md5_locl.h" + +char *MD5_version="MD5 part of SSLeay 0.8.1 19-Jul-1997"; + +/* Implemented from RFC1321 The MD5 Message-Digest Algorithm + */ + +#define INIT_DATA_A (unsigned long)0x67452301L +#define INIT_DATA_B (unsigned long)0xefcdab89L +#define INIT_DATA_C (unsigned long)0x98badcfeL +#define INIT_DATA_D (unsigned long)0x10325476L + +#ifndef NOPROTO +static void md5_block(MD5_CTX *c, unsigned long *p); +#else +static void md5_block(); +#endif + +void MD5_Init(c) +MD5_CTX *c; + { + c->A=INIT_DATA_A; + c->B=INIT_DATA_B; + c->C=INIT_DATA_C; + c->D=INIT_DATA_D; + c->Nl=0; + c->Nh=0; + c->num=0; + } + +void MD5_Update(c, data, len) +MD5_CTX *c; +register unsigned char *data; +unsigned long len; + { + register ULONG *p; + int sw,sc; + ULONG l; + + if (len == 0) return; + + l=(c->Nl+(len<<3))&0xffffffffL; + /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to + * Wei Dai for pointing it out. */ + if (l < c->Nl) /* overflow */ + c->Nh++; + c->Nh+=(len>>29); + c->Nl=l; + + if (c->num != 0) + { + p=c->data; + sw=c->num>>2; + sc=c->num&0x03; + + if ((c->num+len) >= MD5_CBLOCK) + { + l= p[sw]; + p_c2l(data,l,sc); + p[sw++]=l; + for (; swnum); + + md5_block(c,p); + c->num=0; + /* drop through and do the rest */ + } + else + { + int ew,ec; + + c->num+=(int)len; + if ((sc+len) < 4) /* ugly, add char's to a word */ + { + l= p[sw]; + p_c2l_p(data,l,sc,len); + p[sw]=l; + } + else + { + ew=(c->num>>2); + ec=(c->num&0x03); + l= p[sw]; + p_c2l(data,l,sc); + p[sw++]=l; + for (; sw < ew; sw++) + { c2l(data,l); p[sw]=l; } + if (ec) + { + c2l_p(data,l,ec); + p[sw]=l; + } + } + return; + } + } + /* we now can process the input data in blocks of MD5_CBLOCK + * chars and save the leftovers to c->data. */ + p=c->data; + while (len >= MD5_CBLOCK) + { +#if defined(L_ENDIAN) || defined(B_ENDIAN) + memcpy(p,data,MD5_CBLOCK); + data+=MD5_CBLOCK; +#ifdef B_ENDIAN + for (sw=(MD5_LBLOCK/4); sw; sw--) + { + Endian_Reverse32(p[0]); + Endian_Reverse32(p[1]); + Endian_Reverse32(p[2]); + Endian_Reverse32(p[3]); + p+=4; + } +#endif +#else + for (sw=(MD5_LBLOCK/4); sw; sw--) + { + c2l(data,l); *(p++)=l; + c2l(data,l); *(p++)=l; + c2l(data,l); *(p++)=l; + c2l(data,l); *(p++)=l; + } +#endif + p=c->data; + md5_block(c,p); + len-=MD5_CBLOCK; + } + sc=(int)len; + c->num=sc; + if (sc) + { + sw=sc>>2; /* words to copy */ +#ifdef L_ENDIAN + p[sw]=0; + memcpy(p,data,sc); +#else + sc&=0x03; + for ( ; sw; sw--) + { c2l(data,l); *(p++)=l; } + c2l_p(data,l,sc); + *p=l; +#endif + } + } + +static void md5_block(c, X) +MD5_CTX *c; +register ULONG *X; + { + register ULONG A,B,C,D; + + A=c->A; + B=c->B; + C=c->C; + D=c->D; + + /* Round 0 */ + R0(A,B,C,D,X[ 0], 7,0xd76aa478L); + R0(D,A,B,C,X[ 1],12,0xe8c7b756L); + R0(C,D,A,B,X[ 2],17,0x242070dbL); + R0(B,C,D,A,X[ 3],22,0xc1bdceeeL); + R0(A,B,C,D,X[ 4], 7,0xf57c0fafL); + R0(D,A,B,C,X[ 5],12,0x4787c62aL); + R0(C,D,A,B,X[ 6],17,0xa8304613L); + R0(B,C,D,A,X[ 7],22,0xfd469501L); + R0(A,B,C,D,X[ 8], 7,0x698098d8L); + R0(D,A,B,C,X[ 9],12,0x8b44f7afL); + R0(C,D,A,B,X[10],17,0xffff5bb1L); + R0(B,C,D,A,X[11],22,0x895cd7beL); + R0(A,B,C,D,X[12], 7,0x6b901122L); + R0(D,A,B,C,X[13],12,0xfd987193L); + R0(C,D,A,B,X[14],17,0xa679438eL); + R0(B,C,D,A,X[15],22,0x49b40821L); + /* Round 1 */ + R1(A,B,C,D,X[ 1], 5,0xf61e2562L); + R1(D,A,B,C,X[ 6], 9,0xc040b340L); + R1(C,D,A,B,X[11],14,0x265e5a51L); + R1(B,C,D,A,X[ 0],20,0xe9b6c7aaL); + R1(A,B,C,D,X[ 5], 5,0xd62f105dL); + R1(D,A,B,C,X[10], 9,0x02441453L); + R1(C,D,A,B,X[15],14,0xd8a1e681L); + R1(B,C,D,A,X[ 4],20,0xe7d3fbc8L); + R1(A,B,C,D,X[ 9], 5,0x21e1cde6L); + R1(D,A,B,C,X[14], 9,0xc33707d6L); + R1(C,D,A,B,X[ 3],14,0xf4d50d87L); + R1(B,C,D,A,X[ 8],20,0x455a14edL); + R1(A,B,C,D,X[13], 5,0xa9e3e905L); + R1(D,A,B,C,X[ 2], 9,0xfcefa3f8L); + R1(C,D,A,B,X[ 7],14,0x676f02d9L); + R1(B,C,D,A,X[12],20,0x8d2a4c8aL); + /* Round 2 */ + R2(A,B,C,D,X[ 5], 4,0xfffa3942L); + R2(D,A,B,C,X[ 8],11,0x8771f681L); + R2(C,D,A,B,X[11],16,0x6d9d6122L); + R2(B,C,D,A,X[14],23,0xfde5380cL); + R2(A,B,C,D,X[ 1], 4,0xa4beea44L); + R2(D,A,B,C,X[ 4],11,0x4bdecfa9L); + R2(C,D,A,B,X[ 7],16,0xf6bb4b60L); + R2(B,C,D,A,X[10],23,0xbebfbc70L); + R2(A,B,C,D,X[13], 4,0x289b7ec6L); + R2(D,A,B,C,X[ 0],11,0xeaa127faL); + R2(C,D,A,B,X[ 3],16,0xd4ef3085L); + R2(B,C,D,A,X[ 6],23,0x04881d05L); + R2(A,B,C,D,X[ 9], 4,0xd9d4d039L); + R2(D,A,B,C,X[12],11,0xe6db99e5L); + R2(C,D,A,B,X[15],16,0x1fa27cf8L); + R2(B,C,D,A,X[ 2],23,0xc4ac5665L); + /* Round 3 */ + R3(A,B,C,D,X[ 0], 6,0xf4292244L); + R3(D,A,B,C,X[ 7],10,0x432aff97L); + R3(C,D,A,B,X[14],15,0xab9423a7L); + R3(B,C,D,A,X[ 5],21,0xfc93a039L); + R3(A,B,C,D,X[12], 6,0x655b59c3L); + R3(D,A,B,C,X[ 3],10,0x8f0ccc92L); + R3(C,D,A,B,X[10],15,0xffeff47dL); + R3(B,C,D,A,X[ 1],21,0x85845dd1L); + R3(A,B,C,D,X[ 8], 6,0x6fa87e4fL); + R3(D,A,B,C,X[15],10,0xfe2ce6e0L); + R3(C,D,A,B,X[ 6],15,0xa3014314L); + R3(B,C,D,A,X[13],21,0x4e0811a1L); + R3(A,B,C,D,X[ 4], 6,0xf7537e82L); + R3(D,A,B,C,X[11],10,0xbd3af235L); + R3(C,D,A,B,X[ 2],15,0x2ad7d2bbL); + R3(B,C,D,A,X[ 9],21,0xeb86d391L); + + c->A+=A&0xffffffffL; + c->B+=B&0xffffffffL; + c->C+=C&0xffffffffL; + c->D+=D&0xffffffffL; + } + +void MD5_Final(md, c) +unsigned char *md; +MD5_CTX *c; + { + register int i,j; + register ULONG l; + register ULONG *p; + static unsigned char end[4]={0x80,0x00,0x00,0x00}; + unsigned char *cp=end; + + /* c->num should definitly have room for at least one more byte. */ + p=c->data; + j=c->num; + i=j>>2; + + /* purify often complains about the following line as an + * Uninitialized Memory Read. While this can be true, the + * following p_c2l macro will reset l when that case is true. + * This is because j&0x03 contains the number of 'valid' bytes + * already in p[i]. If and only if j&0x03 == 0, the UMR will + * occur but this is also the only time p_c2l will do + * l= *(cp++) instead of l|= *(cp++) + * Many thanks to Alex Tang for pickup this + * 'potential bug' */ +#ifdef PURIFY + if ((j&0x03) == 0) p[i]=0; +#endif + l=p[i]; + p_c2l(cp,l,j&0x03); + p[i]=l; + i++; + /* i is the next 'undefined word' */ + if (c->num >= MD5_LAST_BLOCK) + { + for (; iNl; + p[MD5_LBLOCK-1]=c->Nh; + md5_block(c,p); + cp=md; + l=c->A; l2c(l,cp); + l=c->B; l2c(l,cp); + l=c->C; l2c(l,cp); + l=c->D; l2c(l,cp); + + /* clear stuff, md5_block may be leaving some stuff on the stack + * but I'm not worried :-) */ + c->num=0; +/* memset((char *)&c,0,sizeof(c));*/ + } + +#ifdef undef +int printit(l) +unsigned long *l; + { + int i,ii; + + for (i=0; i<2; i++) + { + for (ii=0; ii<8; ii++) + { + fprintf(stderr,"%08lx ",l[i*8+ii]); + } + fprintf(stderr,"\n"); + } + } +#endif +#endif /* USE_MD5 */ Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/md5_dgst.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/md5_locl.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/md5_locl.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/md5_locl.h (revision 60942) @@ -0,0 +1,190 @@ +/* crypto/md/md5_locl.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * 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 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 cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include "md5.h" + +#define ULONG unsigned long +#define UCHAR unsigned char +#define UINT unsigned int + +#if defined(NOCONST) +#define const +#endif + +#undef c2l +#define c2l(c,l) (l = ((unsigned long)(*((c)++))) , \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<<24)) + +#undef p_c2l +#define p_c2l(c,l,n) { \ + switch (n) { \ + case 0: l =((unsigned long)(*((c)++))); \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + case 3: l|=((unsigned long)(*((c)++)))<<24; \ + } \ + } + +/* NOTE the pointer is not incremented at the end of this */ +#undef c2l_p +#define c2l_p(c,l,n) { \ + l=0; \ + (c)+=n; \ + switch (n) { \ + case 3: l =((unsigned long)(*(--(c))))<<16; \ + case 2: l|=((unsigned long)(*(--(c))))<< 8; \ + case 1: l|=((unsigned long)(*(--(c)))) ; \ + } \ + } + +#undef p_c2l_p +#define p_c2l_p(c,l,sc,len) { \ + switch (sc) \ + { \ + case 0: l =((unsigned long)(*((c)++))); \ + if (--len == 0) break; \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + if (--len == 0) break; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + } \ + } + +#undef l2c +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff)) + +/* NOTE - c is not incremented as per l2c */ +#undef l2cn +#define l2cn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ + } \ + } + +/* A nice byte order reversal from Wei Dai */ +#if defined(WIN32) +/* 5 instructions with rotate instruction, else 9 */ +#define Endian_Reverse32(a) \ + { \ + unsigned long l=(a); \ + (a)=((ROTATE(l,8)&0x00FF00FF)|(ROTATE(l,24)&0xFF00FF00)); \ + } +#else +/* 6 instructions with rotate instruction, else 8 */ +#define Endian_Reverse32(a) \ + { \ + unsigned long l=(a); \ + l=(((l&0xFF00FF00)>>8L)|((l&0x00FF00FF)<<8L)); \ + (a)=ROTATE(l,16L); \ + } +#endif +/* +#define F(x,y,z) (((x) & (y)) | ((~(x)) & (z))) +#define G(x,y,z) (((x) & (z)) | ((y) & (~(z)))) +*/ + +/* As pointed out by Wei Dai , the above can be + * simplified to the code below. Wei attributes these optimisations + * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel. + */ +#define F(x,y,z) ((((y) ^ (z)) & (x)) ^ (z)) +#define G(x,y,z) ((((x) ^ (y)) & (z)) ^ (y)) +#define H(x,y,z) ((x) ^ (y) ^ (z)) +#define I(x,y,z) (((x) | (~(z))) ^ (y)) + +#undef ROTATE +#if defined(WIN32) +#define ROTATE(a,n) _lrotl(a,n) +#else +#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) +#endif + + +#define R0(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+F((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; };\ + +#define R1(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+G((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; }; + +#define R2(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+H((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; }; + +#define R3(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+I((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; }; Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/md5_locl.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/prandom.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/prandom.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/prandom.c (revision 60942) @@ -0,0 +1,851 @@ +#ifndef LINT +static const char rcsid[] = "$Header: /proj/cvs/isc/bind/src/lib/dst/prandom.c,v 1.8 1999/10/13 16:39:24 vixie Exp $"; +#endif +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, 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 TRUSTED INFORMATION SYSTEMS + * 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 +#include +#include +#include +#include +#include + +#include "dst_internal.h" +#include "prand_conf.h" + +#include "port_after.h" + +#ifndef DST_NUM_HASHES +#define DST_NUM_HASHES 4 +#endif +#ifndef DST_NUMBER_OF_COUNTERS +#define DST_NUMBER_OF_COUNTERS 5 /* 32 * 5 == 160 == SHA(1) > MD5 */ +#endif + +/* + * the constant below is a prime number to make fixed data structues like + * stat and time wrap over blocks. This adds certain uncertanty to what is + * in each digested block. + * The prime number 2879 has the special property that when + * divided by 2,4 and 6 the result is also a prime numbers + */ + +#ifndef DST_RANDOM_BLOCK_SIZE +#define DST_RANDOM_BLOCK_SIZE 2879 +#endif + +/* + * This constant dictatates how many bits we shift to the right before using a + */ +#ifndef DST_SHIFT +#define DST_SHIFT 9 +#endif + +/* + * An initalizer that is as bad as any other with half the bits set + */ +#ifndef DST_RANDOM_PATTERN +#define DST_RANDOM_PATTERN 0x8765CA93 +#endif +/* + * things must have changed in the last 3600 seconds to be used + */ +#define MAX_OLD 3600 + + +/* + * these two data structure are used to process input data into digests, + * + * The first structure is containts a pointer to a DST HMAC key + * the variables accompanying are used for + * step : select every step byte from input data for the hash + * block: number of data elements going into each hash + * digested: number of data elements digested so far + * curr: offset into the next input data for the first byte. + */ +typedef struct hash { + DST_KEY *key; + void *ctx; + int digested, block, step, curr; +} prand_hash; + +/* + * This data structure controlls number of hashes and keeps track of + * overall progress in generating correct number of bytes of output. + * output : array to store the output data in + * needed : how many bytes of output are needed + * filled : number of bytes in output so far. + * bytes : total number of bytes processed by this structure + * file_digest : the HMAC key used to digest files. + */ +typedef struct work { + int needed, filled, bytes; + u_char *output; + prand_hash *hash[DST_NUM_HASHES]; + DST_KEY *file_digest; +} dst_work; + + +/* + * forward function declarations + */ +static int get_dev_random(u_char *output, int size); +static int do_time(dst_work *work); +static int do_ls(dst_work *work); +static int unix_cmd(dst_work *work); +static int digest_file(dst_work *work); + +static void force_hash(dst_work *work, prand_hash *hash); +static int do_hash(dst_work *work, prand_hash *hash, u_char *input, + int size); +static int my_digest(dst_work *tmp, u_char *input, int size); +static prand_hash *get_hmac_key(int step, int block); + +static int own_random(dst_work *work); + + +/* + * variables used in the quick random number generator + */ +static u_int32_t ran_val = DST_RANDOM_PATTERN; +static u_int32_t ran_cnt = (DST_RANDOM_PATTERN >> 10); + +/* + * setting the quick_random generator to particular values or if both + * input parameters are 0 then set it to initial vlaues + */ + +void +dst_s_quick_random_set(u_int32_t val, u_int32_t cnt) +{ + ran_val = (val == 0) ? DST_RANDOM_PATTERN : val; + ran_cnt = (cnt == 0) ? (DST_RANDOM_PATTERN >> 10) : cnt; +} + +/* + * this is a quick and random number generator that seems to generate quite + * good distribution of data + */ +u_int32_t +dst_s_quick_random(int inc) +{ + ran_val = ((ran_val >> 13) ^ (ran_val << 19)) ^ + ((ran_val >> 7) ^ (ran_val << 25)); + if (inc > 0) /* only increasing values accepted */ + ran_cnt += inc; + ran_val += ran_cnt++; + return (ran_val); +} + +/* + * get_dev_random: Function to read /dev/random reliably + * this function returns how many bytes where read from the device. + * port_after.h should set the control variable HAVE_DEV_RANDOM + */ +static int +get_dev_random(u_char *output, int size) +{ +#ifdef HAVE_DEV_RANDOM + struct stat st; + int n = 0, fd = -1, s; + + s = stat("/dev/random", &st); + if (s == 0 && S_ISCHR(st.st_mode)) { + if ((fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) != -1) { + if ((n = read(fd, output, size)) < 0) + n = 0; + close(fd); + } + return (n); + } +#endif + return (0); +} + +/* + * Portable way of getting the time values if gettimeofday is missing + * then compile with -DMISSING_GETTIMEOFDAY time() is POSIX compliant but + * gettimeofday() is not. + * Time of day is predictable, we are looking for the randomness that comes + * the last few bits in the microseconds in the timer are hard to predict when + * this is invoked at the end of other operations + */ +struct timeval *mtime; +static int +do_time(dst_work *work) +{ + int cnt = 0; + static u_char tmp[sizeof(struct timeval) + sizeof(struct timezone)]; + struct timezone *zone; + + zone = (struct timezone *) tmp; + mtime = (struct timeval *)(tmp + sizeof(struct timezone)); + gettimeofday(mtime, zone); + cnt = sizeof(tmp); + my_digest(work, tmp, sizeof(tmp)); + + return (cnt); +} + +/* + * this function simulates the ls command, but it uses stat which gives more + * information and is harder to guess + * Each call to this function will visit the next directory on the list of + * directories, in a circular manner. + * return value is the number of bytes added to the temp buffer + * + * do_ls() does not visit subdirectories + * if attacker has access to machine it can guess most of the values seen + * thus it is important to only visit directories that are freqently updated + * Attacker that has access to the network can see network traffic + * when NFS mounted directories are accessed and know exactly the data used + * but may not know exactly in what order data is used. + * Returns the number of bytes that where returned in stat structures + */ +static int +do_ls(dst_work *work) +{ + struct dir_info { + uid_t uid; + gid_t gid; + off_t size; + time_t atime, mtime, ctime; + }; + static struct dir_info dir_info; + struct stat buf; + struct dirent *entry; + static int i = 0; + static unsigned long d_round = 0; + struct timeval tv; + int n = 0, dir_len, tb_i = 0, out = 0; + + char file_name[1024]; + u_char tmp_buff[1024]; + DIR *dir = NULL; + + if (dirs[i] == NULL) /* if at the end of the list start over */ + i = 0; + if (stat(dirs[i++], &buf)) /* directory does not exist */ + return (0); + + gettimeofday(&tv,NULL); + if (d_round == 0) + d_round = tv.tv_sec - MAX_OLD; + else if (i==1) /* if starting a new round cut what we accept */ + d_round += (tv.tv_sec - d_round)/2; + + if (buf.st_atime < d_round) + return (0); + + EREPORT(("do_ls i %d filled %4d in_temp %4d\n", + i-1, work->filled, work->in_temp)); + memcpy(tmp_buff, &buf, sizeof(buf)); + tb_i += sizeof(buf); + + + if ((dir = opendir(dirs[i-1])) == NULL)/* open it for read */ + return (0); + strcpy(file_name, dirs[i-1]); + dir_len = strlen(file_name); + file_name[dir_len++] = '/'; + while ((entry = readdir(dir))) { + int len = strlen(entry->d_name); + out += len; + if (my_digest(work, (u_char *)entry->d_name, len)) + break; + + memcpy(&file_name[dir_len], entry->d_name, len); + file_name[dir_len + len] = 0x0; + /* for all entries in dir get the stats */ + if (stat(file_name, &buf) == 0) { + n++; /* count successfull stat calls */ + /* copy non static fields */ + dir_info.uid += buf.st_uid; + dir_info.gid += buf.st_gid; + dir_info.size += buf.st_size; + dir_info.atime += buf.st_atime; + dir_info.mtime += buf.st_mtime; + dir_info.ctime += buf.st_ctime; + out += sizeof(dir_info); + if(my_digest(work, (u_char *)&dir_info, + sizeof(dir_info))) + break; + } + } + closedir(dir); /* done */ + out += do_time(work); /* add a time stamp */ + return (out); +} + + +/* + * unix_cmd() + * this function executes the a command from the cmds[] list of unix commands + * configured in the prand_conf.h file + * return value is the number of bytes added to the randomness temp buffer + * + * it returns the number of bytes that where read in + * if more data is needed at the end time is added to the data. + * This function maintains a state to selects the next command to run + * returns the number of bytes read in from the command + */ +static int +unix_cmd(dst_work *work) +{ + static int cmd_index = 0; + int cnt = 0, n; + FILE *pipe; + u_char buffer[4096]; + + if (cmds[cmd_index] == NULL) + cmd_index = 0; + EREPORT(("unix_cmd() i %d filled %4d in_temp %4d\n", + cmd_index, work->filled, work->in_temp)); + pipe = popen(cmds[cmd_index++], "r"); /* execute the command */ + + while ((n = fread(buffer, sizeof(char), sizeof(buffer), pipe)) > 0) { + cnt += n; /* process the output */ + if (my_digest(work, buffer, n)) + break; + /* this adds some randomness to the output */ + cnt += do_time(work); + } + while ((n = fread(buffer, sizeof(char), sizeof(buffer), pipe)) > 0) + NULL; /* drain the pipe */ + pclose(pipe); + return (cnt); /* read how many bytes where read in */ +} + +/* + * digest_file() This function will read a file and run hash over it + * input is a file name + */ +static int +digest_file(dst_work *work) +{ + static int f_cnt = 0; + static unsigned long f_round = 0; + FILE *fp; + void *ctx; + const char *name; + int no, i; + struct stat st; + struct timeval tv; + u_char buf[1024]; + + if (f_round == 0 || files[f_cnt] == NULL || work->file_digest == NULL) + if (gettimeofday(&tv, NULL)) /* only do this if needed */ + return (0); + if (f_round == 0) /* first time called set to one hour ago */ + f_round = (tv.tv_sec - MAX_OLD); + name = files[f_cnt++]; + if (files[f_cnt] == NULL) { /* end of list of files */ + if(f_cnt <= 1) /* list is too short */ + return (0); + f_cnt = 0; /* start again on list */ + f_round += (tv.tv_sec - f_round)/2; /* set new cutoff */ + work->file_digest = dst_free_key(work->file_digest); + } + if (work->file_digest == NULL) { + work->file_digest = dst_buffer_to_key("", KEY_HMAC_MD5, 0, 0, + (u_char *)&tv, sizeof(tv)); + if (work->file_digest == NULL) + return (0); + } + if (access(name, R_OK) || stat(name, &st)) + return (0); /* no such file or not allowed to read it */ + if (strncmp(name, "/proc/", 6) && st.st_mtime < f_round) + return(0); /* file has not changed recently enough */ + if (dst_sign_data(SIG_MODE_INIT, work->file_digest, &ctx, + NULL, 0, NULL, 0)) { + work->file_digest = dst_free_key(work->file_digest); + return (0); + } + if ((fp = fopen(name, "r")) == NULL) + return (0); + for (no = 0; (i = fread(buf, sizeof(*buf), sizeof(buf), fp)) > 0; + no += i) + dst_sign_data(SIG_MODE_UPDATE, work->file_digest, &ctx, + buf, i, NULL, 0); + + fclose(fp); + if (no >= 64) { + i = dst_sign_data(SIG_MODE_FINAL, work->file_digest, &ctx, + NULL, 0, &work->output[work->filled], + DST_HASH_SIZE); + if (i > 0) + work->filled += i; + } + else if (i > 0) + my_digest(work, buf, i); + my_digest(work, (u_char *)name, strlen(name)); + return (no + strlen(name)); +} + +/* + * function to perform the FINAL and INIT operation on a hash if allowed + */ +static void +force_hash(dst_work *work, prand_hash *hash) +{ + int i = 0; + + /* + * if more than half a block then add data to output + * otherwise adde the digest to the next hash + */ + if ((hash->digested * 2) > hash->block) { + i = dst_sign_data(SIG_MODE_FINAL, hash->key, &hash->ctx, + NULL, 0, &work->output[work->filled], + DST_HASH_SIZE); + + hash->digested = 0; + dst_sign_data(SIG_MODE_INIT, hash->key, &hash->ctx, + NULL, 0, NULL, 0); + if (i > 0) + work->filled += i; + } + return; +} + +/* + * This function takes the input data does the selection of data specified + * by the hash control block. + * The step varialbe in the work sturcture determines which 1/step bytes + * are used, + * + */ +static int +do_hash(dst_work *work, prand_hash *hash, u_char *input, int size) +{ + u_char *tmp = input, *tp; + int i, cnt = size, n, needed, avail, dig, tmp_size = 0; + + if (cnt <= 0 || input == NULL) + return (0); + + if (hash->step > 1) { /* if using subset of input data */ + tmp_size = size / hash->step + 2; + tp = tmp = malloc(tmp_size); + for (cnt = 0, i = hash->curr; i < size; i += hash->step, cnt++) + *(tp++) = input[i]; + /* calcutate the starting point in the next input set */ + hash->curr = (hash->step - (i - size)) % hash->step; + } + /* digest the data in block sizes */ + for (n = 0; n < cnt; n += needed) { + avail = (cnt - n); + needed = hash->block - hash->digested; + dig = (avail < needed) ? avail : needed; + dst_sign_data(SIG_MODE_UPDATE, hash->key, &hash->ctx, + &tmp[n], dig, NULL, 0); + hash->digested += dig; + if (hash->digested >= hash->block) + force_hash(work, hash); + if (work->needed < work->filled) { + if (tmp != input) + SAFE_FREE2(tmp, tmp_size); + return (1); + } + } + if (tmp_size > 0) + SAFE_FREE2(tmp, tmp_size); + return (0); +} + +/* + * Copy data from INPUT for length SIZE into the work-block TMP. + * If we fill the work-block, digest it; then, + * if work-block needs more data, keep filling with the rest of the input. + */ +static int +my_digest(dst_work *work, u_char *input, int size) +{ + + int i, full = 0; + static unsigned counter; + + counter += size; + /* first do each one of the hashes */ + for (i = 0; i < DST_NUM_HASHES && full == 0; i++) + full = do_hash(work, work->hash[i], input, size) + + do_hash(work, work->hash[i], (u_char *) &counter, + sizeof(counter)); +/* + * if enough data has be generated do final operation on all hashes + * that have enough date for that + */ + for (i = 0; full && (i < DST_NUM_HASHES); i++) + force_hash(work, work->hash[i]); + + return (full); +} + +/* + * this function gets some semi random data and sets that as an HMAC key + * If we get a valid key this function returns that key initalized + * otherwise it returns NULL; + */ +static prand_hash * +get_hmac_key(int step, int block) +{ + + u_char *buff; + int temp = 0, n = 0, size = 70; + DST_KEY *new_key = NULL; + prand_hash *new = NULL; + + /* use key that is larger than digest algorithms (64) for key size */ + buff = malloc(size); + if (buff == NULL) + return (NULL); + /* do not memset the allocated memory to get random bytes there */ + /* time of day is somewhat random expecialy in the last bytes */ + gettimeofday((struct timeval *) &buff[n], NULL); + n += sizeof(struct timeval); + +/* get some semi random stuff in here stir it with micro seconds */ + if (n < size) { + temp = dst_s_quick_random((int) buff[n - 1]); + memcpy(&buff[n], &temp, sizeof(temp)); + n += sizeof(temp); + } +/* get the pid of this process and its parent */ + if (n < size) { + temp = (int) getpid(); + memcpy(&buff[n], &temp, sizeof(temp)); + n += sizeof(temp); + } + if (n < size) { + temp = (int) getppid(); + memcpy(&buff[n], &temp, sizeof(temp)); + n += sizeof(temp); + } +/* get the user ID */ + if (n < size) { + temp = (int) getuid(); + memcpy(&buff[n], &temp, sizeof(temp)); + n += sizeof(temp); + } +#ifndef GET_HOST_ID_MISSING + if (n < size) { + temp = (int) gethostid(); + memcpy(&buff[n], &temp, sizeof(temp)); + n += sizeof(temp); + } +#endif +/* get some more random data */ + if (n < size) { + temp = dst_s_quick_random((int) buff[n - 1]); + memcpy(&buff[n], &temp, sizeof(temp)); + n += sizeof(temp); + } +/* covert this into a HMAC key */ + new_key = dst_buffer_to_key("", KEY_HMAC_MD5, 0, 0, buff, size); + SAFE_FREE(buff); + +/* get the control structure */ + if ((new = malloc(sizeof(prand_hash))) == NULL) + return (NULL); + new->digested = new->curr = 0; + new->step = step; + new->block = block; + new->key = new_key; + if (dst_sign_data(SIG_MODE_INIT, new_key, &new->ctx, NULL, 0, NULL, 0)) + return (NULL); + + return (new); +} + +/* + * own_random() + * This function goes out and from various sources tries to generate enough + * semi random data that a hash function can generate a random data. + * This function will iterate between the two main random source sources, + * information from programs and directores in random order. + * This function return the number of bytes added to the random output buffer. + */ +static int +own_random(dst_work *work) +{ + int dir = 0, b; + int bytes, n, cmd = 0, dig = 0; + int start =0; +/* + * now get the initial seed to put into the quick random function from + * the address of the work structure + */ + bytes = (int) getpid(); +/* + * proceed while needed + */ + while (work->filled < work->needed) { + EREPORT(("own_random r %08x b %6d t %6d f %6d\n", + ran_val, bytes, work->in_temp, work->filled)); +/* pick a random number in the range of 0..7 based on that random number + * perform some operations that yield random data + */ + start = work->filled; + n = (dst_s_quick_random(bytes) >> DST_SHIFT) & 0x07; + switch (n) { + case 0: + case 3: + if (sizeof(cmds) > 2 *sizeof(*cmds)) { + b = unix_cmd(work); + cmd += b; + } + break; + + case 1: + case 7: + if (sizeof(dirs) > 2 *sizeof(*dirs)) { + b = do_ls(work); + dir += b; + } + break; + + case 4: + case 5: + /* retry getting data from /dev/random */ + b = get_dev_random(&work->output[work->filled], + work->needed - work->filled); + if (b > 0) + work->filled += b; + break; + + case 6: + if (sizeof(files) > 2 * sizeof(*files)) { + b = digest_file(work); + dig += b; + } + break; + + case 2: + default: /* to make sure we make some progress */ + work->output[work->filled++] = 0xff & + dst_s_quick_random(bytes); + b = 1; + break; + } + if (b > 0) + bytes += b; + } + return (work->filled); +} + + +/* + * dst_s_random() This function will return the requested number of bytes + * of randomness to the caller it will use the best available sources of + * randomness. + * The current order is to use /dev/random, precalculated randomness, and + * finaly use some system calls and programs to generate semi random data that + * is then digested to generate randomness. + * This function is thread safe as each thread uses its own context, but + * concurrent treads will affect each other as they update shared state + * information. + * It is strongly recommended that this function be called requesting a size + * that is not a multiple of the output of the hash function used. + * + * If /dev/random is not available this function is not suitable to generate + * large ammounts of data, rather it is suitable to seed a pseudo-random + * generator + * Returns the number of bytes put in the output buffer + */ +int +dst_s_random(u_char *output, int size) +{ + int n = 0, s, i; + static u_char old_unused[DST_HASH_SIZE * DST_NUM_HASHES]; + static int unused = 0; + + if (size <= 0 || output == NULL) + return (0); + + if (size >= 2048) + return (-1); + /* + * Read from /dev/random + */ + n = get_dev_random(output, size); + /* + * If old data is available and needed use it + */ + if (n < size && unused > 0) { + int need = size - n; + if (unused <= need) { + memcpy(output, old_unused, unused); + n += unused; + unused = 0; + } else { + memcpy(output, old_unused, need); + n += need; + unused -= need; + memcpy(old_unused, &old_unused[need], unused); + } + } + /* + * If we need more use the simulated randomness here. + */ + if (n < size) { + dst_work *my_work = (dst_work *) malloc(sizeof(dst_work)); + if (my_work == NULL) + return (n); + my_work->needed = size - n; + my_work->filled = 0; + my_work->output = (u_char *) malloc(my_work->needed + + DST_HASH_SIZE * + DST_NUM_HASHES); + my_work->file_digest = NULL; + if (my_work->output == NULL) + return (n); + memset(my_work->output, 0x0, my_work->needed); +/* allocate upto 4 different HMAC hash functions out of order */ +#if DST_NUM_HASHES >= 3 + my_work->hash[2] = get_hmac_key(3, DST_RANDOM_BLOCK_SIZE / 2); +#endif +#if DST_NUM_HASHES >= 2 + my_work->hash[1] = get_hmac_key(7, DST_RANDOM_BLOCK_SIZE / 6); +#endif +#if DST_NUM_HASHES >= 4 + my_work->hash[3] = get_hmac_key(5, DST_RANDOM_BLOCK_SIZE / 4); +#endif + my_work->hash[0] = get_hmac_key(1, DST_RANDOM_BLOCK_SIZE); + if (my_work->hash[0] == NULL) /* if failure bail out */ + return (n); + s = own_random(my_work); +/* if more generated than needed store it for future use */ + if (s >= my_work->needed) { + EREPORT(("dst_s_random(): More than needed %d >= %d\n", + s, my_work->needed)); + memcpy(&output[n], my_work->output, my_work->needed); + n += my_work->needed; + /* saving unused data for next time */ + unused = s - my_work->needed; + memcpy(old_unused, &my_work->output[my_work->needed], + unused); + } else { + /* XXXX This should not happen */ + EREPORT(("Not enough %d >= %d\n", s, my_work->needed)); + memcpy(&output[n], my_work->output, s); + n += my_work->needed; + } + +/* delete the allocated work area */ + for (i = 0; i < DST_NUM_HASHES; i++) { + dst_free_key(my_work->hash[i]->key); + SAFE_FREE(my_work->hash[i]); + } + SAFE_FREE(my_work->output); + SAFE_FREE(my_work); + } + return (n); +} + +/* + * A random number generator that is fast and strong + * this random number generator is based on HASHing data, + * the input to the digest function is a collection of + * counters that is incremented between digest operations + * each increment operation amortizes to 2 bits changed in that value + * for 5 counters thus the input will amortize to have 10 bits changed + * The counters are initaly set using the strong random function above + * the HMAC key is selected by the same methold as the HMAC keys for the + * strong random function. + * Each set of counters is used for 2^25 operations + * + * returns the number of bytes written to the output buffer + * or negative number in case of error + */ +int +dst_s_semi_random(u_char *output, int size) +{ + static u_int32_t counter[DST_NUMBER_OF_COUNTERS]; + static u_char semi_old[DST_HASH_SIZE]; + static int semi_loc = 0, cnt = 0, hb_size = 0; + static DST_KEY *my_key = NULL; + prand_hash *hash; + int out = 0, i, n; + + if (output == NULL || size <= 0) + return (-2); + +/* check if we need a new key */ + if (my_key == NULL || cnt > (1 << 25)) { /* get HMAC KEY */ + if (my_key) + my_key->dk_func->destroy(my_key); + if ((hash = get_hmac_key(1, DST_RANDOM_BLOCK_SIZE)) == NULL) + return (0); + my_key = hash->key; +/* check if the key works stir the new key using some old random data */ + hb_size = dst_sign_data(SIG_MODE_ALL, my_key, NULL, + (u_char *) counter, sizeof(counter), + semi_old, sizeof(semi_old)); + if (hb_size <= 0) { + EREPORT(("dst_s_semi_random() Sign of alg %d failed %d\n", + my_key->dk_alg, hb_size)); + return (-1); + } +/* new set the counters to random values */ + dst_s_random((u_char *) counter, sizeof(counter)); + cnt = 0; + } +/* if old data around use it first */ + if (semi_loc < hb_size) { + if (size <= hb_size - semi_loc) { /* need less */ + memcpy(output, &semi_old[semi_loc], size); + semi_loc += size; + return (size); /* DONE */ + } else { + out = hb_size - semi_loc; + memcpy(output, &semi_old[semi_loc], out); + semi_loc += out; + } + } +/* generate more randome stuff */ + while (out < size) { + /* + * modify at least one bit by incrementing at least one counter + * based on the last bit of the last counter updated update + * the next one. + * minimaly this operation will modify at least 1 bit, + * amortized 2 bits + */ + for (n = 0; n < DST_NUMBER_OF_COUNTERS; n++) + i = (int) counter[n]++; + + i = dst_sign_data(SIG_MODE_ALL, my_key, NULL, + (u_char *) counter, hb_size, + semi_old, sizeof(semi_old)); + if (i != hb_size) + EREPORT(("HMAC SIGNATURE FAILURE %d\n", i)); + cnt++; + if (size - out < i) /* Not all data is needed */ + semi_loc = i = size - out; + memcpy(&output[out], semi_old, i); + out += i; + } + return (out); +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/prandom.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/rsaref_link.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/rsaref_link.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/rsaref_link.c (revision 60942) @@ -0,0 +1,754 @@ +#ifdef RSAREF +static const char rcsid[] = "$Header: /proj/cvs/isc/bind/src/lib/dst/rsaref_link.c,v 1.6 1999/10/13 16:39:24 vixie Exp $"; + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, 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 TRUSTED INFORMATION SYSTEMS + * 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. + */ + +/* + * This file contains two components + * 1. Interface to the rsaref library to allow compilation when RSAREF is + * not available all calls to RSAREF are contained inside this file. + * 2. The glue to connvert RSA{REF} KEYS to and from external formats + */ +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dst_internal.h" + +# ifdef __STDC__ +# define PROTOTYPES 1 +# else +# define PROTOTYPES 0 +# endif + +# include +# include + +#include "port_after.h" + + +typedef struct rsakey { + char *rk_signer; + R_RSA_PRIVATE_KEY *rk_Private_Key; + R_RSA_PUBLIC_KEY *rk_Public_Key; +} RSA_Key; + + +static int dst_rsaref_sign(const int mode, DST_KEY *key, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len); +static int dst_rsaref_verify(const int mode, DST_KEY *key, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len); + +static int dst_rsaref_to_dns_key(const DST_KEY *public, u_char *out_str, + const int out_len); +static int dst_rsaref_from_dns_key(DST_KEY *s_key, const u_char *key, + const int len); + +static int dst_rsaref_key_to_file_format(const DST_KEY *dkey, + u_char *buff, + const int buff_len); +static int dst_rsaref_key_from_file_format(DST_KEY *dkey, + const u_char *buff, + const int buff_len); + +static int dst_rsaref_compare_keys(const DST_KEY *rkey1, + const DST_KEY *rkey2); +static void *dst_rsaref_free_key_structure(void *d_key); + +static int dst_rsaref_generate_keypair(DST_KEY *key, const int exp); + +static void dst_rsaref_init_random_struct(R_RANDOM_STRUCT * randomstruct); + +/* + * dst_rsaref_init() Function to answer set up function pointers for RSAREF + * related functions + */ +int +dst_rsaref_init() +{ + if (dst_t_func[KEY_RSA] != NULL) + return (1); + dst_t_func[KEY_RSA] = malloc(sizeof(struct dst_func)); + if (dst_t_func[KEY_RSA] == NULL) + return (0); + memset(dst_t_func[KEY_RSA], 0, sizeof(struct dst_func)); + dst_t_func[KEY_RSA]->sign = dst_rsaref_sign; + dst_t_func[KEY_RSA]->verify = dst_rsaref_verify; + dst_t_func[KEY_RSA]->compare = dst_rsaref_compare_keys; + dst_t_func[KEY_RSA]->generate = dst_rsaref_generate_keypair; + dst_t_func[KEY_RSA]->destroy = dst_rsaref_free_key_structure; + dst_t_func[KEY_RSA]->to_dns_key = dst_rsaref_to_dns_key; + dst_t_func[KEY_RSA]->from_dns_key = dst_rsaref_from_dns_key; + dst_t_func[KEY_RSA]->to_file_fmt = dst_rsaref_key_to_file_format; + dst_t_func[KEY_RSA]->from_file_fmt = dst_rsaref_key_from_file_format; + return (1); +} + +/* + * dst_rsa_sign + * Call RSAREF signing functions to sign a block of data. + * There are three steps to signing, INIT (initialize structures), + * UPDATE (hash (more) data), FINAL (generate a signature). This + * routine performs one or more of these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * key pointer to a RSA key structure that points to public key + * and context to use. + * data data to be signed. + * len length in bytes of data. + * signature location to store signature. + * sig_len size of the signature storage area + * returns + * N Success on SIG_MODE_FINAL = returns signature length in bytes + * 0 Success on SIG_MODE_INIT and UPDATE + * <0 Failure + */ + + +static int +dst_rsaref_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len) +{ + int sign_len = 0; + R_SIGNATURE_CTX *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = malloc(sizeof(*ctx)); + else if (context) + ctx = (R_SIGNATURE_CTX *) *context; + if (ctx == NULL) + return (-1); + + if ((mode & SIG_MODE_INIT) && R_SignInit(ctx, DA_MD5)) + return (SIGN_INIT_FAILURE); + + /* equivalent of SIG_MODE_UPDATE */ + if ((mode & SIG_MODE_UPDATE) && (data && len > 0) && + R_SignUpdate(ctx, (u_char *) data, len)) + return (SIGN_UPDATE_FAILURE); + + if (mode & SIG_MODE_FINAL) { + RSA_Key *key = (RSA_Key *) dkey->dk_KEY_struct; + if (signature == NULL || + sig_len < (int)(key->rk_Public_Key->bits + 7) / 8) + return (SIGN_FINAL_FAILURE); + if(key == NULL || key->rk_Private_Key == NULL) + return (-1); + if (R_SignFinal(ctx, signature, &sign_len, + key->rk_Private_Key)) + return (SIGN_FINAL_FAILURE); + SAFE_FREE(ctx); + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + return (sign_len); +} + + +/* + * dst_rsaref_verify() + * Calls RSAREF verification routines. There are three steps to + * verification, INIT (initialize structures), UPDATE (hash (more) data), + * FINAL (generate a signature). This routine performs one or more of + * these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * key pointer to a RSA key structure that points to public key + * and context to use. + * data data signed. + * len length in bytes of data. + * signature signature. + * sig_len length in bytes of signature. + * returns + * 0 Success + * <0 Failure + */ + +static int +dst_rsaref_verify(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len) +{ + R_SIGNATURE_CTX *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = malloc(sizeof(*ctx)); + else if (context) + ctx = (R_SIGNATURE_CTX *) *context; + if (ctx == NULL) + return (-1); + + if ((mode & SIG_MODE_INIT) && R_VerifyInit(ctx, DA_MD5)) + return (VERIFY_INIT_FAILURE); + + if ((mode & SIG_MODE_UPDATE) && (data && len > 0) && + R_VerifyUpdate(ctx, (u_char *) data, len)) + return (VERIFY_UPDATE_FAILURE); + + if ((mode & SIG_MODE_FINAL)) { + RSA_Key *key = (RSA_Key *) dkey->dk_KEY_struct; + + if (key == NULL || key->rk_Public_Key == NULL) + return (-1); + if (signature == NULL || sig_len <= 0) + return (VERIFY_FINAL_FAILURE); + if (R_VerifyFinal(ctx, (u_char *) signature, sig_len, + key->rk_Public_Key)) + return (VERIFY_FINAL_FAILURE); + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + + return (0); +} + + +/* + * dst_rsaref_to_dns_key + * Converts key in RSAREF to DNS distribution format + * This function gets in a pointer to the public key and a work area + * to write the key into. + * Parameters + * public KEY structure + * out_str buffer to write encoded key into + * out_len size of out_str + * Return + * N >= 0 length of encoded key + * n < 0 error + */ + +static int +dst_rsaref_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len) +{ + int n, loc; + R_RSA_PUBLIC_KEY *public; + u_char *op = (u_char *) out_str; + + if (in_key == NULL || in_key->dk_KEY_struct == NULL || + out_len <= 0 || out_str == NULL) + return (-1); + public = (R_RSA_PUBLIC_KEY *) + ((RSA_Key *) in_key->dk_KEY_struct)->rk_Public_Key; + if (public == NULL) + return (-1); + + memset(op, 0, out_len); + + /* find first non zero */ + for (n = 0; public->exponent[n] == 0x0; n++) ; + + n = (MAX_RSA_MODULUS_LEN - n); /* find lenght of exponent */ + *op++ = (u_int8_t) n; + + if (n > (out_len - (op-out_str))) + return (-1); + memcpy(op, &public->exponent[MAX_RSA_MODULUS_LEN - n], n); + op += n; + n++; /* include the lenght field in this count */ + + /* find first non zero */ + for (loc = 0; public->modulus[loc] == 0x0; loc++) ; + + /*copy exponent */ + if ((MAX_RSA_MODULUS_LEN - loc) > (out_len - (op-out_str))) + return (-1); + memcpy(op, &public->modulus[loc], MAX_RSA_MODULUS_LEN - loc); + n += (MAX_RSA_MODULUS_LEN - loc); + return (n); +} + + +/* + * dst_rsaref_from_dns_key + * Converts from a DNS KEY RR format to an RSA KEY. + * Parameters + * len Length in bytes of DNS key + * key DNS key + * name Key name + * s_key DST structure that will point to the RSA key this routine + * will build. + * Return + * -1 The input key has fields that are larger than this package supports + * 0 The input key, s_key or name was null. + * 1 Success + */ +static int +dst_rsaref_from_dns_key(DST_KEY *s_key, const u_char *key, const int len) +{ + int bytes; + u_char *key_ptr; + RSA_Key *r_key; + + if (key == NULL || s_key == NULL || len < 0) + return (0); + + if (s_key->dk_KEY_struct) { /* do not reuse */ + dst_rsaref_free_key_structure(s_key->dk_KEY_struct); + s_key->dk_KEY_struct = NULL; + } + if (len == 0) /* null key no conversion needed */ + return (1); + + if ((r_key = (RSA_Key *) malloc(sizeof(RSA_Key))) == NULL) { + EREPORT(("dst_rsaref_from_dns_key(): Memory allocation error 1\n")); + return (0); + } + memset(r_key, 0, sizeof(RSA_Key)); + s_key->dk_KEY_struct = (void *) r_key; + r_key->rk_signer = strdup(s_key->dk_key_name); + r_key->rk_Public_Key = (R_RSA_PUBLIC_KEY *) + malloc(sizeof(R_RSA_PUBLIC_KEY)); + if (r_key->rk_Public_Key == NULL) { + EREPORT(("dst_rsaref_from_dns_key(): Memory allocation error 3\n")); + return (0); + } + memset(r_key->rk_Public_Key, 0, sizeof(R_RSA_PUBLIC_KEY)); + key_ptr = (u_char *) key; + bytes = (int) *key_ptr++; /* length of exponent in bytes */ + if (bytes == 0) { /* special case for long exponents */ + bytes = (int) dst_s_get_int16(key_ptr); + key_ptr += sizeof(u_int16_t); + } + if (bytes > MAX_RSA_MODULUS_LEN) { + dst_rsaref_free_key_structure(r_key); + return (-1); + } + memcpy(&r_key->rk_Public_Key->exponent[MAX_RSA_MODULUS_LEN - bytes], + key_ptr, bytes); + + key_ptr += bytes; /* beginning of modulus */ + bytes = len - bytes - 1; /* length of modulus */ + if (bytes > MAX_RSA_MODULUS_LEN) { + dst_rsaref_free_key_structure(r_key); + return (-1); + } + memcpy(&r_key->rk_Public_Key->modulus[MAX_RSA_MODULUS_LEN - bytes], + key_ptr, bytes); + r_key->rk_Public_Key->bits = bytes * 8; + s_key->dk_id = (u_int16_t) dst_s_get_int16((u_char *) + &r_key->rk_Public_Key->modulus[MAX_RSA_MODULUS_LEN - 3]); + s_key->dk_key_size = r_key->rk_Public_Key->bits; + + return (1); +} + + +/* + * dst_rsaref_key_to_file_format + * Encodes an RSA Key into the portable file format. + * Parameters + * rkey RSA KEY structure + * buff output buffer + * buff_len size of output buffer + * Return + * 0 Failure - null input rkey + * -1 Failure - not enough space in output area + * N Success - Length of data returned in buff + */ + +static int +dst_rsaref_key_to_file_format(const DST_KEY *in_key, u_char *buff, + const int buff_len) +{ + u_char *bp; + int len, b_len; + R_RSA_PRIVATE_KEY *rkey; + + if (in_key == NULL || in_key->dk_KEY_struct == NULL) + return (-1); + rkey = (R_RSA_PRIVATE_KEY *) + ((RSA_Key *) in_key->dk_KEY_struct)->rk_Private_Key; + if (rkey == NULL) /* no output */ + return (0); + if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str)) + return (-1); /* no OR not enough space in output area */ + + memset(buff, 0, buff_len); /* just in case */ + /* write file header */ + sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_RSA, "RSA"); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Modulus: ", + rkey->modulus, + MAX_RSA_MODULUS_LEN)) <= 0) + return (-1); + + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "PublicExponent: ", + rkey->publicExponent, + MAX_RSA_MODULUS_LEN)) <= 0) + return (-2); + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "PrivateExponent: ", + rkey->exponent, + MAX_RSA_MODULUS_LEN)) <= 0) + return (-3); + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime1: ", + rkey->prime[0], + MAX_RSA_PRIME_LEN)) < 0) + return (-4); + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime2: ", + rkey->prime[1], + MAX_RSA_PRIME_LEN)) < 0) + return (-5); + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Exponent1: ", + rkey->primeExponent[0], + MAX_RSA_PRIME_LEN)) < 0) + return (-6); + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Exponent2: ", + rkey->primeExponent[1], + MAX_RSA_PRIME_LEN)) < 0) + return (-7); + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Coefficient: ", + rkey->coefficient, + MAX_RSA_PRIME_LEN)) < 0) + return (-8); + bp += len; + b_len -= len; + return (buff_len - b_len); +} + + +/* + * dst_rsaref_key_from_file_format + * Converts contents of a private key file into a private RSA key. + * Parameters + * r_key structure to put key into + * buff buffer containing the encoded key + * buff_len the length of the buffer + * Return + * n >= 0 Foot print of the key converted + * n < 0 Error in conversion + */ + +static int +dst_rsaref_key_from_file_format(DST_KEY *d_key, const u_char *buff, + const int buff_len) +{ + const char *p = (char *) buff; + R_RSA_PRIVATE_KEY key; + int foot = -1; + RSA_Key *r_key; + + if (d_key == NULL || buff == NULL || buff_len < 0) + return (-1); + + memset(&key, 0, sizeof(key)); + + if (!dst_s_verify_str(&p, "Modulus: ")) + return (-3); + + if (!dst_s_conv_bignum_b64_to_u8(&p, key.modulus, MAX_RSA_MODULUS_LEN)) + return (-4); + + key.bits = dst_s_calculate_bits(key.modulus, MAX_RSA_MODULUS_BITS); + + while (*++p && p < (char *) &buff[buff_len]) { + if (dst_s_verify_str(&p, "PublicExponent: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, + key.publicExponent, + MAX_RSA_MODULUS_LEN)) + return (-5); + } else if (dst_s_verify_str(&p, "PrivateExponent: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, key.exponent, + MAX_RSA_MODULUS_LEN)) + return (-6); + } else if (dst_s_verify_str(&p, "Prime1: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, key.prime[0], + MAX_RSA_PRIME_LEN)) + return (-7); + } else if (dst_s_verify_str(&p, "Prime2: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, key.prime[1], + MAX_RSA_PRIME_LEN)) + return (-8); + } else if (dst_s_verify_str(&p, "Exponent1: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, + key.primeExponent[0], + MAX_RSA_PRIME_LEN)) + return (-9); + } else if (dst_s_verify_str(&p, "Exponent2: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, + key.primeExponent[1], + MAX_RSA_PRIME_LEN)) + return (-10); + } else if (dst_s_verify_str(&p, "Coefficient: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, key.coefficient, + MAX_RSA_PRIME_LEN)) + return (-11); + } else { + EREPORT(("dst_rsaref_key_from_file_format: Bad keyword %s\n", p)); + return (-12); + } + } /* while p */ + + r_key = (RSA_Key *) malloc(sizeof(RSA_Key)); + if (r_key == NULL) { + return (-2); + } + memset(r_key, 0, sizeof(*r_key)); + + r_key->rk_Private_Key = + (R_RSA_PRIVATE_KEY *) malloc(sizeof(R_RSA_PRIVATE_KEY)); + if (r_key->rk_Private_Key == NULL) { + EREPORT(("dst_rsaref_key_from_file_format: Memory allocation error\n")); + return (-13); + } + r_key->rk_Public_Key = (R_RSA_PUBLIC_KEY *) r_key->rk_Private_Key; + memcpy(r_key->rk_Private_Key, &key, sizeof(R_RSA_PRIVATE_KEY)); + + r_key->rk_signer = strdup(d_key->dk_key_name); + d_key->dk_KEY_struct = (void *) r_key; + d_key->dk_key_size = r_key->rk_Private_Key->bits; + d_key->dk_id = (u_int16_t) dst_s_get_int16((u_char *) + &r_key->rk_Public_Key->modulus[MAX_RSA_MODULUS_LEN - 3]); + foot = (int) d_key->dk_id; + return (foot); +} + + + +/* + * dst_rsaref_compare_keys + * Compare two keys for equality. + * Return + * 0 The keys are equal + * NON-ZERO The keys are not equal + */ + +static int +dst_rsaref_compare_keys(const DST_KEY *dkey1, const DST_KEY *dkey2) +{ + RSA_Key *rkey1 = (RSA_Key *) dkey1->dk_KEY_struct; + RSA_Key *rkey2 = (RSA_Key *) dkey2->dk_KEY_struct; + + if (rkey1 == NULL && rkey2 == NULL) + return (0); /* same */ + else if (rkey1 == NULL) + return (1); + else if (rkey2 == NULL) + return (2); + return (memcmp(rkey1->rk_Public_Key, rkey2->rk_Public_Key, + sizeof(R_RSA_PUBLIC_KEY))); +} + +/* + * dst_rsaref_generate_keypair + * Generates unique keys that are hard to predict. + * Parameters + * key generic Key structure + * exp the public exponent + * Return + * 0 Failure + * 1 Success + */ + +static int +dst_rsaref_generate_keypair(DST_KEY *key, const int exp) +{ + R_RSA_PUBLIC_KEY *public; + R_RSA_PRIVATE_KEY *private; + R_RSA_PROTO_KEY proto; + R_RANDOM_STRUCT randomStruct; + RSA_Key *rsa; + int status; + + if (key == NULL || key->dk_alg != KEY_RSA) + return (0); + if (key->dk_key_size < MIN_RSA_MODULUS_BITS || + key->dk_key_size > MAX_RSA_MODULUS_BITS) { + EREPORT(("dst_rsaref_generate_keypair: Invalid key size\n")); + return (0); /* these are the limits on key size in RSAREF */ + } + /* allocate space */ + if ((public = (R_RSA_PUBLIC_KEY *) malloc(sizeof(R_RSA_PUBLIC_KEY))) + == NULL) { + EREPORT(("dst_rsaref_generate_keypair: Memory allocation error 1\n")); + return (0); + } + if ((private = (R_RSA_PRIVATE_KEY *) malloc(sizeof(R_RSA_PRIVATE_KEY))) + == NULL) { + EREPORT(("dst_rsaref_generate_keypair: Memory allocation error 2\n")); + return (0); + } + if ((rsa = (RSA_Key *) malloc(sizeof(RSA_Key))) == NULL) { + EREPORT(("dst_rsaref_generate_keypair: Memory allocation error 3\n")); + return (0); + } + memset(public, 0, sizeof(*public)); + memset(private, 0, sizeof(*private)); + + proto.bits = key->dk_key_size; + proto.useFermat4 = exp ? 0x1 : 0x0; /* 1 for f4=65537, 0 for f0=3 */ + EREPORT(("\ndst_rsaref_generate_keypair: Generating KEY for %s Please wait\n", + key->dk_key_name)); + + /* set up random seed */ + dst_rsaref_init_random_struct(&randomStruct); + + /* generate keys */ + status = R_GeneratePEMKeys(public, private, &proto, &randomStruct); + if (status) { + EREPORT(("dst_rsaref_generate_keypair: No Key Pair generated %d\n", + status)); + SAFE_FREE(public); + SAFE_FREE(private); + SAFE_FREE(rsa); + return (0); + } + memset(rsa, 0, sizeof(*rsa)); + rsa->rk_signer = key->dk_key_name; + rsa->rk_Private_Key = private; + rsa->rk_Public_Key = public; + key->dk_KEY_struct = (void *) rsa; + + key->dk_id = (u_int16_t) dst_s_get_int16((u_char *) + &rsa->rk_Public_Key->modulus[MAX_RSA_MODULUS_LEN - 3]); + return (1); +} + + +/* + * dst_rsaref_free_key_structure + * Frees all dynamicly allocated structures in r_key + */ + +static void * +dst_rsaref_free_key_structure(void *v_key) +{ + RSA_Key *r_key = (RSA_Key *) v_key; + + if (r_key != NULL) { + if ((void *) r_key->rk_Private_Key == (void *) r_key->rk_Public_Key) + r_key->rk_Public_Key = NULL; + SAFE_FREE(r_key->rk_Private_Key); + SAFE_FREE(r_key->rk_Public_Key); + SAFE_FREE(r_key->rk_signer); + SAFE_FREE(r_key); + } + return (NULL); +} + + +/* + * dst_rsaref_init_random_struct + * A random seed value is used in key generation. + * This routine gets a bunch of system values to randomize the + * randomstruct. A number of system calls are used to get somewhat + * unpredicable values, then a special function dst_s_prandom() is called + * that will do some magic depending on the system used. + * If this function is executed on reasonably busy machine then the values + * that prandom uses are hard to + * 1. Predict + * 2. Regenerate + * 3. Hard to spy on as nothing is stored to disk and data is consumed + * as fast as it is generated. + */ + +static void +dst_rsaref_init_random_struct(R_RANDOM_STRUCT * randomstruct) +{ + unsigned bytesNeeded; + struct timeval tv; + u_char *array; + int n; + + R_RandomInit(randomstruct); + + /* The runtime of the script is unpredictable within some range + * thus I'm getting the time of day again as this is an hard to guess + * value and the number of characters of the output from the script is + * hard to guess. + * This must be the FIRST CALL + */ + gettimeofday(&tv, 0); + R_RandomUpdate(randomstruct, (u_char *) &tv, + sizeof(struct timeval)); + + /* + * first find out how many bytes I need + */ + R_GetRandomBytesNeeded(&bytesNeeded, randomstruct); + + /* + * get a storage area for it addjust the area for the possible + * side effects of digest functions writing out in blocks + */ + array = (u_char *) malloc(bytesNeeded); + + /* extract the random data from /dev/random if present, generate + * it if not present + * first fill the buffer with semi random data + * then fill as much as possible with good random data + */ + n = dst_random(DST_RAND_SEMI, bytesNeeded, array); + n += dst_random(DST_RAND_KEY, bytesNeeded, array); + if (n <= bytesNeeded) { + SAFE_FREE(array); + return(0); + } + + /* supply the random data (even if it is larger than requested) */ + R_RandomUpdate(randomstruct, array, bytesNeeded); + + SAFE_FREE(array); + + R_GetRandomBytesNeeded(&bytesNeeded, randomstruct); + if (bytesNeeded) { + EREPORT(("InitRandomStruct() didn't initialize enough randomness\n")); + exit(33); + } +} + + +#else +int /* rsaref is not available */ +dst_rsaref_init() +{ + return (0); +} +#endif /* RSAREF */ Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/rsaref_link.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/support.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/support.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/support.c (revision 60942) @@ -0,0 +1,461 @@ +static const char rcsid[] = "$Header: /proj/cvs/isc/bind/src/lib/dst/support.c,v 1.8 1999/10/13 16:39:24 vixie Exp $"; + + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, 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 TRUSTED INFORMATION SYSTEMS + * 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 +#include +#include +#include + +#include "dst_internal.h" + +#include "port_after.h" +/* + * dst_s_conv_bignum_u8_to_b64 + * This function converts binary data stored as a u_char[] to a + * base-64 string. Leading zeroes are discarded. If a header is + * supplied, it is prefixed to the input prior to encoding. The + * output is \n\0 terminated (the \0 is not included in output length). + * Parameters + * out_buf binary data to convert + * header character string to prefix to the output (label) + * bin_data binary data + * bin_len size of binary data + * Return + * -1 not enough space in output work area + * 0 no output + * >0 number of bytes written to output work area + */ + +int +dst_s_conv_bignum_u8_to_b64(char *out_buf, const int out_len, + const char *header, const u_char *bin_data, + const int bin_len) +{ + const u_char *bp = bin_data; + char *op = out_buf; + int lenh = 0, len64 = 0; + int local_in_len = bin_len; + int local_out_len = out_len; + + if (bin_data == NULL || bin_len <= 0) /* no data no */ + return (0); + + if (out_buf == NULL || out_len <= 0) /* no output_work area */ + return (-1); + + /* suppress leading \0 */ + for (; (*bp == 0x0) && (local_in_len > 0); local_in_len--) + bp++; + + if (header) { /* add header to output string */ + lenh = strlen(header); + if (lenh < out_len) + memcpy(op, header, lenh); + else + return (-1); + local_out_len -= lenh; + op += lenh; + } + len64 = b64_ntop(bp, local_in_len, op, local_out_len - 2); + if (len64 < 0) + return (-1); + op += len64++; + *(op++) = '\n'; /* put CR in the output */ + *op = '\0'; /* make sure output is 0 terminated */ + return (lenh + len64); +} + + +/* + * dst_s_verify_str() + * Validate that the input string(*str) is at the head of the input + * buffer(**buf). If so, move the buffer head pointer (*buf) to + * the first byte of data following the string(*str). + * Parameters + * buf Input buffer. + * str Input string. + * Return + * 0 *str is not the head of **buff + * 1 *str is the head of **buff, *buf is is advanced to + * the tail of **buf. + */ + +int +dst_s_verify_str(const char **buf, const char *str) +{ + int b, s; + if (*buf == NULL) /* error checks */ + return (0); + if (str == NULL || *str == '\0') + return (1); + + b = strlen(*buf); /* get length of strings */ + s = strlen(str); + if (s > b || strncmp(*buf, str, s)) /* check if same */ + return (0); /* not a match */ + (*buf) += s; /* advance pointer */ + return (1); +} + + +/* + * dst_s_conv_bignum_b64_to_u8 + * Read a line of base-64 encoded string from the input buffer, + * convert it to binary, and store it in an output area. The + * input buffer is read until reaching a newline marker or the + * end of the buffer. The binary data is stored in the last X + * number of bytes of the output area where X is the size of the + * binary output. If the operation is successful, the input buffer + * pointer is advanced. This procedure does not do network to host + * byte order conversion. + * Parameters + * buf Pointer to encoded input string. Pointer is updated if + * function is successfull. + * loc Output area. + * loclen Size in bytes of output area. + * Return + * >0 Return = number of bytes of binary data stored in loc. + * 0 Failure. + */ + +int +dst_s_conv_bignum_b64_to_u8(const char **buf, u_char *loc, const int loclen) +{ + int blen; + char *bp; + u_char bstr[RAW_KEY_SIZE]; + + if (buf == NULL || *buf == NULL) { /* error checks */ + EREPORT(("dst_s_conv_bignum_b64_to_u8: null input buffer.\n")); + return (0); + } + bp = strchr(*buf, '\n'); /* find length of input line */ + if (bp != NULL) + *bp = (u_char) NULL; + + blen = b64_pton(*buf, bstr, sizeof(bstr)); + if (blen <= 0) { + EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is null.\n")); + return (0); + } + else if (loclen < blen) { + EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is longer than output buffer.\n")); + return (0); + } + if (bp) + *buf = bp; /* advancing buffer past \n */ + memset(loc, 0, loclen - blen); /* clearing unused output area */ + memcpy(loc + loclen - blen, bstr, blen); /* write last blen bytes */ + return (blen); +} + + +/* + * dst_s_calculate_bits + * Given a binary number represented in a u_char[], determine + * the number of significant bits used. + * Parameters + * str An input character string containing a binary number. + * max_bits The maximum possible significant bits. + * Return + * N The number of significant bits in str. + */ + +int +dst_s_calculate_bits(const u_char *str, const int max_bits) +{ + const u_char *p = str; + u_char i, j = 0x80; + int bits; + for (bits = max_bits; *p == 0x00 && bits > 0; p++) + bits -= 8; + for (i = *p; (i & j) != j; j >>= 1) + bits--; + return (bits); +} + + +/* + * calculates a checksum used in kmt for a id. + * takes an array of bytes and a length. + * returns a 16 bit checksum. + */ +u_int16_t +dst_s_id_calc(const u_char *key, const int keysize) +{ + u_int32_t ac; + const u_char *kp = key; + int size = keysize; + + if (!key || (keysize <= 0)) + return (-1); + + for (ac = 0; size > 1; size -= 2, kp += 2) + ac += ((*kp) << 8) + *(kp + 1); + + if (size > 0) + ac += ((*kp) << 8); + ac += (ac >> 16) & 0xffff; + + return (ac & 0xffff); +} + +/* + * dst_s_dns_key_id() Function to calculated DNSSEC footprint from KEY reocrd + * rdata (all of record) + * Input: + * dns_key_rdata: the raw data in wire format + * rdata_len: the size of the input data + * Output: + * the key footprint/id calcuated from the key data + */ +u_int16_t +dst_s_dns_key_id(const u_char *dns_key_rdata, const int rdata_len) +{ + int key_data = 4; + + if (!dns_key_rdata || (rdata_len < key_data)) + return 0; + + /* check the extended parameters bit in the DNS Key RR flags */ + if (dst_s_get_int16(dns_key_rdata) & DST_EXTEND_FLAG) + key_data += 2; + + /* compute id */ + if (dns_key_rdata[3] == KEY_RSA) /* Algorithm RSA */ + return dst_s_get_int16((u_char *) + &dns_key_rdata[rdata_len - 3]); + else + /* compute a checksum on the key part of the key rr */ + return dst_s_id_calc(&dns_key_rdata[key_data], + (rdata_len - key_data)); +} + +/* + * dst_s_get_int16 + * This routine extracts a 16 bit integer from a two byte character + * string. The character string is assumed to be in network byte + * order and may be unaligned. The number returned is in host order. + * Parameter + * buf A two byte character string. + * Return + * The converted integer value. + */ + +u_int16_t +dst_s_get_int16(const u_char *buf) +{ + register u_int16_t a = 0; + a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1])); + return (a); +} + + +/* + * dst_s_get_int32 + * This routine extracts a 32 bit integer from a four byte character + * string. The character string is assumed to be in network byte + * order and may be unaligned. The number returned is in host order. + * Parameter + * buf A four byte character string. + * Return + * The converted integer value. + */ + +u_int32_t +dst_s_get_int32(const u_char *buf) +{ + register u_int32_t a = 0; + a = ((u_int32_t)(buf[0] << 24)) | ((u_int32_t)(buf[1] << 16)) | + ((u_int32_t)(buf[2] << 8)) | ((u_int32_t)(buf[3])); + return (a); +} + + +/* + * dst_s_put_int16 + * Take a 16 bit integer and store the value in a two byte + * character string. The integer is assumed to be in network + * order and the string is returned in host order. + * + * Parameters + * buf Storage for a two byte character string. + * val 16 bit integer. + */ + +void +dst_s_put_int16(u_int8_t *buf, const u_int16_t val) +{ + buf[0] = (u_int8_t)(val >> 8); + buf[1] = (u_int8_t)(val); +} + + +/* + * dst_s_put_int32 + * Take a 32 bit integer and store the value in a four byte + * character string. The integer is assumed to be in network + * order and the string is returned in host order. + * + * Parameters + * buf Storage for a four byte character string. + * val 32 bit integer. + */ + +void +dst_s_put_int32(u_int8_t *buf, const u_int32_t val) +{ + buf[0] = (u_int8_t)(val >> 24); + buf[1] = (u_int8_t)(val >> 16); + buf[2] = (u_int8_t)(val >> 8); + buf[3] = (u_int8_t)(val); +} + + +/* + * dst_s_filename_length + * + * This function returns the number of bytes needed to hold the + * filename for a key file. '/', '\' and ':' are not allowed. + * form: K++. + * + * Returns 0 if the filename would contain either '\', '/' or ':' + */ +size_t +dst_s_filename_length(const char *name, const char *suffix) +{ + if (name == NULL) + return (0); + if (strrchr(name, '\\')) + return (0); + if (strrchr(name, '/')) + return (0); + if (strrchr(name, ':')) + return (0); + if (suffix == NULL) + return (0); + if (strrchr(suffix, '\\')) + return (0); + if (strrchr(suffix, '/')) + return (0); + if (strrchr(suffix, ':')) + return (0); + return (1 + strlen(name) + 6 + strlen(suffix)); +} + + +/* + * dst_s_build_filename () + * Builds a key filename from the key name, it's id, and a + * suffix. '\', '/' and ':' are not allowed. fA filename is of the + * form: K. + * form: K++. + * + * Returns -1 if the conversion fails: + * if the filename would be too long for space allotted + * if the filename would contain a '\', '/' or ':' + * Returns 0 on success + */ + +int +dst_s_build_filename(char *filename, const char *name, u_int16_t id, + int alg, const char *suffix, size_t filename_length) +{ + u_int32_t my_id; + if (filename == NULL) + return (-1); + memset(filename, 0, filename_length); + if (name == NULL) + return (-1); + if (suffix == NULL) + return (-1); + if (filename_length < 1 + strlen(name) + 4 + 6 + 1 + strlen(suffix)) + return (-1); + my_id = id; + sprintf(filename, "K%s+%03d+%05d.%s", name, alg, my_id, + (char *) suffix); + if (strrchr(filename, '/')) + return (-1); + if (strrchr(filename, '\\')) + return (-1); + if (strrchr(filename, ':')) + return (-1); + return (0); +} + +/* + * dst_s_fopen () + * Open a file in the dst_path directory. If perm is specified, the + * file is checked for existence first, and not opened if it exists. + * Parameters + * filename File to open + * mode Mode to open the file (passed directly to fopen) + * perm File permission, if creating a new file. + * Returns + * NULL Failure + * NON-NULL (FILE *) of opened file. + */ +FILE * +dst_s_fopen(const char *filename, const char *mode, int perm) +{ + FILE *fp; + char pathname[PATH_MAX]; + int plen = sizeof(pathname); + + if (*dst_path != '\0') { + strcpy(pathname, dst_path); + plen -= strlen(pathname); + } + else + pathname[0] = '\0'; + + if (plen > strlen(filename)) + strncpy(&pathname[PATH_MAX - plen], filename, plen-1); + else + return (NULL); + + fp = fopen(pathname, mode); + if (perm) + chmod(pathname, perm); + return (fp); +} + +void +dst_s_dump(const int mode, const u_char *data, const int size, + const char *msg) +{ + if (size > 0) { +#ifdef LONG_TEST + static u_char scratch[1000]; + int n ; + n = b64_ntop(data, scratch, size, sizeof(scratch)); + printf("%s: %x %d %s\n", msg, mode, n, scratch); +#else + printf("%s,%x %d\n", msg, mode, size); +#endif + } +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/dst/support.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/Makefile (revision 60942) @@ -0,0 +1,118 @@ +# 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.19 2000/02/29 03:38:22 vixie 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= bsdos +DESTDIR = +DESTLIB = /usr/local/lib +O=o +A=a +CC= cc +LD= ld +SHELL= /bin/sh +CDEBUG= -g +TOP= ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.${A} +LIBBINDR = ../${TOP}/lib/libbind_r.${A} +CFLAGS= ${CDEBUG} -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}: + if test ! -d ${THREADED} ; then mkdir ${THREADED} ; else true ; fi + -(${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.2.3.t5b/contrib/bind/lib/irs/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns.c (revision 60942) @@ -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: dns.c,v 1.15 2000/02/28 07:52:16 vixie 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; + + 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.2.3.t5b/contrib/bind/lib/irs/dns.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns_ho.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns_ho.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns_ho.c (revision 60942) @@ -0,0 +1,717 @@ +/* + * 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.28 2000/04/20 07:47:54 vixie 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 "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 + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +#define BOUNDS_CHECK(ptr, count) \ + if ((ptr) + (count) > eom) { \ + had_error++; \ + continue; \ + } else (void)0 + +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 void map_v4v6_hostent(struct hostent *hp, char **bp, + int *len); +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); +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; + + 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; + 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; + int n, size, type; + u_char buf[MAXPACKET]; + char tmp[NS_MAXDNAME]; + const char *cp; + + if (init(this) == -1) + return (NULL); + + switch (af) { + case AF_INET: + size = INADDRSZ; + type = T_A; + break; + case AF_INET6: + size = IN6ADDRSZ; + type = T_AAAA; + break; + default: + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + return (NULL); + } + + /* + * 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; + + if ((n = res_nsearch(pvt->res, name, C_IN, type, + buf, sizeof buf)) < 0) + return (NULL); + return (gethostans(this, buf, n, name, type, af, size)); +} + +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 qbuf[MAXDNAME+1], *qp; + u_char buf[MAXPACKET]; + struct hostent *hp; + int n, size; + + if (init(this) == -1) + return (NULL); + + 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 = (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); + } + switch (af) { + case AF_INET: + (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", + (uaddr[3] & 0xff), + (uaddr[2] & 0xff), + (uaddr[1] & 0xff), + (uaddr[0] & 0xff)); + break; + case AF_INET6: + qp = qbuf; + for (n = IN6ADDRSZ - 1; n >= 0; n--) { + qp += SPRINTF((qp, "%x.%x.", + uaddr[n] & 0xf, + (uaddr[n] >> 4) & 0xf)); + } + strcpy(qp, "ip6.int"); + break; + default: + abort(); + } + n = res_nquery(pvt->res, qbuf, C_IN, T_PTR, buf, sizeof buf); + if (n < 0) + return (NULL); + hp = gethostans(this, buf, n, qbuf, T_PTR, af, size); + if (!hp) + return (NULL); /* H_ERRNO was set by gethostans() */ + 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); + return (hp); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + return (NULL); +} + +static void +ho_rewind(struct irs_ho *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); +} + +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) +{ + struct pvt *pvt = (struct pvt *)this->private; + int type, class, buflen, ancount, qdcount, n, haveanswer, had_error; + int (*name_ok)(const char *); + const HEADER *hp; + const u_char *eom; + const u_char *cp; + const char *tname, **tap; + char *bp, **ap, **hap; + char tbuf[MAXDNAME+1]; + + tname = qname; + eom = ansbuf + anslen; + switch (qtype) { + case T_A: + case T_AAAA: + 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; + pvt->host.h_name = NULL; + + /* + * Find first satisfactory answer. + */ + if (ansbuf + HFIXEDSZ > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + hp = (HEADER *)ansbuf; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + bp = pvt->hostbuf; + buflen = 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, buflen); + 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) { + /* 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; + bp += n; + buflen -= n; + /* The qname can be abbreviated, but h_name 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, buflen); + 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; + } + if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { + if (ap >= &pvt->host_aliases[MAXALIASES-1]) + continue; + n = dn_expand(ansbuf, eom, cp, tbuf, sizeof tbuf); + if (n < 0 || !maybe_ok(pvt->res, tbuf, name_ok)) { + had_error++; + continue; + } + cp += n; + /* Store alias. */ + *ap++ = bp; + n = strlen(bp) + 1; /* for the \0 */ + bp += n; + buflen -= n; + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > buflen || n > MAXHOSTNAMELEN) { + had_error++; + continue; + } + strcpy(bp, tbuf); + pvt->host.h_name = bp; + bp += n; + buflen -= n; + continue; + } + if (qtype == T_PTR && type == T_CNAME) { + n = dn_expand(ansbuf, eom, cp, tbuf, sizeof tbuf); + if (n < 0 || !maybe_dnok(pvt->res, tbuf)) { + had_error++; + continue; + } + cp += n; + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > buflen) { + had_error++; + continue; + } + strcpy(bp, tbuf); + tname = bp; + bp += n; + buflen -= n; + continue; + } + if (type != qtype) { + cp += n; + continue; + } + switch (type) { + case T_PTR: + if (ns_samename(tname, bp) != 1) { + cp += n; + continue; + } + n = dn_expand(ansbuf, eom, cp, bp, buflen); + if (n < 0 || !maybe_hnok(pvt->res, bp) || + n >= MAXHOSTNAMELEN) { + had_error++; + break; + } + cp += n; + if (!haveanswer) + pvt->host.h_name = 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; + buflen -= n; + } + break; + case T_A: + case T_AAAA: + if (ns_samename(pvt->host.h_name, bp) != 1) { + cp += n; + continue; + } + if (n != pvt->host.h_length) { + cp += n; + continue; + } + if (!haveanswer) { + int nn; + + nn = strlen(bp) + 1; /* for the \0 */ + if (nn >= MAXHOSTNAMELEN) { + cp += n; + had_error++; + continue; + } + pvt->host.h_name = bp; + bp += nn; + buflen -= nn; + } + /* Ensure alignment. */ + bp += sizeof(align) - ((u_long)bp % sizeof(align)); + /* Avoid overflows. */ + if (bp + n >= &pvt->hostbuf[sizeof pvt->hostbuf]) { + had_error++; + continue; + } + if (hap >= &pvt->h_addr_ptrs[MAXADDRS-1]) { + cp += n; + continue; + } + /* Suppress duplicates. */ + for (tap = (const char **)pvt->h_addr_ptrs; + *tap != NULL; + tap++) + if (memcmp(*tap, cp, n) == 0) + break; + if (*tap != NULL) { + cp += n; + continue; + } + /* Store address. */ + memcpy(*hap++ = bp, cp, n); + *hap = NULL; + bp += n; + cp += n; + break; + default: + abort(); + } + if (!had_error) + haveanswer++; + } + if (haveanswer) { + *ap = NULL; + + if (pvt->res->nsort && haveanswer > 1 && qtype == T_A) + addrsort(pvt->res, pvt->h_addr_ptrs, haveanswer); + if (!pvt->host.h_name) { + n = strlen(qname) + 1; /* for the \0 */ + if (n > buflen || n >= MAXHOSTNAMELEN) + goto no_recovery; + strcpy(bp, qname); + pvt->host.h_name = bp; + bp += n; + buflen -= n; + } + if (pvt->res->options & RES_USE_INET6) + map_v4v6_hostent(&pvt->host, &bp, &buflen); + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (&pvt->host); + } + no_recovery: + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); +} + +static void +map_v4v6_hostent(struct hostent *hp, char **bpp, int *lenp) { + 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 = sizeof(align) - ((u_long)*bpp % sizeof(align)); + + if (*lenp < (i + IN6ADDRSZ)) { + /* Out of memory. Truncate address list here. */ + *ap = NULL; + return; + } + *bpp += i; + *lenp -= i; + map_v4v6_address(*ap, *bpp); + *ap = *bpp; + *bpp += IN6ADDRSZ; + *lenp -= 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/dns_sv.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns_sv.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns_sv.c (revision 60942) @@ -0,0 +1,286 @@ +/* + * 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.19 2000/03/30 22:53:56 vixie 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 *); +static struct __res_state * sv_res_get(struct irs_sv *); +static void sv_res_set(struct irs_sv *, + struct __res_state *, + void (*)(void *)); + +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; + sv->res_get = NULL; /* sv_res_get; */ + sv->res_set = NULL; /* sv_res_set; */ + 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) { + errno = ENODEV; + return (NULL); +} + +static void +sv_rewind(struct irs_sv *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(*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])) + 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)) + p++; + if (!*p) + continue; + *p++ = '\0'; + + pvt->serv.s_proto = p; + while (*p && !isspace(*p)) + p++; + if (!*p) + continue; + *p++ = '\0'; + + pvt->serv.s_port = htons((u_short) atoi(p)); + while (*p && !isspace(*p)) + 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)) + 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) { + /* NOOP */ +} + +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); +} Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/gethostent.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gethostent.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gethostent.c (revision 60942) @@ -0,0 +1,891 @@ +/* + * 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.27 2000/04/20 07:10:33 vixie 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) { + 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); +} + +#if !defined(HAS_INET6_STRUCTS) || defined(MISSING_IN6ADDR_ANY) +static const struct in6_addr in6addr_any; +#endif + +#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]; + + he.h_name = (char *)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((struct in6_addr *)src)) || + (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED((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((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. + */ + +static int +scan_interfaces(int *have_v4, int *have_v6) { +#ifndef SIOCGLIFCONF +/* map new to old */ +#define SIOCGLIFCONF SIOCGIFCONF +#define lifc_len ifc_len +#define lifc_buf ifc_buf + struct ifconf lifc; +#else +#define SETFAMILYFLAGS + struct lifconf lifc; +#endif + +#ifndef SIOCGLIFADDR +/* map new to old */ +#define SIOCGLIFADDR SIOCGIFADDR +#endif + +#ifndef SIOCGLIFFLAGS +#define SIOCGLIFFLAGS SIOCGIFFLAGS +#define lifr_addr ifr_addr +#define lifr_name ifr_name +#define lifr_flags ifr_flags +#define ss_family sa_family + struct ifreq lifreq; +#else + struct lifreq lifreq; +#endif + struct in_addr in4; + struct in6_addr in6; + char *buf = NULL, *cp, *cplim; + static 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_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; +#ifdef SETFAMILYFLAGS + lifc.lifc_family = AF_UNSPEC; + lifc.lifc_flags = 0; +#endif + lifc.lifc_len = bufsiz; + lifc.lifc_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(&lifc) >= 0) + break; +#else + 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; + } +#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 + 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, SOICGLIFADDR, (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); +} + +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; + /* + * 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) { + 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.2.3.t5b/contrib/bind/lib/irs/gethostent.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getnameinfo.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getnameinfo.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getnameinfo.c (revision 60942) @@ -0,0 +1,225 @@ +/* + * Issues to be discussed: + * - Thread safe-ness must be checked + * - Return values. There seems to be no standard for return value (RFC2133) + * but INRIA implementation returns EAI_xxx defined for getaddrinfo(). + */ + +/* + * 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 + +#define SUCCESS 0 +#define ANY 0 +#define YES 1 +#define NO 0 + +/* + * 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; + int a_socklen; + int a_off; +} afdl [] = { + /* first entry is linked last... */ + {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in), + 4 /*XXX*/}, + {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6), + 8 /*XXX*/}, + {0, 0, 0}, +}; + +struct sockinet { + u_char si_len; + u_char si_family; + u_short si_port; +}; + +#define ENI_NOSOCKET 0 +#define ENI_NOSERVNAME 1 +#define ENI_NOHOSTNAME 2 +#define ENI_MEMORY 3 +#define ENI_SYSTEM 4 +#define ENI_FAMILY 5 +#define ENI_SALEN 6 + +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 + int len; +#endif + int family, i; + char *addr, *p; + u_char pfx; + static int firsttime = 1; + static char numserv[512]; + static char numaddr[512]; + + + /* dynamically adjust a_off */ + if (firsttime) { + struct afd *p; + u_char *q; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + + for (p = &afdl[0]; p->a_af; p++) { + switch (p->a_af) { + case PF_INET: + q = (u_char *)&sin.sin_addr.s_addr; + p->a_off = q - (u_char *)&sin; + break; + case PF_INET6: + q = (u_char *)&sin6.sin6_addr.s6_addr; + p->a_off = q - (u_char *)&sin6; + break; + default: + break; + } + } + firsttime = 0; + } + + if (sa == NULL) + return ENI_NOSOCKET; + +#ifdef HAVE_SA_LEN + len = sa->sa_len; + if (len != salen) return ENI_SALEN; +#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 ENI_FAMILY; + + found: + if (salen != afd->a_socklen) return ENI_SALEN; + + port = ((struct sockinet *)sa)->si_port; /* network byte order */ + addr = (char *)sa + afd->a_off; + + if (serv == NULL || servlen == 0) { + /* what we should do? */ + } else if (flags & NI_NUMERICSERV) { + snprintf(numserv, strlen(numserv), "%d", ntohs(port)); + if (strlen(numserv) > servlen) + return ENI_MEMORY; + strcpy(serv, numserv); + } else { + sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp"); + if (sp) { + if (strlen(sp->s_name) > servlen) + return ENI_MEMORY; + strcpy(serv, sp->s_name); + } else + return ENI_NOSERVNAME; + } + + switch (sa->sa_family) { + case AF_INET: + if (ntohl(*(u_long *)addr) >> IN_CLASSA_NSHIFT == 0) + flags |= NI_NUMERICHOST; + break; + case AF_INET6: + pfx = *addr; + if (pfx == 0 || pfx == 0xfe || pfx == 0xff) + flags |= NI_NUMERICHOST; + break; + } + if (host == NULL || hostlen == 0) { + /* what should we do? */ + } else if (flags & NI_NUMERICHOST) { + if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) + == NULL) + return ENI_SYSTEM; + if (strlen(numaddr) > hostlen) + return ENI_MEMORY; + strcpy(host, numaddr); + } 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) > hostlen) + return ENI_MEMORY; + strcpy(host, hp->h_name); + } else { + if (flags & NI_NAMEREQD) + return ENI_NOHOSTNAME; + if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) + == NULL) + return ENI_NOHOSTNAME; + if (strlen(numaddr) > hostlen) + return ENI_MEMORY; + strcpy(host, numaddr); + } + } + return SUCCESS; +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getnameinfo.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getpwent.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getpwent.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getpwent.c (revision 60942) @@ -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.2.3.t5b/contrib/bind/lib/irs/getpwent.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/hesiod.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/hesiod.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/hesiod.c (revision 60942) @@ -0,0 +1,504 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: hesiod.c,v 1.21 2000/02/28 14:51:08 vixie 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; + + 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.2.3.t5b/contrib/bind/lib/irs/hesiod.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp.c (revision 60942) @@ -0,0 +1,590 @@ +/* + * 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.6 2000/02/04 08:28:33 vixie 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; + + 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(*p)) p++; + while (isdigit(*p)) p++; + while (isspace(*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); + if (todo > sizeof buffer - 2) { + 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; + } + va_end(ap); + + 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.2.3.t5b/contrib/bind/lib/irs/irp.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl.c (revision 60942) @@ -0,0 +1,138 @@ +/* + * 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.16 2000/02/28 07:52:16 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 "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; + + 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.2.3.t5b/contrib/bind/lib/irs/lcl.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis.c (revision 60942) @@ -0,0 +1,149 @@ +/* + * 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.14 2000/02/28 07:52:16 vixie 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; + + 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.2.3.t5b/contrib/bind/lib/irs/nis.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/util.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/util.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/util.c (revision 60942) @@ -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.11 2000/02/04 08:28:33 vixie 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 (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.2.3.t5b/contrib/bind/lib/irs/util.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/Makefile.BSD =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/Makefile.BSD (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/Makefile.BSD (revision 60942) @@ -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.2.3.t5b/contrib/bind/lib/irs/Makefile.BSD ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/README =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/README (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/README (revision 60942) @@ -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.2.3.t5b/contrib/bind/lib/irs/README ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns_gr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns_gr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns_gr.c (revision 60942) @@ -0,0 +1,280 @@ +/* + * 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.19 1999/01/18 07:46:48 vixie 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) { + 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) { + /* NOOP */ +} + +static int +gr_list(struct irs_gr *this, const char *name, + gid_t basegid, gid_t *groups, int *ngroups) +{ + *ngroups = 0; + /* There's some way to do this in Hesiod. */ + return (-1); +} + +static void +gr_minimize(struct irs_gr *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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/dns_nw.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns_nw.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns_nw.c (revision 60942) @@ -0,0 +1,560 @@ +/* + * 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.19 1999/10/15 19:49:10 vixie 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 + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +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; + + 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) { + return (NULL); +} + +static void +nw_rewind(struct irs_nw *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[MAXPACKET]; + int anslen; + + anslen = res_nsearch(pvt->res, name, C_IN, T_PTR, + ansbuf, sizeof ansbuf); + if (anslen < 0) + return (NULL); + return (get1101mask(this, get1101answer(this, ansbuf, anslen, by_name, + AF_INET, name, NULL, 0))); +} + +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"]; + u_char ansbuf[MAXPACKET]; + 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); + anslen = res_nquery(pvt->res, qbuf, C_IN, T_PTR, + ansbuf, sizeof ansbuf); + if (anslen < 0) + return (NULL); + return (get1101mask(this, get1101answer(this, ansbuf, anslen, by_addr, + AF_INET, NULL, net, len))); +} + +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, buflen, ancount, qdcount, haveanswer; + char *bp, **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; + buflen = 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 > buflen) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + pvt->net.n_name = strcpy(bp, name); + bp += n; + buflen -= n; + } + break; + case by_addr: + if (addr != NULL && addrlen != 0) { + int n = addrlen / 8 + ((addrlen % 8) != 0); + + if (INADDRSZ > buflen) { + 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; + buflen -= 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, buflen); + + 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, buflen); + 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; + buflen -= 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 (buflen < INADDRSZ) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + pvt->net.n_addr = bp; + *bp++ = b4; + *bp++ = b3; + *bp++ = b2; + *bp++ = b1; + buflen -= INADDRSZ; + 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[MAXPACKET], *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); + } + + /* Query for the A RR that would hold this network's mask. */ + anslen = res_nquery(pvt->res, qbuf, C_IN, T_A, ansbuf, sizeof ansbuf); + if (anslen < HFIXEDSZ) + 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) + 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 */ + } + 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(*t) && isupper(*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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/dns_p.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns_p.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns_p.h (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/dns_pr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns_pr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns_pr.c (revision 60942) @@ -0,0 +1,263 @@ +/* + * 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.14 1999/09/04 22:06:14 vixie 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) { + errno = ENODEV; + return (NULL); +} + +static void +pr_rewind(struct irs_pr *this) { + /* NOOP */ +} + +static void +pr_minimize(struct irs_pr *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(*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(*p)) + p++; + if (!*p) + continue; + *p++ = '\0'; + + pvt->proto.p_proto = atoi(p); + while (*p && !isspace(*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(*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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/dns_pw.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns_pw.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/dns_pw.c (revision 60942) @@ -0,0 +1,228 @@ +/* + * 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.18 1999/09/04 22:06:14 vixie 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) { + errno = ENODEV; + return (NULL); +} + +static void +pw_rewind(struct irs_pw *this) { + /* NOOP */ +} + +static void +pw_minimize(struct irs_pw *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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/gai_strerror.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gai_strerror.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gai_strerror.c (revision 60942) @@ -0,0 +1,45 @@ +/* +%%% copyright-cmetz-97 +This software is Copyright 1997-1998 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +*/ + +#include +#include +#include +#include + +char * +gai_strerror(int errnum) { + switch(errnum) { + case 0: + return "no error"; + case EAI_BADFLAGS: + return "invalid value for ai_flags"; + case EAI_NONAME: + return "name or service is not known"; + case EAI_AGAIN: + return "temporary failure in name resolution"; + case EAI_FAIL: + return "non-recoverable failure in name resolution"; + case EAI_NODATA: + return "no address associated with name"; + case EAI_FAMILY: + return "ai_family not supported"; + case EAI_SOCKTYPE: + return "ai_socktype not supported"; + case EAI_SERVICE: + return "service not supported for ai_socktype"; + case EAI_ADDRFAMILY: + return "address family for name not supported"; + case EAI_MEMORY: + return "memory allocation failure"; + case EAI_SYSTEM: + return "system error"; + default: + return "unknown error"; + }; +} Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/gen.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen.c (revision 60942) @@ -0,0 +1,427 @@ +/* + * 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.25 1999/10/13 16:39:29 vixie 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(*tmp) && isspace(*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.2.3.t5b/contrib/bind/lib/irs/gen.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen_gr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen_gr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen_gr.c (revision 60942) @@ -0,0 +1,450 @@ +/* + * 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.21 1999/10/13 16:39:29 vixie 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; + int n, ndst, nnew; + + 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; + } + cp = realloc(pvt->membuf, pvt->membufsize + n); + if (!cp) { + /* No harm done, no work done. */ + return; + } + pvt->membuf = cp; + cp += pvt->membufsize; + pvt->membufsize += n; + + /* + * 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 = 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; + } + 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/gen_ho.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen_ho.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen_ho.c (revision 60942) @@ -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(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: gen_ho.c,v 1.15 1999/10/13 16:39:29 vixie 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 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; + 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 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/gen_ng.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen_ng.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen_ng.c (revision 60942) @@ -0,0 +1,169 @@ +/* + * 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.14 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; + char * curgroup; +}; + +/* Forward */ + +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, char **, char **, 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, char **host, char **user, 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/gen_nw.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen_nw.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen_nw.c (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/gen_p.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen_p.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen_p.h (revision 60942) @@ -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.10 1999/01/18 07:46:50 vixie 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 { + const 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/gen_pr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen_pr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen_pr.c (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/gen_pw.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen_pw.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen_pw.c (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/gen_sv.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen_sv.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gen_sv.c (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/getaddrinfo.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getaddrinfo.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getaddrinfo.c (revision 60942) @@ -0,0 +1,505 @@ +/*- + * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. + * The Berkeley Software Design Inc. software License Agreement specifies + * the terms and conditions for redistribution. + * + * BSDI $Id: getaddrinfo.c,v 8.3 1999/06/11 01:25:58 vixie Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SA(addr) ((struct sockaddr *)(addr)) +#define SIN(addr) ((struct sockaddr_in *)(addr)) +#define SIN6(addr) ((struct sockaddr_in6 *)(addr)) +#define SUN(addr) ((struct sockaddr_un *)(addr)) + +static struct addrinfo + *ai_reverse(struct addrinfo *oai), + *ai_clone(struct addrinfo *oai, int family), + *ai_alloc(int family, int addrlen); +#ifdef AF_LOCAL +static int get_local(const char *name, int socktype, struct addrinfo **res); +#endif + +static int add_ipv4(const char *hostname, int flags, struct addrinfo **aip, + int socktype, int port); +static int add_ipv6(const char *hostname, int flags, struct addrinfo **aip, + int socktype, int port); +static void set_order(int, int (**)()); + +#define FOUND_IPV4 0x1 +#define FOUND_IPV6 0x2 +#define FOUND_MAX 2 + +int +getaddrinfo(const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + struct servent *sp; + char *proto; + int family, socktype, flags, protocol; + struct addrinfo *ai, *ai_list; + int port, err, i; + int (*net_order[FOUND_MAX+1])(); + + if (hostname == NULL && servname == NULL) + return (EAI_NONAME); + + proto = NULL; + if (hints != NULL) { + if (hints->ai_flags & ~(AI_MASK)) + return (EAI_BADFLAGS); + if (hints->ai_addrlen || hints->ai_canonname || + hints->ai_addr || hints->ai_next) { + errno = EINVAL; + return (EAI_SYSTEM); + } + family = hints->ai_family; + socktype = hints->ai_socktype; + protocol = hints->ai_protocol; + flags = hints->ai_flags; + switch (family) { + case AF_UNSPEC: + switch (hints->ai_socktype) { + case SOCK_STREAM: proto = "tcp"; break; + case SOCK_DGRAM: proto = "udp"; break; + } + break; + case AF_INET: + case AF_INET6: + switch (hints->ai_socktype) { + case 0: break; + case SOCK_STREAM: proto = "tcp"; break; + case SOCK_DGRAM: proto = "udp"; break; + case SOCK_RAW: break; + default: return (EAI_SOCKTYPE); + } + break; +#ifdef AF_LOCAL + case AF_LOCAL: + switch (hints->ai_socktype) { + case 0: break; + case SOCK_STREAM: break; + case SOCK_DGRAM: break; + default: return (EAI_SOCKTYPE); + } + break; +#endif + default: + return (EAI_FAMILY); + } + } else { + protocol = 0; + family = 0; + socktype = 0; + flags = 0; + } + +#ifdef AF_LOCAL + /* + * First, deal with AF_LOCAL. If the family was not set, + * then assume AF_LOCAL if the first character of the + * hostname/servname is '/'. + */ + + if (hostname && + (family == AF_LOCAL || (family == 0 && *hostname == '/'))) + return (get_local(hostname, socktype, res)); + + if (servname && + (family == AF_LOCAL || (family == 0 && *servname == '/'))) + return (get_local(servname, socktype, res)); +#endif + + /* + * Ok, only AF_INET and AF_INET6 left. + */ + ai_list = NULL; + + /* + * First, look up the service name (port) if it was + * requested. If the socket type wasn't specified, then + * try and figure it out. + */ + if (servname) { + char *e; + + port = strtol(servname, &e, 10); + if (*e == '\0') { + if (socktype == 0) + return (EAI_SOCKTYPE); + if (port < 0 || port > 65535) + return (EAI_SERVICE); + port = htons(port); + } else { + sp = getservbyname(servname, proto); + if (sp == NULL) + return (EAI_SERVICE); + port = sp->s_port; + if (socktype == 0) { + if (strcmp(sp->s_proto, "tcp")) + socktype = SOCK_STREAM; + else if (strcmp(sp->s_proto, "udp")) + socktype = SOCK_DGRAM; + } + } + } else + port = 0; + + /* + * Next, deal with just a service name, and no hostname. + * (we verified that one of them was non-null up above). + */ + if (hostname == NULL && (flags & AI_PASSIVE) != 0) { + if (family == AF_INET || family == 0) { + ai = ai_alloc(AF_INET, sizeof(struct sockaddr_in)); + if (ai == NULL) + return (EAI_MEMORY); + ai->ai_socktype = socktype; + ai->ai_protocol = protocol; + SIN(ai->ai_addr)->sin_port = port; + ai->ai_next = ai_list; + ai_list = ai; + } + + if (family == AF_INET6 || family == 0) { + ai = ai_alloc(AF_INET6, sizeof(struct sockaddr_in6)); + if (ai == NULL) { + freeaddrinfo(ai_list); + return (EAI_MEMORY); + } + ai->ai_socktype = socktype; + ai->ai_protocol = protocol; + SIN6(ai->ai_addr)->sin6_port = port; + ai->ai_next = ai_list; + ai_list = ai; + } + + *res = ai_list; + return (0); + } + + /* + * If the family isn't specified or AI_NUMERICHOST specified, + * check first to see if it * is a numeric address. + * Though the gethostbyname2() routine + * will recognize numeric addresses, it will only recognize + * the format that it is being called for. Thus, a numeric + * AF_INET address will be treated by the AF_INET6 call as + * a domain name, and vice versa. Checking for both numerics + * here avoids that. + */ + if (hostname != NULL && + (family == 0 || (flags & AI_NUMERICHOST) != 0)) { + char abuf[sizeof(struct in6_addr)]; + char nbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx00")]; + int addrsize, addroff; + + if (inet_aton(hostname, (struct in_addr *)abuf)) { + if (family == AF_INET6) { + /* Convert to a V4 mapped address */ + struct in6_addr *a6 = (struct in6_addr *)abuf; + memcpy(&a6->s6_addr[12], &a6->s6_addr[0], 4); + memset(&a6->s6_addr[10], 0xff, 2); + memset(&a6->s6_addr[0], 0, 10); + goto inet6_addr; + } + addrsize = sizeof(struct in_addr); + addroff = (char *)(&SIN(0)->sin_addr) - (char *)0; + family = AF_INET; + goto common; + + } else if (inet_pton(AF_INET6, hostname, abuf)) { + if (family && family != AF_INET6) + return (EAI_NONAME); + inet6_addr: + addrsize = sizeof(struct in6_addr); + addroff = (char *)(&SIN6(0)->sin6_addr) - (char *)0; + family = AF_INET6; + + common: + if ((ai = ai_clone(ai_list, family)) == NULL) + return (EAI_MEMORY); + ai_list = ai; + ai->ai_socktype = socktype; + SIN(ai->ai_addr)->sin_port = port; + memcpy((char *)ai->ai_addr + addroff, abuf, addrsize); + if (flags & AI_CANONNAME) { + inet_ntop(family, abuf, nbuf, sizeof(nbuf)); + ai->ai_canonname = strdup(nbuf); + } + goto done; + } else if ((flags & AI_NUMERICHOST) != 0){ + return (EAI_NONAME); + } + } + + set_order(family, net_order); + for (i = 0; i < FOUND_MAX; i++) { + if (net_order[i] == NULL) + break; + if ((err = (net_order[i])(hostname, flags, &ai_list, + socktype, port)) != 0) + return(err); + } + + if (ai_list == NULL) + return (EAI_NODATA); + +done: + ai_list = ai_reverse(ai_list); + + *res = ai_list; + return (0); +} + +static void +set_order(family, net_order) + int family; + int (**net_order)(); +{ + char *order, *tok; + int found; + + if (family) { + switch (family) { + case AF_INET: + *net_order++ = add_ipv4; + break; + case AF_INET6: + *net_order++ = add_ipv6; + break; + } + } else { + order = getenv("NET_ORDER"); + found = 0; + while (order != NULL) { + /* We ignore any unknown names. */ + tok = strsep(&order, ":"); + if (strcasecmp(tok, "inet6") == 0) { + if ((found & FOUND_IPV6) == 0) + *net_order++ = add_ipv6; + found |= FOUND_IPV6; + } else if (strcasecmp(tok, "inet") == 0 || + strcasecmp(tok, "inet4") == 0) { + if ((found & FOUND_IPV4) == 0) + *net_order++ = add_ipv4; + found |= FOUND_IPV4; + } + } + + /* Add in anything that we didn't find */ + if ((found & FOUND_IPV4) == 0) + *net_order++ = add_ipv4; + if ((found & FOUND_IPV6) == 0) + *net_order++ = add_ipv6; + } + *net_order = NULL; + return; +} + +static char v4_loop[4] = { 127, 0, 0, 1 }; + +static int +add_ipv4(const char *hostname, int flags, struct addrinfo **aip, + int socktype, int port) +{ + struct addrinfo *ai; + struct hostent *hp; + char **addr; + + if (hostname == NULL && (flags & AI_PASSIVE) == 0) { + if ((ai = ai_clone(*aip, AF_INET)) == NULL) { + freeaddrinfo(*aip); + return(EAI_MEMORY); + } + + *aip = ai; + ai->ai_socktype = socktype; + SIN(ai->ai_addr)->sin_port = port; + memcpy(&SIN(ai->ai_addr)->sin_addr, v4_loop, 4); + } else if ((hp = gethostbyname2(hostname, AF_INET)) != NULL) { + for (addr = hp->h_addr_list; *addr; addr++) { + if ((ai = ai_clone(*aip, hp->h_addrtype)) == NULL) { + freeaddrinfo(*aip); + return(EAI_MEMORY); + } + *aip = ai; + ai->ai_socktype = socktype; + + /* We get IPv6 addresses if RES_USE_INET6 is set */ + if (hp->h_addrtype == AF_INET6) { + SIN6(ai->ai_addr)->sin6_port = port; + memcpy(&SIN6(ai->ai_addr)->sin6_addr, *addr, + hp->h_length); + } else { + SIN(ai->ai_addr)->sin_port = port; + memcpy(&SIN(ai->ai_addr)->sin_addr, *addr, + hp->h_length); + } + if (flags & AI_CANONNAME) + ai->ai_canonname = strdup(hp->h_name); + } + } + return(0); +} + +static char v6_loop[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; + +static int +add_ipv6(const char *hostname, int flags, struct addrinfo **aip, + int socktype, int port) +{ + struct addrinfo *ai; + struct hostent *hp; + char **addr; + + if (hostname == NULL && (flags & AI_PASSIVE) == 0) { + if ((ai = ai_clone(*aip, AF_INET6)) == NULL) { + freeaddrinfo(*aip); + return(EAI_MEMORY); + } + + *aip = ai; + ai->ai_socktype = socktype; + SIN6(ai->ai_addr)->sin6_port = port; + memcpy(&SIN6(ai->ai_addr)->sin6_addr, v6_loop, 16); + } else if ((hp = gethostbyname2(hostname, AF_INET6)) != NULL) { + for (addr = hp->h_addr_list; *addr; addr++) { + if ((ai = ai_clone(*aip, AF_INET6)) == NULL) { + freeaddrinfo(*aip); + return (EAI_MEMORY); + } + *aip = ai; + ai->ai_socktype = socktype; + SIN6(ai->ai_addr)->sin6_port = port; + memcpy(&SIN6(ai->ai_addr)->sin6_addr, *addr, + hp->h_length); + if (flags & AI_CANONNAME) + ai->ai_canonname = strdup(hp->h_name); + } + } + return (0); +} + +void +freeaddrinfo(struct addrinfo *ai) { + struct addrinfo *ai_next; + + while (ai != NULL) { + ai_next = ai->ai_next; + if (ai->ai_addr) + free(ai->ai_addr); + if (ai->ai_canonname) + free(ai->ai_canonname); + free(ai); + ai = ai_next; + } +} + +#ifdef AF_LOCAL +static int +get_local(const char *name, int socktype, struct addrinfo **res) { + struct addrinfo *ai; + struct sockaddr_un *sun; + + if (socktype == 0) + return (EAI_SOCKTYPE); + + if ((ai = ai_alloc(AF_LOCAL, sizeof(*sun))) == NULL) + return (EAI_MEMORY); + + sun = SUN(ai->ai_addr); + strncpy(sun->sun_path, name, sizeof(sun->sun_path)); + + ai->ai_socktype = socktype; + /* + * ai->ai_flags, ai->ai_protocol, ai->ai_canonname, + * and ai->ai_next were initialized to zero. + */ + + *res = ai; + return (0); +} +#endif + +/* + * Allocate an addrinfo structure, and a sockaddr structure + * of the specificed length. We initialize: + * ai_addrlen + * ai_family + * ai_addr + * ai_addr->sa_family + * ai_addr->sa_len (HAVE_SA_LEN) + * and everything else is initialized to zero. + */ +static struct addrinfo * +ai_alloc(int family, int addrlen) { + struct addrinfo *ai; + + if ((ai = (struct addrinfo *)calloc(1, sizeof(*ai))) == NULL) + return (NULL); + + if ((ai->ai_addr = SA(calloc(1, addrlen))) == NULL) { + free(ai); + return (NULL); + } + ai->ai_addrlen = addrlen; + ai->ai_family = family; + ai->ai_addr->sa_family = family; +#ifdef HAVE_SA_LEN + ai->ai_addr->sa_len = addrlen; +#endif + return (ai); +} + +static struct addrinfo * +ai_clone(struct addrinfo *oai, int family) { + struct addrinfo *ai; + + ai = ai_alloc(family, ((family == AF_INET6) ? + sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))); + + if (ai == NULL) { + freeaddrinfo(oai); + return (NULL); + } + if (oai == NULL) + return (ai); + + ai->ai_flags = oai->ai_flags; + ai->ai_socktype = oai->ai_socktype; + ai->ai_protocol = oai->ai_protocol; + ai->ai_canonname = NULL; + ai->ai_next = oai; + return (ai); +} + +static struct addrinfo * +ai_reverse(struct addrinfo *oai) { + struct addrinfo *nai, *tai; + + nai = NULL; + + while (oai) { + /* grab one off the old list */ + tai = oai; + oai = oai->ai_next; + /* put it on the front of the new list */ + tai->ai_next = nai; + nai = tai; + } + return (nai); +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getaddrinfo.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getgrent.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getgrent.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getgrent.c (revision 60942) @@ -0,0 +1,221 @@ +/* + * 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.19 1999/10/13 16:39:30 vixie 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 "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() { + struct net_data *net_data = init(); + + return (setgrent_p(net_data)); +} +#else +int +setgrent() { + 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(const char *name, gid_t basegid, gid_t *groups, int *ngroups) { + 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 && + 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.2.3.t5b/contrib/bind/lib/irs/getgrent.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getgrent_r.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getgrent_r.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getgrent_r.c (revision 60942) @@ -0,0 +1,219 @@ +/* + * 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.4 1999/01/18 07:46:51 vixie 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 +#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 (-1); + } + + 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(const gid_t gid, struct group *gptr, + char *buf, int buflen, struct group **result) { +#else /* POSIX_GETGRGID_R */ +int +getgrgid_r(const 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 (-1); + } + + res = copy_group(ge, gptr, buf, buflen); + *result = res ? NULL : gptr; + return (res); +} + +#ifdef POSIX_GETGRGID_R +struct group * +getgrgid_r(const 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 (-1); + } + + /* 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/gethostent_r.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gethostent_r.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/gethostent_r.c (revision 60942) @@ -0,0 +1,228 @@ +/* + * 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.4 1999/01/18 07:46:52 vixie 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 + +#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); + + HOST_R_ERRNO; + + if (he == NULL) + return (HOST_R_BAD); + + return (copy_hostent(he, hptr, HOST_R_COPY)); +} + +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); + + HOST_R_ERRNO; + + if (he == NULL) + return (HOST_R_BAD); + + return (copy_hostent(he, hptr, HOST_R_COPY)); +} + +/* + * 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(); + + HOST_R_ERRNO; + + if (he == NULL) + return (HOST_R_BAD); + + return (copy_hostent(he, hptr, HOST_R_COPY)); +} + +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() +#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; + i++; + } + 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_systemm = 0; +#endif /* HOST_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/getnetent.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getnetent.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getnetent.c (revision 60942) @@ -0,0 +1,340 @@ +/* + * 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.17 1999/10/13 16:39:30 vixie 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(name[0]) || !isdigit(name[0])) + return (NULL); + for (cp = name; *cp; ++cp) + if (!isascii(*cp) || (!isdigit(*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.2.3.t5b/contrib/bind/lib/irs/getnetent.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getnetent_r.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getnetent_r.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getnetent_r.c (revision 60942) @@ -0,0 +1,191 @@ +/* + * 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.4 1999/01/18 07:46:52 vixie 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 + +#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); + + if (ne == NULL) + return (NET_R_BAD); + + return (copy_netent(ne, nptr, NET_R_COPY)); +} + +#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); + + if (ne == NULL) + return (NET_R_BAD); + + return (copy_netent(ne, nptr, NET_R_COPY)); +} + +/* + * 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(); + + if (ne == NULL) + return (NET_R_BAD); + + return (copy_netent(ne, nptr, NET_R_COPY)); +} + +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 > 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_systemm = 0; +#endif /* NET_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/getnetgrent.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getnetgrent.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getnetgrent.c (revision 60942) @@ -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.14 1999/10/07 20:44:03 vixie 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(char **host, char **user, 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(char **host, char **user, 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.2.3.t5b/contrib/bind/lib/irs/getnetgrent.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getnetgrent_r.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getnetgrent_r.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getnetgrent_r.c (revision 60942) @@ -0,0 +1,134 @@ +/* + * 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.4 1999/01/18 07:46:52 vixie 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 + +#ifdef NGR_R_RETURN + +static NGR_R_RETURN +copy_protoent(char **, char **, char **, char *, char *, 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) { + 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_SET_RESULT + return (NGR_R_SET_RESULT); +#endif +} + +NGR_R_END_RETURN +endnetgrent_r(NGR_R_ENT_ARGS) { + endnetgrent(); + NGR_R_END_RESULT(NGR_R_OK); +} + +/* Private */ + +static int +copy_protoent(char **machinep, char **userp, char **domainp, + char *mp, char *up, char *dp, NGR_R_COPY_ARGS) { + char *cp; + int i, 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; + + if (len > buflen) { + errno = ERANGE; + return (NGR_R_BAD); + } + + cp = buf; + + 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/getprotoent.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getprotoent.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getprotoent.c (revision 60942) @@ -0,0 +1,173 @@ +/* + * 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.15 1999/10/13 16:39:31 vixie Exp $"; +#endif + +/* 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 */ + +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.2.3.t5b/contrib/bind/lib/irs/getprotoent.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getprotoent_r.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getprotoent_r.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getprotoent_r.c (revision 60942) @@ -0,0 +1,185 @@ +/* + * 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.4 1999/01/18 07:46:52 vixie 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 + +#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); + + if (pe == NULL) + return (PROTO_R_BAD); + + return (copy_protoent(pe, pptr, PROTO_R_COPY)); +} + +PROTO_R_RETURN +getprotobynumber_r(int proto, struct protoent *pptr, PROTO_R_ARGS) { + struct protoent *pe = getprotobynumber(proto); + + if (pe == NULL) + return (PROTO_R_BAD); + + return (copy_protoent(pe, pptr, PROTO_R_COPY)); +} + +/* + * 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(); + + if (pe == NULL) + return (PROTO_R_BAD); + + return (copy_protoent(pe, pptr, PROTO_R_COPY)); +} + +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 > 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_systemm = 0; +#endif /* PROTO_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/getpwent_r.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getpwent_r.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getpwent_r.c (revision 60942) @@ -0,0 +1,253 @@ +/* + * 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.3 1999/01/08 19:24:33 vixie 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 +#include +#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 (-1); + } + + 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 (-1); + } + + 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 +setpwent_r(PASS_R_ENT_ARGS) { + + setpwent(); +#ifdef PASS_R_SET_RESULT + return (PASS_R_SET_RESULT); +#endif +} + +PASS_R_END_RETURN +endpwent_r(PASS_R_ENT_ARGS) { + + 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 i, n; + int numptr, 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 (-1); + } + + /* 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_systemm = 0; +#endif /* PASS_R_RETURN */ +#endif /* !def(_REENTRANT) || !def(DO_PTHREADS) || !def(WANT_IRS_PW) */ Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/getservent.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getservent.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getservent.c (revision 60942) @@ -0,0 +1,176 @@ +/* + * 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.16 1999/10/13 16:39:31 vixie Exp $"; +#endif + +/* 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 */ + +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.2.3.t5b/contrib/bind/lib/irs/getservent.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getservent_r.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getservent_r.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/getservent_r.c (revision 60942) @@ -0,0 +1,206 @@ +/* + * 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.3 1999/01/08 19:24:36 vixie 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 + +#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); + + if (se == NULL) + return (SERV_R_BAD); + + return (copy_servent(se, sptr, SERV_R_COPY)); +} + +SERV_R_RETURN +getservbyport_r(int port, const char *proto, + struct servent *sptr, SERV_R_ARGS) { + struct servent *se = getservbyport(port, proto); + + if (se == NULL) + return (SERV_R_BAD); + + return (copy_servent(se, sptr, SERV_R_COPY)); +} + +/* + * 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(); + + if (se == NULL) + return (SERV_R_BAD); + + return (copy_servent(se, sptr, SERV_R_COPY)); +} + +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 > 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_systemm = 0; +#endif /*SERV_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/hesiod_p.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/hesiod_p.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/hesiod_p.h (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/irp_gr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp_gr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp_gr.c (revision 60942) @@ -0,0 +1,405 @@ +/* + * 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.1 1999/01/18 07:46:53 vixie 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 && 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 (p != NULL) + free(p); +} + + +#endif /* WANT_IRS_GR */ Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/irp_ho.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp_ho.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp_ho.c (revision 60942) @@ -0,0 +1,418 @@ +/* + * 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.2 1999/10/13 16:39:31 vixie 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); + + +/* 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; + + 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); + } +} + Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/irp_ng.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp_ng.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp_ng.c (revision 60942) @@ -0,0 +1,266 @@ +/* + * 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.2 1999/10/13 16:39:31 vixie 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 *, char **, char **, 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, char **host, char **user, char **domain) + * + * Notes: + * + * Get the next netgroup item from the cache. + * + */ + +static int +ng_next(struct irs_ng *this, char **host, char **user, 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; + + 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/irp_nw.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp_nw.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp_nw.c (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/irp_p.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp_p.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp_p.h (revision 60942) @@ -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.1 1999/01/18 07:46:54 vixie 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, ...); + + +extern int irp_log_errors; + +#endif Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/irp_pr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp_pr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp_pr.c (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/irp_pw.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp_pw.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp_pw.c (revision 60942) @@ -0,0 +1,356 @@ +/* + * 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.1 1999/01/18 07:46:54 vixie 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); + + if (pw->pw_class != NULL) + free(pw->pw_class); + + 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/irp_sv.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp_sv.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irp_sv.c (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/irpmarshall.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irpmarshall.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irpmarshall.c (revision 60942) @@ -0,0 +1,2332 @@ +/* + * 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.5 1999/10/13 17:11:19 vixie 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" + + +static char *strndup(const char *str, size_t len); +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]; + 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(char **host, char **user, 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(char **host, char **user, char **domain, char *buffer) { + char *p, *q; + char fieldsep = ','; + int myerrno = EINVAL; + + if (user == NULL || host == NULL || domain == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + *host = *user = *domain = NULL; + + p = buffer; + while (isspace(*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); + } + + 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 (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); +} + + + + + +/* + * 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); +} + +#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.2.3.t5b/contrib/bind/lib/irs/irpmarshall.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irs_data.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irs_data.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irs_data.c (revision 60942) @@ -0,0 +1,194 @@ +/* + * 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.14 1999/10/13 16:39:31 vixie Exp $"; +#endif + +#include "port_before.h" + +#ifndef __BIND_NOSTATIC + +#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() { +#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_nclose(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 (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); +} + +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); +} + +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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/irs_data.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irs_data.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irs_data.h (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/irs_p.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irs_p.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/irs_p.h (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/lcl_gr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl_gr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl_gr.c (revision 60942) @@ -0,0 +1,352 @@ +/* + * 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.25 1999/10/13 17:11:19 vixie 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; + + 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 && 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/lcl_ho.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl_ho.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl_ho.c (revision 60942) @@ -0,0 +1,503 @@ +/* + * 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.25 1999/10/13 17:11:19 vixie 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 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 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; + + 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; + 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 = (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; +} + +/* 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/lcl_ng.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl_ng.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl_ng.c (revision 60942) @@ -0,0 +1,438 @@ +/* + * 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.16 1999/10/13 16:39:32 vixie 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" + +/* 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 *, char **, char **, 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; + + 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, char **host, char **user, 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) +{ + 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, *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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/lcl_nw.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl_nw.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl_nw.c (revision 60942) @@ -0,0 +1,369 @@ +/* + * 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.21 1999/10/15 19:49:10 vixie 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; + + 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/lcl_p.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl_p.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl_p.h (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/lcl_pr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl_pr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl_pr.c (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/lcl_pw.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl_pw.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl_pw.c (revision 60942) @@ -0,0 +1,306 @@ +/* + * 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.19 1999/01/18 07:46:57 vixie 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; + + 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/lcl_sv.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl_sv.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/lcl_sv.c (revision 60942) @@ -0,0 +1,432 @@ +/* + * 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.20 1999/10/07 20:44:03 vixie 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; + + 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) + NULL; + else +#endif + if (pvt->sv.fp != NULL) + NULL; + else + 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 (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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/nis_gr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis_gr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis_gr.c (revision 60942) @@ -0,0 +1,352 @@ +/* + * 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.20 1999/01/30 00:53:16 vixie 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, (char *)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) { + /* NOOP */ +} + +/* Private */ + +static struct group * +makegroupent(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/nis_ho.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis_ho.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis_ho.c (revision 60942) @@ -0,0 +1,390 @@ +/* + * 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.16 1999/10/13 16:39:32 vixie 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 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; + 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; + + if (init(this) == -1) + return (NULL); + + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, hosts_byname, (char *)name, strlen(name), + &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 = (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; +} + +/* 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/nis_ng.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis_ng.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis_ng.c (revision 60942) @@ -0,0 +1,295 @@ +/* + * 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.16 1999/01/18 07:46:58 vixie 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 *, char **, char **, 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, char **host, char **user, char **domain) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->cur) + return (0); + *host = (/*const*/ char *)pvt->cur->host; + *user = (/*const*/ char *)pvt->cur->user; + *domain = (/*const*/ char *)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) { + /* 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; + + /* 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; + + r = yp_match(pvt->nis_domain, netgroup_map, (char *)name, 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/nis_nw.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis_nw.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis_nw.c (revision 60942) @@ -0,0 +1,379 @@ +/* + * 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.15 1999/01/18 07:46:58 vixie 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; + + 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); + r = yp_match(pvt->nis_domain, networks_byname, (char *)name, + strlen(name), &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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/nis_p.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis_p.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis_p.h (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/nis_pr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis_pr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis_pr.c (revision 60942) @@ -0,0 +1,294 @@ +/* + * 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.13 1999/01/18 07:46:59 vixie 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; + + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, protocols_byname, (char *)name, + strlen(name), &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) { + /* 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++) + NULL; + while (p > pvt->prbuf && isspace(p[-1])) + p--; + *p = '\0'; + + p = pvt->prbuf; + n = m = 0; + + pvt->proto.p_name = p; + while (*p && !isspace(*p)) + p++; + if (!*p) + return (NULL); + *p++ = '\0'; + + while (*p && isspace(*p)) + p++; + pvt->proto.p_proto = atoi(p); + while (*p && !isspace(*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(*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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/nis_pw.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis_pw.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis_pw.c (revision 60942) @@ -0,0 +1,282 @@ +/* + * 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.16 1999/01/30 00:53:16 vixie 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; + + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, passwd_byname, name, strlen(name), + &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) { + /* 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; + pvt->passwd.pw_class = cp; /* Needs to point at a \0. */ + *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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/nis_sv.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis_sv.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nis_sv.c (revision 60942) @@ -0,0 +1,304 @@ +/* + * 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.14 1999/01/18 07:46:59 vixie 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) { + /* 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(*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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/nul_ng.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nul_ng.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/nul_ng.c (revision 60942) @@ -0,0 +1,109 @@ +/* + * 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.10 1999/01/18 07:46:59 vixie 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 *, char **, char **, 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; + + 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, char **host, char **user, char **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) +{ + errno = ENODEV; + return (-1); +} + +static void +ng_rewind(struct irs_ng *this, const char *netgroup) { + /* NOOP */ +} + +static void +ng_minimize(struct irs_ng *this) { + /* NOOP */ +} Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/irs/pathnames.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/pathnames.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/irs/pathnames.h (revision 60942) @@ -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.2.3.t5b/contrib/bind/lib/irs/pathnames.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/Makefile (revision 60942) @@ -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 8.25 2000/02/29 03:38:23 vixie 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= bsdos +DESTDIR = +DESTLIB = /usr/local/lib +O=o +A=a +CC= cc +LD= ld +SHELL= /bin/sh +CDEBUG= -g +TOP= ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.${A} +LIBBINDR = ../${TOP}/lib/libbind_r.${A} +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} +# -Wimplicit +LD_LIBFLAGS= -x -r +AR= ar cru +RANLIB= ranlib +INSTALL= install +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin +THREADED= threaded + +SRCS= tree.c base64.c bitncmp.c assertions.c \ + memcluster.c logging.c heap.c \ + ctl_p.c ctl_srvr.c ctl_clnt.c \ + eventlib.c ev_connects.c ev_files.c \ + ev_timers.c ev_streams.c ev_waits.c + +OBJS= tree.${O} base64.${O} bitncmp.${O} assertions.${O} \ + memcluster.${O} logging.${O} heap.${O} \ + ctl_p.${O} ctl_srvr.${O} ctl_clnt.${O} \ + eventlib.${O} ev_connects.${O} ev_files.${O} \ + ev_timers.${O} ev_streams.${O} ev_waits.${O} + +all: ${LIBBIND} + +${LIBBIND}: ${OBJS} + ( cd ${THREADED} ; \ + ${AR} ${LIBBINDR} ${ARPREF} ${OBJS} ${ARSUFF} ; \ + ${RANLIB} ${LIBBINDR} ) + ${AR} ${LIBBIND} ${ARPREF} ${OBJS} ${ARSUFF} + ${RANLIB} ${LIBBIND} + +.c.${O}: + if test ! -d ${THREADED} ; then mkdir ${THREADED} ; else true ; fi + ${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.2.3.t5b/contrib/bind/lib/isc/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ctl_p.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ctl_p.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ctl_p.c (revision 60942) @@ -0,0 +1,160 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ctl_p.c,v 8.7 2000/02/04 08:28:33 vixie 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. + */ + +/* Extern. */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ctl_p.h" + +#include "port_after.h" + +/* Constants. */ + +const char * const ctl_sevnames[] = { + "debug", "warning", "error" +}; + +/* Public. */ + +/* + * ctl_logger() + * if ctl_startup()'s caller didn't specify a logger, this one + * is used. this pollutes stderr with all kinds of trash so it will + * probably never be used in real applications. + */ +void +ctl_logger(enum ctl_severity severity, const char *format, ...) { + va_list ap; + static const char me[] = "ctl_logger"; + + fprintf(stderr, "%s(%s): ", me, ctl_sevnames[severity]); + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + fputc('\n', stderr); +} + +int +ctl_bufget(struct ctl_buf *buf, ctl_logfunc logger) { + static const char me[] = "ctl_bufget"; + + REQUIRE(!allocated_p(*buf) && buf->used == 0); + buf->text = memget(MAX_LINELEN); + if (!allocated_p(*buf)) { + (*logger)(ctl_error, "%s: getmem: %s", me, strerror(errno)); + return (-1); + } + buf->used = 0; + return (0); +} + +void +ctl_bufput(struct ctl_buf *buf) { + + REQUIRE(allocated_p(*buf)); + memput(buf->text, MAX_LINELEN); + buf->text = NULL; + buf->used = 0; +} + +const char * +ctl_sa_ntop(const struct sockaddr *sa, + char *buf, size_t size, + ctl_logfunc logger) +{ + static const char me[] = "ctl_sa_ntop"; + static const char punt[] = "[0].-1"; + char tmp[sizeof "255.255.255.255"]; + + switch (sa->sa_family) { + case AF_INET: { + const struct sockaddr_in *in = (struct sockaddr_in *) sa; + + if (inet_ntop(in->sin_family, &in->sin_addr, tmp, sizeof tmp) + == NULL) { + (*logger)(ctl_error, "%s: inet_ntop(%u %04x %08x): %s", + me, in->sin_family, + in->sin_port, in->sin_addr.s_addr, + strerror(errno)); + return (punt); + } + if (strlen(tmp) + sizeof "[].65535" > size) { + (*logger)(ctl_error, "%s: buffer overflow", me); + return (punt); + } + (void) sprintf(buf, "[%s].%u", tmp, ntohs(in->sin_port)); + return (buf); + } +#ifndef NO_SOCKADDR_UN + case AF_UNIX: { + const struct sockaddr_un *un = (struct sockaddr_un *) sa; + int x = sizeof un->sun_path; + + if (x > size) + x = size; + strncpy(buf, un->sun_path, x - 1); + buf[x - 1] = '\0'; + return (buf); + } +#endif + default: + return (punt); + } +} + +void +ctl_sa_copy(const struct sockaddr *src, struct sockaddr *dst) { + switch (src->sa_family) { + case AF_INET: + *((struct sockaddr_in *)dst) = *((struct sockaddr_in *)src); + break; +#ifndef NO_SOCKADDR_UN + case AF_UNIX: + *((struct sockaddr_un *)dst) = *((struct sockaddr_un *)src); + break; +#endif + default: + *dst = *src; + break; + } +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ctl_p.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ctl_srvr.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ctl_srvr.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ctl_srvr.c (revision 60942) @@ -0,0 +1,751 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ctl_srvr.c,v 8.23 2000/02/04 08:28:33 vixie 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. + */ + +/* 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 "ctl_p.h" + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Macros. */ + +#define lastverb_p(verb) (verb->name == NULL || verb->func == NULL) +#define address_expr ctl_sa_ntop((struct sockaddr *)&sess->sa, \ + tmp, sizeof tmp, ctx->logger) + +/* Types. */ + +enum state { + available = 0, initializing, writing, reading, reading_data, + processing, idling, quitting, closing +}; + +union sa_un { + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif +}; + +struct ctl_sess { + LINK(struct ctl_sess) link; + struct ctl_sctx * ctx; + enum state state; + int sock; + union sa_un sa; + evFileID rdID; + evStreamID wrID; + evTimerID rdtiID; + evTimerID wrtiID; + struct ctl_buf inbuf; + struct ctl_buf outbuf; + const struct ctl_verb * verb; + u_int helpcode; + void * respctx; + u_int respflags; + ctl_srvrdone donefunc; + void * uap; + void * csctx; +}; + +struct ctl_sctx { + evContext ev; + void * uctx; + u_int unkncode; + u_int timeoutcode; + const struct ctl_verb * verbs; + const struct ctl_verb * connverb; + int sock; + int max_sess; + int cur_sess; + struct timespec timeout; + ctl_logfunc logger; + evConnID acID; + LIST(struct ctl_sess) sess; +}; + +/* Forward. */ + +static void ctl_accept(evContext, void *, int, + const void *, int, + const void *, int); +static void ctl_close(struct ctl_sess *); +static void ctl_new_state(struct ctl_sess *, + enum state, + const char *); +static void ctl_start_read(struct ctl_sess *); +static void ctl_stop_read(struct ctl_sess *); +static void ctl_readable(evContext, void *, int, int); +static void ctl_rdtimeout(evContext, void *, + struct timespec, + struct timespec); +static void ctl_wrtimeout(evContext, void *, + struct timespec, + struct timespec); +static void ctl_docommand(struct ctl_sess *); +static void ctl_writedone(evContext, void *, int, int); +static void ctl_morehelp(struct ctl_sctx *, + struct ctl_sess *, + const struct ctl_verb *, + const char *, + u_int, void *, void *); +static void ctl_signal_done(struct ctl_sctx *, + struct ctl_sess *); + +/* Private data. */ + +static const char * state_names[] = { + "available", "initializing", "writing", "reading", + "reading_data", "processing", "idling", "quitting", "closing" +}; + +static const char space[] = " "; + +static const struct ctl_verb fakehelpverb = { "fakehelp", ctl_morehelp }; + +/* Public. */ + +/* + * void + * ctl_server() + * create, condition, and start a listener on the control port. + */ +struct ctl_sctx * +ctl_server(evContext lev, const struct sockaddr *sap, size_t sap_len, + const struct ctl_verb *verbs, + u_int unkncode, u_int timeoutcode, + u_int timeout, int backlog, int max_sess, + ctl_logfunc logger, void *uctx) +{ + static const char me[] = "ctl_server"; + static const int on = 1; + const struct ctl_verb *connverb; + struct ctl_sctx *ctx; + int save_errno; + + if (logger == NULL) + logger = ctl_logger; + for (connverb = verbs; + connverb->name != NULL && connverb->func != NULL; + connverb++) + if (connverb->name[0] == '\0') + break; + if (connverb->func == NULL) { + (*logger)(ctl_error, "%s: no connection verb found", me); + return (NULL); + } + ctx = memget(sizeof *ctx); + if (ctx == NULL) { + (*logger)(ctl_error, "%s: getmem: %s", me, strerror(errno)); + return (NULL); + } + ctx->ev = lev; + ctx->uctx = uctx; + ctx->unkncode = unkncode; + ctx->timeoutcode = timeoutcode; + ctx->verbs = verbs; + ctx->timeout = evConsTime(timeout, 0); + ctx->logger = logger; + ctx->connverb = connverb; + ctx->max_sess = max_sess; + ctx->cur_sess = 0; + INIT_LIST(ctx->sess); + ctx->sock = socket(sap->sa_family, SOCK_STREAM, PF_UNSPEC); + if (ctx->sock > evHighestFD(ctx->ev)) { + ctx->sock = -1; + errno = ENOTSOCK; + } + if (ctx->sock < 0) { + save_errno = errno; + (*ctx->logger)(ctl_error, "%s: socket: %s", + me, strerror(errno)); + memput(ctx, sizeof *ctx); + errno = save_errno; + return (NULL); + } + if (ctx->sock > evHighestFD(lev)) { + close(ctx->sock); + (*ctx->logger)(ctl_error, "%s: file descriptor > evHighestFD"); + errno = ENFILE; + memput(ctx, sizeof *ctx); + return (NULL); + } +#ifdef NO_UNIX_REUSEADDR + if (sap->sa_family != AF_UNIX) +#endif + if (setsockopt(ctx->sock, SOL_SOCKET, SO_REUSEADDR, + (char *)&on, sizeof on) != 0) { + (*ctx->logger)(ctl_warning, + "%s: setsockopt(REUSEADDR): %s", + me, strerror(errno)); + } + if (bind(ctx->sock, sap, sap_len) < 0) { + char tmp[MAX_NTOP]; + save_errno = errno; + (*ctx->logger)(ctl_error, "%s: bind: %s: %s", + me, ctl_sa_ntop((struct sockaddr *)sap, + tmp, sizeof tmp, ctx->logger), + strerror(save_errno)); + close(ctx->sock); + memput(ctx, sizeof *ctx); + errno = save_errno; + return (NULL); + } + if (fcntl(ctx->sock, F_SETFD, 1) < 0) { + (*ctx->logger)(ctl_warning, "%s: fcntl: %s", me, + strerror(errno)); + } + if (evListen(lev, ctx->sock, backlog, ctl_accept, ctx, + &ctx->acID) < 0) { + save_errno = errno; + (*ctx->logger)(ctl_error, "%s: evListen(fd %d): %s", + me, (void *)ctx->sock, strerror(errno)); + close(ctx->sock); + memput(ctx, sizeof *ctx); + errno = save_errno; + return (NULL); + } + (*ctx->logger)(ctl_debug, "%s: new ctx %p, sock %d", + me, ctx, ctx->sock); + return (ctx); +} + +/* + * void + * ctl_endserver(ctx) + * if the control listener is open, close it. clean out all eventlib + * stuff. close all active sessions. + */ +void +ctl_endserver(struct ctl_sctx *ctx) { + static const char me[] = "ctl_endserver"; + struct ctl_sess *this, *next; + + (*ctx->logger)(ctl_debug, "%s: ctx %p, sock %d, acID %p, sess %p", + me, ctx, ctx->sock, ctx->acID.opaque, ctx->sess); + if (ctx->acID.opaque != NULL) { + (void)evCancelConn(ctx->ev, ctx->acID); + ctx->acID.opaque = NULL; + } + if (ctx->sock != -1) { + (void) close(ctx->sock); + ctx->sock = -1; + } + for (this = HEAD(ctx->sess); this != NULL; this = next) { + next = NEXT(this, link); + ctl_close(this); + } + memput(ctx, sizeof *ctx); +} + +/* + * If body is non-NULL then it we add a "." line after it. + * Caller must have escaped lines with leading ".". + */ +void +ctl_response(struct ctl_sess *sess, u_int code, const char *text, + u_int flags, void *respctx, ctl_srvrdone donefunc, void *uap, + const char *body, size_t bodylen) +{ + static const char me[] = "ctl_response"; + struct iovec iov[3], *iovp = iov; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP], *pc; + int n; + + REQUIRE(sess->state == initializing || + sess->state == processing || + sess->state == reading_data || + sess->state == writing); + REQUIRE(sess->wrtiID.opaque == NULL); + REQUIRE(sess->wrID.opaque == NULL); + ctl_new_state(sess, writing, me); + sess->donefunc = donefunc; + sess->uap = uap; + if (!allocated_p(sess->outbuf) && + ctl_bufget(&sess->outbuf, ctx->logger) < 0) { + (*ctx->logger)(ctl_error, "%s: %s: cant get an output buffer", + me, address_expr); + goto untimely; + } + if (sizeof "000-\r\n" + strlen(text) > MAX_LINELEN) { + (*ctx->logger)(ctl_error, "%s: %s: output buffer ovf, closing", + me, address_expr); + goto untimely; + } + sess->outbuf.used = SPRINTF((sess->outbuf.text, "%03d%c%s\r\n", + code, (flags & CTL_MORE) != 0 ? '-' : ' ', + text)); + for (pc = sess->outbuf.text, n = 0; n < sess->outbuf.used-2; pc++, n++) + if (!isascii(*pc) || !isprint(*pc)) + *pc = '\040'; + *iovp++ = evConsIovec(sess->outbuf.text, sess->outbuf.used); + if (body != NULL) { + *iovp++ = evConsIovec((char *)body, bodylen); + *iovp++ = evConsIovec(".\r\n", 3); + } + (*ctx->logger)(ctl_debug, "%s: [%d] %s", me, + sess->outbuf.used, sess->outbuf.text); + if (evWrite(ctx->ev, sess->sock, iov, iovp - iov, + ctl_writedone, sess, &sess->wrID) < 0) { + (*ctx->logger)(ctl_error, "%s: %s: evWrite: %s", me, + address_expr, strerror(errno)); + goto untimely; + } + if (evSetIdleTimer(ctx->ev, ctl_wrtimeout, sess, ctx->timeout, + &sess->wrtiID) < 0) + { + (*ctx->logger)(ctl_error, "%s: %s: evSetIdleTimer: %s", me, + address_expr, strerror(errno)); + goto untimely; + } + if (evTimeRW(ctx->ev, sess->wrID, sess->wrtiID) < 0) { + (*ctx->logger)(ctl_error, "%s: %s: evTimeRW: %s", me, + address_expr, strerror(errno)); + untimely: + ctl_signal_done(ctx, sess); + ctl_close(sess); + return; + } + sess->respctx = respctx; + sess->respflags = flags; +} + +void +ctl_sendhelp(struct ctl_sess *sess, u_int code) { + static const char me[] = "ctl_sendhelp"; + struct ctl_sctx *ctx = sess->ctx; + + sess->helpcode = code; + sess->verb = &fakehelpverb; + ctl_morehelp(ctx, sess, NULL, me, CTL_MORE, (void *)ctx->verbs, NULL); +} + +void * +ctl_getcsctx(struct ctl_sess *sess) { + return (sess->csctx); +} + +void * +ctl_setcsctx(struct ctl_sess *sess, void *csctx) { + void *old = sess->csctx; + + sess->csctx = csctx; + return (old); +} + +/* Private functions. */ + +static void +ctl_accept(evContext lev, void *uap, int fd, + const void *lav, int lalen, + const void *rav, int ralen) +{ + static const char me[] = "ctl_accept"; + struct ctl_sctx *ctx = uap; + struct ctl_sess *sess = NULL; + char tmp[MAX_NTOP]; + + if (fd < 0) { + (*ctx->logger)(ctl_error, "%s: accept: %s", + me, strerror(errno)); + return; + } + if (ctx->cur_sess == ctx->max_sess) { + (*ctx->logger)(ctl_error, "%s: %s: too many control sessions", + me, ctl_sa_ntop((struct sockaddr *)rav, + tmp, sizeof tmp, + ctx->logger)); + (void) close(fd); + return; + } + sess = memget(sizeof *sess); + if (sess == NULL) { + (*ctx->logger)(ctl_error, "%s: memget: %s", me, + strerror(errno)); + (void) close(fd); + return; + } + if (fcntl(fd, F_SETFD, 1) < 0) { + (*ctx->logger)(ctl_warning, "%s: fcntl: %s", me, + strerror(errno)); + } + ctx->cur_sess++; + APPEND(ctx->sess, sess, link); + sess->ctx = ctx; + sess->sock = fd; + sess->wrID.opaque = NULL; + sess->rdID.opaque = NULL; + sess->wrtiID.opaque = NULL; + sess->rdtiID.opaque = NULL; + sess->respctx = NULL; + sess->csctx = NULL; + if (((struct sockaddr *)rav)->sa_family == AF_UNIX) + ctl_sa_copy((struct sockaddr *)lav, + (struct sockaddr *)&sess->sa); + else + ctl_sa_copy((struct sockaddr *)rav, + (struct sockaddr *)&sess->sa); + sess->donefunc = NULL; + buffer_init(sess->inbuf); + buffer_init(sess->outbuf); + sess->state = available; + ctl_new_state(sess, initializing, me); + sess->verb = ctx->connverb; + (*ctx->logger)(ctl_debug, "%s: %s: accepting (fd %d)", + me, address_expr, sess->sock); + (*ctx->connverb->func)(ctx, sess, ctx->connverb, "", 0, + (struct sockaddr *)rav, ctx->uctx); +} + +static void +ctl_new_state(struct ctl_sess *sess, enum state new_state, const char *reason) +{ + static const char me[] = "ctl_new_state"; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + (*ctx->logger)(ctl_debug, "%s: %s: %s -> %s (%s)", + me, address_expr, + state_names[sess->state], + state_names[new_state], reason); + sess->state = new_state; +} + +static void +ctl_close(struct ctl_sess *sess) { + static const char me[] = "ctl_close"; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + REQUIRE(sess->state == initializing || + sess->state == writing || + sess->state == reading || + sess->state == processing || + sess->state == reading_data || + sess->state == idling); + REQUIRE(sess->sock != -1); + if (sess->state == reading || sess->state == reading_data) + ctl_stop_read(sess); + else if (sess->state == writing) { + if (sess->wrID.opaque != NULL) { + (void) evCancelRW(ctx->ev, sess->wrID); + sess->wrID.opaque = NULL; + } + if (sess->wrtiID.opaque != NULL) { + (void) evClearIdleTimer(ctx->ev, sess->wrtiID); + sess->wrtiID.opaque = NULL; + } + } + ctl_new_state(sess, closing, me); + (void) close(sess->sock); + if (allocated_p(sess->inbuf)) + ctl_bufput(&sess->inbuf); + if (allocated_p(sess->outbuf)) + ctl_bufput(&sess->outbuf); + (*ctx->logger)(ctl_debug, "%s: %s: closed (fd %d)", + me, address_expr, sess->sock); + UNLINK(ctx->sess, sess, link); + memput(sess, sizeof *sess); + ctx->cur_sess--; +} + +static void +ctl_start_read(struct ctl_sess *sess) { + static const char me[] = "ctl_start_read"; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + REQUIRE(sess->state == initializing || + sess->state == writing || + sess->state == processing || + sess->state == idling); + REQUIRE(sess->rdtiID.opaque == NULL); + REQUIRE(sess->rdID.opaque == NULL); + sess->inbuf.used = 0; + if (evSetIdleTimer(ctx->ev, ctl_rdtimeout, sess, ctx->timeout, + &sess->rdtiID) < 0) + { + (*ctx->logger)(ctl_error, "%s: %s: evSetIdleTimer: %s", me, + address_expr, strerror(errno)); + ctl_close(sess); + return; + } + if (evSelectFD(ctx->ev, sess->sock, EV_READ, + ctl_readable, sess, &sess->rdID) < 0) { + (*ctx->logger)(ctl_error, "%s: %s: evSelectFD: %s", me, + address_expr, strerror(errno)); + return; + } + ctl_new_state(sess, reading, me); +} + +static void +ctl_stop_read(struct ctl_sess *sess) { + static const char me[] = "ctl_stop_read"; + struct ctl_sctx *ctx = sess->ctx; + + REQUIRE(sess->state == reading || sess->state == reading_data); + REQUIRE(sess->rdID.opaque != NULL); + (void) evDeselectFD(ctx->ev, sess->rdID); + sess->rdID.opaque = NULL; + if (sess->rdtiID.opaque != NULL) { + (void) evClearIdleTimer(ctx->ev, sess->rdtiID); + sess->rdtiID.opaque = NULL; + } + ctl_new_state(sess, idling, me); +} + +static void +ctl_readable(evContext lev, void *uap, int fd, int evmask) { + static const char me[] = "ctl_readable"; + struct ctl_sess *sess = uap; + struct ctl_sctx *ctx = sess->ctx; + char *eos, tmp[MAX_NTOP]; + ssize_t n; + + REQUIRE(sess != NULL); + REQUIRE(fd >= 0); + REQUIRE(evmask == EV_READ); + REQUIRE(sess->state == reading || sess->state == reading_data); + evTouchIdleTimer(lev, sess->rdtiID); + if (!allocated_p(sess->inbuf) && + ctl_bufget(&sess->inbuf, ctx->logger) < 0) { + (*ctx->logger)(ctl_error, "%s: %s: cant get an input buffer", + me, address_expr); + ctl_close(sess); + return; + } + n = read(sess->sock, sess->inbuf.text + sess->inbuf.used, + MAX_LINELEN - sess->inbuf.used); + if (n <= 0) { + (*ctx->logger)(ctl_debug, "%s: %s: read: %s", + me, address_expr, + (n == 0) ? "Unexpected EOF" : strerror(errno)); + ctl_close(sess); + return; + } + sess->inbuf.used += n; + eos = memchr(sess->inbuf.text, '\n', sess->inbuf.used); + if (eos != NULL && eos != sess->inbuf.text && eos[-1] == '\r') { + eos[-1] = '\0'; + if ((sess->respflags & CTL_DATA) != 0) { + INSIST(sess->verb != NULL); + (*sess->verb->func)(sess->ctx, sess, sess->verb, + sess->inbuf.text, + CTL_DATA, sess->respctx, + sess->ctx->uctx); + } else { + ctl_stop_read(sess); + ctl_docommand(sess); + } + sess->inbuf.used -= ((eos - sess->inbuf.text) + 1); + if (sess->inbuf.used == 0) + ctl_bufput(&sess->inbuf); + else + memmove(sess->inbuf.text, eos + 1, sess->inbuf.used); + return; + } + if (sess->inbuf.used == MAX_LINELEN) { + (*ctx->logger)(ctl_error, "%s: %s: line too long, closing", + me, address_expr); + ctl_close(sess); + } +} + +static void +ctl_wrtimeout(evContext lev, void *uap, + struct timespec due, + struct timespec itv) +{ + static const char me[] = "ctl_wrtimeout"; + struct ctl_sess *sess = uap; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + REQUIRE(sess->state == writing); + sess->wrtiID.opaque = NULL; + (*ctx->logger)(ctl_warning, "%s: %s: write timeout, closing", + me, address_expr); + if (sess->wrID.opaque != NULL) { + (void) evCancelRW(ctx->ev, sess->wrID); + sess->wrID.opaque = NULL; + } + ctl_signal_done(ctx, sess); + ctl_new_state(sess, processing, me); + ctl_close(sess); +} + +static void +ctl_rdtimeout(evContext lev, void *uap, + struct timespec due, + struct timespec itv) +{ + static const char me[] = "ctl_rdtimeout"; + struct ctl_sess *sess = uap; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + REQUIRE(sess->state == reading); + sess->rdtiID.opaque = NULL; + (*ctx->logger)(ctl_warning, "%s: %s: timeout, closing", + me, address_expr); + if (sess->state == reading || sess->state == reading_data) + ctl_stop_read(sess); + ctl_signal_done(ctx, sess); + ctl_new_state(sess, processing, me); + ctl_response(sess, ctx->timeoutcode, "Timeout.", CTL_EXIT, NULL, + NULL, NULL, NULL, 0); +} + +static void +ctl_docommand(struct ctl_sess *sess) { + static const char me[] = "ctl_docommand"; + char *name, *rest, tmp[MAX_NTOP]; + struct ctl_sctx *ctx = sess->ctx; + const struct ctl_verb *verb; + + REQUIRE(allocated_p(sess->inbuf)); + (*ctx->logger)(ctl_debug, "%s: %s: \"%s\" [%u]", + me, address_expr, + sess->inbuf.text, (u_int)sess->inbuf.used); + ctl_new_state(sess, processing, me); + name = sess->inbuf.text + strspn(sess->inbuf.text, space); + rest = name + strcspn(name, space); + if (*rest != '\0') { + *rest++ = '\0'; + rest += strspn(rest, space); + } + for (verb = ctx->verbs; + verb != NULL && verb->name != NULL && verb->func != NULL; + verb++) + if (verb->name[0] != '\0' && strcasecmp(name, verb->name) == 0) + break; + if (verb != NULL && verb->name != NULL && verb->func != NULL) { + sess->verb = verb; + (*verb->func)(ctx, sess, verb, rest, 0, NULL, ctx->uctx); + } else { + char buf[1100]; + + if (sizeof "Unrecognized command \"\" (args \"\")" + + strlen(name) + strlen(rest) > sizeof buf) + strcpy(buf, "Unrecognized command (buf ovf)"); + else + sprintf(buf, + "Unrecognized command \"%s\" (args \"%s\")", + name, rest); + ctl_response(sess, ctx->unkncode, buf, 0, NULL, NULL, NULL, + NULL, 0); + } +} + +static void +ctl_writedone(evContext lev, void *uap, int fd, int bytes) { + static const char me[] = "ctl_writedone"; + struct ctl_sess *sess = uap; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + int save_errno = errno; + + REQUIRE(sess->state == writing); + REQUIRE(fd == sess->sock); + REQUIRE(sess->wrtiID.opaque != NULL); + sess->wrID.opaque = NULL; + (void) evClearIdleTimer(ctx->ev, sess->wrtiID); + sess->wrtiID.opaque = NULL; + if (bytes < 0) { + (*ctx->logger)(ctl_error, "%s: %s: %s", + me, address_expr, strerror(save_errno)); + ctl_close(sess); + return; + } + + INSIST(allocated_p(sess->outbuf)); + ctl_bufput(&sess->outbuf); + if ((sess->respflags & CTL_EXIT) != 0) { + ctl_signal_done(ctx, sess); + ctl_close(sess); + return; + } else if ((sess->respflags & CTL_MORE) != 0) { + INSIST(sess->verb != NULL); + (*sess->verb->func)(sess->ctx, sess, sess->verb, "", + CTL_MORE, sess->respctx, sess->ctx->uctx); + } else { + ctl_signal_done(ctx, sess); + ctl_start_read(sess); + } +} + +static void +ctl_morehelp(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *text, + u_int respflags, void *respctx, void *uctx) +{ + struct ctl_verb *this = respctx, *next = this + 1; + + REQUIRE(!lastverb_p(this)); + REQUIRE((respflags & CTL_MORE) != 0); + if (lastverb_p(next)) + respflags &= ~CTL_MORE; + ctl_response(sess, sess->helpcode, this->help, respflags, next, + NULL, NULL, NULL, 0); +} + +static void +ctl_signal_done(struct ctl_sctx *ctx, struct ctl_sess *sess) { + if (sess->donefunc != NULL) { + (*sess->donefunc)(ctx, sess, sess->uap); + sess->donefunc = NULL; + } +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ctl_srvr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_connects.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_connects.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_connects.c (revision 60942) @@ -0,0 +1,349 @@ +/* + * 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. + */ + +/* ev_connects.c - implement asynch connect/accept for the eventlib + * vix 16sep96 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_connects.c,v 8.26 2000/02/04 08:28:34 vixie Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include +#include + +#include + +#include +#include +#include "eventlib_p.h" + +#include "port_after.h" + +/* Macros. */ + +#define GETXXXNAME(f, s, sa, len) ( \ + (f((s), (&sa), (&len)) >= 0) ? 0 : \ + (errno != EAFNOSUPPORT && errno != EOPNOTSUPP) ? -1 : ( \ + memset(&(sa), 0, sizeof (sa)), \ + (len) = sizeof (sa), \ + (sa).sa_family = AF_UNIX, \ + 0 \ + ) \ + ) + +/* Forward. */ + +static void listener(evContext ctx, void *uap, int fd, int evmask); +static void connector(evContext ctx, void *uap, int fd, int evmask); + +/* Public. */ + +int +evListen(evContext opaqueCtx, int fd, int maxconn, + evConnFunc func, void *uap, evConnID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evConn *new; + int mode; + + OKNEW(new); + new->flags = EV_CONN_LISTEN; + OK(mode = fcntl(fd, F_GETFL, NULL)); /* side effect: validate fd. */ + /* + * Remember the nonblocking status. We assume that either evSelectFD + * has not been done to this fd, or that if it has then the caller + * will evCancelConn before they evDeselectFD. If our assumptions + * are not met, then we might restore the old nonblocking status + * incorrectly. + */ + if ((mode & PORT_NONBLOCK) == 0) { + OK(fcntl(fd, F_SETFL, mode | PORT_NONBLOCK)); + new->flags |= EV_CONN_BLOCK; + } + OK(listen(fd, maxconn)); + if (evSelectFD(opaqueCtx, fd, EV_READ, listener, new, &new->file) < 0){ + int save = errno; + + FREE(new); + errno = save; + return (-1); + } + new->flags |= EV_CONN_SELECTED; + new->func = func; + new->uap = uap; + new->fd = fd; + if (ctx->conns != NULL) + ctx->conns->prev = new; + new->prev = NULL; + new->next = ctx->conns; + ctx->conns = new; + if (id) + id->opaque = new; + return (0); +} + +int +evConnect(evContext opaqueCtx, int fd, void *ra, int ralen, + evConnFunc func, void *uap, evConnID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evConn *new; + + OKNEW(new); + new->flags = 0; + /* Do the select() first to get the socket into nonblocking mode. */ + if (evSelectFD(opaqueCtx, fd, EV_MASK_ALL, + connector, new, &new->file) < 0) { + int save = errno; + + FREE(new); + errno = save; + return (-1); + } + new->flags |= EV_CONN_SELECTED; + if (connect(fd, ra, ralen) < 0 && + errno != EWOULDBLOCK && + errno != EAGAIN && + errno != EINPROGRESS) { + int save = errno; + + (void) evDeselectFD(opaqueCtx, new->file); + FREE(new); + errno = save; + return (-1); + } + /* No error, or EWOULDBLOCK. select() tells when it's ready. */ + new->func = func; + new->uap = uap; + new->fd = fd; + if (ctx->conns != NULL) + ctx->conns->prev = new; + new->prev = NULL; + new->next = ctx->conns; + ctx->conns = new; + if (id) + id->opaque = new; + return (0); +} + +int +evCancelConn(evContext opaqueCtx, evConnID id) { + evContext_p *ctx = opaqueCtx.opaque; + evConn *this = id.opaque; + evAccept *acc, *nxtacc; + int mode; + + if ((this->flags & EV_CONN_SELECTED) != 0) + (void) evDeselectFD(opaqueCtx, this->file); + if ((this->flags & EV_CONN_BLOCK) != 0) { + mode = fcntl(this->fd, F_GETFL, NULL); + if (mode == -1) { + if (errno != EBADF) + return (-1); + } else + OK(fcntl(this->fd, F_SETFL, mode | PORT_NONBLOCK)); + } + + /* Unlink from ctx->conns. */ + if (this->prev != NULL) + this->prev->next = this->next; + else + ctx->conns = this->next; + if (this->next != NULL) + this->next->prev = this->prev; + + /* + * Remove `this' from the ctx->accepts list (zero or more times). + */ + for (acc = HEAD(ctx->accepts), nxtacc = NULL; + acc != NULL; + acc = nxtacc) + { + nxtacc = NEXT(acc, link); + if (acc->conn == this) { + UNLINK(ctx->accepts, acc, link); + close(acc->fd); + FREE(acc); + } + } + + /* Wrap up and get out. */ + FREE(this); + return (0); +} + +int evHold(evContext opaqueCtx, evConnID id) { + evConn *this = id.opaque; + + if ((this->flags & EV_CONN_LISTEN) == 0) { + errno = EINVAL; + return (-1); + } + if ((this->flags & EV_CONN_SELECTED) == 0) + return (0); + this->flags &= ~EV_CONN_SELECTED; + return (evDeselectFD(opaqueCtx, this->file)); +} + +int evUnhold(evContext opaqueCtx, evConnID id) { + evConn *this = id.opaque; + int ret; + + if ((this->flags & EV_CONN_LISTEN) == 0) { + errno = EINVAL; + return (-1); + } + if ((this->flags & EV_CONN_SELECTED) != 0) + return (0); + ret = evSelectFD(opaqueCtx, this->fd, EV_READ, listener, this, + &this->file); + if (ret == 0) + this->flags |= EV_CONN_SELECTED; + return (ret); +} + +int +evTryAccept(evContext opaqueCtx, evConnID id, int *sys_errno) { + evContext_p *ctx = opaqueCtx.opaque; + evConn *conn = id.opaque; + evAccept *new; + + if ((conn->flags & EV_CONN_LISTEN) == 0) { + errno = EINVAL; + return (-1); + } + OKNEW(new); + new->conn = conn; + new->ralen = sizeof new->ra; + new->fd = accept(conn->fd, &new->ra.sa, &new->ralen); + if (new->fd > ctx->highestFD) { + close(new->fd); + new->fd = -1; + new->ioErrno = ENOTSOCK; + } + if (new->fd >= 0) { + new->lalen = sizeof new->la; + if (GETXXXNAME(getsockname, new->fd, new->la.sa, new->lalen) < 0) { + new->ioErrno = errno; + (void) close(new->fd); + new->fd = -1; + } else + new->ioErrno = 0; + } else { + new->ioErrno = errno; + if (errno == EAGAIN || errno == EWOULDBLOCK) { + FREE(new); + return (-1); + } + } + APPEND(ctx->accepts, new, link); + *sys_errno = new->ioErrno; + return (0); +} + +/* Private. */ + +static void +listener(evContext opaqueCtx, void *uap, int fd, int evmask) { + evContext_p *ctx = opaqueCtx.opaque; + evConn *conn = uap; + union { + struct sockaddr sa; + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif + } la, ra; + int new, lalen = 0, ralen; + + REQUIRE((evmask & EV_READ) != 0); + ralen = sizeof ra; + new = accept(fd, &ra.sa, &ralen); + if (new > ctx->highestFD) { + close(new); + new = -1; + errno = ENOTSOCK; + } + if (new >= 0) { + lalen = sizeof la; + if (GETXXXNAME(getsockname, new, la.sa, lalen) < 0) { + int save = errno; + + (void) close(new); + errno = save; + new = -1; + } + } else if (errno == EAGAIN || errno == EWOULDBLOCK) + return; + (*conn->func)(opaqueCtx, conn->uap, new, &la.sa, lalen, &ra.sa, ralen); +} + +static void +connector(evContext opaqueCtx, void *uap, int fd, int evmask) { + evConn *conn = uap; + union { + struct sockaddr sa; + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif + } la, ra; + int lalen, ralen; + char buf[1]; + void *conn_uap; + evConnFunc conn_func; + evConnID id; + int socket_errno = 0; + int optlen; + + lalen = sizeof la; + ralen = sizeof ra; + conn_uap = conn->uap; + conn_func = conn->func; + id.opaque = conn; +#ifdef SO_ERROR + optlen = sizeof socket_errno; + if (fd < 0 && + getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, (char *)&socket_errno, + &optlen) < 0) + socket_errno = errno; + else + errno = socket_errno; +#endif + if (evCancelConn(opaqueCtx, id) < 0 || + socket_errno || +#ifdef NETREAD_BROKEN + 0 || +#else + read(fd, buf, 0) < 0 || +#endif + GETXXXNAME(getsockname, fd, la.sa, lalen) < 0 || + GETXXXNAME(getpeername, fd, ra.sa, ralen) < 0) { + int save = errno; + + (void) close(fd); /* XXX closing caller's fd */ + errno = save; + fd = -1; + } + (*conn_func)(opaqueCtx, conn_uap, fd, &la.sa, lalen, &ra.sa, ralen); +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_connects.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_waits.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_waits.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_waits.c (revision 60942) @@ -0,0 +1,246 @@ +/* + * 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. + */ + +/* ev_waits.c - implement deferred function calls for the eventlib + * vix 05dec95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_waits.c,v 8.10 2000/02/04 07:25:50 vixie Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include + +#include +#include +#include "eventlib_p.h" + +#include "port_after.h" + +/* Forward. */ + +static void print_waits(evContext_p *ctx); +static evWaitList * evNewWaitList(evContext_p *); +static void evFreeWaitList(evContext_p *, evWaitList *); +static evWaitList * evGetWaitList(evContext_p *, const void *, int); + + +/* Public. */ + +/* + * Enter a new wait function on the queue. + */ +int +evWaitFor(evContext opaqueCtx, const void *tag, + evWaitFunc func, void *uap, evWaitID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evWait *new; + evWaitList *wl = evGetWaitList(ctx, tag, 1); + + OKNEW(new); + new->func = func; + new->uap = uap; + new->tag = tag; + new->next = NULL; + if (wl->last != NULL) { + wl->last->next = new; + } else { + wl->first = new; + } + wl->last = new; + if (id != NULL) + id->opaque = new; + if (ctx->debug >= 9) + print_waits(ctx); + return (0); +} + +/* + * Mark runnable all waiting functions having a certain tag. + */ +int +evDo(evContext opaqueCtx, const void *tag) { + evContext_p *ctx = opaqueCtx.opaque; + evWaitList *wl = evGetWaitList(ctx, tag, 0); + evWait *first; + + if (!wl) { + errno = ENOENT; + return (-1); + } + + first = wl->first; + INSIST(first != NULL); + + if (ctx->waitDone.last != NULL) + ctx->waitDone.last->next = first; + else + ctx->waitDone.first = first; + ctx->waitDone.last = wl->last; + evFreeWaitList(ctx, wl); + + return (0); +} + +/* + * Remove a waiting (or ready to run) function from the queue. + */ +int +evUnwait(evContext opaqueCtx, evWaitID id) { + evContext_p *ctx = opaqueCtx.opaque; + evWait *this, *prev; + evWaitList *wl; + int found = 0; + + this = id.opaque; + INSIST(this != NULL); + wl = evGetWaitList(ctx, this->tag, 0); + if (wl != NULL) { + for (prev = NULL, this = wl->first; + this != NULL; + prev = this, this = this->next) + if (this == (evWait *)id.opaque) { + found = 1; + if (prev != NULL) + prev->next = this->next; + else + wl->first = this->next; + if (wl->last == this) + wl->last = prev; + if (wl->first == NULL) + evFreeWaitList(ctx, wl); + break; + } + } + + if (!found) { + /* Maybe it's done */ + for (prev = NULL, this = ctx->waitDone.first; + this != NULL; + prev = this, this = this->next) + if (this == (evWait *)id.opaque) { + found = 1; + if (prev != NULL) + prev->next = this->next; + else + ctx->waitDone.first = this->next; + if (ctx->waitDone.last == this) + ctx->waitDone.last = prev; + break; + } + } + + if (!found) { + errno = ENOENT; + return (-1); + } + + FREE(this); + + if (ctx->debug >= 9) + print_waits(ctx); + + return (0); +} + +int +evDefer(evContext opaqueCtx, evWaitFunc func, void *uap) { + evContext_p *ctx = opaqueCtx.opaque; + evWait *new; + + OKNEW(new); + new->func = func; + new->uap = uap; + new->tag = NULL; + new->next = NULL; + if (ctx->waitDone.last != NULL) + ctx->waitDone.last->next = new; + else + ctx->waitDone.first = new; + ctx->waitDone.last = new; + if (ctx->debug >= 9) + print_waits(ctx); + return (0); +} + +/* Private. */ + +static void +print_waits(evContext_p *ctx) { + evWaitList *wl; + evWait *this; + + evPrintf(ctx, 9, "wait waiting:\n"); + for (wl = ctx->waitLists; wl != NULL; wl = wl->next) { + INSIST(wl->first != NULL); + evPrintf(ctx, 9, " tag %#x:", wl->first->tag); + for (this = wl->first; this != NULL; this = this->next) + evPrintf(ctx, 9, " %#x", this); + evPrintf(ctx, 9, "\n"); + } + evPrintf(ctx, 9, "wait done:"); + for (this = ctx->waitDone.first; this != NULL; this = this->next) + evPrintf(ctx, 9, " %#x", this); + evPrintf(ctx, 9, "\n"); +} + +static evWaitList * +evNewWaitList(evContext_p *ctx) { + evWaitList *new; + + NEW(new); + if (new == NULL) + return (NULL); + new->first = new->last = NULL; + new->prev = NULL; + new->next = ctx->waitLists; + if (new->next != NULL) + new->next->prev = new; + ctx->waitLists = new; + return (new); +} + +static void +evFreeWaitList(evContext_p *ctx, evWaitList *this) { + + INSIST(this != NULL); + + if (this->prev != NULL) + this->prev->next = this->next; + else + ctx->waitLists = this->next; + if (this->next != NULL) + this->next->prev = this->prev; + FREE(this); +} + +static evWaitList * +evGetWaitList(evContext_p *ctx, const void *tag, int should_create) { + evWaitList *this; + + for (this = ctx->waitLists; this != NULL; this = this->next) { + if (this->first != NULL && this->first->tag == tag) + break; + } + if (this == NULL && should_create) + this = evNewWaitList(ctx); + return (this); +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_waits.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/eventlib.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/eventlib.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/eventlib.c (revision 60942) @@ -0,0 +1,676 @@ +/* + * 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. + */ + +/* eventlib.c - implement glue for the eventlib + * vix 09sep95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: eventlib.c,v 1.45 2000/02/04 07:25:39 vixie Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include "eventlib_p.h" + +#include "port_after.h" + +/* Forward. */ + +#ifdef NEED_PSELECT +static int pselect(int, void *, void *, void *, + struct timespec *, + const sigset_t *); +#endif + +/* Public. */ + +int +evCreate(evContext *opaqueCtx) { + evContext_p *ctx; + + /* Make sure the memory heap is initialized. */ + if (meminit(0, 0) < 0 && errno != EEXIST) + return (-1); + + OKNEW(ctx); + + /* Global. */ + ctx->cur = NULL; + + /* Debugging. */ + ctx->debug = 0; + ctx->output = NULL; + + /* Connections. */ + ctx->conns = NULL; + INIT_LIST(ctx->accepts); + + /* Files. */ + ctx->files = NULL; + FD_ZERO(&ctx->rdNext); + FD_ZERO(&ctx->wrNext); + FD_ZERO(&ctx->exNext); + FD_ZERO(&ctx->nonblockBefore); + ctx->fdMax = -1; + ctx->fdNext = NULL; + ctx->fdCount = 0; /* Invalidate {rd,wr,ex}Last. */ + ctx->highestFD = FD_SETSIZE - 1; +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastFdCount = 0; +#endif + memset(ctx->fdTable, 0, sizeof ctx->fdTable); + + /* Streams. */ + ctx->streams = NULL; + ctx->strDone = NULL; + ctx->strLast = NULL; + + /* Timers. */ + ctx->lastEventTime = evNowTime(); +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastSelectTime = ctx->lastEventTime; +#endif + ctx->timers = evCreateTimers(ctx); + if (ctx->timers == NULL) + return (-1); + + /* Waits. */ + ctx->waitLists = NULL; + ctx->waitDone.first = ctx->waitDone.last = NULL; + ctx->waitDone.prev = ctx->waitDone.next = NULL; + + opaqueCtx->opaque = ctx; + return (0); +} + +void +evSetDebug(evContext opaqueCtx, int level, FILE *output) { + evContext_p *ctx = opaqueCtx.opaque; + + ctx->debug = level; + ctx->output = output; +} + +int +evDestroy(evContext opaqueCtx) { + evContext_p *ctx = opaqueCtx.opaque; + int revs = 424242; /* Doug Adams. */ + evWaitList *this_wl, *next_wl; + evWait *this_wait, *next_wait; + + /* Connections. */ + while (revs-- > 0 && ctx->conns != NULL) { + evConnID id; + + id.opaque = ctx->conns; + (void) evCancelConn(opaqueCtx, id); + } + INSIST(revs >= 0); + + /* Streams. */ + while (revs-- > 0 && ctx->streams != NULL) { + evStreamID id; + + id.opaque = ctx->streams; + (void) evCancelRW(opaqueCtx, id); + } + + /* Files. */ + while (revs-- > 0 && ctx->files != NULL) { + evFileID id; + + id.opaque = ctx->files; + (void) evDeselectFD(opaqueCtx, id); + } + INSIST(revs >= 0); + + /* Timers. */ + evDestroyTimers(ctx); + + /* Waits. */ + for (this_wl = ctx->waitLists; + revs-- > 0 && this_wl != NULL; + this_wl = next_wl) { + next_wl = this_wl->next; + for (this_wait = this_wl->first; + revs-- > 0 && this_wait != NULL; + this_wait = next_wait) { + next_wait = this_wait->next; + FREE(this_wait); + } + FREE(this_wl); + } + for (this_wait = ctx->waitDone.first; + revs-- > 0 && this_wait != NULL; + this_wait = next_wait) { + next_wait = this_wait->next; + FREE(this_wait); + } + + FREE(ctx); + return (0); +} + +int +evGetNext(evContext opaqueCtx, evEvent *opaqueEv, int options) { + evContext_p *ctx = opaqueCtx.opaque; + struct timespec nextTime; + evTimer *nextTimer; + evEvent_p *new; + int x, pselect_errno, timerPast; +#ifdef EVENTLIB_TIME_CHECKS + struct timespec interval; +#endif + + /* Ensure that exactly one of EV_POLL or EV_WAIT was specified. */ + x = ((options & EV_POLL) != 0) + ((options & EV_WAIT) != 0); + if (x != 1) + ERR(EINVAL); + + /* Get the time of day. We'll do this again after select() blocks. */ + ctx->lastEventTime = evNowTime(); + + again: + /* Finished accept()'s do not require a select(). */ + if (!EMPTY(ctx->accepts)) { + OKNEW(new); + new->type = Accept; + new->u.accept.this = HEAD(ctx->accepts); + UNLINK(ctx->accepts, HEAD(ctx->accepts), link); + opaqueEv->opaque = new; + return (0); + } + + /* Stream IO does not require a select(). */ + if (ctx->strDone != NULL) { + OKNEW(new); + new->type = Stream; + new->u.stream.this = ctx->strDone; + ctx->strDone = ctx->strDone->nextDone; + if (ctx->strDone == NULL) + ctx->strLast = NULL; + opaqueEv->opaque = new; + return (0); + } + + /* Waits do not require a select(). */ + if (ctx->waitDone.first != NULL) { + OKNEW(new); + new->type = Wait; + new->u.wait.this = ctx->waitDone.first; + ctx->waitDone.first = ctx->waitDone.first->next; + if (ctx->waitDone.first == NULL) + ctx->waitDone.last = NULL; + opaqueEv->opaque = new; + return (0); + } + + /* Get the status and content of the next timer. */ + if ((nextTimer = heap_element(ctx->timers, 1)) != NULL) { + nextTime = nextTimer->due; + timerPast = (evCmpTime(nextTime, ctx->lastEventTime) <= 0); + } else + timerPast = 0; /* Make gcc happy. */ + + evPrintf(ctx, 9, "evGetNext: fdCount %d\n", ctx->fdCount); + if (ctx->fdCount == 0) { + static const struct timespec NoTime = {0, 0L}; + enum { JustPoll, Block, Timer } m; + struct timespec t, *tp; + + /* Are there any events at all? */ + if ((options & EV_WAIT) != 0 && !nextTimer && ctx->fdMax == -1) + ERR(ENOENT); + + /* Figure out what select()'s timeout parameter should be. */ + if ((options & EV_POLL) != 0) { + m = JustPoll; + t = NoTime; + tp = &t; + } else if (nextTimer == NULL) { + m = Block; + /* ``t'' unused. */ + tp = NULL; + } else if (timerPast) { + m = JustPoll; + t = NoTime; + tp = &t; + } else { + m = Timer; + /* ``t'' filled in later. */ + tp = &t; + } +#ifdef EVENTLIB_TIME_CHECKS + if (ctx->debug > 0) { + interval = evSubTime(ctx->lastEventTime, + ctx->lastSelectTime); + if (interval.tv_sec > 0) + evPrintf(ctx, 1, + "time between pselect() %u.%09u count %d\n", + interval.tv_sec, interval.tv_nsec, + ctx->lastFdCount); + } +#endif + do { + /* XXX need to copy only the bits we are using. */ + ctx->rdLast = ctx->rdNext; + ctx->wrLast = ctx->wrNext; + ctx->exLast = ctx->exNext; + + if (m == Timer) { + INSIST(tp == &t); + t = evSubTime(nextTime, ctx->lastEventTime); + } + + evPrintf(ctx, 4, + "pselect(%d, 0x%lx, 0x%lx, 0x%lx, %d.%09ld)\n", + ctx->fdMax+1, + (u_long)ctx->rdLast.fds_bits[0], + (u_long)ctx->wrLast.fds_bits[0], + (u_long)ctx->exLast.fds_bits[0], + tp ? tp->tv_sec : -1, + tp ? tp->tv_nsec : -1); + + /* XXX should predict system's earliness and adjust. */ + x = pselect(ctx->fdMax+1, + &ctx->rdLast, &ctx->wrLast, &ctx->exLast, + tp, NULL); + pselect_errno = errno; + + evPrintf(ctx, 4, "select() returns %d (err: %s)\n", + x, (x == -1) ? strerror(errno) : "none"); + + /* Anything but a poll can change the time. */ + if (m != JustPoll) + ctx->lastEventTime = evNowTime(); + + /* Select() likes to finish about 10ms early. */ + } while (x == 0 && m == Timer && + evCmpTime(ctx->lastEventTime, nextTime) < 0); +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastSelectTime = ctx->lastEventTime; +#endif + if (x < 0) { + if (pselect_errno == EINTR) { + if ((options & EV_NULL) != 0) + goto again; + OKNEW(new); + new->type = Null; + /* No data. */ + opaqueEv->opaque = new; + return (0); + } + if (pselect_errno == EBADF) { + for (x = 0; x <= ctx->fdMax; x++) { + struct stat sb; + + if (FD_ISSET(x, &ctx->rdNext) == 0 && + FD_ISSET(x, &ctx->wrNext) == 0 && + FD_ISSET(x, &ctx->exNext) == 0) + continue; + if (fstat(x, &sb) == -1 && + errno == EBADF) + evPrintf(ctx, 1, "EBADF: %d\n", + x); + } + abort(); + } + ERR(pselect_errno); + } + if (x == 0 && (nextTimer == NULL || !timerPast) && + (options & EV_POLL)) + ERR(EWOULDBLOCK); + ctx->fdCount = x; +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastFdCount = x; +#endif + } + INSIST(nextTimer || ctx->fdCount); + + /* Timers go first since we'd like them to be accurate. */ + if (nextTimer && !timerPast) { + /* Has anything happened since we blocked? */ + timerPast = (evCmpTime(nextTime, ctx->lastEventTime) <= 0); + } + if (nextTimer && timerPast) { + OKNEW(new); + new->type = Timer; + new->u.timer.this = nextTimer; + opaqueEv->opaque = new; + return (0); + } + + /* No timers, so there should be a ready file descriptor. */ + x = 0; + while (ctx->fdCount > 0) { + evFile *fid; + int fd, eventmask; + + if (ctx->fdNext == NULL) { + if (++x == 2) { + /* + * Hitting the end twice means that the last + * select() found some FD's which have since + * been deselected. + * + * On some systems, the count returned by + * selects is the total number of bits in + * all masks that are set, and on others it's + * the number of fd's that have some bit set, + * and on others, it's just broken. We + * always assume that it's the number of + * bits set in all masks, because that's what + * the man page says it should do, and + * the worst that can happen is we do an + * extra select(). + */ + ctx->fdCount = 0; + break; + } + ctx->fdNext = ctx->files; + } + fid = ctx->fdNext; + ctx->fdNext = fid->next; + + fd = fid->fd; + eventmask = 0; + if (FD_ISSET(fd, &ctx->rdLast)) + eventmask |= EV_READ; + if (FD_ISSET(fd, &ctx->wrLast)) + eventmask |= EV_WRITE; + if (FD_ISSET(fd, &ctx->exLast)) + eventmask |= EV_EXCEPT; + eventmask &= fid->eventmask; + if (eventmask != 0) { + if ((eventmask & EV_READ) != 0) { + FD_CLR(fd, &ctx->rdLast); + ctx->fdCount--; + } + if ((eventmask & EV_WRITE) != 0) { + FD_CLR(fd, &ctx->wrLast); + ctx->fdCount--; + } + if ((eventmask & EV_EXCEPT) != 0) { + FD_CLR(fd, &ctx->exLast); + ctx->fdCount--; + } + OKNEW(new); + new->type = File; + new->u.file.this = fid; + new->u.file.eventmask = eventmask; + opaqueEv->opaque = new; + return (0); + } + } + if (ctx->fdCount < 0) { + /* + * select()'s count is off on a number of systems, and + * can result in fdCount < 0. + */ + evPrintf(ctx, 4, "fdCount < 0 (%d)\n", ctx->fdCount); + ctx->fdCount = 0; + } + + /* We get here if the caller deselect()'s an FD. Gag me with a goto. */ + goto again; +} + +int +evDispatch(evContext opaqueCtx, evEvent opaqueEv) { + evContext_p *ctx = opaqueCtx.opaque; + evEvent_p *ev = opaqueEv.opaque; +#ifdef EVENTLIB_TIME_CHECKS + void *func; + struct timespec start_time; + struct timespec interval; +#endif + +#ifdef EVENTLIB_TIME_CHECKS + if (ctx->debug > 0) + start_time = evNowTime(); +#endif + ctx->cur = ev; + switch (ev->type) { + case Accept: { + evAccept *this = ev->u.accept.this; + + evPrintf(ctx, 5, + "Dispatch.Accept: fd %d -> %d, func %#x, uap %#x\n", + this->conn->fd, this->fd, + this->conn->func, this->conn->uap); + errno = this->ioErrno; + (this->conn->func)(opaqueCtx, this->conn->uap, this->fd, + &this->la, this->lalen, + &this->ra, this->ralen); +#ifdef EVENTLIB_TIME_CHECKS + func = this->conn->func; +#endif + break; + } + case File: { + evFile *this = ev->u.file.this; + int eventmask = ev->u.file.eventmask; + + evPrintf(ctx, 5, + "Dispatch.File: fd %d, mask 0x%x, func %#x, uap %#x\n", + this->fd, this->eventmask, this->func, this->uap); + (this->func)(opaqueCtx, this->uap, this->fd, eventmask); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Stream: { + evStream *this = ev->u.stream.this; + + evPrintf(ctx, 5, + "Dispatch.Stream: fd %d, func %#x, uap %#x\n", + this->fd, this->func, this->uap); + errno = this->ioErrno; + (this->func)(opaqueCtx, this->uap, this->fd, this->ioDone); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Timer: { + evTimer *this = ev->u.timer.this; + + evPrintf(ctx, 5, "Dispatch.Timer: func %#x, uap %#x\n", + this->func, this->uap); + (this->func)(opaqueCtx, this->uap, this->due, this->inter); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Wait: { + evWait *this = ev->u.wait.this; + + evPrintf(ctx, 5, + "Dispatch.Wait: tag %#x, func %#x, uap %#x\n", + this->tag, this->func, this->uap); + (this->func)(opaqueCtx, this->uap, this->tag); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Null: { + /* No work. */ +#ifdef EVENTLIB_TIME_CHECKS + func = NULL; +#endif + break; + } + default: { + abort(); + } + } +#ifdef EVENTLIB_TIME_CHECKS + if (ctx->debug > 0) { + interval = evSubTime(evNowTime(), start_time); + /* + * Complain if it took longer than 50 milliseconds. + * + * We call getuid() to make an easy to find mark in a kernel + * trace. + */ + if (interval.tv_sec > 0 || interval.tv_nsec > 50000000) + evPrintf(ctx, 1, + "dispatch interval %u.%09u uid %d type %d func %p\n", + interval.tv_sec, interval.tv_nsec, + getuid(), ev->type, func); + } +#endif + ctx->cur = NULL; + evDrop(opaqueCtx, opaqueEv); + return (0); +} + +void +evDrop(evContext opaqueCtx, evEvent opaqueEv) { + evContext_p *ctx = opaqueCtx.opaque; + evEvent_p *ev = opaqueEv.opaque; + + switch (ev->type) { + case Accept: { + FREE(ev->u.accept.this); + break; + } + case File: { + /* No work. */ + break; + } + case Stream: { + evStreamID id; + + id.opaque = ev->u.stream.this; + (void) evCancelRW(opaqueCtx, id); + break; + } + case Timer: { + evTimer *this = ev->u.timer.this; + evTimerID opaque; + + /* Check to see whether the user func cleared the timer. */ + if (heap_element(ctx->timers, this->index) != this) { + evPrintf(ctx, 5, "Dispatch.Timer: timer rm'd?\n"); + break; + } + /* + * Timer is still there. Delete it if it has expired, + * otherwise set it according to its next interval. + */ + if (this->inter.tv_sec == 0 && this->inter.tv_nsec == 0L) { + opaque.opaque = this; + (void) evClearTimer(opaqueCtx, opaque); + } else { + opaque.opaque = this; + (void) evResetTimer(opaqueCtx, opaque, this->func, + this->uap, + evAddTime(ctx->lastEventTime, + this->inter), + this->inter); + } + break; + } + case Wait: { + FREE(ev->u.wait.this); + break; + } + case Null: { + /* No work. */ + break; + } + default: { + abort(); + } + } + FREE(ev); +} + +int +evMainLoop(evContext opaqueCtx) { + evEvent event; + int x; + + while ((x = evGetNext(opaqueCtx, &event, EV_WAIT)) == 0) + if ((x = evDispatch(opaqueCtx, event)) < 0) + break; + return (x); +} + +int +evHighestFD(evContext opaqueCtx) { + evContext_p *ctx = opaqueCtx.opaque; + + return (ctx->highestFD); +} + +void +evPrintf(const evContext_p *ctx, int level, const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + if (ctx->output != NULL && ctx->debug >= level) { + vfprintf(ctx->output, fmt, ap); + fflush(ctx->output); + } + va_end(ap); +} + +#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.2.3.t5b/contrib/bind/lib/isc/eventlib.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/eventlib_p.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/eventlib_p.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/eventlib_p.h (revision 60942) @@ -0,0 +1,213 @@ +/* + * 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. + */ + +/* eventlib_p.h - private interfaces for eventlib + * vix 09sep95 [initial] + * + * $Id: eventlib_p.h,v 1.28 2000/02/04 08:28:34 vixie Exp $ + */ + +#ifndef _EVENTLIB_P_H +#define _EVENTLIB_P_H + +#include +#include +#include +#include +#include + +#define EVENTLIB_DEBUG 1 + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define EV_MASK_ALL (EV_READ | EV_WRITE | EV_EXCEPT) +#define ERR(e) return (errno = (e), -1) +#define OK(x) if ((x) < 0) ERR(errno); else (void)NULL + +#define NEW(p) if (((p) = memget(sizeof *(p))) != NULL) \ + FILL(p); \ + else \ + (void)NULL; +#define OKNEW(p) if (!((p) = memget(sizeof *(p)))) { \ + errno = ENOMEM; \ + return (-1); \ + } else \ + FILL(p) +#define FREE(p) memput((p), sizeof *(p)) + +#if EVENTLIB_DEBUG +#define FILL(p) memset((p), 0xF5, sizeof *(p)) +#else +#define FILL(p) +#endif + +typedef struct evConn { + evConnFunc func; + void * uap; + int fd; + int flags; +#define EV_CONN_LISTEN 0x0001 /* Connection is a listener. */ +#define EV_CONN_SELECTED 0x0002 /* evSelectFD(conn->file). */ +#define EV_CONN_BLOCK 0x0004 /* Listener fd was blocking. */ + evFileID file; + struct evConn * prev; + struct evConn * next; +} evConn; + +typedef struct evAccept { + int fd; + union { + struct sockaddr sa; + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif + } la; + int lalen; + union { + struct sockaddr sa; + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif + } ra; + int ralen; + int ioErrno; + evConn * conn; + LINK(struct evAccept) link; +} evAccept; + +typedef struct evFile { + evFileFunc func; + void * uap; + int fd; + int eventmask; + int preemptive; + struct evFile * prev; + struct evFile * next; + struct evFile * fdprev; + struct evFile * fdnext; +} evFile; + +typedef struct evStream { + evStreamFunc func; + void * uap; + evFileID file; + evTimerID timer; + int flags; +#define EV_STR_TIMEROK 0x0001 /* IFF timer valid. */ + int fd; + struct iovec * iovOrig; + int iovOrigCount; + struct iovec * iovCur; + int iovCurCount; + int ioTotal; + int ioDone; + int ioErrno; + struct evStream *prevDone, *nextDone; + struct evStream *prev, *next; +} evStream; + +typedef struct evTimer { + evTimerFunc func; + void * uap; + struct timespec due, inter; + int index; +} evTimer; + +typedef struct evWait { + evWaitFunc func; + void * uap; + const void * tag; + struct evWait * next; +} evWait; + +typedef struct evWaitList { + evWait * first; + evWait * last; + struct evWaitList * prev; + struct evWaitList * next; +} evWaitList; + +typedef struct evEvent_p { + enum { Accept, File, Stream, Timer, Wait, Free, Null } type; + union { + struct { evAccept *this; } accept; + struct { evFile *this; int eventmask; } file; + struct { evStream *this; } stream; + struct { evTimer *this; } timer; + struct { evWait *this; } wait; + struct { struct evEvent_p *next; } free; + struct { const void *placeholder; } null; + } u; +} evEvent_p; + +typedef struct { + /* Global. */ + const evEvent_p *cur; + /* Debugging. */ + int debug; + FILE *output; + /* Connections. */ + evConn *conns; + LIST(evAccept) accepts; + /* Files. */ + evFile *files, *fdNext; + fd_set rdLast, rdNext; + fd_set wrLast, wrNext; + fd_set exLast, exNext; + fd_set nonblockBefore; + int fdMax, fdCount, highestFD; + evFile *fdTable[FD_SETSIZE]; +#ifdef EVENTLIB_TIME_CHECKS + struct timespec lastSelectTime; + int lastFdCount; +#endif + /* Streams. */ + evStream *streams; + evStream *strDone, *strLast; + /* Timers. */ + struct timespec lastEventTime; + heap_context timers; + /* Waits. */ + evWaitList *waitLists; + evWaitList waitDone; +} evContext_p; + +/* eventlib.c */ +#define evPrintf __evPrintf +void evPrintf(const evContext_p *ctx, int level, const char *fmt, ...); + +/* ev_timers.c */ +#define evCreateTimers __evCreateTimers +heap_context evCreateTimers(const evContext_p *); +#define evDestroyTimers __evDestroyTimers +void evDestroyTimers(const evContext_p *); + +/* ev_waits.c */ +#define evFreeWait __evFreeWait +evWait *evFreeWait(evContext_p *ctx, evWait *old); + +#endif /*_EVENTLIB_P_H*/ Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/eventlib_p.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/logging.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/logging.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/logging.c (revision 60942) @@ -0,0 +1,700 @@ +/* + * 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: logging.c,v 8.26 2000/04/23 02:19:02 vixie 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 "port_after.h" + +#ifdef VSPRINTF_CHAR +# define VSPRINTF(x) strlen(vsprintf/**/x) +#else +# define VSPRINTF(x) ((size_t)vsprintf x) +#endif + +#include "logging_p.h" + +static const int syslog_priority[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE, + LOG_WARNING, LOG_ERR, LOG_CRIT }; + +static const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + +static char *level_text[] = { "info: ", "notice: ", "warning: ", "error: ", + "critical: " }; + +static void +version_rename(log_channel chan) { + unsigned int ver; + char old_name[PATH_MAX+1]; + char new_name[PATH_MAX+1]; + + ver = chan->out.file.versions; + if (ver < 1) + return; + if (ver > LOG_MAX_VERSIONS) + ver = LOG_MAX_VERSIONS; + /* + * Need to have room for '.nn' (XXX assumes LOG_MAX_VERSIONS < 100) + */ + if (strlen(chan->out.file.name) > (PATH_MAX-3)) + return; + for (ver--; ver > 0; ver--) { + sprintf(old_name, "%s.%d", chan->out.file.name, ver-1); + sprintf(new_name, "%s.%d", chan->out.file.name, ver); + (void)rename(old_name, new_name); + } + sprintf(new_name, "%s.0", chan->out.file.name); + (void)rename(chan->out.file.name, new_name); +} + +FILE * +log_open_stream(log_channel chan) { + FILE *stream; + int fd, flags; + struct stat sb; + int regular; + + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (NULL); + } + + /* + * Don't open already open streams + */ + if (chan->out.file.stream != NULL) + return (chan->out.file.stream); + + if (stat(chan->out.file.name, &sb) < 0) { + if (errno != ENOENT) { + syslog(LOG_ERR, + "log_open_stream: stat of %s failed: %s", + chan->out.file.name, strerror(errno)); + chan->flags |= LOG_CHANNEL_BROKEN; + return (NULL); + } + regular = 1; + } else + regular = (sb.st_mode & S_IFREG); + + if (chan->out.file.versions) { + if (!regular) { + syslog(LOG_ERR, + "log_open_stream: want versions but %s isn't a regular file", + chan->out.file.name); + chan->flags |= LOG_CHANNEL_BROKEN; + errno = EINVAL; + return (NULL); + } + } + + flags = O_WRONLY|O_CREAT|O_APPEND; + + if ((chan->flags & LOG_TRUNCATE) != 0) { + if (regular) { + (void)unlink(chan->out.file.name); + flags |= O_EXCL; + } else { + syslog(LOG_ERR, + "log_open_stream: want truncation but %s isn't a regular file", + chan->out.file.name); + chan->flags |= LOG_CHANNEL_BROKEN; + errno = EINVAL; + return (NULL); + } + } + + fd = open(chan->out.file.name, flags, + S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); + if (fd < 0) { + syslog(LOG_ERR, "log_open_stream: open(%s) failed: %s", + chan->out.file.name, strerror(errno)); + chan->flags |= LOG_CHANNEL_BROKEN; + return (NULL); + } + stream = fdopen(fd, "a"); + if (stream == NULL) { + syslog(LOG_ERR, "log_open_stream: fdopen() failed"); + chan->flags |= LOG_CHANNEL_BROKEN; + return (NULL); + } + (void) fchown(fd, chan->out.file.owner, chan->out.file.group); + + chan->out.file.stream = stream; + return (stream); +} + +int +log_close_stream(log_channel chan) { + FILE *stream; + + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (0); + } + stream = chan->out.file.stream; + chan->out.file.stream = NULL; + if (stream != NULL && fclose(stream) == EOF) + return (-1); + return (0); +} + +FILE * +log_get_stream(log_channel chan) { + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (NULL); + } + return (chan->out.file.stream); +} + +char * +log_get_filename(log_channel chan) { + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (NULL); + } + return (chan->out.file.name); +} + +int +log_check_channel(log_context lc, int level, log_channel chan) { + int debugging, chan_level; + + REQUIRE(lc != NULL); + + debugging = ((lc->flags & LOG_OPTION_DEBUG) != 0); + + /* + * If not debugging, short circuit debugging messages very early. + */ + if (level > 0 && !debugging) + return (0); + + if ((chan->flags & (LOG_CHANNEL_BROKEN|LOG_CHANNEL_OFF)) != 0) + return (0); + + /* Some channels only log when debugging is on. */ + if ((chan->flags & LOG_REQUIRE_DEBUG) && !debugging) + return (0); + + /* Some channels use the global level. */ + if ((chan->flags & LOG_USE_CONTEXT_LEVEL) != 0) { + chan_level = lc->level; + } else + chan_level = chan->level; + + if (level > chan_level) + return (0); + + return (1); +} + +int +log_check(log_context lc, int category, int level) { + log_channel_list lcl; + int debugging; + + REQUIRE(lc != NULL); + + debugging = ((lc->flags & LOG_OPTION_DEBUG) != 0); + + /* + * If not debugging, short circuit debugging messages very early. + */ + if (level > 0 && !debugging) + return (0); + + if (category < 0 || category > lc->num_categories) + category = 0; /* use default */ + lcl = lc->categories[category]; + if (lcl == NULL) { + category = 0; + lcl = lc->categories[0]; + } + + for ( /* nothing */; lcl != NULL; lcl = lcl->next) { + if (log_check_channel(lc, level, lcl->channel)) + return (1); + } + return (0); +} + +void +log_vwrite(log_context lc, int category, int level, const char *format, + va_list args) { + log_channel_list lcl; + int pri, debugging, did_vsprintf = 0; + int original_category; + FILE *stream; + log_channel chan; + struct timeval tv; + struct tm *local_tm; + char *category_name; + char *level_str; + char time_buf[256]; + char level_buf[256]; + + REQUIRE(lc != NULL); + + debugging = (lc->flags & LOG_OPTION_DEBUG); + + /* + * If not debugging, short circuit debugging messages very early. + */ + if (level > 0 && !debugging) + return; + + if (category < 0 || category > lc->num_categories) + category = 0; /* use default */ + original_category = category; + lcl = lc->categories[category]; + if (lcl == NULL) { + category = 0; + lcl = lc->categories[0]; + } + + /* + * Get the current time and format it. + */ + time_buf[0]='\0'; + if (gettimeofday(&tv, NULL) < 0) { + syslog(LOG_INFO, "gettimeofday failed in log_vwrite()"); + } else { +#ifdef HAVE_TIME_R + localtime_r((time_t *)&tv.tv_sec, &local_tm); +#else + local_tm = localtime((time_t *)&tv.tv_sec); +#endif + if (local_tm != NULL) { + sprintf(time_buf, "%02d-%s-%4d %02d:%02d:%02d.%03ld ", + local_tm->tm_mday, months[local_tm->tm_mon], + local_tm->tm_year+1900, local_tm->tm_hour, + local_tm->tm_min, local_tm->tm_sec, + (long)tv.tv_usec/1000); + } + } + + /* + * Make a string representation of the current category and level + */ + + if (lc->category_names != NULL && + lc->category_names[original_category] != NULL) + category_name = lc->category_names[original_category]; + else + category_name = ""; + + if (level >= log_critical) { + if (level >= 0) { + sprintf(level_buf, "debug %d: ", level); + level_str = level_buf; + } else + level_str = level_text[-level-1]; + } else { + sprintf(level_buf, "level %d: ", level); + level_str = level_buf; + } + + /* + * Write the message to channels. + */ + for ( /* nothing */; lcl != NULL; lcl = lcl->next) { + chan = lcl->channel; + + if (!log_check_channel(lc, level, chan)) + continue; + + if (!did_vsprintf) { + if (VSPRINTF((lc->buffer, format, args)) > + LOG_BUFFER_SIZE) { + syslog(LOG_CRIT, + "memory overrun in log_vwrite()"); + exit(1); + } + did_vsprintf = 1; + } + + switch (chan->type) { + case log_syslog: + if (level >= log_critical) + pri = (level >= 0) ? 0 : -level; + else + pri = -log_critical; + syslog(chan->out.facility|syslog_priority[pri], + "%s%s%s%s", + (chan->flags & LOG_TIMESTAMP) ? time_buf : "", + (chan->flags & LOG_PRINT_CATEGORY) ? + category_name : "", + (chan->flags & LOG_PRINT_LEVEL) ? + level_str : "", + lc->buffer); + break; + case log_file: + stream = chan->out.file.stream; + if (stream == NULL) { + stream = log_open_stream(chan); + if (stream == NULL) + break; + } + if (chan->out.file.max_size != ULONG_MAX) { + long pos; + + pos = ftell(stream); + if (pos >= 0 && + (unsigned long)pos > + chan->out.file.max_size) { + /* + * try to roll over the log files, + * ignoring all all return codes + * except the open (we don't want + * to write any more anyway) + */ + log_close_stream(chan); + version_rename(chan); + stream = log_open_stream(chan); + if (stream == NULL) + break; + } + } + fprintf(stream, "%s%s%s%s\n", + (chan->flags & LOG_TIMESTAMP) ? time_buf : "", + (chan->flags & LOG_PRINT_CATEGORY) ? + category_name : "", + (chan->flags & LOG_PRINT_LEVEL) ? + level_str : "", + lc->buffer); + fflush(stream); + break; + case log_null: + break; + default: + syslog(LOG_ERR, + "unknown channel type in log_vwrite()"); + } + } +} + +void +log_write(log_context lc, int category, int level, const char *format, ...) { + va_list args; + + va_start(args, format); + log_vwrite(lc, category, level, format, args); + va_end(args); +} + +/* + * Functions to create, set, or destroy contexts + */ + +int +log_new_context(int num_categories, char **category_names, log_context *lc) { + log_context nlc; + + nlc = memget(sizeof (struct log_context)); + if (nlc == NULL) { + errno = ENOMEM; + return (-1); + } + nlc->num_categories = num_categories; + nlc->category_names = category_names; + nlc->categories = memget(num_categories * sizeof (log_channel_list)); + if (nlc->categories == NULL) { + memput(nlc, sizeof (struct log_context)); + errno = ENOMEM; + return (-1); + } + memset(nlc->categories, '\0', + num_categories * sizeof (log_channel_list)); + nlc->flags = 0U; + nlc->level = 0; + *lc = nlc; + return (0); +} + +void +log_free_context(log_context lc) { + log_channel_list lcl, lcl_next; + log_channel chan; + int i; + + REQUIRE(lc != NULL); + + for (i = 0; i < lc->num_categories; i++) + for (lcl = lc->categories[i]; lcl != NULL; lcl = lcl_next) { + lcl_next = lcl->next; + chan = lcl->channel; + (void)log_free_channel(chan); + memput(lcl, sizeof (struct log_channel_list)); + } + memput(lc->categories, + lc->num_categories * sizeof (log_channel_list)); + memput(lc, sizeof (struct log_context)); +} + +int +log_add_channel(log_context lc, int category, log_channel chan) { + log_channel_list lcl; + + if (lc == NULL || category < 0 || category >= lc->num_categories) { + errno = EINVAL; + return (-1); + } + + lcl = memget(sizeof (struct log_channel_list)); + if (lcl == NULL) { + errno = ENOMEM; + return(-1); + } + lcl->channel = chan; + lcl->next = lc->categories[category]; + lc->categories[category] = lcl; + chan->references++; + return (0); +} + +int +log_remove_channel(log_context lc, int category, log_channel chan) { + log_channel_list lcl, prev_lcl, next_lcl; + int found = 0; + + if (lc == NULL || category < 0 || category >= lc->num_categories) { + errno = EINVAL; + return (-1); + } + + for (prev_lcl = NULL, lcl = lc->categories[category]; + lcl != NULL; + lcl = next_lcl) { + next_lcl = lcl->next; + if (lcl->channel == chan) { + log_free_channel(chan); + if (prev_lcl != NULL) + prev_lcl->next = next_lcl; + else + lc->categories[category] = next_lcl; + memput(lcl, sizeof (struct log_channel_list)); + /* + * We just set found instead of returning because + * the channel might be on the list more than once. + */ + found = 1; + } else + prev_lcl = lcl; + } + if (!found) { + errno = ENOENT; + return (-1); + } + return (0); +} + +int +log_option(log_context lc, int option, int value) { + if (lc == NULL) { + errno = EINVAL; + return (-1); + } + switch (option) { + case LOG_OPTION_DEBUG: + if (value) + lc->flags |= option; + else + lc->flags &= ~option; + break; + case LOG_OPTION_LEVEL: + lc->level = value; + break; + default: + errno = EINVAL; + return (-1); + } + return (0); +} + +int +log_category_is_active(log_context lc, int category) { + if (lc == NULL) { + errno = EINVAL; + return (-1); + } + if (category >= 0 && category < lc->num_categories && + lc->categories[category] != NULL) + return (1); + return (0); +} + +log_channel +log_new_syslog_channel(unsigned int flags, int level, int facility) { + log_channel chan; + + chan = memget(sizeof (struct log_channel)); + if (chan == NULL) { + errno = ENOMEM; + return (NULL); + } + chan->type = log_syslog; + chan->flags = flags; + chan->level = level; + chan->out.facility = facility; + chan->references = 0; + return (chan); +} + +log_channel +log_new_file_channel(unsigned int flags, int level, + char *name, FILE *stream, unsigned int versions, + unsigned long max_size) { + log_channel chan; + + chan = memget(sizeof (struct log_channel)); + if (chan == NULL) { + errno = ENOMEM; + return (NULL); + } + chan->type = log_file; + chan->flags = flags; + chan->level = level; + if (name != NULL) { + size_t len; + + len = strlen(name); + /* + * Quantize length to a multiple of 256. There's space for the + * NUL, since if len is a multiple of 256, the size chosen will + * be the next multiple. + */ + chan->out.file.name_size = ((len / 256) + 1) * 256; + chan->out.file.name = memget(chan->out.file.name_size); + if (chan->out.file.name == NULL) { + memput(chan, sizeof (struct log_channel)); + errno = ENOMEM; + return (NULL); + } + /* This is safe. */ + strcpy(chan->out.file.name, name); + } else { + chan->out.file.name_size = 0; + chan->out.file.name = NULL; + } + chan->out.file.stream = stream; + chan->out.file.versions = versions; + chan->out.file.max_size = max_size; + chan->out.file.owner = getuid(); + chan->out.file.group = getgid(); + chan->references = 0; + return (chan); +} + +int +log_set_file_owner(log_channel chan, uid_t owner, gid_t group) { + if (chan->type != log_file) { + errno = EBADF; + return (-1); + } + chan->out.file.owner = owner; + chan->out.file.group = group; + return (0); +} + +log_channel +log_new_null_channel() { + log_channel chan; + + chan = memget(sizeof (struct log_channel)); + if (chan == NULL) { + errno = ENOMEM; + return (NULL); + } + chan->type = log_null; + chan->flags = LOG_CHANNEL_OFF; + chan->level = log_info; + chan->references = 0; + return (chan); +} + +int +log_inc_references(log_channel chan) { + if (chan == NULL) { + errno = EINVAL; + return (-1); + } + chan->references++; + return (0); +} + +int +log_dec_references(log_channel chan) { + if (chan == NULL || chan->references <= 0) { + errno = EINVAL; + return (-1); + } + chan->references--; + return (0); +} + +log_channel_type +log_get_channel_type(log_channel chan) { + REQUIRE(chan != NULL); + + return (chan->type); +} + +int +log_free_channel(log_channel chan) { + if (chan == NULL || chan->references <= 0) { + errno = EINVAL; + return (-1); + } + chan->references--; + if (chan->references == 0) { + if (chan->type == log_file) { + if ((chan->flags & LOG_CLOSE_STREAM) && + chan->out.file.stream != NULL) + (void)fclose(chan->out.file.stream); + if (chan->out.file.name != NULL) + memput(chan->out.file.name, + chan->out.file.name_size); + } + memput(chan, sizeof (struct log_channel)); + } + return (0); +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/logging.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/logging.mdoc =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/logging.mdoc (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/logging.mdoc (revision 60942) @@ -0,0 +1,1052 @@ +.\" $Id: logging.mdoc,v 8.4 2000/04/23 02:19:02 vixie 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. +.\" +.\" The following six UNCOMMENTED lines are required. +.Dd January 1, 1996 +.\"Os OPERATING_SYSTEM [version/release] +.Os BSD 4 +.\"Dt DOCUMENT_TITLE [section number] [volume] +.Dt LOGGING @SYSCALL_EXT@ +.Sh NAME +.Nm log_open_stream , +.Nm log_close_stream , +.Nm log_get_stream , +.Nm log_get_filename , +.Nm log_vwrite , +.Nm log_write , +.Nm log_new_context , +.Nm log_free_context , +.Nm log_add_channel , +.Nm log_remove_channel , +.Nm log_option , +.Nm log_category_is_active , +.Nm log_new_syslog_channel , +.Nm log_new_file_channel , +.Nm log_set_file_owner , +.Nm log_new_null_channel , +.Nm log_inc_references , +.Nm log_dec_references , +.Nm log_free_channel +.Nd logging system +.Sh SYNOPSIS +.Fd #include +.Ft FILE * +.Fn log_open_stream "log_channel chan" +.Ft int +.Fn log_close_stream "log_channel chan" +.Ft FILE * +.Fn log_get_stream "log_channel chan" +.Ft char * +.Fn log_get_filename "log_channel chan" +.Ft void +.Fn log_vwrite "log_context lc" "int category" "int level" \ + "const char *format" va_list args" +.Ft void +.Fn log_write "log_context lc" "int category" "int level" \ + "const char *format" "..." +.Ft int +.Fn log_check_channel "log_context lc" "int level" "log_channel chan" +.Ft int +.Fn log_check "log_context lc" "int category" "int level" +.Ft int +.Fn log_new_context "int num_categories" "char **category_names" \ + "log_context *lc" +.Ft void +.Fn log_free_context "log_context lc" +.Ft int +.Fn log_add_channel "log_context lc" "int category" "log_channel chan" +.Ft int +.Fn log_remove_channel "log_context lc" "int category" "log_channel chan" +.Ft int +.Fn log_option "log_context lc" "int option" "int value" +.Ft int +.Fn log_category_is_active "log_context lc" "int category" +.Ft log_channel +.Fn log_new_syslog_channel "unsigned int flags" "int level" "int facility" +.Ft log_channel +.Fn log_new_file_channel "unsigned int flags" "int level" \ + "char *name" "FILE *stream" "unsigned int versions" \ + "unsigned long max_size" +.Ft int +.Fn log_set_file_owner "log_channel chan" "uid_t owner" "gid_t group" +.Ft log_channel +.Fn log_new_null_channel "void" +.Ft int +.Fn log_inc_references "log_channel chan" +.Ft int +.Fn log_dec_references "log_channel chan" +.Ft int +.Fn log_free_channel "log_channel chan" +.Sh DESCRIPTION +The +.Sy ISC +.Nm logging library +is flexible logging system which is based upon a set of concepts: +.Nm logging channels , +.Nm categories , +and +.Nm logging contexts . +.Pp +The basic building block is the +.Dq Nm logging channel , +which includes a +.Nm priority +(logging level), which type of logging is to occur, and other +flags and information associated with technical aspects of the logging. +The set of priorities which are supported is shown below, in the section +.Sx Message Priorities . +A priority sets a threshold for message logging; a logging channel will +.Em only +log those messages which are +.Em at least as important +as its priority indicates. (The fact that +.Dq more important +means +.Dq more negative , +under the current scheme, is an implementation detail; if a channel has +a priority of +.Dv log_error , +then it will +.Em not +log messages with the +.Dv log_warning +priority, but it +.Em will +log messages with the +.Dv log_error +or +.Dv log_critical +priority.) +.Pp +The +.Nm logging channel +also has an indication of the type of logging performed. Currently, +the supported +.Nm logging types +include (see also +.Sx Logging Types , +below): +.Bl -tag -width "log_syslog" -compact -offset indent +.It Dv log_syslog +for +.Xr syslog 3 Ns -style +logging +.It Dv log_file +for use of a file +.It Dv log_null +for +.Em no +logging +.El +A new logging channel is created by calling either +.Fn log_new_syslog_channel , +.Fn log_new_file_channel , +or +.Fn log_new_null_channel , +respectively. +When a channel is no longer to be used, it can be freed using +.Fn log_free_channel . +.Pp +Both +.Dv log_syslog +and +.Dv log_file +channel types can include more information; for instance, a +.Dv log_syslog Ns -type +channel allows the specification of a +.Xr syslog 3 Ns -style +.Dq facility , +and a +.Dv log_file Ns -type +channels allows the caller to set a maximum file size and number +of versions. (See +.Fn log_new_syslog_channel +or +.Fn log_new_file_channel , +below.) +Additionally, once a logging channel of type +.Dv log_file +is defined, the functions +.Fn log_open_stream +and +.Fn log_close_stream +can open or close the stream associated with the logging channel's logging +filename. The +.Fn log_get_stream +and +.Fn log_get_filename +functions return the stream or filename, respectively, of such a logging +channel. Also unique to logging channels of type +.Dv log_file +is the +.Fn log_set_file_owner +function, which tells the logging system what user and group ought to own +newly created files (which is only effective if the caller is privileged.) +.Pp +Callers provide +.Dq Nm categories , +determining both the number of such categories and any (optional) names. +Categories are like array indexes in C; if the caller declares +.Dq Va n +categories, then they are considered to run from 0 to +.Va n-1 ; +with this scheme, a category number would be invalid if it were negative or +greater than/equal to +.Va n . +Each category can have its own list of +.Nm logging channels +associated with it; we say that such a channel is +.Dq in +the particular category. +.Sy NOTE: +Individual logging channels can appear in more than one category. +.Pp +A +.Dq Nm logging context +is the set of all +.Nm logging channels +associated with the context's +.Nm categories; +thus, a particular +.Nm category +scheme is associated with a particular +.Nm logging context. +.Sy NOTE: +A logging channel may appear in more than one logging context, and in +multiple categories within each logging context. +.Pp +Use +.Fn log_add_channel +and +.Fn log_remove_channel +to add or remove a logging channel to some category in a logging context. +To see if a given category in a logging context is being used, use the +Boolean test +.Fn log_category_is_active . +.Pp +A +.Nm logging context +can also have a +.Nm priority +(logging level) +and various flags associated with the whole context; in order to alter the +flags or change the priority of a context, use +.Fn log_option . +.Ss Message Priorities +Currently, five +.Nm priorities +(logging levels) are supported (they can also be found in the header file): +.Bd -literal -offset indent +#define log_critical (-5) +#define log_error (-4) +#define log_warning (-3) +#define log_notice (-2) +#define log_info (-1) +.Ed +.Pp +In the current implementation, logging messages which have a level greater +than 0 are considered to be debugging messages. +.Ss Logging Types +The three different +.Nm logging types +currently supported are different values of the enumerated type +.Ft log_output_type +(these are also listed in the header file): +.Bd -literal -offset indent +typedef enum { log_syslog, log_file, log_null } log_output_type; +.Ed +.Ss Logging Channel Flags +There are several flags which can be set on a logging channel; the flags +and their meanings are as follows (they are also found in the header file): +.Bl -tag -width "LOG_USE_CONTEXT_LEVEL " -offset indent +.It Dv LOG_CHANNEL_BROKEN +This is set only when some portion of +.Fn log_open_stream +fails: +.Xr open 2 +or +.Xr fdopen 3 +fail; +.Xr stat 2 +fails in a +.Dq bad +way; versioning or truncation is requested on a non-normal file. +.It Dv LOG_CHANNEL_OFF +This is set for channels opened by +.Fn log_new_null_channel . +.It Dv LOG_CLOSE_STREAM +If this flag is set, then +.Fn log_free_channel +will free a +.No non- Dv NULL +stream of a logging channel which is being +.Xr free 3 Ns -d +(if the logging channel is of type +.Dv log_file , +of course). +.It Dv LOG_PRINT_CATEGORY +If set, +.Fn log_vwrite +will insert the category name, if available, into logging messages which are +logged to channels of type +.Dv log_syslog +or +.Dv log_file . +.It Dv LOG_PRINT_LEVEL +If set, +.Fn log_vwrite +will insert a string identifying the message priority level into the +information logged to channels of type +.Dv log_syslog +or +.Dv log_file . +.It Dv LOG_REQUIRE_DEBUG +Only log debugging messages (i.e., those with a priority greater than zero). +.It Dv LOG_TIMESTAMP +If set, +.Fn log_vwrite +will insert a timestamp into logging messages which are logged to channels of +type +.Dv log_syslog +or +.Dv log_file . +.It Dv LOG_TRUNCATE +Truncate logging file when re-opened ( +.Fn log_open_stream +will +.Xr unlink 2 +the file and then +.Xr open 2 +a new file of the same name with the +.Dv O_EXCL +bit set). +.It Dv LOG_USE_CONTEXT_LEVEL +Use the logging context's priority or logging level, rather than the logging +channel's own priority. This can be useful for those channels which are +included in multiple logging contexts. +.El +.Ss FUNCTION DESCRIPTIONS +The function +.Fn log_open_stream +is for use with channels which log to a file; i.e., logging channels with a +.Va type +field set to +.Dq Dv log_file . +If the logging channel pointed to by +.Dq Fa chan +is valid, it attempts to open (and return) the stream associated with that +channel. If the stream is already opened, then it is returned; otherwise, +.Xr stat 2 +is used to test the filename for the stream. +.Pp +At this point, if the logging file is supposed to have different +.Va versions +(i.e., incremented version numbers; higher numbers indicate older versions +of the logging file). If so, then any existing versions are +.Xr rename 2 Ns -d +to have one version-number higher than previously, and the +.Dq current +filename for the stream is set to the +.Dq \&.0 +form of the name. Next, if the logging file is supposed to be truncated +(i.e., the +.Dv LOG_TRUNCATE +bit of the +.Va flags +field of the logging channel structure is set), then any file with the +.Dq current +filename for the stream is +.X4 unlink 2 Ns -d . +.Sy NOTE: +If the logging file is +.Em not +a regular file, and either of the above operations (version numbering +or truncation) is supposed to take place, a +.Dv NULL +file pointer is returned. +.Pp +Finally, the filename associated with the logging channel is +.Xr open 2 Ns -d +using the appropriate flags and a mode which sets the read/write permissions +for the user, group, and others. The file descriptor returned by +.Xr open 2 +is then passed to +.Xr fopen 3 , +with the append mode set, and the stream returned by this call is stored +in the +.Fa chan +structure and returned. +.Pp +If +.Fn log_open_stream +fails at any point, then the +.Dv LOG_CHANNEL_BROKEN +bit of the +.Va flags +field of the logging channel pointed to by +.Fa chan +is set, a +.Dv NULL +is returned, and +.Va errno +contains pertinent information. +.Pp +The +.Fn log_close_stream +function closes the stream associated with the logging channel pointed to by +.Dq Fa chan +(if +.Fa chan +is valid and the stream exists and can be closed properly by +.Xr fclose 3 ) . +The stream is set to +.Dv NULL +even if the call to +.Xr fclose 3 +fails. +.Pp +The function +.Fn log_get_stream +returns the stream associated with the logging channel pointed to by +.Dq Fa chan , +if it is +.No non- Ns Dv NULL +and specifies a logging channel which has a +.Dv FILE * +or stream associated with it. +.Pp +The +.Fn log_get_filename +function returns the name of the file associated with the logging channel +pointed to by +.Dq Fa chan , +if it is +.No non- Ns Dv NULL +and specifies a logging channel which has a file associated with it. +.Pp +The +.Fn log_vwrite +function performs the actual logging of a message to the various logging +channels of a logging context +.Fa lc . +The message consists of an +.Xr fprint 3 Ns -style +.Fa format +and its associated +.Fa args +(if any); it will be written to all logging channels in the given +.Fa category +which have a priority set to +.Fa level +or any +.Em less important +priority value. If the +.Fa category +is not valid or has no logging channels, then the category defaults to 0. +.Pp +There are a number of conditions under which a call to +.Fn log_vwrite +will not result in actually logging the message: if there is no logging channel +at even the default category (0), or if a given channel is either +.Dq broken +or +.Dq off +(i.e., its flags have +.Dv LOG_CHANNEL_BROKEN +or +.Dv LOG_CHANNEL_OFF +set, respectively), or if the logging channel channel is of type +.Dv log_null . +Additionally, if the logging channel's flag has +.Dv LOG_REQUIRE_DEBUG +set and the message is not a debugging message (i.e., has a level greater +than 0), then it will not be logged. +Finally, if the message's priority is less important than the +channel's logging level (the priority threshold), will not be logged. +.Sy NOTE: +If a logging channel's flag has +.Dv LOG_USE_CONTEXT_LEVEL +set, it will use the logging context's priority, rather than its own. +.Pp +If all of these hurdles are passed, then only +.Dv log_syslog +and +.Dv log_file +channels actually can have logging. For channels which use +.Xr syslog 3 , +the channel's +.Xr syslog 3 +facility is used in conjunction with a potentially modified form of the +message's priority level, since +.Xr syslog 3 +has its own system of priorities +.Pq Pa /usr/include/syslog.h . +All debug messages (priority >= 0) are mapped to +.Xr syslog 3 Ns 's +.Dv LOG_DEBUG +priority, all messages +.Dq more important +than +.Dv log_critical +are mapped to +.Dv LOG_CRIT , +and the priorities corresponding to the ones listed in the section +.Sx Message Priorities +are given the obvious corresponding +.Xr syslog 3 +priority. +.Pp +For +.Dv log_file +type logging channels, if the file size is greater than the maximum file +size, then no logging occurs. (The same thing happens if a +.Dv NULL +stream is encountered and +.Fn log_open_stream +fails to open the channel's stream.) +.Pp +For both logging to normal files and logging via +.Xr syslog 3 , +the value of the flags +.Dv LOG_TIMESTAMP , +.Dv LOG_PRINT_CATEGORY , +and +.Dv LOG_PRINT_LEVEL +are used in determining whether or not these items are included in the logged +information. +.Pp +The +.Fn log_write +function is merely a front-end to a call to +.Fn log_vwrite ; +see the description of that function, above, for more information. +.Pp +.Fn log_check +and +.Fn log_check_channel +are used to see if a contemplated logging call will actually generate any +output, which is useful when creating a log message involves non-trivial +work. +.Fn log_check +will return non-zero if a call to +.Fn log_vwrite +with the given +.Fa category +and +.Fa level +would generate output on any channels, and zero otherwise. +.Fn log_check_channel +will return non-zero if writing to the +.Fa chan +at the given +.Fa level +would generate output. +.Pp +The function +.Fn log_new_context +creates a new +.Nm logging context , +and stores this in the +.Dq Va opaque +field of the argument +.Dq Fa lc , +and opaque structure used internally. This new +.Nm context +will include the +.Dq Fa num_categories +and +.Dq Fa category_names +which are supplied; the latter can be +.Dv NULL . +.Sy NOTE: +Since +.Dq Fa category_names +is used directly, it +.Em must not +be freed by the caller, if it is +.No non- Ns Dv NULL . +The initial logging flags and priority are both set to zero. +.Pp +The +.Fn log_free_context +function is used to free the opaque structure +.Dq Va lc.opaque +and its components. +.Sy NOTE: +The +.Dq Va opaque +field of +.Dq Fa lc +.Em must +be +.No non- Ns Dv NULL . +For each of the various +.Dq categories +(indicated by the +.Dq Va num_categories +which were in the corresponding call to +.Fn log_new_context ) +associated with the given +.Nm logging context , +.Em all +of the +.Nm logging channels +are +.Xr free 3 Ns -d . +The opaque structure itself is then +.Xr free 3 Ns -d , +and +.Dq Va lc.opaque +is set to +.Dv NULL . +.Pp +.Sy NOTE: +The function +.Fn log_free_context +does +.Em not +free the memory associated with +.Fa category_names , +since the logging library did not allocate the memory for it, originally; +it was supplied in the call to +.Fn log_new_context . +.Pp +The function +.Fn log_add_channel +adds the +.Nm logging channel +.Dq Fa chan +to the list of logging channels in the given +.Fa category +of the +.Nm logging context +.Dq Fa lc . +No checking is performed to see whether or not +.Fa chan +is already present in the given +.Fa category , +so multiple instances in a single +.Fa category +can occur (but see +.Fn log_remove_channel , +below). +.Pp +The +.Fn log_remove_channel +function +removes +.Em all +occurrences of the +.Nm logging channel +.Dq Fa chan +from the list of logging channels in the given +.Fa category +of the +.Nm logging context +.Dq Fa lc . +It also attempts to free the channel by calling +.Fn log_free_channel +(see its description, below). +.Pp +The +.Fn log_option +function is used to change the +.Fa option +of the indicated logging context +.Fa lc +to the given +.Fa value . +The +.Fa option +can be either +.Dv LOG_OPTION_LEVEL +or +.Dv LOG_OPTION_DEBUG ; +in the first case, the log context's debugging level is reset to the +indicated level. If the +.Fa option +is +.Dv LOG_OPTION_DEBUG , +then a non-zero +.Fa value +results in setting the debug flag of the logging context, while a zero +.Fa value +means that the debug flag is reset. +.Pp +The +.Fn log_category_is_active +test returns a 1 if the given +.Fa category +of the indicated logging context +.Fa lc +has at least one logging channel, and 0, otherwise. +.Pp +The functions +.Fn log_new_syslog_channel , +.Fn log_new_file_channel , +and +.Fn log_new_null_channel +create a new channel of the type specified (thus, the difference in arguments); +the +.Dq Va type +field of the new +.Dq Ft struct log_channel +is always set to the appropriate value. +.Pp +The +.Fn log_new_syslog_channel +function +.Xr malloc 3 Ns -s +a new +.Ft struct log_channel +of +.Va type +.Dv log_syslog , +i.e., a logging channel which will use +.Xr syslog 3 . +The new structure is filled out with the +.Dq Fa flags , +.Dq Fa level , +and +.Dq Fa facility +which are given; the +.Va references +field is initialized to zero. +See +.Sx Logging Channel Flags +and +.Sx Message Priorities , +above, or the header file for information about acceptable values for +.Dq Fa flags , +and +.Dq Fa level . +The +.Dq Fa facility . +can be any valid +.Xr syslog 3 +facility; see the appropriate system header file or manpage for more +information. +.Pp +.Ft log_channel +.Fn log_new_file_channel "unsigned int flags" "int level" \ + "char *name" "FILE *stream" "unsigned int versions" \ + "unsigned long max_size" +.Pp +.Fn log_new_null_channel +.Pp +The functions +.Fn log_inc_references +and +.Fn log_dec_references +increment or decrements, respectively, the +.Va references +field of the logging channel pointed to by +.Dq Fa chan , +if it is a valid channel (and if the +.Va references +field is strictly positive, in the case of +.Fn log_dec_references ) . +These functions are meant to track changes in the number of different clients +which refer to the given logging channel. +.Pp +The +.Fn log_free_channel +function frees the +field of the logging channel pointed to by +.Dq Fa chan +if there are no more outstanding references to it. If the channel uses a file, +the stream is +.Xr fclose 3 Ns -d +(if the +.Dv LOG_CLOSE_STREAM +flag is set), and the filename, if +.No non- Ns Dv NULL , +is +.Xr free 3 Ns -d +before +.Dq Fa chan +is +.Xr free 3 Ns -d . +.Pp +.\" The following requests should be uncommented and +.\" used where appropriate. This next request is +.\" for sections 2 and 3 function return values only. +.Sh RETURN VALUES +.\" This next request is for sections 1, 6, 7 & 8 only +.Bl -tag -width "log_category_is_active()" +.It Fn log_open_stream +.Dv NULL +is returned under any of several error conditions: +a) if +.Dq Fa chan +is either +.Dv NULL +or a +.No non- Ns Dv log_file +channel +.Pq Va errno No is set to Dv EINVAL ; +b) if either versioning or truncation is requested for a non-normal file +.Pq Va errno No is set to Dv EINVAL ; +c) if any of +.Xr stat 2 , +.Xr open 2 , +or +.Xr fdopen 3 +fails +.Po Va errno +is set by the call which failed +.Pc . +If some value other than +.Dv NULL +is returned, then it is a valid logging stream (either newly-opened or +already-open). +.It Fn log_close_stream +-1 if the stream associated with +.Dq Fa chan +is +.No non- Ns Dv NULL +and the call to +.Xr fclose 3 +fails. +0 if successful or the logging channel pointed to by +.Dq Fa chan +is invalid (i.e., +.Dv NULL +or not a logging channel which has uses a file); in the latter case, +.Va errno +is set to +.Dv EINVAL . +.It Fn log_get_stream +.Dv NULL +under the same conditions as those under which +.Fn log_close_stream , +above, returns 0 (including the setting of +.Va errno ) . +Otherwise, the stream associated with the logging channel is returned. +.It Fn log_get_filename +.Dv NULL +under the same conditions as those under which +.Fn log_close_stream , +above, returns 0 (including the setting of +.Va errno ) . +Otherwise, the name of the file associated with the logging channel is +returned. +.It Fn log_new_context +-1 if +.Xr malloc 3 +fails +.Pq with Va errno No set to Dv ENOMEM . +Otherwise, 0, with +.Dq Va lc->opaque +containing the new structures and information. +.It Fn log_add_channel +-1 if +a) either +.Dq Va lc.opaque +is +.Dv NULL +or +.Fa category +is invalid (negative or greater than or equal to +.Va lcp->num_categories ), with +.Va errno +set to +.Dv EINVAL ; +b) +.Xr malloc 3 +fails +.Pq with Va errno No set to Dv ENOMEM . +Otherwise, 0. +.It Fn log_remove_channel +-1 if +a) either +.Dq Va lc.opaque +is +.Dv NULL +or +.Fa category +is invalid, as under failure condition a) for +.Fn log_add_channel , +above, including the setting of +.Va errno ; +b) no channel numbered +.Fa chan +is found in the logging context indicated by +.Fa lc +.Pq with Va errno No set to Dv ENOENT . +Otherwise, 0. +.It Fn log_option +-1 if +a) +.Dq Va lc.opaque +is +.Dv NULL , +b) +.Fa option +specifies an unknown logging option ; +in either case, +.Va errno +is set to +.Dv EINVAL . +Otherwise, 0. +.It Fn log_category_is_active +-1 if +.Dq Va lc.opaque +is +.Dv NULL +.Pq with Va errno No set to Dv EINVAL ; +1 if the +.Fa category +number is valid and there are logging channels in this +.Fa category +within the indicated logging context; 0 if the +.Fa category +number is invalid or there are no logging channels in this +.Fa category +within the indicated logging context. +.It Fn log_new_syslog_channel +.Dv NULL +if +.Xr malloc 3 +fails +.Pq with Va errno No set to ENOMEM ; +otherwise, a valid +.Dv log_syslog Ns -type +.Ft log_channel . +.It Fn log_new_file_channel +.Dv NULL +if +.Xr malloc 3 +fails +.Pq with Va errno No set to ENOMEM ; +otherwise, a valid +.Dv log_file Ns -type +.Ft log_channel . +.It Fn log_new_null_channel +.Dv NULL +if +.Xr malloc 3 +fails +.Pq with Va errno No set to ENOMEM ; +otherwise, a valid +.Dv log_null Ns -type +.Ft log_channel . +.It Fn log_inc_references +-1 if +.Dq Fa chan +is +.Dv NULL +.Pq with Va errno set to Dv EINVAL . +Otherwise, 0. +.It Fn log_dec_references +-1 if +.Dq Fa chan +is +.Dv NULL +or its +.Va references +field is already <= 0 +.Pq with Va errno set to Dv EINVAL . +Otherwise, 0. +.It Fn log_free_channel +-1 under the same conditions as +.Fn log_dec_references , +above, including the setting of +.Va errno ; +0 otherwise. +.El +.\" .Sh ENVIRONMENT +.Sh FILES +.Bl -tag -width "isc/logging.h" +.It Pa isc/logging.h +include file for logging library +.It Pa syslog.h +.Xr syslog 3 Ns -style +priorities +.El +.\" .Sh EXAMPLES +.\" This next request is for sections 1, 6, 7 & 8 only +.\" (command return values (to shell) and +.\" fprintf/stderr type diagnostics) +.\" .Sh DIAGNOSTICS +.\" The next request is for sections 2 and 3 error +.\" and signal handling only. +.Sh ERRORS +This table shows which functions can return the indicated error in the +.Va errno +variable; see the +.Sx RETURN VALUES +section, above, for more information. +.Bl -tag -width "(any0other0value)0" +.It Dv EINVAL +.Fn log_open_stream , +.Fn log_close_stream , +.Fn log_get_stream , +.Fn log_get_filename , +.Fn log_add_channel , +.Fn log_remove_channel , +.Fn log_option , +.Fn log_category_is_active , +.Fn log_inc_references , +.Fn log_dec_references , +.Fn log_free_channel . +.It Dv ENOENT +.Fn log_remove_channel . +.It Dv ENOMEM +.Fn log_new_context , +.Fn log_add_channel , +.Fn log_new_syslog_channel , +.Fn log_new_file_channel , +.Fn log_new_null_channel . +.It (any other value) +returned via a pass-through of an error code from +.Xr stat 2 , +.Xr open 2 , +or +.Xr fdopen 3 , +which can occur in +.Fn log_open_stream +and functions which call it +.Pq currently, only Fn log_vwrite . +.El +.Pp +Additionally, +.Fn log_vwrite +and +.Fn log_free_context +will fail via +.Fn assert +if +.Dq Va lc.opaque +is +.Dv NULL . +The function +.Fn log_vwrite +can also exit with a critical error logged via +.Xr syslog 3 +indicating a memory overrun +.Sh SEE ALSO +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr syslog 3 . +The HTML documentation includes a file, +.Pa logging.html , +which has more information about this logging system. +.\" .Sh STANDARDS +.\" .Sh HISTORY +.Sh AUTHORS +Bob Halley...TODO +.\" .Sh BUGS Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/logging.mdoc ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/logging_p.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/logging_p.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/logging_p.h (revision 60942) @@ -0,0 +1,60 @@ +/* + * 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 LOGGING_P_H +#define LOGGING_P_H + +typedef struct log_file_desc { + char *name; + size_t name_size; + FILE *stream; + unsigned int versions; + unsigned long max_size; + uid_t owner; + gid_t group; +} log_file_desc; + +typedef union log_output { + int facility; + log_file_desc file; +} log_output; + +struct log_channel { + int level; /* don't log messages > level */ + log_channel_type type; + log_output out; + unsigned int flags; + int references; +}; + +typedef struct log_channel_list { + log_channel channel; + struct log_channel_list *next; +} *log_channel_list; + +#define LOG_BUFFER_SIZE 20480 + +struct log_context { + int num_categories; + char **category_names; + log_channel_list *categories; + int flags; + int level; + char buffer[LOG_BUFFER_SIZE]; +}; + +#endif /* !LOGGING_P_H */ Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/logging_p.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/assertions.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/assertions.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/assertions.c (revision 60942) @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1997,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: assertions.c,v 8.3 1999/01/08 19:25:14 vixie Exp $"; +#endif + +#include "port_before.h" + +#include +#include +#include +#include + +#include + +#include "port_after.h" + +/* + * Forward. + */ + +static void default_assertion_failed(char *, int, assertion_type, char *, int); + +/* + * Public. + */ + +assertion_failure_callback __assertion_failed = default_assertion_failed; + +void +set_assertion_failure_callback(assertion_failure_callback f) { + if (f == NULL) + __assertion_failed = default_assertion_failed; + else + __assertion_failed = f; +} + +char * +assertion_type_to_text(assertion_type type) { + char *result; + + switch (type) { + case assert_require: + result = "REQUIRE"; + break; + case assert_ensure: + result = "ENSURE"; + break; + case assert_insist: + result = "INSIST"; + break; + case assert_invariant: + result = "INVARIANT"; + break; + default: + result = NULL; + } + return (result); +} + +/* + * Private. + */ + +static void +default_assertion_failed(char *file, int line, assertion_type type, char *cond, + int print_errno) +{ + fprintf(stderr, "%s:%d: %s(%s)%s%s failed.\n", + file, line, assertion_type_to_text(type), cond, + (print_errno) ? ": " : "", + (print_errno) ? strerror(errno) : ""); + abort(); + /* NOTREACHED */ +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/assertions.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/assertions.mdoc =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/assertions.mdoc (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/assertions.mdoc (revision 60942) @@ -0,0 +1,134 @@ +.\" $Id: assertions.mdoc,v 8.2 1999/01/08 19:25:15 vixie Exp $ +.\" +.\"Copyright (c) 1997,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 17, 1997 +.Dt ASSERTIONS 3 +.Os ISC +.Sh NAME +.Nm REQUIRE , +.Nm REQUIRE_ERR , +.Nm ENSURE , +.Nm ENSURE_ERR , +.Nm INSIST , +.Nm INSIST_ERR , +.Nm INVARIANT , +.Nm INVARIANT_ERR , +.Nm set_assertion_failure_callback +.Nd assertion system +.Sh SYNOPSIS +.Fd #include +.Fo "typedef void (*assertion_failure_callback)" +.Fa "char *filename" +.Fa "int line" +.Fa "assertion_type type" +.Fa "char *condition" +.Fa "int print_errno" +.Fc +.Fn REQUIRE "int boolean_expression" +.Fn REQUIRE_ERR "int boolean_expression" +.Fn ENSURE "int boolean_expression" +.Fn ENSURE_ERR "int boolean_expression" +.Fn INSIST "int boolean_expression" +.Fn INSIST_ERR "int boolean_expression" +.Fn INVARIANT "int boolean_expression" +.Fn INVARIANT_ERR "int boolean_expression" +.Ft void +.Fn set_assertion_failure_callback "assertion_failure_callback callback" +.Ft char * +.Fn assertion_type_to_text "assertion_type type" +.Sh DESCRIPTION +The +.Fn REQUIRE , +.Fn ENSURE , +.Fn INSIST , +and +.Fn INVARIANT +macros evaluate a boolean expression, and if it is false, they invoke the +current assertion failure callback. The default callback will print a message +to +.Li stderr +describing the failure, and then cause the program to dump core. +If the +.Dq Fn _ERR +variant of the assertion is used, the callback will include +.Fn strerror "errno" +in its message. +.Pp +Each assertion type has an associated +.Li CHECK +macro. If this macro's value is +.Dq 0 +when +.Dq "" +is included, then assertions of that type will not be checked. E.g. + +.Dl #define CHECK_ENSURE 0 + +will disable checking of +.Fn ENSURE +and +.Fn ENSURE_ERR . +The macros +.Li CHECK_ALL +and +.Li CHECK_NONE +may also be used, respectively specifying that either all or none of the +assertion types should be checked. +.Pp +.Fn set_assertion_failure_callback +specifies the function to call when an assertion fails. +.Pp +When an +.li +assertion_failure_callback +is called, the +.Fa filename +and +.Fa line +arguments specify the filename and line number of the failing assertion. +The +.Fa type +is one of: +.Bd -literal -offset indent +assert_require +assert_ensure +assert_insist +assert_invariant +.Ed + +and may be used by the callback to determine the type of the failing +assertion. +.Fa condition +is the literal text of the assertion that failed. +.Fa print_errno +will be non-zero if the callback should print +.Fa strerror "errno" +as part of its output. +.Pp +.Fn assertion_type_to_text +returns a textual representation of +.Fa type . +For example, +.Fn assertion_type_to_text "assert_require" +returns the string +.Dq REQUIRE . +.Sh SEE ALSO +Bertrand Meyer, +.Sy Object-Oriented Software Construction, +2nd edition, Prentice\-Hall, 1997, ISBN 0\-13\-629155\-4, chapter 11. +.Sh AUTHOR +Bob Halley (ISC). Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/assertions.mdoc ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/base64.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/base64.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/base64.c (revision 60942) @@ -0,0 +1,320 @@ +/* + * 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) 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: base64.c,v 8.7 1999/10/13 16:39:33 vixie Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "port_after.h" + +#define Assert(Cond) if (!(Cond)) abort() + +static const char Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +int +b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { + size_t datalength = 0; + u_char input[3]; + u_char output[4]; + size_t i; + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + Assert(output[3] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (datalength); +} + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +b64_pton(src, target, targsize) + char const *src; + u_char *target; + size_t targsize; +{ + int tarindex, state, ch; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = *src++) != '\0') { + if (isspace(ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) /* A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + default: + abort(); + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace(ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace(ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/base64.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/bitncmp.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/bitncmp.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/bitncmp.c (revision 60942) @@ -0,0 +1,66 @@ +/* + * 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: bitncmp.c,v 1.6 1999/01/08 19:25:20 vixie Exp $"; +#endif + +#include "port_before.h" + +#include + +#include + +#include "port_after.h" + +#include + +/* + * int + * bitncmp(l, r, n) + * compare bit masks l and r, for n bits. + * return: + * -1, 1, or 0 in the libc tradition. + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0x11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), June 1996 + */ +int +bitncmp(const void *l, const void *r, int n) { + u_int lb, rb; + int x, b; + + b = n / 8; + x = memcmp(l, r, b); + if (x) + return (x); + + lb = ((u_char *)l)[b]; + rb = ((u_char *)r)[b]; + for (b = n % 8; b > 0; b--) { + if ((lb & 0x80) != (rb & 0x80)) { + if (lb & 0x80) + return (1); + return (-1); + } + lb <<= 1; + rb <<= 1; + } + return (0); +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/bitncmp.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/bitncmp.mdoc =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/bitncmp.mdoc (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/bitncmp.mdoc (revision 60942) @@ -0,0 +1,82 @@ +.\" $Id: bitncmp.mdoc,v 8.2 1999/01/08 19:25:21 vixie Exp $ +.\" +.\"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. +.\" +.Dd June 1, 1996 +.Dt BITNCMP 3 +.Os BSD 4 +.Sh NAME +.Nm bitncmp +.Nd compare bit masks +.Sh SYNOPSIS +.Ft int +.Fn bitncmp "const void *l" "const void *r" "int n" +.Sh DESCRIPTION +The function +.Fn bitncmp +compares the +.Dq Fa n +most-significant bits of the two masks pointed to by +.Dq Fa l +and +.Dq Fa r , +and returns an integer less than, equal to, or greater than 0, according to +whether or not +.Dq Fa l +is lexicographically less than, equal to, or greater than +.Dq Fa r +when taken to be unsigned characters (this behaviour is just like that of +.Xr memcmp 3 ) . +.Pp +.Sy NOTE: +.Fn Bitncmp +assumes +.Sy network byte order ; +this means that the fourth octet of +.Li 192.5.5.240/28 +.Li 0x11110000 . +.Sh RETURN VALUES +.Fn Bitncmp +returns values in the manner of +.Xr memcmp 3 : +.Bd -filled -offset indent ++1 if +.Dq Fa 1 +is greater than +.Dq Fa r ; +.Pp +-1 if +.Dq Fa l +is less than +.Dq Fa r ; +and +.Pp +0 if +.Dq Fa l +is equal to +.Dq Fa r , +.Ed +.Pp +where +.Dq Fa l +and +.Dq Fa r +are both interpreted as strings of unsigned characters (through bit +.Dq Fa n .) +.Sh SEE ALSO +.Xr memcmp 3 . +.Sh AUTHOR +Paul Vixie (ISC). Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/bitncmp.mdoc ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ctl_clnt.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ctl_clnt.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ctl_clnt.c (revision 60942) @@ -0,0 +1,581 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ctl_clnt.c,v 8.14 1999/10/13 16:39:33 vixie 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. + */ + +/* Extern. */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ctl_p.h" + +#include "port_after.h" + +/* Constants. */ + + +/* Macros. */ + +#define donefunc_p(ctx) ((ctx).donefunc != NULL) +#define arpacode_p(line) (isdigit(line[0]) && isdigit(line[1]) && \ + isdigit(line[2])) +#define arpacont_p(line) (line[3] == '-') +#define arpadone_p(line) (line[3] == ' ' || line[3] == '\t' || \ + line[3] == '\r' || line[3] == '\0') + +/* Types. */ + +enum state { + initializing = 0, connecting, connected, destroyed +}; + +struct ctl_tran { + LINK(struct ctl_tran) link; + LINK(struct ctl_tran) wlink; + struct ctl_cctx * ctx; + struct ctl_buf outbuf; + ctl_clntdone donefunc; + void * uap; +}; + +struct ctl_cctx { + enum state state; + evContext ev; + int sock; + ctl_logfunc logger; + ctl_clntdone donefunc; + void * uap; + evConnID coID; + evTimerID tiID; + evFileID rdID; + evStreamID wrID; + struct ctl_buf inbuf; + struct timespec timeout; + LIST(struct ctl_tran) tran; + LIST(struct ctl_tran) wtran; +}; + +/* Forward. */ + +static struct ctl_tran *new_tran(struct ctl_cctx *, ctl_clntdone, void *, int); +static void start_write(struct ctl_cctx *); +static void destroy(struct ctl_cctx *, int); +static void error(struct ctl_cctx *); +static void new_state(struct ctl_cctx *, enum state); +static void conn_done(evContext, void *, int, + const void *, int, + const void *, int); +static void write_done(evContext, void *, int, int); +static void start_read(struct ctl_cctx *); +static void stop_read(struct ctl_cctx *); +static void readable(evContext, void *, int, int); +static void start_timer(struct ctl_cctx *); +static void stop_timer(struct ctl_cctx *); +static void touch_timer(struct ctl_cctx *); +static void timer(evContext, void *, + struct timespec, struct timespec); + +/* Private data. */ + +static const char * const state_names[] = { + "initializing", "connecting", "connected", "destroyed" +}; + +/* Public. */ + +/* + * void + * ctl_client() + * create, condition, and connect to a listener on the control port. + */ +struct ctl_cctx * +ctl_client(evContext lev, const struct sockaddr *cap, size_t cap_len, + const struct sockaddr *sap, size_t sap_len, + ctl_clntdone donefunc, void *uap, + u_int timeout, ctl_logfunc logger) +{ + static const char me[] = "ctl_client"; + static const int on = 1; + struct ctl_cctx *ctx; + + if (logger == NULL) + logger = ctl_logger; + ctx = memget(sizeof *ctx); + if (ctx == NULL) { + (*logger)(ctl_error, "%s: getmem: %s", me, strerror(errno)); + goto fatal; + } + ctx->state = initializing; + ctx->ev = lev; + ctx->logger = logger; + ctx->timeout = evConsTime(timeout, 0); + ctx->donefunc = donefunc; + ctx->uap = uap; + ctx->coID.opaque = NULL; + ctx->tiID.opaque = NULL; + ctx->rdID.opaque = NULL; + ctx->wrID.opaque = NULL; + buffer_init(ctx->inbuf); + INIT_LIST(ctx->tran); + INIT_LIST(ctx->wtran); + ctx->sock = socket(sap->sa_family, SOCK_STREAM, PF_UNSPEC); + if (ctx->sock > evHighestFD(ctx->ev)) { + ctx->sock = -1; + errno = ENOTSOCK; + } + if (ctx->sock < 0) { + (*ctx->logger)(ctl_error, "%s: socket: %s", + me, strerror(errno)); + goto fatal; + } + if (cap != NULL) { + if (setsockopt(ctx->sock, SOL_SOCKET, SO_REUSEADDR, + (char *)&on, sizeof on) != 0) { + (*ctx->logger)(ctl_warning, + "%s: setsockopt(REUSEADDR): %s", + me, strerror(errno)); + } + if (bind(ctx->sock, cap, cap_len) < 0) { + (*ctx->logger)(ctl_error, "%s: bind: %s", me, + strerror(errno)); + goto fatal; + } + } + if (evConnect(lev, ctx->sock, (struct sockaddr *)sap, sap_len, + conn_done, ctx, &ctx->coID) < 0) { + (*ctx->logger)(ctl_error, "%s: evConnect(fd %d): %s", + me, (void *)ctx->sock, strerror(errno)); + fatal: + if (ctx != NULL) { + if (ctx->sock >= 0) + close(ctx->sock); + memput(ctx, sizeof *ctx); + } + return (NULL); + } + new_state(ctx, connecting); + return (ctx); +} + +/* + * void + * ctl_endclient(ctx) + * close a client and release all of its resources. + */ +void +ctl_endclient(struct ctl_cctx *ctx) { + if (ctx->state != destroyed) + destroy(ctx, 0); + memput(ctx, sizeof *ctx); +} + +/* + * int + * ctl_command(ctx, cmd, len, donefunc, uap) + * Queue a transaction, which will begin with sending cmd + * and complete by calling donefunc with the answer. + */ +int +ctl_command(struct ctl_cctx *ctx, const char *cmd, size_t len, + ctl_clntdone donefunc, void *uap) +{ + struct ctl_tran *tran; + char *pc; + int n; + + switch (ctx->state) { + case destroyed: + errno = ENOTCONN; + return (-1); + case connecting: + case connected: + break; + default: + abort(); + } + if (len >= MAX_LINELEN) { + errno = EMSGSIZE; + return (-1); + } + tran = new_tran(ctx, donefunc, uap, 1); + if (tran == NULL) + return (-1); + if (ctl_bufget(&tran->outbuf, ctx->logger) < 0) + return (-1); + memcpy(tran->outbuf.text, cmd, len); + tran->outbuf.used = len; + for (pc = tran->outbuf.text, n = 0; n < tran->outbuf.used; pc++, n++) + if (!isascii(*pc) || !isprint(*pc)) + *pc = '\040'; + start_write(ctx); + return (0); +} + +/* Private. */ + +static struct ctl_tran * +new_tran(struct ctl_cctx *ctx, ctl_clntdone donefunc, void *uap, int w) { + struct ctl_tran *new = memget(sizeof *new); + + if (new == NULL) + return (NULL); + new->ctx = ctx; + buffer_init(new->outbuf); + new->donefunc = donefunc; + new->uap = uap; + APPEND(ctx->tran, new, link); + if (w) + APPEND(ctx->wtran, new, wlink); + else + INIT_LINK(new, wlink); + return (new); +} + +static void +start_write(struct ctl_cctx *ctx) { + static const char me[] = "isc/ctl_clnt::start_write"; + struct ctl_tran *tran; + struct iovec iov[2], *iovp = iov; + + REQUIRE(ctx->state == connecting || ctx->state == connected); + /* If there is a write in progress, don't try to write more yet. */ + if (ctx->wrID.opaque != NULL) + return; + /* If there are no trans, make sure timer is off, and we're done. */ + if (EMPTY(ctx->wtran)) { + if (ctx->tiID.opaque != NULL) + stop_timer(ctx); + return; + } + /* Pull it off the head of the write queue. */ + tran = HEAD(ctx->wtran); + UNLINK(ctx->wtran, tran, wlink); + /* Since there are some trans, make sure timer is successfully "on". */ + if (ctx->tiID.opaque != NULL) + touch_timer(ctx); + else + start_timer(ctx); + if (ctx->state == destroyed) + return; + /* Marshall a newline-terminated message and clock it out. */ + *iovp++ = evConsIovec(tran->outbuf.text, tran->outbuf.used); + *iovp++ = evConsIovec("\r\n", 2); + if (evWrite(ctx->ev, ctx->sock, iov, iovp - iov, + write_done, tran, &ctx->wrID) < 0) { + (*ctx->logger)(ctl_error, "%s: evWrite: %s", me, + strerror(errno)); + error(ctx); + return; + } + if (evTimeRW(ctx->ev, ctx->wrID, ctx->tiID) < 0) { + (*ctx->logger)(ctl_error, "%s: evTimeRW: %s", me, + strerror(errno)); + error(ctx); + return; + } +} + +static void +destroy(struct ctl_cctx *ctx, int notify) { + struct ctl_tran *this, *next; + + if (ctx->sock != -1) { + (void) close(ctx->sock); + ctx->sock = -1; + } + switch (ctx->state) { + case connecting: + REQUIRE(ctx->wrID.opaque == NULL); + REQUIRE(EMPTY(ctx->tran)); + /* + * This test is nec'y since destroy() can be called from + * start_read() while the state is still "connecting". + */ + if (ctx->coID.opaque != NULL) { + (void)evCancelConn(ctx->ev, ctx->coID); + ctx->coID.opaque = NULL; + } + break; + case connected: + REQUIRE(ctx->coID.opaque == NULL); + if (ctx->wrID.opaque != NULL) { + (void)evCancelRW(ctx->ev, ctx->wrID); + ctx->wrID.opaque = NULL; + } + if (ctx->rdID.opaque != NULL) + stop_read(ctx); + break; + case destroyed: + break; + default: + abort(); + } + if (allocated_p(ctx->inbuf)) + ctl_bufput(&ctx->inbuf); + for (this = HEAD(ctx->tran); this != NULL; this = next) { + next = NEXT(this, link); + if (allocated_p(this->outbuf)) + ctl_bufput(&this->outbuf); + if (notify && this->donefunc != NULL) + (*this->donefunc)(ctx, this->uap, NULL, 0); + memput(this, sizeof *this); + } + if (ctx->tiID.opaque != NULL) + stop_timer(ctx); + new_state(ctx, destroyed); +} + +static void +error(struct ctl_cctx *ctx) { + REQUIRE(ctx->state != destroyed); + destroy(ctx, 1); +} + +static void +new_state(struct ctl_cctx *ctx, enum state new_state) { + static const char me[] = "isc/ctl_clnt::new_state"; + + (*ctx->logger)(ctl_debug, "%s: %s -> %s", me, + state_names[ctx->state], state_names[new_state]); + ctx->state = new_state; +} + +static void +conn_done(evContext ev, void *uap, int fd, + const void *la, int lalen, + const void *ra, int ralen) +{ + static const char me[] = "isc/ctl_clnt::conn_done"; + struct ctl_cctx *ctx = uap; + struct ctl_tran *tran; + + ctx->coID.opaque = NULL; + if (fd < 0) { + (*ctx->logger)(ctl_error, "%s: evConnect: %s", me, + strerror(errno)); + error(ctx); + return; + } + new_state(ctx, connected); + tran = new_tran(ctx, ctx->donefunc, ctx->uap, 0); + if (tran == NULL) { + (*ctx->logger)(ctl_error, "%s: new_tran failed: %s", me, + strerror(errno)); + error(ctx); + return; + } + start_read(ctx); + if (ctx->state == destroyed) { + (*ctx->logger)(ctl_error, "%s: start_read failed: %s", + me, strerror(errno)); + error(ctx); + return; + } +} + +static void +write_done(evContext lev, void *uap, int fd, int bytes) { + struct ctl_tran *tran = (struct ctl_tran *)uap; + struct ctl_cctx *ctx = tran->ctx; + + ctx->wrID.opaque = NULL; + if (ctx->tiID.opaque != NULL) + touch_timer(ctx); + ctl_bufput(&tran->outbuf); + start_write(ctx); + if (bytes < 0) + destroy(ctx, 1); + else + start_read(ctx); +} + +static void +start_read(struct ctl_cctx *ctx) { + static const char me[] = "isc/ctl_clnt::start_read"; + + REQUIRE(ctx->state == connecting || ctx->state == connected); + REQUIRE(ctx->rdID.opaque == NULL); + if (evSelectFD(ctx->ev, ctx->sock, EV_READ, readable, ctx, + &ctx->rdID) < 0) + { + (*ctx->logger)(ctl_error, "%s: evSelect(fd %d): %s", me, + ctx->sock, strerror(errno)); + error(ctx); + return; + } +} + +static void +stop_read(struct ctl_cctx *ctx) { + REQUIRE(ctx->coID.opaque == NULL); + REQUIRE(ctx->rdID.opaque != NULL); + (void)evDeselectFD(ctx->ev, ctx->rdID); + ctx->rdID.opaque = NULL; +} + +static void +readable(evContext ev, void *uap, int fd, int evmask) { + static const char me[] = "isc/ctl_clnt::readable"; + struct ctl_cctx *ctx = uap; + struct ctl_tran *tran; + ssize_t n; + char *eos; + + REQUIRE(ctx != NULL); + REQUIRE(fd >= 0); + REQUIRE(evmask == EV_READ); + REQUIRE(ctx->state == connected); + REQUIRE(!EMPTY(ctx->tran)); + tran = HEAD(ctx->tran); + if (!allocated_p(ctx->inbuf) && + ctl_bufget(&ctx->inbuf, ctx->logger) < 0) { + (*ctx->logger)(ctl_error, "%s: can't get an input buffer", me); + error(ctx); + return; + } + n = read(ctx->sock, ctx->inbuf.text + ctx->inbuf.used, + MAX_LINELEN - ctx->inbuf.used); + if (n <= 0) { + (*ctx->logger)(ctl_warning, "%s: read: %s", me, + (n == 0) ? "Unexpected EOF" : strerror(errno)); + error(ctx); + return; + } + if (ctx->tiID.opaque != NULL) + touch_timer(ctx); + ctx->inbuf.used += n; + (*ctx->logger)(ctl_debug, "%s: read %d, used %d", me, + n, ctx->inbuf.used); + again: + eos = memchr(ctx->inbuf.text, '\n', ctx->inbuf.used); + if (eos != NULL && eos != ctx->inbuf.text && eos[-1] == '\r') { + int done = 0; + + eos[-1] = '\0'; + if (!arpacode_p(ctx->inbuf.text)) { + /* XXX Doesn't FTP do this sometimes? Is it legal? */ + (*ctx->logger)(ctl_error, "%s: no arpa code (%s)", me, + ctx->inbuf.text); + error(ctx); + return; + } + if (arpadone_p(ctx->inbuf.text)) + done = 1; + else if (arpacont_p(ctx->inbuf.text)) + done = 0; + else { + /* XXX Doesn't FTP do this sometimes? Is it legal? */ + (*ctx->logger)(ctl_error, "%s: no arpa flag (%s)", me, + ctx->inbuf.text); + error(ctx); + return; + } + (*tran->donefunc)(ctx, tran->uap, ctx->inbuf.text, + (done ? 0 : CTL_MORE)); + ctx->inbuf.used -= ((eos - ctx->inbuf.text) + 1); + if (ctx->inbuf.used == 0) + ctl_bufput(&ctx->inbuf); + else + memmove(ctx->inbuf.text, eos + 1, ctx->inbuf.used); + if (done) { + UNLINK(ctx->tran, tran, link); + memput(tran, sizeof *tran); + stop_read(ctx); + start_write(ctx); + return; + } + if (allocated_p(ctx->inbuf)) + goto again; + return; + } + if (ctx->inbuf.used == MAX_LINELEN) { + (*ctx->logger)(ctl_error, "%s: line too long (%-10s...)", me, + ctx->inbuf.text); + error(ctx); + } +} + +/* Timer related stuff. */ + +static void +start_timer(struct ctl_cctx *ctx) { + static const char me[] = "isc/ctl_clnt::start_timer"; + + REQUIRE(ctx->tiID.opaque == NULL); + if (evSetIdleTimer(ctx->ev, timer, ctx, ctx->timeout, &ctx->tiID) < 0){ + (*ctx->logger)(ctl_error, "%s: evSetIdleTimer: %s", me, + strerror(errno)); + error(ctx); + return; + } +} + +static void +stop_timer(struct ctl_cctx *ctx) { + static const char me[] = "isc/ctl_clnt::stop_timer"; + + REQUIRE(ctx->tiID.opaque != NULL); + if (evClearIdleTimer(ctx->ev, ctx->tiID) < 0) { + (*ctx->logger)(ctl_error, "%s: evClearIdleTimer: %s", me, + strerror(errno)); + error(ctx); + return; + } + ctx->tiID.opaque = NULL; +} + +static void +touch_timer(struct ctl_cctx *ctx) { + REQUIRE(ctx->tiID.opaque != NULL); + + evTouchIdleTimer(ctx->ev, ctx->tiID); +} + +static void +timer(evContext ev, void *uap, struct timespec due, struct timespec itv) { + static const char me[] = "isc/ctl_clnt::timer"; + struct ctl_cctx *ctx = uap; + + ctx->tiID.opaque = NULL; + (*ctx->logger)(ctl_error, "%s: timeout after %u seconds while %s", me, + ctx->timeout.tv_sec, state_names[ctx->state]); + error(ctx); +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ctl_clnt.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ctl_p.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ctl_p.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ctl_p.h (revision 60942) @@ -0,0 +1,22 @@ +struct ctl_buf { + char * text; + size_t used; +}; + +#define MAX_LINELEN 990 /* Like SMTP. */ +#define MAX_NTOP (sizeof "[255.255.255.255].65535") + +#define allocated_p(Buf) ((Buf).text != NULL) +#define buffer_init(Buf) ((Buf).text = 0, (Buf.used) = 0) + +#define ctl_bufget __ctl_bufget +#define ctl_bufput __ctl_bufput +#define ctl_sa_ntop __ctl_sa_ntop +#define ctl_sa_copy __ctl_sa_copy + +int ctl_bufget(struct ctl_buf *, ctl_logfunc); +void ctl_bufput(struct ctl_buf *); +const char * ctl_sa_ntop(const struct sockaddr *, char *, size_t, + ctl_logfunc); +void ctl_sa_copy(const struct sockaddr *, + struct sockaddr *); Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ctl_p.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_files.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_files.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_files.c (revision 60942) @@ -0,0 +1,272 @@ +/* + * 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. + */ + +/* ev_files.c - implement asynch file IO for the eventlib + * vix 11sep95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_files.c,v 1.19 1999/10/07 20:44:04 vixie Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include +#include + +#include +#include +#include + +#include +#include "eventlib_p.h" + +#include "port_after.h" + +static evFile *FindFD(const evContext_p *ctx, int fd, int eventmask); + +int +evSelectFD(evContext opaqueCtx, + int fd, + int eventmask, + evFileFunc func, + void *uap, + evFileID *opaqueID +) { + evContext_p *ctx = opaqueCtx.opaque; + evFile *id; + int mode; + + evPrintf(ctx, 1, + "evSelectFD(ctx %#x, fd %d, mask 0x%x, func %#x, uap %#x)\n", + ctx, fd, eventmask, func, uap); + if (eventmask == 0 || (eventmask & ~EV_MASK_ALL) != 0) + ERR(EINVAL); + if (fd > ctx->highestFD) + ERR(EINVAL); + OK(mode = fcntl(fd, F_GETFL, NULL)); /* side effect: validate fd. */ + + /* + * The first time we touch a file descriptor, we need to check to see + * if the application already had it in O_NONBLOCK mode and if so, all + * of our deselect()'s have to leave it in O_NONBLOCK. If not, then + * all but our last deselect() has to leave it in O_NONBLOCK. + */ + id = FindFD(ctx, fd, EV_MASK_ALL); + if (id == NULL) { + if (mode & PORT_NONBLOCK) + FD_SET(fd, &ctx->nonblockBefore); + else { + OK(fcntl(fd, F_SETFL, mode | PORT_NONBLOCK)); + FD_CLR(fd, &ctx->nonblockBefore); + } + } + + /* + * If this descriptor is already in use, search for it again to see + * if any of the eventmask bits we want to set are already captured. + * We cannot usefully capture the same fd event more than once in the + * same context. + */ + if (id != NULL && FindFD(ctx, fd, eventmask) != NULL) + ERR(ETOOMANYREFS); + + /* Allocate and fill. */ + OKNEW(id); + id->func = func; + id->uap = uap; + id->fd = fd; + id->eventmask = eventmask; + + /* + * Insert at head. Order could be important for performance if we + * believe that evGetNext()'s accesses to the fd_sets will be more + * serial and therefore more cache-lucky if the list is ordered by + * ``fd.'' We do not believe these things, so we don't do it. + * + * The interesting sequence is where GetNext() has cached a select() + * result and the caller decides to evSelectFD() on some descriptor. + * Since GetNext() starts at the head, it can miss new entries we add + * at the head. This is not a serious problem since the event being + * evSelectFD()'d for has to occur before evSelectFD() is called for + * the file event to be considered "missed" -- a real corner case. + * Maintaining a "tail" pointer for ctx->files would fix this, but I'm + * not sure it would be ``more correct.'' + */ + if (ctx->files != NULL) + ctx->files->prev = id; + id->prev = NULL; + id->next = ctx->files; + ctx->files = id; + + /* Insert into fd table. */ + if (ctx->fdTable[fd] != NULL) + ctx->fdTable[fd]->fdprev = id; + id->fdprev = NULL; + id->fdnext = ctx->fdTable[fd]; + ctx->fdTable[fd] = id; + + /* Turn on the appropriate bits in the {rd,wr,ex}Next fd_set's. */ + if (eventmask & EV_READ) + FD_SET(fd, &ctx->rdNext); + if (eventmask & EV_WRITE) + FD_SET(fd, &ctx->wrNext); + if (eventmask & EV_EXCEPT) + FD_SET(fd, &ctx->exNext); + + /* Update fdMax. */ + if (fd > ctx->fdMax) + ctx->fdMax = fd; + + /* Remember the ID if the caller provided us a place for it. */ + if (opaqueID) + opaqueID->opaque = id; + + evPrintf(ctx, 5, + "evSelectFD(fd %d, mask 0x%x): new masks: 0x%lx 0x%lx 0x%lx\n", + fd, eventmask, + (u_long)ctx->rdNext.fds_bits[0], + (u_long)ctx->wrNext.fds_bits[0], + (u_long)ctx->exNext.fds_bits[0]); + + return (0); +} + +int +evDeselectFD(evContext opaqueCtx, evFileID opaqueID) { + evContext_p *ctx = opaqueCtx.opaque; + evFile *del = opaqueID.opaque; + evFile *cur; + int mode, eventmask; + + if (!del) { + evPrintf(ctx, 11, "evDeselectFD(NULL) ignored\n"); + errno = EINVAL; + return (-1); + } + + evPrintf(ctx, 1, "evDeselectFD(fd %d, mask 0x%x)\n", + del->fd, del->eventmask); + + /* Get the mode. Unless the file has been closed, errors are bad. */ + mode = fcntl(del->fd, F_GETFL, NULL); + if (mode == -1 && errno != EBADF) + ERR(errno); + + /* Remove from the list of files. */ + if (del->prev != NULL) + del->prev->next = del->next; + else + ctx->files = del->next; + if (del->next != NULL) + del->next->prev = del->prev; + + /* Remove from the fd table. */ + if (del->fdprev != NULL) + del->fdprev->fdnext = del->fdnext; + else + ctx->fdTable[del->fd] = del->fdnext; + if (del->fdnext != NULL) + del->fdnext->fdprev = del->fdprev; + + /* + * If the file descriptor does not appear in any other select() entry, + * and if !EV_WASNONBLOCK, and if we got no EBADF when we got the mode + * earlier, then: restore the fd to blocking status. + */ + if (!(cur = FindFD(ctx, del->fd, EV_MASK_ALL)) && + !FD_ISSET(del->fd, &ctx->nonblockBefore) && + mode != -1) { + /* + * Note that we won't return an error status to the caller if + * this fcntl() fails since (a) we've already done the work + * and (b) the caller didn't ask us anything about O_NONBLOCK. + */ + (void) fcntl(del->fd, F_SETFL, mode & ~PORT_NONBLOCK); + } + + /* + * Now find all other uses of this descriptor and OR together an event + * mask so that we don't turn off {rd,wr,ex}Next bits that some other + * file event is using. As an optimization, stop if the event mask + * fills. + */ + eventmask = 0; + for ((void)NULL; + cur != NULL && eventmask != EV_MASK_ALL; + cur = cur->next) + if (cur->fd == del->fd) + eventmask |= cur->eventmask; + + /* OK, now we know which bits we can clear out. */ + if (!(eventmask & EV_READ)) { + FD_CLR(del->fd, &ctx->rdNext); + if (FD_ISSET(del->fd, &ctx->rdLast)) { + FD_CLR(del->fd, &ctx->rdLast); + ctx->fdCount--; + } + } + if (!(eventmask & EV_WRITE)) { + FD_CLR(del->fd, &ctx->wrNext); + if (FD_ISSET(del->fd, &ctx->wrLast)) { + FD_CLR(del->fd, &ctx->wrLast); + ctx->fdCount--; + } + } + if (!(eventmask & EV_EXCEPT)) { + FD_CLR(del->fd, &ctx->exNext); + if (FD_ISSET(del->fd, &ctx->exLast)) { + FD_CLR(del->fd, &ctx->exLast); + ctx->fdCount--; + } + } + + /* If this was the maxFD, find the new one. */ + if (del->fd == ctx->fdMax) { + ctx->fdMax = -1; + for (cur = ctx->files; cur; cur = cur->next) + if (cur->fd > ctx->fdMax) + ctx->fdMax = cur->fd; + } + + /* If this was the fdNext, cycle that to the next entry. */ + if (del == ctx->fdNext) + ctx->fdNext = del->next; + + evPrintf(ctx, 5, + "evDeselectFD(fd %d, mask 0x%x): new masks: 0x%lx 0x%lx 0x%lx\n", + del->fd, eventmask, + (u_long)ctx->rdNext.fds_bits[0], + (u_long)ctx->wrNext.fds_bits[0], + (u_long)ctx->exNext.fds_bits[0]); + + /* Couldn't free it before now since we were using fields out of it. */ + FREE(del); + + return (0); +} + +static evFile * +FindFD(const evContext_p *ctx, int fd, int eventmask) { + evFile *id; + + for (id = ctx->fdTable[fd]; id != NULL; id = id->fdnext) + if (id->fd == fd && (id->eventmask & eventmask) != 0) + break; + return (id); +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_files.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_streams.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_streams.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_streams.c (revision 60942) @@ -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. + */ + +/* ev_streams.c - implement asynch stream file IO for the eventlib + * vix 04mar96 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_streams.c,v 8.21 1999/10/07 20:44:04 vixie Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include +#include + +#include + +#include +#include +#include "eventlib_p.h" + +#include "port_after.h" + +static int copyvec(evStream *str, const struct iovec *iov, int iocnt); +static void consume(evStream *str, size_t bytes); +static void done(evContext opaqueCtx, evStream *str); +static void writable(evContext opaqueCtx, void *uap, int fd, int evmask); +static void readable(evContext opaqueCtx, void *uap, int fd, int evmask); + +struct iovec +evConsIovec(void *buf, size_t cnt) { + struct iovec ret; + + memset(&ret, 0xf5, sizeof ret); + ret.iov_base = buf; + ret.iov_len = cnt; + return (ret); +} + +int +evWrite(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt, + evStreamFunc func, void *uap, evStreamID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evStream *new; + int save; + + OKNEW(new); + new->func = func; + new->uap = uap; + new->fd = fd; + new->flags = 0; + if (evSelectFD(opaqueCtx, fd, EV_WRITE, writable, new, &new->file) < 0) + goto free; + if (copyvec(new, iov, iocnt) < 0) + goto free; + new->prevDone = NULL; + new->nextDone = NULL; + if (ctx->streams != NULL) + ctx->streams->prev = new; + new->prev = NULL; + new->next = ctx->streams; + ctx->streams = new; + if (id != NULL) + id->opaque = new; + return (0); + free: + save = errno; + FREE(new); + errno = save; + return (-1); +} + +int +evRead(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt, + evStreamFunc func, void *uap, evStreamID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evStream *new; + int save; + + OKNEW(new); + new->func = func; + new->uap = uap; + new->fd = fd; + new->flags = 0; + if (evSelectFD(opaqueCtx, fd, EV_READ, readable, new, &new->file) < 0) + goto free; + if (copyvec(new, iov, iocnt) < 0) + goto free; + new->prevDone = NULL; + new->nextDone = NULL; + if (ctx->streams != NULL) + ctx->streams->prev = new; + new->prev = NULL; + new->next = ctx->streams; + ctx->streams = new; + if (id) + id->opaque = new; + return (0); + free: + save = errno; + FREE(new); + errno = save; + return (-1); +} + +int +evTimeRW(evContext opaqueCtx, evStreamID id, evTimerID timer) /*ARGSUSED*/ { + evStream *str = id.opaque; + + str->timer = timer; + str->flags |= EV_STR_TIMEROK; + return (0); +} + +int +evUntimeRW(evContext opaqueCtx, evStreamID id) /*ARGSUSED*/ { + evStream *str = id.opaque; + + str->flags &= ~EV_STR_TIMEROK; + return (0); +} + +int +evCancelRW(evContext opaqueCtx, evStreamID id) { + evContext_p *ctx = opaqueCtx.opaque; + evStream *old = id.opaque; + + /* + * The streams list is doubly threaded. First, there's ctx->streams + * that's used by evDestroy() to find and cancel all streams. Second, + * there's ctx->strDone (head) and ctx->strLast (tail) which thread + * through the potentially smaller number of "IO completed" streams, + * used in evGetNext() to avoid scanning the entire list. + */ + + /* Unlink from ctx->streams. */ + if (old->prev != NULL) + old->prev->next = old->next; + else + ctx->streams = old->next; + if (old->next != NULL) + old->next->prev = old->prev; + + /* + * If 'old' is on the ctx->strDone list, remove it. Update + * ctx->strLast if necessary. + */ + if (old->prevDone == NULL && old->nextDone == NULL) { + /* + * Either 'old' is the only item on the done list, or it's + * not on the done list. If the former, then we unlink it + * from the list. If the latter, we leave the list alone. + */ + if (ctx->strDone == old) { + ctx->strDone = NULL; + ctx->strLast = NULL; + } + } else { + if (old->prevDone != NULL) + old->prevDone->nextDone = old->nextDone; + else + ctx->strDone = old->nextDone; + if (old->nextDone != NULL) + old->nextDone->prevDone = old->prevDone; + else + ctx->strLast = old->prevDone; + } + + /* Deallocate the stream. */ + if (old->file.opaque) + evDeselectFD(opaqueCtx, old->file); + memput(old->iovOrig, sizeof (struct iovec) * old->iovOrigCount); + FREE(old); + return (0); +} + +/* Copy a scatter/gather vector and initialize a stream handler's IO. */ +static int +copyvec(evStream *str, const struct iovec *iov, int iocnt) { + int i; + + str->iovOrig = (struct iovec *)memget(sizeof(struct iovec) * iocnt); + if (str->iovOrig == NULL) { + errno = ENOMEM; + return (-1); + } + str->ioTotal = 0; + for (i = 0; i < iocnt; i++) { + str->iovOrig[i] = iov[i]; + str->ioTotal += iov[i].iov_len; + } + str->iovOrigCount = iocnt; + str->iovCur = str->iovOrig; + str->iovCurCount = str->iovOrigCount; + str->ioDone = 0; + return (0); +} + +/* Pull off or truncate lead iovec(s). */ +static void +consume(evStream *str, size_t bytes) { + while (bytes > 0) { + if (bytes < str->iovCur->iov_len) { + str->iovCur->iov_len -= bytes; + str->iovCur->iov_base = (void *) + ((u_char *)str->iovCur->iov_base + bytes); + str->ioDone += bytes; + bytes = 0; + } else { + bytes -= str->iovCur->iov_len; + str->ioDone += str->iovCur->iov_len; + str->iovCur++; + str->iovCurCount--; + } + } +} + +/* Add a stream to Done list and deselect the FD. */ +static void +done(evContext opaqueCtx, evStream *str) { + evContext_p *ctx = opaqueCtx.opaque; + + if (ctx->strLast != NULL) { + str->prevDone = ctx->strLast; + ctx->strLast->nextDone = str; + ctx->strLast = str; + } else { + INSIST(ctx->strDone == NULL); + ctx->strDone = ctx->strLast = str; + } + evDeselectFD(opaqueCtx, str->file); + str->file.opaque = NULL; + /* evDrop() will call evCancelRW() on us. */ +} + +/* Dribble out some bytes on the stream. (Called by evDispatch().) */ +static void +writable(evContext opaqueCtx, void *uap, int fd, int evmask) { + evStream *str = uap; + int bytes; + + bytes = writev(fd, str->iovCur, str->iovCurCount); + if (bytes > 0) { + if ((str->flags & EV_STR_TIMEROK) != 0) + evTouchIdleTimer(opaqueCtx, str->timer); + consume(str, bytes); + } else { + if (bytes < 0 && errno != EINTR) { + str->ioDone = -1; + str->ioErrno = errno; + } + } + if (str->ioDone == -1 || str->ioDone == str->ioTotal) + done(opaqueCtx, str); +} + +/* Scoop up some bytes from the stream. (Called by evDispatch().) */ +static void +readable(evContext opaqueCtx, void *uap, int fd, int evmask) { + evStream *str = uap; + int bytes; + + bytes = readv(fd, str->iovCur, str->iovCurCount); + if (bytes > 0) { + if ((str->flags & EV_STR_TIMEROK) != 0) + evTouchIdleTimer(opaqueCtx, str->timer); + consume(str, bytes); + } else { + if (bytes == 0) + str->ioDone = 0; + else { + if (errno != EINTR) { + str->ioDone = -1; + str->ioErrno = errno; + } + } + } + if (str->ioDone <= 0 || str->ioDone == str->ioTotal) + done(opaqueCtx, str); +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_streams.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_timers.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_timers.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_timers.c (revision 60942) @@ -0,0 +1,404 @@ +/* + * 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. + */ + +/* ev_timers.c - implement timers for the eventlib + * vix 09sep95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_timers.c,v 1.25 1999/10/07 20:44:04 vixie Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include + +#include +#include "eventlib_p.h" + +#include "port_after.h" + +/* Constants. */ + +#define BILLION 1000000000 + +/* Forward. */ + +static int due_sooner(void *, void *); +static void set_index(void *, int); +static void free_timer(void *, void *); +static void print_timer(void *, void *); +static void idle_timeout(evContext, void *, struct timespec, struct timespec); + +/* Private type. */ + +typedef struct { + evTimerFunc func; + void * uap; + struct timespec lastTouched; + struct timespec max_idle; + evTimer * timer; +} idle_timer; + +/* Public. */ + +struct timespec +evConsTime(time_t sec, long nsec) { + struct timespec x; + + x.tv_sec = sec; + x.tv_nsec = nsec; + return (x); +} + +struct timespec +evAddTime(struct timespec addend1, struct timespec addend2) { + struct timespec x; + + x.tv_sec = addend1.tv_sec + addend2.tv_sec; + x.tv_nsec = addend1.tv_nsec + addend2.tv_nsec; + if (x.tv_nsec >= BILLION) { + x.tv_sec++; + x.tv_nsec -= BILLION; + } + return (x); +} + +struct timespec +evSubTime(struct timespec minuend, struct timespec subtrahend) { + struct timespec x; + + x.tv_sec = minuend.tv_sec - subtrahend.tv_sec; + if (minuend.tv_nsec >= subtrahend.tv_nsec) + x.tv_nsec = minuend.tv_nsec - subtrahend.tv_nsec; + else { + x.tv_nsec = BILLION - subtrahend.tv_nsec + minuend.tv_nsec; + x.tv_sec--; + } + return (x); +} + +int +evCmpTime(struct timespec a, struct timespec b) { + long x = a.tv_sec - b.tv_sec; + + if (x == 0L) + x = a.tv_nsec - b.tv_nsec; + return (x < 0L ? (-1) : x > 0L ? (1) : (0)); +} + +struct timespec +evNowTime() { + struct timeval now; + + if (gettimeofday(&now, NULL) < 0) + return (evConsTime(0, 0)); + return (evTimeSpec(now)); +} + +struct timespec +evLastEventTime(evContext opaqueCtx) { + evContext_p *ctx = opaqueCtx.opaque; + + return (ctx->lastEventTime); +} + +struct timespec +evTimeSpec(struct timeval tv) { + struct timespec ts; + + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + return (ts); +} + +struct timeval +evTimeVal(struct timespec ts) { + struct timeval tv; + + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000; + return (tv); +} + +int +evSetTimer(evContext opaqueCtx, + evTimerFunc func, + void *uap, + struct timespec due, + struct timespec inter, + evTimerID *opaqueID +) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *id; + + evPrintf(ctx, 1, +"evSetTimer(ctx %#x, func %#x, uap %#x, due %d.%09ld, inter %d.%09ld)\n", + ctx, func, uap, + due.tv_sec, due.tv_nsec, + inter.tv_sec, inter.tv_nsec); + + /* due={0,0} is a magic cookie meaning "now." */ + if (due.tv_sec == 0 && due.tv_nsec == 0L) + due = evNowTime(); + + /* Allocate and fill. */ + OKNEW(id); + id->func = func; + id->uap = uap; + id->due = due; + id->inter = inter; + + if (heap_insert(ctx->timers, id) < 0) + return (-1); + + /* Remember the ID if the caller provided us a place for it. */ + if (opaqueID) + opaqueID->opaque = id; + + if (ctx->debug > 7) { + evPrintf(ctx, 7, "timers after evSetTimer:\n"); + (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); + } + + return (0); +} + +int +evClearTimer(evContext opaqueCtx, evTimerID id) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *del = id.opaque; + + if (ctx->cur != NULL && + ctx->cur->type == Timer && + ctx->cur->u.timer.this == del) { + evPrintf(ctx, 8, "deferring delete of timer (executing)\n"); + /* + * Setting the interval to zero ensures that evDrop() will + * clean up the timer. + */ + del->inter = evConsTime(0, 0); + return (0); + } + + if (heap_element(ctx->timers, del->index) != del) + ERR(ENOENT); + + if (heap_delete(ctx->timers, del->index) < 0) + return (-1); + FREE(del); + + if (ctx->debug > 7) { + evPrintf(ctx, 7, "timers after evClearTimer:\n"); + (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); + } + + return (0); +} + +int +evResetTimer(evContext opaqueCtx, + evTimerID id, + evTimerFunc func, + void *uap, + struct timespec due, + struct timespec inter +) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *timer = id.opaque; + struct timespec old_due; + int result=0; + + if (heap_element(ctx->timers, timer->index) != timer) + ERR(ENOENT); + + old_due = timer->due; + + timer->func = func; + timer->uap = uap; + timer->due = due; + timer->inter = inter; + + switch (evCmpTime(due, old_due)) { + case -1: + result = heap_increased(ctx->timers, timer->index); + break; + case 0: + result = 0; + break; + case 1: + result = heap_decreased(ctx->timers, timer->index); + break; + } + + if (ctx->debug > 7) { + evPrintf(ctx, 7, "timers after evResetTimer:\n"); + (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); + } + + return (result); +} + +int +evSetIdleTimer(evContext opaqueCtx, + evTimerFunc func, + void *uap, + struct timespec max_idle, + evTimerID *opaqueID +) { + evContext_p *ctx = opaqueCtx.opaque; + idle_timer *tt; + + /* Allocate and fill. */ + OKNEW(tt); + tt->func = func; + tt->uap = uap; + tt->lastTouched = ctx->lastEventTime; + tt->max_idle = max_idle; + + if (evSetTimer(opaqueCtx, idle_timeout, tt, + evAddTime(ctx->lastEventTime, max_idle), + max_idle, opaqueID) < 0) { + FREE(tt); + return (-1); + } + + tt->timer = opaqueID->opaque; + + return (0); +} + +int +evClearIdleTimer(evContext opaqueCtx, evTimerID id) { + evTimer *del = id.opaque; + idle_timer *tt = del->uap; + + FREE(tt); + return (evClearTimer(opaqueCtx, id)); +} + +int +evResetIdleTimer(evContext opaqueCtx, + evTimerID opaqueID, + evTimerFunc func, + void *uap, + struct timespec max_idle +) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *timer = opaqueID.opaque; + idle_timer *tt = timer->uap; + + tt->func = func; + tt->uap = uap; + tt->lastTouched = ctx->lastEventTime; + tt->max_idle = max_idle; + + return (evResetTimer(opaqueCtx, opaqueID, idle_timeout, tt, + evAddTime(ctx->lastEventTime, max_idle), + max_idle)); +} + +int +evTouchIdleTimer(evContext opaqueCtx, evTimerID id) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *t = id.opaque; + idle_timer *tt = t->uap; + + tt->lastTouched = ctx->lastEventTime; + + return (0); +} + +/* Public to the rest of eventlib. */ + +heap_context +evCreateTimers(const evContext_p *ctx) { + return (heap_new(due_sooner, set_index, 2048)); +} + +void +evDestroyTimers(const evContext_p *ctx) { + (void) heap_for_each(ctx->timers, free_timer, NULL); + (void) heap_free(ctx->timers); +} + +/* Private. */ + +static int +due_sooner(void *a, void *b) { + evTimer *a_timer, *b_timer; + + a_timer = a; + b_timer = b; + return (evCmpTime(a_timer->due, b_timer->due) < 0); +} + +static void +set_index(void *what, int index) { + evTimer *timer; + + timer = what; + timer->index = index; +} + +static void +free_timer(void *what, void *uap) { + evTimer *t = what; + FREE(t); +} + +static void +print_timer(void *what, void *uap) { + evTimer *cur = what; + evContext_p *ctx = uap; + + cur = what; + evPrintf(ctx, 7, + " func %p, uap %p, due %d.%09ld, inter %d.%09ld\n", + cur->func, cur->uap, + cur->due.tv_sec, cur->due.tv_nsec, + cur->inter.tv_sec, cur->inter.tv_nsec); +} + +static void +idle_timeout(evContext opaqueCtx, + void *uap, + struct timespec due, + struct timespec inter +) { + evContext_p *ctx = opaqueCtx.opaque; + idle_timer *this = uap; + struct timespec idle; + + idle = evSubTime(ctx->lastEventTime, this->lastTouched); + if (evCmpTime(idle, this->max_idle) >= 0) { + (this->func)(opaqueCtx, this->uap, this->timer->due, + this->max_idle); + /* + * Setting the interval to zero will cause the timer to + * be cleaned up in evDrop(). + */ + this->timer->inter = evConsTime(0, 0); + FREE(this); + } else { + /* evDrop() will reschedule the timer. */ + this->timer->inter = evSubTime(this->max_idle, idle); + } +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/ev_timers.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/eventlib.mdoc =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/eventlib.mdoc (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/eventlib.mdoc (revision 60942) @@ -0,0 +1,854 @@ +.\" $Id: eventlib.mdoc,v 1.20 1999/08/18 22:09:04 vixie 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 March 6, 1996 +.Dt EVENTLIB 3 +.Os BSD 4 +.Sh NAME +.Nm evConnFunc , +.Nm evFileFunc , +.Nm evStreamFunc , +.Nm evTimerFunc , +.Nm evWaitFunc , +.Nm evCreate , +.Nm evDestroy , +.Nm evGetNext , +.Nm evDispatch , +.Nm evDrop , +.Nm evMainLoop , +.Nm evConsTime , +.Nm evTimeSpec , +.Nm evTimeVal , +.Nm evAddTime , +.Nm evSubTime , +.Nm evCmpTime , +.Nm evNowTime , +.Nm evLastEventTime , +.Nm evSetTimer , +.Nm evResetTimer , +.Nm evClearTimer , +.Nm evSetIdleTimer , +.Nm evTouchIdleTimer , +.Nm evClearIdleTimer , +.Nm evWaitFor , +.Nm evDo , +.Nm evUnwait , +.Nm evDefer , +.Nm evSelectFD , +.Nm evDeselectFD , +.Nm evWrite , +.Nm evRead , +.Nm evCancelRW , +.Nm evTimeRW , +.Nm evUntimeRW , +.Nm evListen , +.Nm evConnect , +.Nm evCancelConn , +.Nm evHold , +.Nm evUnhold , +.Nm evTryAccept , +.Nm evConsIovec , +.Nm evSetDebug , +.Nm evPrintf , +.Nm evInitID , +.Nm evTestID +.Nd event handling library +.Sh SYNOPSIS +.Fd #include +.Ft typedef void +.Fn (*evConnFunc) "evContext ctx" "void *uap" "int fd" \ +"const void *la" "int lalen" "const void *ra" "int ralen" +.Ft typedef void +.Fn (*evTimerFunc) "evContext ctx" "void *uap" \ +"struct timespec due" "struct timespec inter" +.Ft typedef void +.Fn (*evFileFunc) "evContext ctx" "void *uap" "int fd" "int eventmask" +.Ft typedef void +.Fn (*evStreamFunc) "evContext ctx" "void *uap" "int fd" "int bytes" +.Ft typedef void +.Fn (*evWaitFunc) "evContext ctx" "void *uap" "const void *tag" +.Ft int +.Fn evCreate "evContext *ctx" +.Ft int +.Fn evDestroy "evContext ctx" +.Ft int +.Fn evGetNext "evContext ctx" "evEvent *ev" "int options" +.Ft int +.Fn evDispatch "evContext ctx" "evEvent ev" +.Ft void +.Fn evDrop "evContext ctx" "evEvent ev" +.Ft int +.Fn evMainLoop "evContext ctx" +.Ft struct timespec +.Fn evConsTime "int sec" "int usec" +.Ft struct timespec +.Fn evTimeSpec "struct timeval tv" +.Ft struct timeval +.Fn evTimeVal "struct timespec ts" +.Ft struct timespec +.Fn evAddTime "struct timespec addend1" "struct timespec addend2" +.Ft struct timespec +.Fn evSubTime "struct timespec minuend" "struct timespec subtrahend" +.Ft struct timespec +.Fn evCmpTime "struct timespec a" "struct timespec b" +.Ft struct timespec +.Fn evNowTime "void" +.Ft struct timespec +.Fn evLastEventTime "evContext opaqueCtx" +.Ft int +.Fn evSetTimer "evContext ctx" "evTimerFunc func" "void *uap" \ +"struct timespec due" "struct timespec inter" "evTimerID *id" +.Ft int +.Fn evResetTimer "evContext ctx" "evTimerID id" "evTimerFunc func" \ +"void *uap" "struct timespec due" "struct timespec inter" +.Ft int +.Fn evClearTimer "evContext ctx" "evTimerID id" +.Ft int +.Fn evSetIdleTimer "evContext opaqueCtx" "evTimerFunc func" "void *uap" \ +"struct timespec max_idle" "evTimerID *opaqueID" +.Ft int +.Fn evTouchIdleTimer "evContext opaqueCtx" "evTimerID id" +.Ft int +.Fn evResetIdleTimer "evContext opaqueCtx" "evTimerID id" "evTimerFunc func" \ +"void *uap" "struct timespec max_idle" +.Ft int +.Fn evClearIdleTimer "evContext opaqueCtx" "evTimerID id" +.Ft int +.Fn evWaitFor "evContext opaqueCtx" "const void *tag" \ +"evWaitFunc func" "void *uap" "evWaitID *id" +.Ft int +.Fn evDo "evContext opaqueCtx" "const void *tag" +.Ft int +.Fn evUnwait "evContext opaqueCtx" "evWaitID id" +.Ft int +.Fn evDefer "evContext opaqueCtx" "evWaitFunc func" "void *uap" +.Ft int +.Fn evSelectFD "evContext ctx" "int fd" "int eventmask" \ +"evFileFunc func" "void *uap" "evFileID *id" +.Ft int +.Fn evDeselectFD "evContext ctx" "evFileID id" +.Ft struct iovec +.Fn evConsIovec "void *buf" "size_t cnt" +.Ft int +.Fn evWrite "evContext ctx" "int fd" "const struct iovec *iov" "int cnt" \ +"evStreamFunc func" "void *uap" "evStreamID *id" +.Ft int +.Fn evRead "evContext ctx" "int fd" "const struct iovec *iov" "int cnt" \ +"evStreamFunc func" "void *uap" "evStreamID *id" +.Ft int +.Fn evCancelRW "evContext ctx" "evStreamID id" +.Ft int +.Fn evTimeRW "evContext opaqueCtx" "evStreamID id" "evTimerID timer" +.Ft int +.Fn evUntimeRW "evContext opaqueCtx" "evStreamID id" +.Ft int +.Fn evListen "evContext ctx" "int fd" "int maxconn" \ +"evConnFunc func" "void *uap" "evConnID *id" +.Ft int +.Fn evConnect "evContext ctx" "int fd" "void *ra" "int ralen" \ +"evConnFunc func" "void *uap" "evConnID *id" +.Ft int +.Fn evCancelConn "evContext ctx" "evConnID id" +.Ft int +.Fn evHold "evContext ctx" "evConnID id" +.Ft int +.Fn evUnhold "evContext ctx" "evConnID id" +.Ft int +.Fn evTryAccept "evContext ctx" "evConnID id" "int *sys_errno" +.Ft void +.Fn evSetDebug "evContext ctx" "int level" "FILE *output" +.Ft void +.Fn evPrintf "const evContext_p *ctx" "int level" "const char *fmt" "..." +.Ft void +.Fn evInitID "*\s-1ID\s+1" +.Ft int +.Fn evTestID "\s-1ID\s+1" +.Sh DESCRIPTION +This library provides multiple outstanding asynchronous timers and I/O +to a cooperating application. The model is similar to that of the X +Toolkit, in that events are registered with the library and the application +spends most of its time in the +.Fn evMainLoop +function. If an application already has a main loop, it can safely register +events with this library as long as it periodically calls the +.Fn evGetNext +and +.Fn evDispatch +functions. (Note that +.Fn evGetNext +has both polling and blocking modes.) +.Pp +The function +.Fn evCreate +creates an event context which is needed by all the other functions in this +library. All information used internally by this library is bound to this +context, rather than to static storage. This makes the library +.Dq thread safe, +and permits other library functions to use events without +disrupting the application's use of events. +.Pp +The function +.Fn evDestroy +destroys a context that has been created by +.Fn evCreate . +All dynamic memory bound to this context will be freed. An implicit +.Fn evTimerClear +will be done on all timers set in this event context. An implicit +.Fn evDeselectFD +will be done on all file descriptors selected in this event context. +.Pp +The function +.Fn evGetNext +potentially waits for and then retrieves the next asynchronous event, +placing it in the object of the +.Fa ev +pointer argument. The following +.Fa options +are available: +.Fa EV_POLL , +meaning that +.Fn evGetNext +should not block, but rather return +.Dq Fa -1 +with +.Fa errno +set to +.Fa EWOULDBLOCK +if no events have occurred; +.Fa EV_WAIT , +which tells +.Fn evGetNext +to block internally until the next event occurs; and +.Fa EV_NULL , +which tells +.Fn evGetNext +that it should return a special +.Dq no-op +event, which is ignored by +.Fn evDispatch +but handled correctly by +.Fn evDrop . +.Fa EV_NULL +can be necessary to the correct functioning of a caller\-written equivilent to +.Fn evMainLoop , +wherein perterbations caused by external system events must be polled for, and +the default behaviour of internally ignoring such events is undesirable. +Note that +.Fa EV_POLL +and +.Fa EV_WAIT +are mutually exclusive. +.Pp +The function +.Fn evDispatch +dispatches an event retrieved by +.Fn evGetNext . +This usually involves calling the function that was associated with the event +when the event was registered with +.Fn evSetTimer , +.Fn evResetTimer , +or +.Fn evSelectFD . +All events retrieved by +.Fn evGetNext +must be given over to +.Fn evDispatch +at some point, since there is some dynamic memory associated with each event. +.Pp +The function +.Fn evDrop +deallocates dynamic memory that has been allocated by +.Fn evGetNext . +Calling +.Fn evDispatch +has the side effect of calling +.Fn evDrop , +but if you are going to drop the event rather than dispatch it, you will have +to call +.Fn evDrop +directly. +.Pp +The function +.Fn evMainLoop +is just: +.Bd -literal -offset indent +while ((x = evGetNext(opaqueCtx, &event, EV_WAIT)) == 0) + if ((x = evDispatch(opaqueCtx, event)) < 0) + break; +return (x); +.Ed +.Pp +In other words, get events and dispatch them until an error occurs. One such +error would be that all the events under this context become unregistered; in +that event, there will be nothing to wait for and +.Fn evGetNext +becomes an undefined operation. +.Pp +The function +.Fn evConsTime +is a constructor for +.Dq Fa struct timespec +which allows these structures to be created and then passed as arguments to +other functions without the use of temporary variables. (If C had inline +constructors, there would be no need for this function.) +.Pp +The functions +.Fn evTimeSpec +and +.Fn evTimeVal +are utilities which allow the caller to convert a +.Dq Fa struct timeval +to a +.Dq Fa struct timespec +(the function of +.Fn evTimeSpec ) +or vice versa (the function of +.Fn evTimeVal ) . +Note that the name of the function indicates the type of the return value. +.Pp +The function +.Fn evAddTime +adds two +.Dq Fa struct timespec +values and returns the result as a +.Dq Fa struct timespec. +.Pp +The function +.Fn evSubTime +subtracts its second +.Dq Fa struct timespec +argument from its first +.Dq Fa struct timespec +argument and returns the result as a +.Dq Fa struct timespec. +.Pp +The function +.Fn evCmpTime +compares its two +.Dq Fa struct timespec +arguments and returns an +.Dq Fa int +that is less than zero if the first argument specifies an earlier time than +the second, or more than zero if the first argument specifies a later time +than the second, or equal to zero if both arguments specify the same time. +.Pp +The function +.Fn evNowTime +returns a +.Dq Fa struct timespec +which either describes the current time (using +.Xr gettimeofday 2 ) , +if successful, or has its fields set to zero, if there is an error. +(In the latter case, the caller can check +.Va errno , +since it will be set by +.Xr gettimeofday 2 . ) +.Pp +The function +.Fn evLastEventTime +returns the +.Dq Fa struct timespec +which describes the last time that certain events happened to the +event context indicated by +.Fa opaqueCtx . +This value is updated by +.Fn evCreate +and +.Fn evGetNext +(upon entry and after +.Xr select 2 +returns); it is routinely compared with other times in the internal handling +of, e.g., timers. +.Pp +The function +.Fn evSetTimer +registers a timer event, which will be delivered as a function call to the +function specified by the +.Fa func +argument. The event will be delivered at absolute time +.Fa due , +and then if time +.Fa inter +is not equal to +.Dq Fa evConsTime(0,0) , +subsequently at intervals equal to time +.Fa inter . +As a special case, specifying a +.Fa due +argument equal to +.Dq Fa evConsTime(0,0) +means +.Dq due immediately. +The +.Fa opaqueID +argument, if specified as a value other than +.Fa NULL , +will be used to store the resulting +.Dq timer \s-1ID\s+1 , +useful as an argument to +.Fn evClearTimer . +Note that in a +.Dq one\-shot +timer (which has an +.Fa inter +argument equal to +.Dq Fa evConsTime(0,0) +.\" putting the ) after the Dq Fa arg did not work well. --vix +) the user function +.Fa func +should deallocate any dynamic memory that is uniquely bound to the +.Fa uap , +since no handles to this memory will exist within the event library +after a one\-shot timer has been delivered. +.Pp +The function +.Fn evResetTimer +resets the values of the timer specified by +.Fa id +to the given arguments. The arguments are the same as in the description of +.Fn evSetTimer +above. +.Pp +The function +.Fn evClearTimer +will unregister the timer event specified by +.Fa id . +Note that if the +.Fa uap +specified in the corresponding +.Fn evSetTimer +call is uniquely bound to any dynamic memory, then that dynamic memory should +be freed by the caller before the handle is lost. After a call to +.Fn evClearTimer , +no handles to this +.Fa uap +will exist within the event library. +.Pp +The function +.Fn evSetIdleTimer +is similar to (and built on) +.Fn evSetTimer ; +it registers an idle timer event which provides for the function call to +.Fa func +to occur. However, for an +.Em idle +timer, the call will occur after at least +.Dq Fa max_idle +time has passed since the time the idle timer was +.Dq last touched ; +originally, this is set to the time returned by +.Fn evLastEventTime +(described above) for the event context specified by +.Fa opaqueCtx . +This is a +.Dq one\-shot +timer, but the time at which the +.Fa func +is actually called can be changed by recourse to +.Fn evTouchIdleTimer +(described below). The pointer to the underlying +.Dq timer \s-1ID\s+1 +is returned in +.Fa opaqueID , +if it is +.No non- Ns Dv NULL . +.Pp +The +.Fn evTouchIdleTimer +function updates the idle timer associated with +.Fa id , +setting its idea of the time it was last accessed to the value returned by +.Fn evLastEventTime +(described above) for the event context specified by +.Fa opaqueCtx . +This means that the idle timer will expire after at least +.Fa max_idle +time has passed since this (possibly new) time, providing a caller mechanism +for resetting the call to the +.Fa func +associated with the idle timer. (See the description of +.Fn evSetIdleTimer , +above, for information about +.Fa func +and +.Fa max_idle . ) +.Pp +The +.Fn evResetIdleTimer +function reschedules a timer and resets the callback function and its argument. +Note that resetting a timer also ``touches'' it. +.Pp +The +.Fn evClearIdleTimer +function unregisters the idle timer associated with +.Fa id . +See the discussion under +.Fn evClearTimer , +above, for information regarding caller handling of the +.Fa uap +associated with the corresponding +.Fn evSetIdleTimer +call. +.Pp +The function +.Fn evWaitFor +places the function +.Fa func +on the given event context's wait queue with the associated (possibly +.Dv NULL ) +.Dq Fa tag ; +if +.Fa id +is +.No non- Ns Dv NULL , +then it will contain the +.Dq wait \s-1ID\s+1 +associated with the created queue element. +.Pp +The function +.Fn evDo +marks +.Em all +of the +.Dq waiting +functions in the given event context's wait queue with the associated (possibly +.Dv NULL ) +.Dq Fa tag +as runnable. This places these functions in a +.Dq done +queue which will be read by +.Fn evGetNext . +.Pp +The function +.Fn evUnwait +will search for the +.Dq wait \s-1ID\s+1 +.Fa id +in the wait queue of the given event context; if an element with the given +.Fa id +is not found, then the +.Dq done +queue of that context is searched. If found, the queue element is removed +from the appropriate list. +.Pp +The function +.Fn evDefer +causes a function (specified as +.Fa func , +with argument +.Fa uap ) +to be dispatched at some later time. Note that the +.Fa tag +argument to +.Fa func +will always be +.Fa NULL +when dispatched. +.Pp +The function +.Fn evSelectFD +registers a file I/O event for the file descriptor specified by +.Fa fd . +Bits in the +.Fa eventmask +argument are named +.Fa EV_READ , +.Fa EV_WRITE , +and +.Fa EV_EXCEPT . +At least one of these bits must be specified. If the +.Fa id +argument is not equal to +.Fa NULL , +it will be used to store a unique ``file event \s-1ID\s+1'' for this event, +which is useful in subsequent calls to +.Fn evDeselectFD . +A file descriptor will be made nonblocking using the +.Fa O_NONBLOCK +flag with +.Xr fcntl 2 +on its first concurrent registration via +.Fn evSelectFD . +An +.Fn evSelectFD +remains in effect until cancelled via +.Fn evDeselectFD . +.Pp +The function +.Fn evDeselectFD +unregisters the ``file event'' specified by the +.Fa id +argument. If the corresponding +.Fa uap +uniquely points to dynamic memory, that memory should be freed before its +handle is lost, since after a call to +.Fn evDeselectFD , +no handles to this event's +.Fa uap +will remain within the event library. A file descriptor will be taken out of +nonblocking mode (see +.Fa O_NONBLOCK +and +.Xr fcntl 2 ) +when its last event registration is removed via +.Fn evDeselectFD , +if it was in blocking mode before the first registration via +.Fn evSelectFD . +.Pp +The function +.Fn evConsIovec +is a constructor for a single +.Ft struct iovec +structure, which is useful for +.Fn evWrite +and +.Fn evRead . +.Pp +The functions +.Fn evWrite +and +.Fn evRead +start asynchronous stream I/O operations on file descriptor +.Fa fd . +The data to be written or read is in the scatter/gather descriptor specified by +.Fa iov +and +.Fa cnt . +The supplied function +.Fa func +will be called with argument +.Fa uap +when the I/O operation is complete. If +.Fa id +is not +.Fa NULL , +it will be filled a with the stream event identifier suitable for use with +.Fn evCancelRW . +.Pp +The function +.Fn evCancelRW +extinguishes an outstanding +.Fn evWrite +or +.Fn evRead +call. System I/O calls cannot always be cancelled, but you are guaranteed +that the +.Fa func +function supplied to +.Fn evWrite +or +.Fn evRead +will not be called after a call to +.Fn evCancelRW . +Care should be taken not to deallocate or otherwise reuse the space pointed +to by the segment descriptors in +.Fa iov +unless the underlying file descriptor is closed first. +.Pp +The function +.Fn evTimeRW +sets the stream associated with the given stream \s-1ID\s+1 +.Dq Fa id +to have the idle timer associated with the timer \s-1ID\s+1 +.Dq Fa timer . +.Pp +The function +.Fn evUntimeRW +says that the stream associated with the given stream \s-1ID\s+1 +.Dq Fa id +should ignore its idle timer, if present. +.Pp +The functions +.Fn evListen , +.Fn evConnect , +and +.Fn evCancelConn +can be used to manage asynchronous incoming and outgoing socket connections. +Sockets to be used with these functions should first be created with +.Xr socket 2 +and given a local name with +.Xr bind 2 . +It is extremely unlikely that the same socket will ever be +useful for both incoming and outgoing connections. The +.Fa id +argument to +.Fn evListen +and +.Fn evConnect +is either +.Fa NULL +or the address of a +.Ft evFileID +variable which can then be used in a subsequent call to +.Fn evCancelConn . +.Pp +After a call to +.Fn evListen , +each incoming connection arriving on +.Fa fd +will cause +.Fa func +to be called with +.Fa uap +as one of its arguments. +.Fn evConnect +initiates an outgoing connection on +.Fa fd +to destination address +.Fa ra +(whose length is +.Fa ralen ). +When the connection is complete, +.Fa func +will be called with +.Fa uap +as one of its arguments. The argument +.Fa fd +to +.Fn (*func)() +will be +.Fa -1 +if an error occurred that prevented this connection from completing +successfully. In this case +.Fn errno +will have been set and the socket described by +.Fa fd +will have been closed. The +.Fn evCancelConn +function will prevent delivery of all pending and subsequent +events for the outstanding connection. The +.Fn evHold +function will suspend the acceptance of new connections on the listener +specified by +.Fa id . +Connections will be queued by the protocol stack up to the system's limit. The +.Fn evUnhold +function will reverse the effects of +.Fn evHold , +allowing incoming connections to be delivered for listener +.Fa id . +The +.Fn evTryAccept +function will poll the listener specified by +.Fa id , +accepting a new connection if one is available, and queuing a connection event +for later retrieval by +.Fn evGetNext . +If the connection event queued is an accept error(), sys_errno will contain +the error code; otherwise it will be zero. All connection events queued by +.Fn evTryAccept +will be delivered by +.Fn evGetNext +before a new select is done on the listener. +.Pp +The function +.Fn evSetDebug +sets the debugging +.Fa level +and diagnostic +.Fa output +file handle for an event context. Greater numeric levels will +result in more verbose output being sent to the output FILE during program +execution. +.Pp +The function +.Fn evPrintf +prints a message with the format +.Dq Fa fmt +and the following arguments (if any), on the output stream associated +with the event context pointed to by +.Fa ctx . +The message is output if the event context's debug level is greater than +or equal to the indicated +.Fa level . +.Pp +The function +.Fn evInitID +will initialize an opaque +.Dq evConn \s-1ID\s+1 , +.Dq evFile \s-1ID\s+1 , +.Dq evStream \s-1ID\s+1 , +.Dq evTimer \s-1ID\s+1 , +.Dq evWait \s-1ID\s+1 , +.Dq evContext , +or +.Dq evEvent , +which is passed by reference. +.Pp +The function +.Fn evTestID +will examine an opaque \s-1ID\s+1 and return +.Dq TRUE +only if it is not in its initialized state. +.Sh RETURN VALUES +All the functions whose return type is +.Dq Fa int +use the standard convention of returning zero (0) to indicate success, or +returning +.Dq Fa -1 +and setting +.Fa errno +to indicate failure. +.Sh FILE +.Pa heap.h , +which is in the +.Pa src/lib/isc +directory of the current +.Sy BIND +distribution. +.Sh ERRORS +The possible values for +.Fa errno +when one of the +.Dq Fa int +functions in this library returns +.Dq Fa -1 +include those of the Standard C Library and also: +.Bl -tag -width EWOULDBLOCKAA +.It Bq Er EINVAL +Some function argument has an unreasonable value. +.It Bq Er EINVAL +The specified file descriptor has an integer value greater than the default +.Fa FD_SETSIZE , +meaning that the application's limit is higher than the library's. +.It Bq Er ENOENT +The specified +.Dq event \s-1ID\s+1 +does not exist. +.It Bq Er EWOULDBLOCK +No events have occurred and the +.Fa EV_POLL +option was specified. +.It Bq Er EBADF +The specified signal was unblocked outside the library. +.El +.Sh SEE ALSO +.Xr gettimeofday 2 , +.Xr select 2 , +.Xr fcntl 3 , +.Xr malloc 3 , +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr readv 3 , +.Xr writev 3 . +.Sh BUGS +This huge man page needs to be broken up into a handful of smaller ones. +.Sh HISTORY +The +.Nm eventlib +library was designed by Paul Vixie with excellent advice from his friends +and with tips 'o the cap to the X Consortium and the implementors of DEC SRC +Modula-3. Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/eventlib.mdoc ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/heap.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/heap.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/heap.c (revision 60942) @@ -0,0 +1,221 @@ +/* + * Copyright (c) 1997,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. + */ + +/* + * Heap implementation of priority queues adapted from the following: + * + * _Introduction to Algorithms_, Cormen, Leiserson, and Rivest, + * MIT Press / McGraw Hill, 1990, ISBN 0-262-03141-8, chapter 7. + * + * _Algorithms_, Second Edition, Sedgewick, Addison-Wesley, 1988, + * ISBN 0-201-06673-4, chapter 11. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: heap.c,v 8.7 1999/10/13 16:39:34 vixie Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include +#include +#include + +#include "port_after.h" + +#include + +/* + * Note: to make heap_parent and heap_left easy to compute, the first + * element of the heap array is not used; i.e. heap subscripts are 1-based, + * not 0-based. + */ +#define heap_parent(i) ((i) >> 1) +#define heap_left(i) ((i) << 1) + +#define ARRAY_SIZE_INCREMENT 512 + +heap_context +heap_new(heap_higher_priority_func higher_priority, heap_index_func index, + int array_size_increment) { + heap_context ctx; + + ctx = (heap_context)malloc(sizeof (struct heap_context)); + if (ctx == NULL || higher_priority == NULL) + return (NULL); + ctx->array_size = 0; + if (array_size_increment == 0) + ctx->array_size_increment = ARRAY_SIZE_INCREMENT; + else + ctx->array_size_increment = array_size_increment; + ctx->heap_size = 0; + ctx->heap = NULL; + ctx->higher_priority = higher_priority; + ctx->index = index; + return (ctx); +} + +int +heap_free(heap_context ctx) { + if (ctx == NULL) { + errno = EINVAL; + return (-1); + } + + if (ctx->heap != NULL) + free(ctx->heap); + free(ctx); + + return (0); +} + +static int +heap_resize(heap_context ctx) { + void **new_heap; + + ctx->array_size += ctx->array_size_increment; + new_heap = (void **)realloc(ctx->heap, + (ctx->array_size) * (sizeof (void *))); + if (new_heap == NULL) { + errno = ENOMEM; + return (-1); + } + ctx->heap = new_heap; + return (0); +} + +static void +float_up(heap_context ctx, int i, void *elt) { + int p; + + for ( p = heap_parent(i); + i > 1 && ctx->higher_priority(elt, ctx->heap[p]); + i = p, p = heap_parent(i) ) { + ctx->heap[i] = ctx->heap[p]; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); + } + ctx->heap[i] = elt; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); +} + +static void +sink_down(heap_context ctx, int i, void *elt) { + int j, size, half_size; + + size = ctx->heap_size; + half_size = size / 2; + while (i <= half_size) { + /* find smallest of the (at most) two children */ + j = heap_left(i); + if (j < size && ctx->higher_priority(ctx->heap[j+1], + ctx->heap[j])) + j++; + if (ctx->higher_priority(elt, ctx->heap[j])) + break; + ctx->heap[i] = ctx->heap[j]; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); + i = j; + } + ctx->heap[i] = elt; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); +} + +int +heap_insert(heap_context ctx, void *elt) { + int i; + + if (ctx == NULL || elt == NULL) { + errno = EINVAL; + return (-1); + } + + i = ++ctx->heap_size; + if (ctx->heap_size >= ctx->array_size && heap_resize(ctx) < 0) + return (-1); + + float_up(ctx, i, elt); + + return (0); +} + +int +heap_delete(heap_context ctx, int i) { + void *elt; + + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (-1); + } + + elt = ctx->heap[ctx->heap_size]; + if (--ctx->heap_size > 0) + sink_down(ctx, i, elt); + + return (0); +} + +int +heap_increased(heap_context ctx, int i) { + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (-1); + } + + float_up(ctx, i, ctx->heap[i]); + + return (0); +} + +int +heap_decreased(heap_context ctx, int i) { + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (-1); + } + + sink_down(ctx, i, ctx->heap[i]); + + return (0); +} + +void * +heap_element(heap_context ctx, int i) { + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (NULL); + } + + return (ctx->heap[i]); +} + +int +heap_for_each(heap_context ctx, heap_for_each_func action, void *uap) { + int i; + + if (ctx == NULL || action == NULL) { + errno = EINVAL; + return (-1); + } + + for (i = 1; i <= ctx->heap_size; i++) + (action)(ctx->heap[i], uap); + return (0); +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/heap.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/heap.mdoc =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/heap.mdoc (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/heap.mdoc (revision 60942) @@ -0,0 +1,369 @@ +.\" $Id: heap.mdoc,v 8.5 1999/01/08 19:25:38 vixie Exp $ +.\" +.\"Copyright (c) 1997,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 Jan 1, 1997 +.\"Os OPERATING_SYSTEM [version/release] +.Os BSD 4 +.\" TODO--get correct section # below!! +.Dt HEAP @SYSCALL_EXT@ +.Sh DESCRIPTION +.Nm heap_new , +.Nm heap_free , +.Nm heap_insert , +.Nm heap_delete , +.Nm heap_increased , +.Nm heap_decreased , +.Nm heap_element , +.Nm heap_for_each +.Nd heap implementation of priority queues +.Sh SYNOPSIS +.Fd #include \&"heap.h\&" +.Ft heap_context +.Fn heap_new "heap_higher_priority_func higher_priority" \ +"heap_index_func index" "int array_size_increment" +.Ft int +.Fn heap_free "heap_context ctx" +.Ft int +.Fn heap_insert "heap_context ctx" "void *elt" +.Ft int +.Fn heap_delete "heap_context ctx" "int i" +.Ft int +.Fn heap_increased "heap_context ctx" "int i" +.Ft int +.Fn heap_decreased "heap_context ctx" "int i" +.Ft void * +.Fn heap_element "heap_context ctx" "int i" +.Ft int +.Fn heap_for_each "heap_context ctx" "heap_for_each_func action" "void *uap" +.Sh DESCRIPTION +These functions implement heap\-based priority queues. The user defines a +priority scheme, and provides a function for comparison of the priority +of heap elements +.Po see the description of the +.Ft heap_higher_priority_func +function pointer, below +.Pc . +.Pp +Each of the functions depends upon the +.Ft heap_context +type, which is a pointer to a +.Ft struct heap_context +.Pq see Pa heap.h No for more information . +.Pp +The +.Pa heap.h +header file also defines the following set of function +function pointers: +.Bd -literal -offset indent +typedef int (*heap_higher_priority_func)(void *, void *); +typedef void (*heap_index_func)(void *, int); +typedef void (*heap_for_each_func)(void *, void *); +.Ed +.Pp +These are pointers to user-defined functions. +The +.Ft heap_higher_priority_func +type is a pointer to a function which compares two +different heap (queue) elements and returns an +.Ft int +which answers the question, "Does the first queue element +have a higher priority than the second?" In other words, +a function pointer of this type +.Em must +return a number greater than zero +if the element indicated by the first argument is of a higher priority than +that indicated by the second element, and zero otherwise. +.Pp +The other two function pointers are documented in the descriptions +of +.Fn heap_new +.Pq Va heap_index_func +and +.Fn heap_for_each +.Pq Va heap_for_each_func , +below. +.Pp +The function +.Fn heap_new +initializes a +.Ft struct heap_context +and returns a pointer to it. The +.Fa higher_priority +function pointer +.Em must +be +.No non\- Ns Dv NULL . +As explained above, this refers to a +function supplied by the user which compares the priority of two different +queue or heap elements; see above for more information. +The second argument, +.Fa index , +is a pointer to a user-defined function whose arguments are +a heap element and its index in the heap. +.Fa Index +is intended to provide the user a means of knowing the internal index +of an element in the heap while maintaining the opacity of the implementation; +since the user has to know the actual indexes of heap elements in order to use, +e.g., +.Fn heap_delete +or +.Fn heap_element , +the user +.Fa index +function could store the index in the heap element, itself. If +.Fa index +is +.No non\- Ns Dv NULL , +then it is called +.Em whenever +the index of an element changes, allowing the user to stay up\-to\-date +with index changes. +The last argument, +.Fa array_size_increment +will be used, as its name suggests, by +.Xr malloc 3 +or +.Xr realloc 3 +to increment the array which implements the heap; if zero, a default value +will be used. +.Pp +The +.Fn heap_free +function frees the given +.Ft heap_context +argument +.Pq Fa ctx , +which also frees the entire +.Nm heap , +if it is +.No non\- Ns Dv NULL . +The argument +.Fa ctx +should be +.No non\- Ns Dv NULL . +.Pp +The +.Fn heap_insert +function is used to insert the new heap element +.Fa elt +into the appropriate place (priority\-wise) in the +.Ft heap +indicated by +.Fa ctx +.Po a pointer to a +.Ft heap_context +.Pc . +If +.No non\- Ns Dv NULL , +the user-defined +.Ft higher_priority +function pointer associated with the indicated +.Nm heap +is used to determine that +.Dq appropriate place ; +the highest\-priority elements are at the front of the queue (top of +the heap). +(See the description of +.Fn heap_new , +above, for more information.) +.Pp +The function +.Fn heap_delete +is used to delete the +.Fa i\- Ns th +element of the queue (heap), and fixing up the queue (heap) from that +element onward via the priority as determined by the user function +pointed to by +.Ft higher_priority +function pointer +.Pq see description of Fn heap_new, No above . +.Pp +.Fn heap_increased +.Pp +.Fn heap_decreased +.Pp +The +.Fn heap_element +function returns the +.Fa i\- Ns th +element of the queue/heap indicated by +.Fa ctx , +if possible. +.Pp +The +.Fn heap_for_each +function provides a mechanism for the user to increment through the entire +queue (heap) and perform some +.Fa action +upon each of the queue elements. This +.Fa action +is pointer to a user\-defined function with two arguments, the first of +which should be interpreted by the user's function as a heap element. The +second value passed to the user function is just the +.Fa uap +argument to +.Fn heap_for_each ; +this allows the user to specify additional arguments, if necessary, to +the function pointed to by +.Fa action . +.\" The following requests should be uncommented and +.\" used where appropriate. This next request is +.\" for sections 2 and 3 function return values only. +.Sh RETURN VALUES +.Bl -tag -width "heap_decreased()" +.It Fn heap_new +.Dv NULL +if unable to +.Xr malloc 3 +a +.Ft struct heap_context +or if the +.Fa higher_priority +function pointer is +.Dv NULL; +otherwise, a valid +.Ft heap_context +.Ns . +.It Fn heap_free +-1 if +.Fa ctx +is +.Dv NULL +(with +.Va errno +set to +.Dv EINVAL ) ; +otherwise, 0. +.It Fn heap_insert +-1 +if either +.Fa ctx +or +.Fa elt +is +.Dv NULL , +or if an attempt to +.Xr malloc 3 +or +.Xr realloc 3 +the heap array fails (with +.Va errno +set to +.Dv EINVAL +or +.Dv ENOMEM , +respectively). +Otherwise, 0. +.It Fn heap_delete +-1 if +.Fa ctx +is +.Dv NULL +or +.Fa i +is out\-of\-range (with +.Va errno +set to +.Dv EINVAL ) ; +0 otherwise. +.It Fn heap_increased +As for +.Fn heap_delete . +.It Fn heap_decreased +As for +.Fn heap_delete . +.It Fn heap_element +NULL if +.Fa ctx +is +.Dv NULL +or +.Fa i +out\-of-bounds (with +.Va errno +set to +.Dv EINVAL ) ; +otherwise, a pointer to the +.Fa i\- Ns th +queue element. +.It Fn heap_for_each +-1 if either +.Fa ctx +or +.Fa action +is +.Dv NULL +(with +.Va errno +set to +.Dv EINVAL ) ; +0 otherwise. +.El +.\" This next request is for sections 1, 6, 7 & 8 only +.\" .Sh ENVIRONMENT +.Sh FILES +.Bl -tag -width "heap.h000" +.It Pa heap.h + heap library header file +.El +.\" .Sh EXAMPLES +.\" This next request is for sections 1, 6, 7 & 8 only +.\" (command return values (to shell) and +.\" fprintf/stderr type diagnostics) +.Sh DIAGNOSTICS +Please refer to +.Sx RETURN VALUES . +.\" The next request is for sections 2 and 3 error +.\" and signal handling only. +.Sh ERRORS +The variable +.Va errno +is set by +.Fn heap_free , +.Fn heap_insert , +.Fn heap_delete , +.Fn heap_increased , +and +.Fn heap_decreased +under the conditions of invalid input +.Pq Dv EINVAL +or lack of memory +.Pq Dv ENOMEM ; +please refer to +.Sx RETURN VALUES . +.Sh SEE ALSO +.Xr malloc 3 , +.Xr realloc 3 . +.Pp +Cormen, Leiserson, and Rivest, +.Sy Introduction to Algorithms, +MIT Press / McGraw Hill, 1990, ISBN 0\-262\-03141\-8, chapter 7. +.Pp +Sedgewick, +.Sy Algorithms, +2nd ed'n, Addison\-Wesley, 1988, ISBN 0\-201\-06673\-4, chapter 11. +.\" .Sh STANDARDS +.\" .Sh HISTORY +.Sh AUTHORS +The +.Nm heap +library was implemented by Bob Halley (halley@vix.com) of Vixie Enterprises, +Inc., for the Internet Software consortium, and was adapted from +the two books listed in the +.Sx SEE ALSO +section, above. +.\" .Sh BUGS Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/heap.mdoc ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/memcluster.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/memcluster.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/memcluster.c (revision 60942) @@ -0,0 +1,510 @@ +/* + * Copyright (c) 1997,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. + */ + + +/* When this symbol is defined allocations via memget are made slightly + bigger and some debugging info stuck before and after the region given + back to the caller. */ +/* #define DEBUGGING_MEMCLUSTER */ + + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: memcluster.c,v 8.19 1999/10/13 17:11:22 vixie Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#ifdef MEMCLUSTER_RECORD +#ifndef DEBUGGING_MEMCLUSTER +#define DEBUGGING_MEMCLUSTER +#endif +#endif + +#define DEF_MAX_SIZE 1100 +#define DEF_MEM_TARGET 4096 + +typedef u_int32_t fence_t; + +typedef struct { + void * next; +#if defined(DEBUGGING_MEMCLUSTER) +#if defined(MEMCLUSTER_RECORD) + const char * file; + int line; +#endif + int size; + fence_t fencepost; +#endif +} memcluster_element; + +#define SMALL_SIZE_LIMIT sizeof(memcluster_element) +#define P_SIZE sizeof(void *) +#define FRONT_FENCEPOST 0xfebafeba +#define BACK_FENCEPOST 0xabefabef +#define FENCEPOST_SIZE 4 + +#ifndef MEMCLUSTER_LITTLE_MALLOC +#define MEMCLUSTER_BIG_MALLOC 1 +#define NUM_BASIC_BLOCKS 64 +#endif + +struct stats { + u_long gets; + u_long totalgets; + u_long blocks; + u_long freefrags; +}; + +/* Private data. */ + +static size_t max_size; +static size_t mem_target; +static size_t mem_target_half; +static size_t mem_target_fudge; +static memcluster_element ** freelists; +#ifdef MEMCLUSTER_RECORD +static memcluster_element ** activelists; +#endif +#ifdef MEMCLUSTER_BIG_MALLOC +static memcluster_element * basic_blocks; +#endif +static struct stats * stats; + +/* Forward. */ + +static size_t quantize(size_t); +#if defined(DEBUGGING_MEMCLUSTER) +static void check(unsigned char *, int, size_t); +#endif + +/* Public. */ + +int +meminit(size_t init_max_size, size_t target_size) { + +#if defined(DEBUGGING_MEMCLUSTER) + INSIST(sizeof(fence_t) == FENCEPOST_SIZE); +#endif + if (freelists != NULL) { + errno = EEXIST; + return (-1); + } + if (init_max_size == 0) + max_size = DEF_MAX_SIZE; + else + max_size = init_max_size; + if (target_size == 0) + mem_target = DEF_MEM_TARGET; + else + mem_target = target_size; + mem_target_half = mem_target / 2; + mem_target_fudge = mem_target + mem_target / 4; + freelists = malloc(max_size * sizeof (memcluster_element *)); + stats = malloc((max_size+1) * sizeof (struct stats)); + if (freelists == NULL || stats == NULL) { + errno = ENOMEM; + return (-1); + } + memset(freelists, 0, + max_size * sizeof (memcluster_element *)); + memset(stats, 0, (max_size + 1) * sizeof (struct stats)); +#ifdef MEMCLUSTER_RECORD + activelists = malloc((max_size + 1) * sizeof (memcluster_element *)); + if (activelists == NULL) { + errno = ENOMEM; + return (-1); + } + memset(activelists, 0, + (max_size + 1) * sizeof (memcluster_element *)); +#endif +#ifdef MEMCLUSTER_BIG_MALLOC + basic_blocks = NULL; +#endif + return (0); +} + +void * +__memget(size_t size) { + return (__memget_record(size, NULL, 0)); +} + +void * +__memget_record(size_t size, const char *file, int line) { + size_t new_size = quantize(size); +#if defined(DEBUGGING_MEMCLUSTER) + memcluster_element *e; + char *p; + fence_t fp = BACK_FENCEPOST; +#endif + void *ret; + + if (freelists == NULL) + if (meminit(0, 0) == -1) + return (NULL); + if (size == 0) { + errno = EINVAL; + return (NULL); + } + if (size >= max_size || new_size >= max_size) { + /* memget() was called on something beyond our upper limit. */ + stats[max_size].gets++; + stats[max_size].totalgets++; +#if defined(DEBUGGING_MEMCLUSTER) + e = malloc(new_size); + if (e == NULL) { + errno = ENOMEM; + return (NULL); + } + e->next = NULL; + e->size = size; +#ifdef MEMCLUSTER_RECORD + e->file = file; + e->line = line; + e->next = activelists[max_size]; + activelists[max_size] = e; +#endif + e->fencepost = FRONT_FENCEPOST; + p = (char *)e + sizeof *e + size; + memcpy(p, &fp, sizeof fp); + return ((char *)e + sizeof *e); +#else + return (malloc(size)); +#endif + } + + /* + * If there are no blocks in the free list for this size, get a chunk + * of memory and then break it up into "new_size"-sized blocks, adding + * them to the free list. + */ + if (freelists[new_size] == NULL) { + int i, frags; + size_t total_size; + void *new; + char *curr, *next; + +#ifdef MEMCLUSTER_BIG_MALLOC + if (basic_blocks == NULL) { + new = malloc(NUM_BASIC_BLOCKS * mem_target); + if (new == NULL) { + errno = ENOMEM; + return (NULL); + } + curr = new; + next = curr + mem_target; + for (i = 0; i < (NUM_BASIC_BLOCKS - 1); i++) { + ((memcluster_element *)curr)->next = next; + curr = next; + next += mem_target; + } + /* + * curr is now pointing at the last block in the + * array. + */ + ((memcluster_element *)curr)->next = NULL; + basic_blocks = new; + } + total_size = mem_target; + new = basic_blocks; + basic_blocks = basic_blocks->next; +#else + if (new_size > mem_target_half) + total_size = mem_target_fudge; + else + total_size = mem_target; + new = malloc(total_size); + if (new == NULL) { + errno = ENOMEM; + return (NULL); + } +#endif + frags = total_size / new_size; + stats[new_size].blocks++; + stats[new_size].freefrags += frags; + /* Set up a linked-list of blocks of size "new_size". */ + curr = new; + next = curr + new_size; + for (i = 0; i < (frags - 1); i++) { +#if defined (DEBUGGING_MEMCLUSTER) + memset(curr, 0xa5, new_size); +#endif + ((memcluster_element *)curr)->next = next; + curr = next; + next += new_size; + } + /* curr is now pointing at the last block in the array. */ +#if defined (DEBUGGING_MEMCLUSTER) + memset(curr, 0xa5, new_size); +#endif + ((memcluster_element *)curr)->next = freelists[new_size]; + freelists[new_size] = new; + } + + /* The free list uses the "rounded-up" size "new_size". */ +#if defined (DEBUGGING_MEMCLUSTER) + e = freelists[new_size]; + ret = (char *)e + sizeof *e; + /* + * Check to see if this buffer has been written to while on free list. + */ + check(ret, 0xa5, new_size - sizeof *e); + /* + * Mark memory we are returning. + */ + memset(ret, 0xe5, size); +#else + ret = freelists[new_size]; +#endif + freelists[new_size] = freelists[new_size]->next; +#if defined(DEBUGGING_MEMCLUSTER) + e->next = NULL; + e->size = size; + e->fencepost = FRONT_FENCEPOST; +#ifdef MEMCLUSTER_RECORD + e->file = file; + e->line = line; + e->next = activelists[size]; + activelists[size] = e; +#endif + p = (char *)e + sizeof *e + size; + memcpy(p, &fp, sizeof fp); +#endif + + /* + * The stats[] uses the _actual_ "size" requested by the + * caller, with the caveat (in the code above) that "size" >= the + * max. size (max_size) ends up getting recorded as a call to + * max_size. + */ + stats[size].gets++; + stats[size].totalgets++; + stats[new_size].freefrags--; +#if defined(DEBUGGING_MEMCLUSTER) + return ((char *)e + sizeof *e); +#else + return (ret); +#endif +} + +/* + * This is a call from an external caller, + * so we want to count this as a user "put". + */ +void +__memput(void *mem, size_t size) { + __memput_record(mem, size, NULL, 0); +} + +void +__memput_record(void *mem, size_t size, const char *file, int line) { + size_t new_size = quantize(size); +#if defined (DEBUGGING_MEMCLUSTER) + memcluster_element *e; +#ifdef MEMCLUSTER_RECORD + memcluster_element *prev, *el; +#endif + int fp; + char *p; +#endif + REQUIRE(freelists != NULL); + + if (size == 0) { + errno = EINVAL; + return; + } + +#if defined (DEBUGGING_MEMCLUSTER) + e = (memcluster_element *) ((char *)mem - sizeof *e); + INSIST(e->fencepost == FRONT_FENCEPOST); + INSIST(e->size == size); + p = (char *)e + sizeof *e + size; + memcpy(&fp, p, sizeof fp); + INSIST(fp == BACK_FENCEPOST); + INSIST(((int)mem % 4) == 0); +#ifdef MEMCLUSTER_RECORD + prev = NULL; + if (size == max_size || new_size >= max_size) + el = activelists[max_size]; + else + el = activelists[size]; + while (el != NULL && el != e) { + prev = el; + el = el->next; + } + INSIST(el != NULL); /* double free */ + if (prev == NULL) { + if (size == max_size || new_size >= max_size) + activelists[max_size] = el->next; + else + activelists[size] = el->next; + } else + prev->next = el->next; +#endif +#endif + + if (size == max_size || new_size >= max_size) { + /* memput() called on something beyond our upper limit */ +#if defined(DEBUGGING_MEMCLUSTER) + free(e); +#else + free(mem); +#endif + + INSIST(stats[max_size].gets != 0); + stats[max_size].gets--; + return; + } + + /* The free list uses the "rounded-up" size "new_size": */ +#if defined(DEBUGGING_MEMCLUSTER) + memset(mem, 0xa5, new_size - sizeof *e); /* catch write after free */ + e->size = 0; /* catch double memput() */ +#ifdef MEMCLUSTER_RECORD + e->file = file; + e->line = line; +#endif + e->next = freelists[new_size]; + freelists[new_size] = (void *)e; +#else + ((memcluster_element *)mem)->next = freelists[new_size]; + freelists[new_size] = (memcluster_element *)mem; +#endif + + /* + * The stats[] uses the _actual_ "size" requested by the + * caller, with the caveat (in the code above) that "size" >= the + * max. size (max_size) ends up getting recorded as a call to + * max_size. + */ + INSIST(stats[size].gets != 0); + stats[size].gets--; + stats[new_size].freefrags++; +} + +void * +__memget_debug(size_t size, const char *file, int line) { + void *ptr; + ptr = __memget_record(size, file, line); + 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_record(ptr, size, file, line); +} + +/* + * Print the stats[] on the stream "out" with suitable formatting. + */ +void +memstats(FILE *out) { + size_t i; +#ifdef MEMCLUSTER_RECORD + memcluster_element *e; +#endif + + if (freelists == NULL) + return; + for (i = 1; i <= max_size; i++) { + const struct stats *s = &stats[i]; + + if (s->totalgets == 0 && s->gets == 0) + continue; + fprintf(out, "%s%5d: %11lu gets, %11lu rem", + (i == max_size) ? ">=" : " ", + i, s->totalgets, s->gets); + if (s->blocks != 0) + fprintf(out, " (%lu bl, %lu ff)", + s->blocks, s->freefrags); + fputc('\n', out); + } +#ifdef MEMCLUSTER_RECORD + fprintf(out, "Active Memory:\n"); + for (i = 1; i <= max_size; i++) { + if ((e = activelists[i]) != NULL) + while (e != NULL) { + fprintf(out, "%s:%d %#p:%d\n", + e->file != NULL ? e->file : + "", e->line, + (char *)e + sizeof *e, e->size); + e = e->next; + } + } +#endif +} + +/* Private. */ + +/* + * Round up size to a multiple of sizeof(void *). This guarantees that a + * block is at least sizeof void *, and that we won't violate alignment + * restrictions, both of which are needed to make lists of blocks. + */ +static size_t +quantize(size_t size) { + int remainder; + /* + * If there is no remainder for the integer division of + * + * (rightsize/P_SIZE) + * + * then we already have a good size; if not, then we need + * to round up the result in order to get a size big + * enough to satisfy the request _and_ aligned on P_SIZE boundaries. + */ + remainder = size % P_SIZE; + if (remainder != 0) + size += P_SIZE - remainder; +#if defined(DEBUGGING_MEMCLUSTER) + return (size + SMALL_SIZE_LIMIT + sizeof (int)); +#else + return (size); +#endif +} + +#if defined(DEBUGGING_MEMCLUSTER) +static void +check(unsigned char *a, int value, size_t len) { + int i; + for (i = 0; i < len; i++) + INSIST(a[i] == value); +} +#endif Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/memcluster.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/memcluster.mdoc =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/memcluster.mdoc (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/memcluster.mdoc (revision 60942) @@ -0,0 +1,375 @@ +.\" $Id: memcluster.mdoc,v 8.2 1999/01/08 19:25:46 vixie 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. +.\" +.\" The following six UNCOMMENTED lines are required. +.Dd Month day, year +.\"Os OPERATING_SYSTEM [version/release] +.Os BSD 4 +.\"Dt DOCUMENT_TITLE [section number] [volume] +.Dt memcluster 3 +.Sh NAME +.Nm meminit , +.Nm memget , +.Nm memput , +.Nm memstats +.Nd memory allocation/deallocation system +.Sh SYNOPSIS +.Fd #include \& +.Ft void * +.Fn memget "size_t size" +.Ft void +.Fn memput "void *mem" "size_t size" +.Ft void +.Fn memstats "FILE *out" +.Sh DESCRIPTION +These functions access a memory management system which allows callers to not +fragment memory to the extent which can ordinarily occur through many random +calls to +.Xr malloc 3 . +Instead, +.Fn memget +gets a large contiguous chunk of blocks of the requested +.Fa size +and parcels out these blocks as requested. The symmetric call is +.Fn memput , +which callers use to return a piece of memory obtained from +.Fn memget . +Statistics about memory usage are returned by +.Fn memstats , +which prints a report on the stream +.Fa out . +.Ss INTERNALS +Internally, linked lists of free memory blocks are stored in an array. +The size of this array is determined by the value +.Dv MEM_FREECOUNT , +currently set to 1100. In general, for any requested blocksize +.Dq Fa size , +any free blocks will be stored on the linked list at that index. +No free lists are managed for blocks greater than or equal to +.Dv MEM_FREECOUNT +bytes; instead, calls to +.Xr malloc 3 +or +.Xr free 3 +are made, directly. +.Pp +Since the blocks are actually stored as linked lists, they must at least +be large enough to hold a pointer to the next block. This size, which is +.Dv SMALL_SIZE_LIMIT , +is currently defined as +.Bd -literal -offset indent +#define SMALL_SIZE_LIMIT sizeof(struct { void *next; }) +.Ed +.Pp +Both +.Fn memget +and +.Fn memput +enforce this limit; for example, any call to +.Fn memget +requesting a block smaller than +.Dv SMALL_SIZE_LIMIT +bytes will actually be considered to be of size +.Dv SMALL_SIZE_LIMIT +internally. (Such a caller request will be logged for +.Fn memstats +purposes using the caller-requested +.Fa size ; +see the discussion of +.Fn memstats , +below, for more information.) +.Pp +Additionally, the requested +.Fa size +will be adjusted so that when a large +.Xr malloc 3 Ns No -d +chunk of memory is broken up into a linked list, the blocks will all fall on +the correct memory alignment boundaries. Thus, one can conceptualize a call +which mentions +.Fa size +as resulting in a +.Fa new_size +which is used internally. +.Pp +In order to more efficiently allocate memory, there is a +.Dq target +size for calls to +.Xr malloc 3 . +It is given by the pre-defined value +.Dv MEM_TARGET , +which is currently 4096 bytes. +For any requested block +.Fa size , +enough memory is +.Xr malloc 3 Ns No -d +in order to fill up a block of about +.Dv MEM_TARGET +bytes. +.No [ Ns Sy NOTE : +For allocations larger than +.Dv MEM_TARGET Ns No /2 +bytes, there is a +.Dq fudge factor +introduced which boosts the target size by 25% of +.Dv MEM_TARGET . +This means that enough memory for two blocks +will actually be allocated for any +.Fa size +such that +.Pq Dv MEM_TARGET Ns No / 3 +.No < Fa size No < +.Pq Dv MEM_TARGET Ns No *5/8 , +provided that the value of +.Dv MEM_FREECOUNT +is at least as large as the upper limit shown above.] +.Pp +.Ss FUNCTION DESCRIPTIONS +.Pp +The function +.Fn memget +returns a pointer to a block of memory of at least the requested +.Fa size . +After adjusting +.Fa size +to the value +.Va new_size +as mentioned above in the +.Sx INTERNALS +subsection, the internal array of free lists is checked. +If there is no block of the needed +.Va new_size , +then +.Fn memget +will +.Xr malloc 3 +a chunk of memory which is as many times as +.Va new_size +will fit into the target size. This memory is then turned into a linked list +of +.Va new_size Ns No -sized +blocks which are given out as requested; the last such block is the first one +returned by +.Fn memget . +If the requested +.Fa size +is zero or negative, then +.Dv NULL +is returned and +.Va errno +is set to +.Dv EINVAL ; +if +.Fa size +is larger than or equal to the pre-defined maximum size +.Dv MEM_FREECOUNT , +then only a single block of exactly +.Fa size +will be +.Xr malloc 3 Ns No -d +and returned. +.Pp +The +.Fn memput +call is used to return memory once the caller is finished with it. +After adjusting +.Fa size +the the value +.Va new_size +as mentioned in the +.Sx INTERNALS +subsection, above, the block is placed at the head of the free list of +.Va new_size Ns No -sized blocks. +If the given +.Fa size +is zero or negative, then +.Va errno +is set to +.Dv EINVAL , +as for +.Fn memget . +If +.Fa size +is larger than or equal to the pre-defined maximum size +.Dv MEM_FREECOUNT , +then the block is immediately +.Xr free 3 Ns No -d . +.Pp +.Sy NOTE : +It is important that callers give +.Fn memput +.Em only +blocks of memory which were previously obtained from +.Fn memget +if the block is +.Em actually +less than +.Dv SMALL_SIZE_LIMIT +bytes in size. Since all blocks will be added to a free list, any block +which is not at least +.Dv SMALL_SIZE_LIMIT +bytes long will not be able to hold a pointer to the next block in the +free list. +.Pp +The +.Fn memstats +function will summarize the number of calls to +.Fn memget +and +.Fn memput +for any block size from 1 byte up to +.Pq Dv MEM_FREECOUNT No - 1 +bytes, followed by a single line for any calls using a +.Fa size +greater than or equal to +.Dv MEM_FREECOUNT ; +a brief header with shell-style comment lines prefaces the report and +explains the information. The +.Dv FILE +pointer +.Fa out +identifies the stream which is used for this report. Currently, +.Fn memstat +reports the number of calls to +.Fn memget +and +.Fn memput +using the caller-supplied value +.Fa size ; +the percentage of outstanding blocks of a given size (i.e., the percentage +by which calls to +.Fn memget +exceed +.Fn memput ) +are also reported on the line for blocks of the given +.Fa size . +However, the percent of blocks used is computed using the number of +blocks allocated according to the internal parameter +.Va new_size ; +it is the percentage of blocks used to those available at a given +.Va new_size , +and is computed using the +.Em total +number of caller +.Dq gets +for any caller +.Fa size Ns No -s +which map to the internally-computed +.Va new_size . +Keep in mind that +.Va new_size +is generally +.Em not +equal to +.Fa size , +which has these implications: +.Bl -enum -offset -indent means that, for +.It +For +.Fa size +smaller than +.Dv SMALL_SIZE_LIMIT , +.Fn memstat +.Em will +show statistics for caller requests under +.Fa size , +but "percent used" information about such blocks will be reported under +.Dv SMALL_SIZE_LIMIT Ns No -sized +blocks. +.It +As a general case of point 1, internal statistics are reported on the the +line corresponding to +.Va new_size , +so that, for a given caller-supplied +.Fa size , +the associated internal information will appear on that line or on the next +line which shows "percent used" information. +.El +.Pp +.Sy NOTE : +If the caller returns blocks of a given +.Fa size +and requests others of +.Fa size Ns No -s +which map to the same internal +.Va new_size , +it is possible for +.Fn memstats +to report usage of greater than 100% for blocks of size +.Va new_size . +This should be viewed as A Good Thing. +.Sh RETURN VALUES +The function +.Fn memget +returns a +.No non- Ns Dv NULL +pointer to a block of memory of the requested +.Fa size . +It returns +.Dv NULL +if either the +.Fa size +is invalid (less than or equal to zero) or a +.Xr malloc 3 +of a new block of memory fails. In the former case, +.Va errno +is set to +.Dv EINVAL ; +in the latter, it is set to +.Dv ENOMEM . +.Pp +Neither +.Fn memput +nor +.Fn memstats +return a value. +.\" This next request is for sections 1, 6, 7 & 8 only +.\" .Sh ENVIRONMENT +.\" .Sh FILES +.\" .Sh EXAMPLES +.\" This next request is for sections 1, 6, 7 & 8 only +.\" (command return values (to shell) and +.\" fprintf/stderr type diagnostics) +.\" .Sh DIAGNOSTICS +.\" The next request is for sections 2 and 3 error +.\" and signal handling only. +.Sh ERRORS +.Va errno +is set as follows: +.Bl -tag -width "ENOMEM " -offset indent +.It Dv EINVAL +set by both +.Fn memget +and +.Fn memput +if the +.Fa size +is zero or negative +.It Dv ENOMEM +set by +.Fn memget +if a call to +.Xr malloc 3 +fails +.El +.Sh SEE ALSO +.Xr free 3 , +.Xr malloc 3 . +.\" .Sh STANDARDS +.\" .Sh HISTORY +.Sh AUTHORS +Steven J. Richardson and Paul Vixie, Vixie Enterprises. +.\" .Sh BUGS Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/memcluster.mdoc ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/tree.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/tree.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/tree.c (revision 60942) @@ -0,0 +1,532 @@ +#ifndef LINT +static const char rcsid[] = "$Id: tree.c,v 8.9 1999/01/08 19:25:47 vixie Exp $"; +#endif + +/* + * tree - balanced binary tree library + * + * vix 05apr94 [removed vixie.h dependencies; cleaned up formatting, names] + * vix 22jan93 [revisited; uses RCS, ANSI, POSIX; has bug fixes] + * vix 23jun86 [added delete uar to add for replaced nodes] + * vix 20jun86 [added tree_delete per wirth a+ds (mod2 v.) p. 224] + * vix 06feb86 [added tree_mung()] + * vix 02feb86 [added tree balancing from wirth "a+ds=p" p. 220-221] + * vix 14dec85 [written] + */ + +/* + * This program text was created by Paul Vixie using examples from the book: + * "Algorithms & Data Structures," Niklaus Wirth, Prentice-Hall, 1986, ISBN + * 0-13-022005-1. Any errors in the conversion from Modula-2 to C are Paul + * Vixie's. + */ + +/* + * 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. + */ + +/*#define DEBUG "tree"*/ + +#include "port_before.h" + +#include +#include + +#include "port_after.h" + +#include +#include + +#ifdef DEBUG +static int debugDepth = 0; +static char *debugFuncs[256]; +# define ENTER(proc) { \ + debugFuncs[debugDepth] = proc; \ + fprintf(stderr, "ENTER(%d:%s.%s)\n", \ + debugDepth, DEBUG, \ + debugFuncs[debugDepth]); \ + debugDepth++; \ + } +# define RET(value) { \ + debugDepth--; \ + fprintf(stderr, "RET(%d:%s.%s)\n", \ + debugDepth, DEBUG, \ + debugFuncs[debugDepth]); \ + return (value); \ + } +# define RETV { \ + debugDepth--; \ + fprintf(stderr, "RETV(%d:%s.%s)\n", \ + debugDepth, DEBUG, \ + debugFuncs[debugDepth]); \ + return; \ + } +# define MSG(msg) fprintf(stderr, "MSG(%s)\n", msg); +#else +# define ENTER(proc) ; +# define RET(value) return (value); +# define RETV return; +# define MSG(msg) ; +#endif + +#ifndef TRUE +# define TRUE 1 +# define FALSE 0 +#endif + +static tree * sprout(tree **, tree_t, int *, int (*)(), void (*)()); +static int delete(tree **, int (*)(), tree_t, void (*)(), int *, int *); +static void del(tree **, int *, tree **, void (*)(), int *); +static void bal_L(tree **, int *); +static void bal_R(tree **, int *); + +void +tree_init(tree **ppr_tree) { + ENTER("tree_init") + *ppr_tree = NULL; + RETV +} + +tree_t +tree_srch(tree **ppr_tree, int (*pfi_compare)(), tree_t p_user) { + ENTER("tree_srch") + + if (*ppr_tree) { + int i_comp = (*pfi_compare)(p_user, (**ppr_tree).data); + + if (i_comp > 0) + RET(tree_srch(&(**ppr_tree).right, + pfi_compare, + p_user)) + + if (i_comp < 0) + RET(tree_srch(&(**ppr_tree).left, + pfi_compare, + p_user)) + + /* not higher, not lower... this must be the one. + */ + RET((**ppr_tree).data) + } + + /* grounded. NOT found. + */ + RET(NULL) +} + +tree_t +tree_add(tree **ppr_tree, int (*pfi_compare)(), + tree_t p_user, void (*pfv_uar)()) +{ + int i_balance = FALSE; + + ENTER("tree_add") + if (!sprout(ppr_tree, p_user, &i_balance, pfi_compare, pfv_uar)) + RET(NULL) + RET(p_user) +} + +int +tree_delete(tree **ppr_p, int (*pfi_compare)(), + tree_t p_user, void (*pfv_uar)()) +{ + int i_balance = FALSE, i_uar_called = FALSE; + + ENTER("tree_delete"); + RET(delete(ppr_p, pfi_compare, p_user, pfv_uar, + &i_balance, &i_uar_called)) +} + +int +tree_trav(tree **ppr_tree, int (*pfi_uar)()) { + ENTER("tree_trav") + + if (!*ppr_tree) + RET(TRUE) + + if (!tree_trav(&(**ppr_tree).left, pfi_uar)) + RET(FALSE) + if (!(*pfi_uar)((**ppr_tree).data)) + RET(FALSE) + if (!tree_trav(&(**ppr_tree).right, pfi_uar)) + RET(FALSE) + RET(TRUE) +} + +void +tree_mung(tree **ppr_tree, void (*pfv_uar)()) { + ENTER("tree_mung") + if (*ppr_tree) { + tree_mung(&(**ppr_tree).left, pfv_uar); + tree_mung(&(**ppr_tree).right, pfv_uar); + if (pfv_uar) + (*pfv_uar)((**ppr_tree).data); + memput(*ppr_tree, sizeof(tree)); + *ppr_tree = NULL; + } + RETV +} + +static tree * +sprout(tree **ppr, tree_t p_data, int *pi_balance, + int (*pfi_compare)(), void (*pfv_delete)()) +{ + tree *p1, *p2, *sub; + int cmp; + + ENTER("sprout") + + /* are we grounded? if so, add the node "here" and set the rebalance + * flag, then exit. + */ + if (!*ppr) { + MSG("grounded. adding new node, setting h=true") + *ppr = (tree *) memget(sizeof(tree)); + if (*ppr) { + (*ppr)->left = NULL; + (*ppr)->right = NULL; + (*ppr)->bal = 0; + (*ppr)->data = p_data; + *pi_balance = TRUE; + } + RET(*ppr); + } + + /* compare the data using routine passed by caller. + */ + cmp = (*pfi_compare)(p_data, (*ppr)->data); + + /* if LESS, prepare to move to the left. + */ + if (cmp < 0) { + MSG("LESS. sprouting left.") + sub = sprout(&(*ppr)->left, p_data, pi_balance, + pfi_compare, pfv_delete); + if (sub && *pi_balance) { /* left branch has grown */ + MSG("LESS: left branch has grown") + switch ((*ppr)->bal) { + case 1: + /* right branch WAS longer; bal is ok now */ + MSG("LESS: case 1.. bal restored implicitly") + (*ppr)->bal = 0; + *pi_balance = FALSE; + break; + case 0: + /* balance WAS okay; now left branch longer */ + MSG("LESS: case 0.. balnce bad but still ok") + (*ppr)->bal = -1; + break; + case -1: + /* left branch was already too long. rebal */ + MSG("LESS: case -1: rebalancing") + p1 = (*ppr)->left; + if (p1->bal == -1) { /* LL */ + MSG("LESS: single LL") + (*ppr)->left = p1->right; + p1->right = *ppr; + (*ppr)->bal = 0; + *ppr = p1; + } else { /* double LR */ + MSG("LESS: double LR") + + p2 = p1->right; + p1->right = p2->left; + p2->left = p1; + + (*ppr)->left = p2->right; + p2->right = *ppr; + + if (p2->bal == -1) + (*ppr)->bal = 1; + else + (*ppr)->bal = 0; + + if (p2->bal == 1) + p1->bal = -1; + else + p1->bal = 0; + *ppr = p2; + } /*else*/ + (*ppr)->bal = 0; + *pi_balance = FALSE; + } /*switch*/ + } /*if*/ + RET(sub) + } /*if*/ + + /* if MORE, prepare to move to the right. + */ + if (cmp > 0) { + MSG("MORE: sprouting to the right") + sub = sprout(&(*ppr)->right, p_data, pi_balance, + pfi_compare, pfv_delete); + if (sub && *pi_balance) { + MSG("MORE: right branch has grown") + + switch ((*ppr)->bal) { + case -1: + MSG("MORE: balance was off, fixed implicitly") + (*ppr)->bal = 0; + *pi_balance = FALSE; + break; + case 0: + MSG("MORE: balance was okay, now off but ok") + (*ppr)->bal = 1; + break; + case 1: + MSG("MORE: balance was off, need to rebalance") + p1 = (*ppr)->right; + if (p1->bal == 1) { /* RR */ + MSG("MORE: single RR") + (*ppr)->right = p1->left; + p1->left = *ppr; + (*ppr)->bal = 0; + *ppr = p1; + } else { /* double RL */ + MSG("MORE: double RL") + + p2 = p1->left; + p1->left = p2->right; + p2->right = p1; + + (*ppr)->right = p2->left; + p2->left = *ppr; + + if (p2->bal == 1) + (*ppr)->bal = -1; + else + (*ppr)->bal = 0; + + if (p2->bal == -1) + p1->bal = 1; + else + p1->bal = 0; + + *ppr = p2; + } /*else*/ + (*ppr)->bal = 0; + *pi_balance = FALSE; + } /*switch*/ + } /*if*/ + RET(sub) + } /*if*/ + + /* not less, not more: this is the same key! replace... + */ + MSG("FOUND: Replacing data value") + *pi_balance = FALSE; + if (pfv_delete) + (*pfv_delete)((*ppr)->data); + (*ppr)->data = p_data; + RET(*ppr) +} + +static int +delete(tree **ppr_p, int (*pfi_compare)(), tree_t p_user, + void (*pfv_uar)(), int *pi_balance, int *pi_uar_called) +{ + tree *pr_q; + int i_comp, i_ret; + + ENTER("delete") + + if (*ppr_p == NULL) { + MSG("key not in tree") + RET(FALSE) + } + + i_comp = (*pfi_compare)((*ppr_p)->data, p_user); + if (i_comp > 0) { + MSG("too high - scan left") + i_ret = delete(&(*ppr_p)->left, pfi_compare, p_user, pfv_uar, + pi_balance, pi_uar_called); + if (*pi_balance) + bal_L(ppr_p, pi_balance); + } else if (i_comp < 0) { + MSG("too low - scan right") + i_ret = delete(&(*ppr_p)->right, pfi_compare, p_user, pfv_uar, + pi_balance, pi_uar_called); + if (*pi_balance) + bal_R(ppr_p, pi_balance); + } else { + MSG("equal") + pr_q = *ppr_p; + if (pr_q->right == NULL) { + MSG("right subtree null") + *ppr_p = pr_q->left; + *pi_balance = TRUE; + } else if (pr_q->left == NULL) { + MSG("right subtree non-null, left subtree null") + *ppr_p = pr_q->right; + *pi_balance = TRUE; + } else { + MSG("neither subtree null") + del(&pr_q->left, pi_balance, &pr_q, + pfv_uar, pi_uar_called); + if (*pi_balance) + bal_L(ppr_p, pi_balance); + } + if (!*pi_uar_called && pfv_uar) + (*pfv_uar)(pr_q->data); + /* Thanks to wuth@castrov.cuc.ab.ca for the following stmt. */ + memput(pr_q, sizeof(tree)); + i_ret = TRUE; + } + RET(i_ret) +} + +static void +del(tree **ppr_r, int *pi_balance, tree **ppr_q, + void (*pfv_uar)(), int *pi_uar_called) +{ + ENTER("del") + + if ((*ppr_r)->right != NULL) { + del(&(*ppr_r)->right, pi_balance, ppr_q, + pfv_uar, pi_uar_called); + if (*pi_balance) + bal_R(ppr_r, pi_balance); + } else { + if (pfv_uar) + (*pfv_uar)((*ppr_q)->data); + *pi_uar_called = TRUE; + (*ppr_q)->data = (*ppr_r)->data; + *ppr_q = *ppr_r; + *ppr_r = (*ppr_r)->left; + *pi_balance = TRUE; + } + + RETV +} + +static void +bal_L(tree **ppr_p, int *pi_balance) { + tree *p1, *p2; + int b1, b2; + + ENTER("bal_L") + MSG("left branch has shrunk") + + switch ((*ppr_p)->bal) { + case -1: + MSG("was imbalanced, fixed implicitly") + (*ppr_p)->bal = 0; + break; + case 0: + MSG("was okay, is now one off") + (*ppr_p)->bal = 1; + *pi_balance = FALSE; + break; + case 1: + MSG("was already off, this is too much") + p1 = (*ppr_p)->right; + b1 = p1->bal; + if (b1 >= 0) { + MSG("single RR") + (*ppr_p)->right = p1->left; + p1->left = *ppr_p; + if (b1 == 0) { + MSG("b1 == 0") + (*ppr_p)->bal = 1; + p1->bal = -1; + *pi_balance = FALSE; + } else { + MSG("b1 != 0") + (*ppr_p)->bal = 0; + p1->bal = 0; + } + *ppr_p = p1; + } else { + MSG("double RL") + p2 = p1->left; + b2 = p2->bal; + p1->left = p2->right; + p2->right = p1; + (*ppr_p)->right = p2->left; + p2->left = *ppr_p; + if (b2 == 1) + (*ppr_p)->bal = -1; + else + (*ppr_p)->bal = 0; + if (b2 == -1) + p1->bal = 1; + else + p1->bal = 0; + *ppr_p = p2; + p2->bal = 0; + } + } + RETV +} + +static void +bal_R(tree **ppr_p, int *pi_balance) { + tree *p1, *p2; + int b1, b2; + + ENTER("bal_R") + MSG("right branch has shrunk") + switch ((*ppr_p)->bal) { + case 1: + MSG("was imbalanced, fixed implicitly") + (*ppr_p)->bal = 0; + break; + case 0: + MSG("was okay, is now one off") + (*ppr_p)->bal = -1; + *pi_balance = FALSE; + break; + case -1: + MSG("was already off, this is too much") + p1 = (*ppr_p)->left; + b1 = p1->bal; + if (b1 <= 0) { + MSG("single LL") + (*ppr_p)->left = p1->right; + p1->right = *ppr_p; + if (b1 == 0) { + MSG("b1 == 0") + (*ppr_p)->bal = -1; + p1->bal = 1; + *pi_balance = FALSE; + } else { + MSG("b1 != 0") + (*ppr_p)->bal = 0; + p1->bal = 0; + } + *ppr_p = p1; + } else { + MSG("double LR") + p2 = p1->right; + b2 = p2->bal; + p1->right = p2->left; + p2->left = p1; + (*ppr_p)->left = p2->right; + p2->right = *ppr_p; + if (b2 == -1) + (*ppr_p)->bal = 1; + else + (*ppr_p)->bal = 0; + if (b2 == 1) + p1->bal = -1; + else + p1->bal = 0; + *ppr_p = p2; + p2->bal = 0; + } + } + RETV +} Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/tree.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/tree.mdoc =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/tree.mdoc (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/tree.mdoc (revision 60942) @@ -0,0 +1,154 @@ +.\" $Id: tree.mdoc,v 8.2 1999/01/08 19:25:48 vixie 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 April 5, 1994 +.Dt TREE 3 +.Os BSD 4 +.Sh NAME +.Nm tree_init , +.Nm tree_mung , +.Nm tree_srch , +.Nm tree_add , +.Nm tree_delete , +.Nm tree_trav +.Nd balanced binary tree routines +.Sh SYNOPSIS +.Ft void +.Fn tree_init "void **tree" +.Ft void * +.Fn tree_srch "void **tree" "int (*compare)()" "void *data" +.Ft void +.Fn tree_add(tree, compare, data, del_uar) "void **tree" "int (*compare)()" \ +"void *data" "void (*del_uar)()" +.Ft int +.Fn tree_delete(tree, compare, data, del_uar) "void **tree" "int (*compare)()" \ +"void *data" "void (*del_uar)()" +.Ft int +.Fn tree_trav(tree, trav_uar) "void **tree" "int (*trav_uar)()" +.Ft void +.Fn tree_mung(tree, del_uar) "void **tree" "void (*del_uar)()" +.Sh DESCRIPTION +These functions create and manipulate a balanced binary (AVL) tree. Each node +of the tree contains the expected left & right subtree pointers, a short int +balance indicator, and a pointer to the user data. On a 32 bit system, this +means an overhead of 4+4+2+4 bytes per node (or, on a RISC or otherwise +alignment constrained system with implied padding, 4+4+4+4 bytes per node). +There is no key data type enforced by this package; a caller supplied +compare routine is used to compare user data blocks. +.Pp +Balanced binary trees are very fast on searches and replacements, but have a +moderately high cost for additions and deletions. If your application does a +lot more searches and replacements than it does additions and deletions, the +balanced (AVL) binary tree is a good choice for a data structure. +.Pp +.Fn Tree_init +creates an empty tree and binds it to +.Dq Fa tree +(which for this and all other routines in this package should be declared as +a pointer to void or int, and passed by reference), which can then be used by +other routines in this package. Note that more than one +.Dq Fa tree +variable can exist at once; thus multiple trees can be manipulated +simultaneously. +.Pp +.Fn Tree_srch +searches a tree for a specific node and returns either +.Fa NULL +if no node was found, or the value of the user data pointer if the node +was found. +.Fn compare +is the address of a function to compare two user data blocks. This routine +should work much the way +.Xr strcmp 3 +does; in fact, +.Xr strcmp +could be used if the user data was a \s-2NUL\s+2 terminated string. +.Dq Fa Data +is the address of a user data block to be used by +.Fn compare +as the search criteria. The tree is searched for a node where +.Fn compare +returns 0. +.Pp +.Fn Tree_add +inserts or replaces a node in the specified tree. The tree specified by +.Dq Fa tree +is searched as in +.Fn tree_srch, +and if a node is found to match +.Dq Fa data, +then the +.Fn del_uar +function, if non\-\s-2NULL\s+2, is called with the address of the user data +block for the node (this routine should deallocate any dynamic memory which +is referenced exclusively by the node); the user data pointer for the node +is then replaced by the value of +.Dq Fa data. +If no node is found to match, a new node is added (which may or may not +cause a transparent rebalance operation), with a user data pointer equal to +.Dq Fa data. +A rebalance may or may not occur, depending on where the node is added +and what the rest of the tree looks like. +.Fn Tree_add +will return the +.Dq Fa data +pointer unless catastrophe occurs in which case it will return \s-2NULL\s+2. +.Pp +.Fn Tree_delete +deletes a node from +.Dq Fa tree. +A rebalance may or may not occur, depending on where the node is removed from +and what the rest of the tree looks like. +.Fn Tree_delete +returns TRUE if a node was deleted, FALSE otherwise. +.Pp +.Fn Tree_trav +traverses all of +.Dq Fa tree, +calling +.Fn trav_uar +with the address of each user data block. If +.Fn trav_uar +returns FALSE at any time, +.Fn tree_trav +will immediately return FALSE to its caller. Otherwise all nodes will be +reached and +.Fn tree_trav +will return TRUE. +.Pp +.Fn Tree_mung +deletes every node in +.Dq Fa tree, +calling +.Fn del_uar +(if it is not \s-2NULL\s+2) with the user data address from each node (see +.Fn tree_add +and +.Fn tree_delete +above). The tree is left in the same state that +.Fn tree_init +leaves it in \- i.e., empty. +.Sh BUGS +Should have a way for the caller to specify application-specific +.Xr malloc +and +.Xr free +functions to be used internally when allocating meta data. +.Sh AUTHOR +Paul Vixie, converted and augumented from Modula\-2 examples in +.Dq Algorithms & Data Structures , +Niklaus Wirth, Prentice\-Hall, ISBN 0\-13\-022005\-1. Property changes on: vendor/bind/8.2.3.t5b/contrib/bind/lib/isc/tree.mdoc ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/Makefile (revision 60942) @@ -0,0 +1,91 @@ +# +# 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.19 2000/02/29 03:38:23 vixie 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= bsdos +DESTDIR = +DESTLIB = /usr/local/lib +O=o +A=a +CC= cc +LD= ld +SHELL= /bin/sh +CDEBUG= -g +TOP= ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.${A} +LIBBINDR = ../${TOP}/lib/libbind_r.${A} +CFLAGS= ${CDEBUG} -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}: + if test ! -d ${THREADED} ; then mkdir ${THREADED} ; else true ; fi + ${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.2.3.t5b/contrib/bind/lib/nameser/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_name.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_name.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_name.c (revision 60942) @@ -0,0 +1,670 @@ +/* + * 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.15 2000/03/30 22:53:46 vixie Exp $"; +#endif + +#include "port_before.h" + +#include + +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +/* Data. */ + +static const char digits[] = "0123456789"; + +/* 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 *); + +/* 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; + + cp = src; + dn = dst; + eom = dst + dstsiz; + + while ((n = *cp++) != 0) { + if ((n & NS_CMPRSFLGS) != 0) { + /* Some kind of compression pointer. */ + errno = EMSGSIZE; + return (-1); + } + if (dn != dst) { + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '.'; + } + if (dn + n >= eom) { + errno = EMSGSIZE; + return (-1); + } + for ((void)NULL; n > 0; n--) { + 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; + char *cp; + + escaped = 0; + bp = dst; + eom = dst + dstsiz; + label = bp++; + + while ((c = *src++) != 0) { + if (escaped) { + 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); + } + 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; + + cp = src; + dn = dst; + eom = dst + dstsiz; + + while ((n = *cp++) != 0) { + if ((n & NS_CMPRSFLGS) != 0) { + /* Some kind of compression pointer. */ + errno = EMSGSIZE; + return (-1); + } + *dn++ = n; + if (dn + n >= eom) { + errno = EMSGSIZE; + return (-1); + } + for ((void)NULL; n > 0; n--) { + 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; + + 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: + /* Limit checks. */ + if (dstp + n + 1 >= dstlim || srcp + n >= eom) { + errno = EMSGSIZE; + return (-1); + } + checked += n + 1; + *dstp++ = n; + memcpy(dstp, srcp, n); + dstp += n; + srcp += n; + 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 { + n = *srcp; + if ((n & NS_CMPRSFLGS) != 0) { + errno = EMSGSIZE; + return (-1); + } + l += n + 1; + if (l > MAXCDNAME) { + errno = EMSGSIZE; + return (-1); + } + srcp += n + 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) { /* Should not happen. */ + goto cleanup; + } + 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; + + 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_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: /* '\\' */ + /* 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 */ + 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); +} Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/nameser/ns_print.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_print.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_print.c (revision 60942) @@ -0,0 +1,821 @@ +/* + * 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.18 2000/02/29 05:48:12 vixie 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 (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] != '.') { + 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)); + 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: + 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[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, siz; + char base64_cert[8192], *leader, tmp[40]; + + 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) { + 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_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; + } + + default: + comment = "unknown RR type"; + goto hexify; + } + return (buf - obuf); + formerr: + comment = "RR format error"; + hexify: { + int n, m; + char *p; + + len = SPRINTF((tmp, "\\#(\t\t; %s", 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 (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. */ + 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/nameser/ns_verify.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_verify.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_verify.c (revision 60942) @@ -0,0 +1,479 @@ +/* + * 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.13 2000/03/29 15:55:00 bwelling 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 "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 > 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; + 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/nameser/ns_date.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_date.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_date.c (revision 60942) @@ -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.2 1999/10/13 16:39:35 vixie 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(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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/nameser/ns_netint.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_netint.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_netint.c (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/nameser/ns_parse.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_parse.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_parse.c (revision 60942) @@ -0,0 +1,198 @@ +/* + * 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.13 1999/10/13 16:39:35 vixie 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_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 < 0 || 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->_ptr, handle->_eom, section, + rrnum - handle->_rrnum); + + if (b < 0) + return (-1); + handle->_ptr += b; + handle->_rrnum = rrnum; + } + + /* Do the parse. */ + b = dn_expand(handle->_msg, handle->_eom, + handle->_ptr, rr->name, NS_MAXDNAME); + if (b < 0) + return (-1); + handle->_ptr += b; + if (handle->_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom) + RETERR(EMSGSIZE); + NS_GET16(rr->type, handle->_ptr); + NS_GET16(rr->rr_class, handle->_ptr); + if (section == ns_s_qd) { + rr->ttl = 0; + rr->rdlength = 0; + rr->rdata = NULL; + } else { + if (handle->_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom) + RETERR(EMSGSIZE); + NS_GET32(rr->ttl, handle->_ptr); + NS_GET16(rr->rdlength, handle->_ptr); + if (handle->_ptr + rr->rdlength > handle->_eom) + RETERR(EMSGSIZE); + rr->rdata = handle->_ptr; + handle->_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->_ptr = NULL; + } else { + msg->_rrnum = 0; + msg->_ptr = msg->_sections[(int)sect]; + } +} Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/nameser/ns_samedomain.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_samedomain.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_samedomain.c (revision 60942) @@ -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 1999/10/15 21:06:51 vixie 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/nameser/ns_sign.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_sign.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_sign.c (revision 60942) @@ -0,0 +1,348 @@ +/* + * 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.8 1999/10/13 16:39:36 vixie 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 "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) +{ + 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, NULL, NULL); + 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 > 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) +{ + 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_sign(msg, msglen, msgsize, error, state->key, + state->sig, state->siglen, + state->sig, &state->siglen, 0)); + + 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, NULL, NULL); + 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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/nameser/ns_ttl.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_ttl.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/nameser/ns_ttl.c (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/resolv/Makefile =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/Makefile (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/Makefile (revision 60942) @@ -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.33 2000/02/29 03:38:24 vixie 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= bsdos +DESTDIR = +DESTLIB = /usr/local/lib +O=o +A=a +CC= cc +LD= ld +SHELL= /bin/sh +CDEBUG= -g +TOP= ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.${A} +LIBBINDR = ../${TOP}/lib/libbind_r.${A} +CFLAGS= ${CDEBUG} -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}: + if test ! -d ${THREADED} ; then mkdir ${THREADED} ; else true ; fi + ${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.2.3.t5b/contrib/bind/lib/resolv/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/res_debug.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/res_debug.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/res_debug.c (revision 60942) @@ -0,0 +1,1045 @@ +/* + * 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.34 2000/02/29 05:30:55 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" + +#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 { + 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"}, + {C_CHAOS, "CHAOS"}, + {C_HS, "HS"}, + {C_HS, "HESIOD"}, + {C_ANY, "ANY"}, + {C_NONE, "NONE"}, + {C_IN, (char *)0} +}; + +/* + * Names of message sections. + */ +const struct res_sym __p_default_section_syms[] = { + {ns_s_qd, "QUERY"}, + {ns_s_an, "ANSWER"}, + {ns_s_ns, "AUTHORITY"}, + {ns_s_ar, "ADDITIONAL"}, + {0, (char *)0} +}; + +const struct res_sym __p_update_section_syms[] = { + {S_ZONE, "ZONE"}, + {S_PREREQ, "PREREQUISITE"}, + {S_UPDATE, "UPDATE"}, + {S_ADDT, "ADDITIONAL"}, + {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_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_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) { + return (sym_ntos(__p_type_syms, type, (int *)0)); +} + +/* + * 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) { + return (sym_ntos(__p_class_syms, class, (int *)0)); +} + +/* + * 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"; + /* 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, "%ld.%.2ld", val/100, val%100); + return (retbuf); +} + +/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */ +static u_int8_t +precsize_aton(strptr) + char **strptr; +{ + unsigned int mval = 0, cmval = 0; + u_int8_t retval = 0; + char *cp; + int exponent; + int mantissa; + + cp = *strptr; + + while (isdigit(*cp)) + mval = mval * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* centimeters */ + cp++; + if (isdigit(*cp)) { + cmval = (*cp++ - '0') * 10; + if (isdigit(*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(latlonstrptr,which) + char **latlonstrptr; + int *which; +{ + char *cp; + u_int32_t retval; + int deg = 0, min = 0, secs = 0, secsfrac = 0; + + cp = *latlonstrptr; + + while (isdigit(*cp)) + deg = deg * 10 + (*cp++ - '0'); + + while (isspace(*cp)) + cp++; + + if (!(isdigit(*cp))) + goto fndhemi; + + while (isdigit(*cp)) + min = min * 10 + (*cp++ - '0'); + + while (isspace(*cp)) + cp++; + + if (!(isdigit(*cp))) + goto fndhemi; + + while (isdigit(*cp)) + secs = secs * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* decimal seconds */ + cp++; + if (isdigit(*cp)) { + secsfrac = (*cp++ - '0') * 100; + if (isdigit(*cp)) { + secsfrac += (*cp++ - '0') * 10; + if (isdigit(*cp)) { + secsfrac += (*cp++ - '0'); + } + } + } + } + + while (!isspace(*cp)) /* if any trailing garbage */ + cp++; + + while (isspace(*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(*cp)) /* if any trailing garbage */ + cp++; + + while (isspace(*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(*cp)) + altmeters = altmeters * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* decimal meters */ + cp++; + if (isdigit(*cp)) { + altfrac = (*cp++ - '0') * 10; + if (isdigit(*cp)) { + altfrac += (*cp++ - '0'); + } + } + } + + alt = (10000000 + (altsign * (altmeters * 100 + altfrac))); + + while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */ + cp++; + + while (isspace(*cp) && (cp < maxcp)) + cp++; + + if (cp >= maxcp) + goto defaults; + + siz = precsize_aton(&cp); + + while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */ + cp++; + + while (isspace(*cp) && (cp < maxcp)) + cp++; + + if (cp >= maxcp) + goto defaults; + + hp = precsize_aton(&cp); + + while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */ + cp++; + + while (isspace(*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 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; + int altmeters, altfrac, altsign; + + 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 = -1; + } else { + altval = templ - referencealt; + altsign = 1; + } + + 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) * altsign; + + if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL) + sizestr = error; + if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL) + hpstr = error; + if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL) + vpstr = error; + + sprintf(ascii, + "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm", + latdeg, latmin, latsec, latsecfrac, northsouth, + longdeg, longmin, longsec, longsecfrac, eastwest, + altmeters, altfrac, sizestr, hpstr, vpstr); + + if (sizestr != error) + free(sizestr); + if (hpstr != error) + free(hpstr); + if (vpstr != error) + 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); +} Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/resolv/res_debug.h =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/res_debug.h (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/res_debug.h (revision 60942) @@ -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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/resolv/res_findzonecut.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/res_findzonecut.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/res_findzonecut.c (revision 60942) @@ -0,0 +1,601 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: res_findzonecut.c,v 8.9 1999/12/21 09:33:34 cyarnell 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 + +#include "port_after.h" + +/* Data structures. */ + +typedef struct rr_a { + LINK(struct rr_a) link; + struct in_addr addr; +} rr_a; +typedef LIST(rr_a) rrset_a; + +typedef struct rr_ns { + LINK(struct rr_ns) link; + const char * name; + rrset_a addrs; +} rr_ns; +typedef LIST(rr_ns) rrset_ns; + +/* Forward. */ + +static int satisfy(res_state, + const char *, rrset_ns *, struct in_addr *, int); +static int add_addrs(res_state, rr_ns *, struct in_addr *, int); +static int get_soa(res_state, const char *, ns_class, + char *, size_t, char *, size_t, + rrset_ns *); +static int get_ns(res_state, const char *, ns_class, rrset_ns *); +static int get_glue(res_state, ns_class, rrset_ns *); +static int save_ns(res_state, ns_msg *, ns_sect, + const char *, ns_class, rrset_ns *); +static int save_a(res_state, ns_msg *, ns_sect, + const char *, ns_class, rrset_a *); +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 dprintf(const char *, ...); + +/* Macros. */ + +#define DPRINTF(x) do {\ + int save_errno = errno; \ + if ((statp->options & RES_DEBUG) != 0) 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. + * + * we cannot fail to find an SOA in this way. ultimately we'll return + * a zname indicating the root zone if that's the closest enclosing zone. + * 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) +{ + 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, 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, &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, &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, struct in_addr *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, struct in_addr *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, + 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, 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, 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('zname', %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, 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, 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 (EMPTY(nsrr->addrs)) { + 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, + &nsrr->addrs) < 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, + 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_LIST(nsrr->addrs); + APPEND(*nsrrsp, nsrr, link); + } + if (save_a(statp, msg, ns_s_ar, + nsrr->name, class, &nsrr->addrs) < 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, + rrset_a *arrsp) +{ + 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_class(rr) != class || + ns_samename(ns_rr_name(rr), owner) != 1 || + ns_rr_rdlen(rr) != NS_INADDRSZ) + continue; + arr = malloc(sizeof *arr); + if (arr == NULL) { + DPRINTF(("save_a: malloc failed")); + return (-1); + } + memcpy(&arr->addr, ns_rr_rdata(rr), NS_INADDRSZ); + APPEND(*arrsp, 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; + + while ((arr = HEAD(nsrr->addrs)) != NULL) { + UNLINK(nsrr->addrs, arr, link); + free(arr); + } + free((char *)nsrr->name); + 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 +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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/resolv/res_init.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/res_init.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/res_init.c (revision 60942) @@ -0,0 +1,502 @@ +/* + * 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.16 2000/05/09 07:10:12 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 "port_after.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(); + } + +#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); + 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; + + /* 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 in_addr a; + + cp = buf + sizeof("nameserver") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) { + statp->nsaddr_list[nserv].sin_addr = a; + statp->nsaddr_list[nserv].sin_family = AF_INET; + statp->nsaddr_list[nserv].sin_port = + htons(NAMESERVER_PORT); + 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(*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(*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); + } + 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; + +#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, "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; + } else { + /* XXX - print a warning here? */ + } + /* 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; + } + } + statp->_u._ext.nscount = 0; +} Property changes on: vendor/bind/8.2.3.t5b/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.2.3.t5b/contrib/bind/lib/resolv/res_query.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/res_query.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/res_query.c (revision 60942) @@ -0,0 +1,407 @@ +/* + * 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.20 2000/02/29 05:39:12 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 "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; + + 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)); + 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 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; + + 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++) { + + 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 name has any dots at all, and no earlier 'as-is' query + * for the name, and "." is not on the search list, then try an as-is + * query now. + */ + if (statp->ndots && !(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(*cp1); ++cp1) + ; + if (!*cp1) + break; + *cp1 = '\0'; + if (ns_samename(buf, name) == 1) { + while (isspace(*++cp1)) + ; + if (!*cp1) + break; + for (cp2 = cp1 + 1; *cp2 && !isspace(*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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/resolv/res_send.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/res_send.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/res_send.c (revision 60942) @@ -0,0 +1,859 @@ +/* + * 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.38 2000/03/30 20:16:51 vixie 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" + +#define EXT(res) ((res)->_u._ext) + +static const int highestFD = FD_SETSIZE - 1; + +/* Forward. */ + +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, + struct sockaddr_in); +static void Perror(const res_state, FILE *, const char *, int); +static int sock_eq(struct sockaddr_in *, struct sockaddr_in *); +#ifdef NEED_PSELECT +static int pselect(int, void *, void *, void *, + struct timespec *, + const sigset_t *); +#endif + +/* Reachover. */ + +void res_pquery(const res_state, const u_char *, int, FILE *); + +/* 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_in *inp) { + struct sockaddr_in ina; + int ns; + + ina = *inp; + for (ns = 0; ns < statp->nscount; ns++) { + const struct sockaddr_in *srv = &statp->nsaddr_list[ns]; + + if (srv->sin_family == ina.sin_family && + srv->sin_port == ina.sin_port && + (srv->sin_addr.s_addr == INADDR_ANY || + srv->sin_addr.s_addr == ina.sin_addr.s_addr)) + return (1); + } + 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(((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(((HEADER*)buf1)->qdcount); + + if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2) + return (-1); + + /* + * Only header section present in replies to + * dynamic update packets. + */ + if ((((HEADER *)buf1)->opcode == ns_o_update) && + (((HEADER *)buf2)->opcode == ns_o_update)) + return (1); + + if (qdcount != ntohs(((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; + + 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; + + if (EXT(statp).nscount != statp->nscount) + needclose++; + else + for (ns = 0; ns < statp->nscount; ns++) + if (!sock_eq(&statp->nsaddr_list[ns], + &EXT(statp).nsaddrs[ns])) { + needclose++; + break; + } + if (needclose) + res_nclose(statp); + } + + /* + * Maybe initialize our private copy of the ns_addr_list. + */ + if (EXT(statp).nscount == 0) { + for (ns = 0; ns < statp->nscount; ns++) { + EXT(statp).nsaddrs[ns] = statp->nsaddr_list[ns]; + EXT(statp).nstimes[ns] = RES_MAXTIME; + EXT(statp).nssocks[ns] = -1; + } + 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) { + struct sockaddr_in ina; + int lastns = statp->nscount - 1; + + ina = statp->nsaddr_list[0]; + for (ns = 0; ns < lastns; ns++) + statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1]; + statp->nsaddr_list[lastns] = ina; + } + + /* + * Send request, RETRY times, or until successful. + */ + for (try = 0; try < statp->retry; try++) { + for (ns = 0; ns < statp->nscount; ns++) { + struct sockaddr_in *nsap = &statp->nsaddr_list[ns]; + 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: + return (-1); + } + } while (!done); + } + + Dprint(statp->options & RES_DEBUG, + (stdout, ";; Querying server (# %d) address = %s\n", + ns + 1, inet_ntoa(nsap->sin_addr))); + + 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) + return (-1); + 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) + return (-1); + 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, ""), + 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: + return (-1); + } + } 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); +} + +/* Private */ + +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 = (HEADER *) buf; + HEADER *anhp = (HEADER *) ans; + struct sockaddr_in *nsap = &statp->nsaddr_list[ns]; + int truncating, connreset, resplen, n; + struct iovec iov[2]; + u_short len; + u_char *cp; + + 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_in peer; + int size = sizeof peer; + + if (getpeername(statp->_vcsock, + (struct sockaddr *)&peer, &size) < 0 || + !sock_eq(&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(PF_INET, 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, (struct sockaddr *)nsap, + sizeof *nsap) < 0) { + *terrno = errno; + Aerror(statp, stderr, "connect/vc", errno, *nsap); + 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); + iov[1] = evConsIovec((void*)buf, 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 = (HEADER *) buf; + HEADER *anhp = (HEADER *) ans; + const struct sockaddr_in *nsap = &statp->nsaddr_list[ns]; + struct timespec now, timeout, finish; + fd_set dsmask; + struct sockaddr_in from; + int fromlen, resplen, seconds, n, s; + + if (EXT(statp).nssocks[ns] == -1) { + EXT(statp).nssocks[ns] = socket(PF_INET, 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], (struct sockaddr *)nsap, + sizeof *nsap) < 0) { + Aerror(statp, stderr, "connect(dg)", errno, *nsap); + 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, (char*)buf, buflen, 0) != buflen) { + Perror(statp, stderr, "send", errno); + res_nclose(statp); + return (0); + } +#else /* !CANNOT_CONNECT_DGRAM */ + if (sendto(s, (char*)buf, buflen, 0, + (struct sockaddr *)nsap, sizeof *nsap) != buflen) + { + Aerror(statp, stderr, "sendto", errno, *nsap); + 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); + wait: + FD_ZERO(&dsmask); + FD_SET(s, &dsmask); + 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) { + now = evNowTime(); + if (evCmpTime(finish, now) > 0) { + timeout = evSubTime(finish, now); + goto wait; + } + } + Perror(statp, stderr, "select", errno); + res_nclose(statp); + return (0); + } + errno = 0; + fromlen = sizeof(struct sockaddr_in); + 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, &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; + } + 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, + struct sockaddr_in address) +{ + int save = errno; + + if ((statp->options & RES_DEBUG) != 0) { + char tmp[sizeof "255.255.255.255"]; + + fprintf(file, "res_send: %s ([%s].%u): %s\n", + string, + inet_ntop(address.sin_family, &address.sin_addr, + tmp, sizeof tmp), + ntohs(address.sin_port), + 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_in *a1, struct sockaddr_in *a2) { + return ((a1->sin_family == a2->sin_family) && + (a1->sin_port == a2->sin_port) && + (a1->sin_addr.s_addr == a2->sin_addr.s_addr)); +} + +#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.2.3.t5b/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.2.3.t5b/contrib/bind/lib/resolv/herror.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/herror.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/herror.c (revision 60942) @@ -0,0 +1,121 @@ +/* + * 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.11 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 + +#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; + extern int * __h_errno(); + + if (s != NULL && *s != '\0') { + v->iov_base = (/*noconst*/ char *)s; + v->iov_len = strlen(s); + v++; + v->iov_base = ": "; + v->iov_len = 2; + v++; + } + v->iov_base = (char *)hstrerror(*__h_errno()); + v->iov_len = strlen(v->iov_base); + v++; + v->iov_base = "\n"; + 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.2.3.t5b/contrib/bind/lib/resolv/herror.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/res_comp.c =================================================================== --- vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/res_comp.c (nonexistent) +++ vendor/bind/8.2.3.t5b/contrib/bind/lib/resolv/res_comp.c (revision 60942) @@ -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