summaryrefslogtreecommitdiffstats
path: root/contrib/bind/lib
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1999-11-30 02:43:11 +0000
committerpeter <peter@FreeBSD.org>1999-11-30 02:43:11 +0000
commit4ef23ce6957fc75fc005885496d605fed48213e1 (patch)
tree7828b08c74ef918938b1b853c98f0cb41edac52c /contrib/bind/lib
parent67e0f3ce71726dc4058c2f80a813341a59244dbd (diff)
downloadFreeBSD-src-4ef23ce6957fc75fc005885496d605fed48213e1.zip
FreeBSD-src-4ef23ce6957fc75fc005885496d605fed48213e1.tar.gz
Import bind v8.2.2.p5, minus the crypto for the time being. The bind
package does have BXA export approval, but the licensing strings on the dnssafe code are a bit unpleasant. The crypto is easy to restore and bind will run without it - just without full dnssec support. Obtained from: The Internet Software Consortium (www.isc.org)
Diffstat (limited to 'contrib/bind/lib')
-rw-r--r--contrib/bind/lib/Makefile39
-rw-r--r--contrib/bind/lib/dst/Makefile96
-rw-r--r--contrib/bind/lib/dst/README27
-rw-r--r--contrib/bind/lib/dst/bsafe_link.c1125
-rw-r--r--contrib/bind/lib/dst/cylink_link.c676
-rw-r--r--contrib/bind/lib/dst/dst_api.c1068
-rw-r--r--contrib/bind/lib/dst/dst_internal.h163
-rw-r--r--contrib/bind/lib/dst/eay_dss_link.c624
-rw-r--r--contrib/bind/lib/dst/hmac_link.c493
-rw-r--r--contrib/bind/lib/dst/md5.h101
-rw-r--r--contrib/bind/lib/dst/md5_dgst.c368
-rw-r--r--contrib/bind/lib/dst/md5_locl.h190
-rw-r--r--contrib/bind/lib/dst/prandom.c851
-rw-r--r--contrib/bind/lib/dst/rsaref_link.c754
-rw-r--r--contrib/bind/lib/dst/support.c461
-rw-r--r--contrib/bind/lib/inet/Makefile29
-rw-r--r--contrib/bind/lib/inet/inet_addr.c78
-rw-r--r--contrib/bind/lib/inet/inet_cidr_ntop.c129
-rw-r--r--contrib/bind/lib/inet/inet_cidr_pton.c153
-rw-r--r--contrib/bind/lib/inet/inet_lnaof.c2
-rw-r--r--contrib/bind/lib/inet/inet_makeaddr.c2
-rw-r--r--contrib/bind/lib/inet/inet_net_ntop.c7
-rw-r--r--contrib/bind/lib/inet/inet_net_pton.c41
-rw-r--r--contrib/bind/lib/inet/inet_neta.c4
-rw-r--r--contrib/bind/lib/inet/inet_netof.c2
-rw-r--r--contrib/bind/lib/inet/inet_network.c15
-rw-r--r--contrib/bind/lib/inet/inet_ntoa.c6
-rw-r--r--contrib/bind/lib/inet/inet_ntop.c7
-rw-r--r--contrib/bind/lib/inet/inet_pton.c9
-rw-r--r--contrib/bind/lib/inet/nsap_addr.c4
-rw-r--r--contrib/bind/lib/irs/Makefile66
-rw-r--r--contrib/bind/lib/irs/Makefile.BSD5
-rw-r--r--contrib/bind/lib/irs/README4
-rw-r--r--contrib/bind/lib/irs/dns.c63
-rw-r--r--contrib/bind/lib/irs/dns_gr.c46
-rw-r--r--contrib/bind/lib/irs/dns_ho.c167
-rw-r--r--contrib/bind/lib/irs/dns_nw.c153
-rw-r--r--contrib/bind/lib/irs/dns_p.h13
-rw-r--r--contrib/bind/lib/irs/dns_pr.c42
-rw-r--r--contrib/bind/lib/irs/dns_pw.c46
-rw-r--r--contrib/bind/lib/irs/dns_sv.c49
-rw-r--r--contrib/bind/lib/irs/gai_strerror.c45
-rw-r--r--contrib/bind/lib/irs/gen.c107
-rw-r--r--contrib/bind/lib/irs/gen_gr.c73
-rw-r--r--contrib/bind/lib/irs/gen_ho.c150
-rw-r--r--contrib/bind/lib/irs/gen_ng.c20
-rw-r--r--contrib/bind/lib/irs/gen_nw.c110
-rw-r--r--contrib/bind/lib/irs/gen_p.h9
-rw-r--r--contrib/bind/lib/irs/gen_pr.c66
-rw-r--r--contrib/bind/lib/irs/gen_pw.c66
-rw-r--r--contrib/bind/lib/irs/gen_sv.c66
-rw-r--r--contrib/bind/lib/irs/getaddrinfo.c505
-rw-r--r--contrib/bind/lib/irs/getgrent.c180
-rw-r--r--contrib/bind/lib/irs/getgrent_r.c219
-rw-r--r--contrib/bind/lib/irs/gethostent.c765
-rw-r--r--contrib/bind/lib/irs/gethostent_r.c228
-rw-r--r--contrib/bind/lib/irs/getnameinfo.c230
-rw-r--r--contrib/bind/lib/irs/getnetent.c250
-rw-r--r--contrib/bind/lib/irs/getnetent_r.c191
-rw-r--r--contrib/bind/lib/irs/getnetgrent.c110
-rw-r--r--contrib/bind/lib/irs/getnetgrent_r.c134
-rw-r--r--contrib/bind/lib/irs/getprotoent.c139
-rw-r--r--contrib/bind/lib/irs/getprotoent_r.c185
-rw-r--r--contrib/bind/lib/irs/getpwent.c160
-rw-r--r--contrib/bind/lib/irs/getpwent_r.c253
-rw-r--r--contrib/bind/lib/irs/getservent.c150
-rw-r--r--contrib/bind/lib/irs/getservent_r.c206
-rw-r--r--contrib/bind/lib/irs/hesiod.c95
-rw-r--r--contrib/bind/lib/irs/hesiod_p.h9
-rw-r--r--contrib/bind/lib/irs/irp.c583
-rw-r--r--contrib/bind/lib/irs/irp_gr.c405
-rw-r--r--contrib/bind/lib/irs/irp_ho.c418
-rw-r--r--contrib/bind/lib/irs/irp_ng.c266
-rw-r--r--contrib/bind/lib/irs/irp_nw.c375
-rw-r--r--contrib/bind/lib/irs/irp_p.h61
-rw-r--r--contrib/bind/lib/irs/irp_pr.c353
-rw-r--r--contrib/bind/lib/irs/irp_pw.c356
-rw-r--r--contrib/bind/lib/irs/irp_sv.c369
-rw-r--r--contrib/bind/lib/irs/irpmarshall.c2332
-rw-r--r--contrib/bind/lib/irs/irs_data.c171
-rw-r--r--contrib/bind/lib/irs/irs_data.h19
-rw-r--r--contrib/bind/lib/irs/irs_p.h17
-rw-r--r--contrib/bind/lib/irs/lcl.c64
-rw-r--r--contrib/bind/lib/irs/lcl_gr.c37
-rw-r--r--contrib/bind/lib/irs/lcl_ho.c158
-rw-r--r--contrib/bind/lib/irs/lcl_ng.c19
-rw-r--r--contrib/bind/lib/irs/lcl_nw.c148
-rw-r--r--contrib/bind/lib/irs/lcl_p.h7
-rw-r--r--contrib/bind/lib/irs/lcl_pr.c70
-rw-r--r--contrib/bind/lib/irs/lcl_pw.c38
-rw-r--r--contrib/bind/lib/irs/lcl_sv.c344
-rw-r--r--contrib/bind/lib/irs/nis.c61
-rw-r--r--contrib/bind/lib/irs/nis_gr.c25
-rw-r--r--contrib/bind/lib/irs/nis_ho.c112
-rw-r--r--contrib/bind/lib/irs/nis_ng.c30
-rw-r--r--contrib/bind/lib/irs/nis_nw.c111
-rw-r--r--contrib/bind/lib/irs/nis_p.h8
-rw-r--r--contrib/bind/lib/irs/nis_pr.c21
-rw-r--r--contrib/bind/lib/irs/nis_pw.c43
-rw-r--r--contrib/bind/lib/irs/nis_sv.c22
-rw-r--r--contrib/bind/lib/irs/nul_ng.c11
-rw-r--r--contrib/bind/lib/irs/pathnames.h10
-rw-r--r--contrib/bind/lib/irs/util.c6
-rw-r--r--contrib/bind/lib/isc/Makefile28
-rw-r--r--contrib/bind/lib/isc/assertions.c4
-rw-r--r--contrib/bind/lib/isc/assertions.mdoc4
-rw-r--r--contrib/bind/lib/isc/base64.c4
-rw-r--r--contrib/bind/lib/isc/bitncmp.c4
-rw-r--r--contrib/bind/lib/isc/bitncmp.mdoc4
-rw-r--r--contrib/bind/lib/isc/ctl_clnt.c581
-rw-r--r--contrib/bind/lib/isc/ctl_p.c156
-rw-r--r--contrib/bind/lib/isc/ctl_p.h22
-rw-r--r--contrib/bind/lib/isc/ctl_srvr.c744
-rw-r--r--contrib/bind/lib/isc/ev_connects.c41
-rw-r--r--contrib/bind/lib/isc/ev_files.c15
-rw-r--r--contrib/bind/lib/isc/ev_streams.c9
-rw-r--r--contrib/bind/lib/isc/ev_timers.c6
-rw-r--r--contrib/bind/lib/isc/ev_waits.c9
-rw-r--r--contrib/bind/lib/isc/eventlib.c35
-rw-r--r--contrib/bind/lib/isc/eventlib.mdoc31
-rw-r--r--contrib/bind/lib/isc/eventlib_p.h6
-rw-r--r--contrib/bind/lib/isc/heap.c4
-rw-r--r--contrib/bind/lib/isc/heap.mdoc4
-rw-r--r--contrib/bind/lib/isc/logging.c28
-rw-r--r--contrib/bind/lib/isc/logging.mdoc4
-rw-r--r--contrib/bind/lib/isc/logging_p.h2
-rw-r--r--contrib/bind/lib/isc/memcluster.c213
-rw-r--r--contrib/bind/lib/isc/memcluster.mdoc4
-rw-r--r--contrib/bind/lib/isc/tree.c6
-rw-r--r--contrib/bind/lib/isc/tree.mdoc4
-rw-r--r--contrib/bind/lib/nameser/Makefile33
-rw-r--r--contrib/bind/lib/nameser/ns_date.c128
-rw-r--r--contrib/bind/lib/nameser/ns_name.c65
-rw-r--r--contrib/bind/lib/nameser/ns_netint.c10
-rw-r--r--contrib/bind/lib/nameser/ns_parse.c122
-rw-r--r--contrib/bind/lib/nameser/ns_print.c93
-rw-r--r--contrib/bind/lib/nameser/ns_samedomain.c206
-rw-r--r--contrib/bind/lib/nameser/ns_sign.c348
-rw-r--r--contrib/bind/lib/nameser/ns_ttl.c6
-rw-r--r--contrib/bind/lib/nameser/ns_verify.c471
-rw-r--r--contrib/bind/lib/resolv/Makefile36
-rw-r--r--contrib/bind/lib/resolv/herror.c37
-rw-r--r--contrib/bind/lib/resolv/res_comp.c8
-rw-r--r--contrib/bind/lib/resolv/res_data.c251
-rw-r--r--contrib/bind/lib/resolv/res_debug.c213
-rw-r--r--contrib/bind/lib/resolv/res_debug.h34
-rw-r--r--contrib/bind/lib/resolv/res_findzonecut.c596
-rw-r--r--contrib/bind/lib/resolv/res_init.c200
-rw-r--r--contrib/bind/lib/resolv/res_mkquery.c40
-rw-r--r--contrib/bind/lib/resolv/res_mkupdate.c721
-rw-r--r--contrib/bind/lib/resolv/res_mkupdate.h17
-rw-r--r--contrib/bind/lib/resolv/res_query.c180
-rw-r--r--contrib/bind/lib/resolv/res_send.c479
-rw-r--r--contrib/bind/lib/resolv/res_sendsigned.c130
-rw-r--r--contrib/bind/lib/resolv/res_update.c589
155 files changed, 24696 insertions, 2258 deletions
diff --git a/contrib/bind/lib/Makefile b/contrib/bind/lib/Makefile
index 5029f2f..18fa7c8 100644
--- a/contrib/bind/lib/Makefile
+++ b/contrib/bind/lib/Makefile
@@ -1,4 +1,4 @@
-# Copyright (c) 1996 by Internet Software Consortium
+# 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
@@ -13,9 +13,9 @@
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
# SOFTWARE.
-# $Id: Makefile,v 8.10 1997/09/26 17:56:00 halley Exp $
+# $Id: Makefile,v 8.22 1999/06/08 01:42:57 vixie Exp $
-SUBDIRS = resolv irs isc bsd inet nameser
+SUBDIRS = resolv irs isc bsd inet nameser dst
# 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
@@ -31,51 +31,70 @@ 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 cruv
+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}" "PIDDIR=${PIDDIR}" "DESTMAN=${DESTMAN}" \
+ "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}" \
+ "INCL=../${INCL}" "PORTINCL=../${PORTINCL}" "EXE=${EXE}" \
"LIBBIND=../${LIBBIND}" "LIBPORT=../${LIBPORT}" \
- "INSTALL=${INSTALL}" "CPPFLAGS=${CPPFLAGS}" "TOP=../${TOP}"
+ "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}
+all:: ${LIBTS} ${LIBRTS}
+
+${LIBRTS}: ${LIBBINDR}
+ ${RANLIB} ${LIBBINDR}
+ sleep 1 && touch ${LIBRTS}
${LIBTS}: ${LIBBIND}
${RANLIB} ${LIBBIND}
- touch ${LIBTS}
+ 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 -o bin -g bin -m 644 ${LIBBIND} \
+ ${INSTALL} -c ${INSTALL_LIB} -m 644 ${LIBBIND} \
${DESTDIR}${DESTLIB}/${LIB}
( cd ${DESTDIR}${DESTLIB} ; ${RANLIB} ${LIB} )
diff --git a/contrib/bind/lib/dst/Makefile b/contrib/bind/lib/dst/Makefile
new file mode 100644
index 0000000..f99813c
--- /dev/null
+++ b/contrib/bind/lib/dst/Makefile
@@ -0,0 +1,96 @@
+# Copyright (c) 1996,1999 by Internet Software Consortium
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+# CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+# PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+# SOFTWARE.
+
+# $Id: Makefile,v 1.13 1999/03/07 09:33:47 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=
+CRYPTFLAGS= -DHMAC_MD5 -DUSE_MD5
+
+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} ; fi
+ ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} ${REENTRANT} ${CRYPTINCL} ${CRYPTFLAGS} -c $*.c -o ${THREADED}/$*.${O}
+ -${LDS} ${LD} ${LD_LIBFLAGS} ${THREADED}/$*.${O} -o a.out && \
+ ${LDS} mv a.out ${THREADED}/$*.${O}
+ ${CC} ${CPPFLAGS} ${CFLAGS} ${CRYPTINCL} ${CRYPTFLAGS} -c $*.c
+ -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} -o a.out && \
+ ${LDS} mv a.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}
+ -rmdir ${THREADED}
+
+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.
diff --git a/contrib/bind/lib/dst/README b/contrib/bind/lib/dst/README
new file mode 100644
index 0000000..6283e58
--- /dev/null
+++ b/contrib/bind/lib/dst/README
@@ -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<path to rsa include files>
+
+ if you have BSAFE
+ CRYPTFLAGS must include -DBSAFE
+ CRYPTINCL must include -I<path to bsafe include files>
+
+ 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.
diff --git a/contrib/bind/lib/dst/bsafe_link.c b/contrib/bind/lib/dst/bsafe_link.c
new file mode 100644
index 0000000..8b24d99
--- /dev/null
+++ b/contrib/bind/lib/dst/bsafe_link.c
@@ -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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include "dst_internal.h"
+
+# ifdef __STDC__
+# define PROTOTYPES 1
+# else
+# define PROTOTYPES 0
+# endif
+
+# ifdef BSAFE
+# include <aglobal.h>
+# include <bsafe.h>
+# else
+# include <global.h>
+# include <bsafe2.h>
+# include <bigmaxes.h>
+# 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 */
diff --git a/contrib/bind/lib/dst/cylink_link.c b/contrib/bind/lib/dst/cylink_link.c
new file mode 100644
index 0000000..c7cb276
--- /dev/null
+++ b/contrib/bind/lib/dst/cylink_link.c
@@ -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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+
+#include "dst_internal.h"
+#include <toolkit.h>
+
+#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 */
diff --git a/contrib/bind/lib/dst/dst_api.c b/contrib/bind/lib/dst/dst_api.c
new file mode 100644
index 0000000..6dde481
--- /dev/null
+++ b/contrib/bind/lib/dst/dst_api.c
@@ -0,0 +1,1068 @@
+#ifndef LINT
+static const char rcsid[] = "$Header: /proj/cvs/isc/bind/src/lib/dst/dst_api.c,v 1.13 1999/10/13 16:39:22 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 <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <memory.h>
+#include <ctype.h>
+#include <time.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#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:
+ * K<key->dk_name>+<key->dk_alg>+<key->dk_id>.<private key suffix>.
+ * 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<in_name><in_id>.<public key suffix> 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> <protocol> <algorithm> <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<name>+<alg>+<id>.public and K<name>+<alg>+<id>.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);
+ }
+}
+
diff --git a/contrib/bind/lib/dst/dst_internal.h b/contrib/bind/lib/dst/dst_internal.h
new file mode 100644
index 0000000..66bfed4
--- /dev/null
+++ b/contrib/bind/lib/dst/dst_internal.h
@@ -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 <limits.h>
+#include <sys/param.h>
+#if (!defined(BSD)) || (BSD < 199306)
+# include <sys/bitypes.h>
+#else
+# include <sys/types.h>
+#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 <isc/dst.h>
+/*
+ * 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 */
diff --git a/contrib/bind/lib/dst/eay_dss_link.c b/contrib/bind/lib/dst/eay_dss_link.c
new file mode 100644
index 0000000..b060bf0
--- /dev/null
+++ b/contrib/bind/lib/dst/eay_dss_link.c
@@ -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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+
+#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 */
diff --git a/contrib/bind/lib/dst/hmac_link.c b/contrib/bind/lib/dst/hmac_link.c
new file mode 100644
index 0000000..1f96bca
--- /dev/null
+++ b/contrib/bind/lib/dst/hmac_link.c
@@ -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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#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
+
+
+
+
+
+
+
diff --git a/contrib/bind/lib/dst/md5.h b/contrib/bind/lib/dst/md5.h
new file mode 100644
index 0000000..c8b1580
--- /dev/null
+++ b/contrib/bind/lib/dst/md5.h
@@ -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
diff --git a/contrib/bind/lib/dst/md5_dgst.c b/contrib/bind/lib/dst/md5_dgst.c
new file mode 100644
index 0000000..82e5a38
--- /dev/null
+++ b/contrib/bind/lib/dst/md5_dgst.c
@@ -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 <stdio.h>
+#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 <weidai@eskimo.com> 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 (; sw<MD5_LBLOCK; sw++)
+ {
+ c2l(data,l);
+ p[sw]=l;
+ }
+ len-=(MD5_CBLOCK-c->num);
+
+ 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 <altitude@cic.net> 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 (; i<MD5_LBLOCK; i++)
+ p[i]=0;
+ md5_block(c,p);
+ i=0;
+ }
+ for (; i<(MD5_LBLOCK-2); i++)
+ p[i]=0;
+ p[MD5_LBLOCK-2]=c->Nl;
+ 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 */
diff --git a/contrib/bind/lib/dst/md5_locl.h b/contrib/bind/lib/dst/md5_locl.h
new file mode 100644
index 0000000..b2f0028
--- /dev/null
+++ b/contrib/bind/lib/dst/md5_locl.h
@@ -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 <stdlib.h>
+#include <string.h>
+#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 <weidai@eskimo.com> */
+#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 <weidai@eskimo.com>, 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; };
diff --git a/contrib/bind/lib/dst/prandom.c b/contrib/bind/lib/dst/prandom.c
new file mode 100644
index 0000000..0a66e61
--- /dev/null
+++ b/contrib/bind/lib/dst/prandom.c
@@ -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 <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <dirent.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#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 <NUMBER_OF_COUNTERS>
+ * 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);
+}
diff --git a/contrib/bind/lib/dst/rsaref_link.c b/contrib/bind/lib/dst/rsaref_link.c
new file mode 100644
index 0000000..19c9a67
--- /dev/null
+++ b/contrib/bind/lib/dst/rsaref_link.c
@@ -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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+
+#include "dst_internal.h"
+
+# ifdef __STDC__
+# define PROTOTYPES 1
+# else
+# define PROTOTYPES 0
+# endif
+
+# include <global.h>
+# include <rsaref.h>
+
+#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 */
diff --git a/contrib/bind/lib/dst/support.c b/contrib/bind/lib/dst/support.c
new file mode 100644
index 0000000..d50aa07
--- /dev/null
+++ b/contrib/bind/lib/dst/support.c
@@ -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 <stdio.h>
+#include <unistd.h>
+#include <memory.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#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<keyname>+<alg>+<id>.<suffix>
+ *
+ * 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<keyname><id>.<suffix>
+ * form: K<keyname>+<alg>+<id>.<suffix>
+ *
+ * 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
+ }
+}
diff --git a/contrib/bind/lib/inet/Makefile b/contrib/bind/lib/inet/Makefile
index 80bff87..04c4c1f 100644
--- a/contrib/bind/lib/inet/Makefile
+++ b/contrib/bind/lib/inet/Makefile
@@ -1,4 +1,4 @@
-# Copyright (c) 1996 by Internet Software Consortium
+# 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
@@ -13,7 +13,7 @@
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
# SOFTWARE.
-# $Id: Makefile,v 8.8 1997/05/21 19:32:07 halley Exp $
+# $Id: Makefile,v 8.16 1999/03/03 08:07:16 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
@@ -31,36 +31,53 @@ 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 cruv
+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}:
- ${CC} ${CPPFLAGS} ${CFLAGS} -c $*.c
- -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} && ${LDS} mv a.out $*.${O}
+ if test ! -d ${THREADED} ; then mkdir ${THREADED} ; fi
+ ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} ${REENTRANT} -c $*.c \
+ -o ${THREADED}/$*.${O}
+ -${LDS} ${LD} ${LD_LIBFLAGS} ${THREADED}/$*.${O} -o a.out && \
+ ${LDS} mv a.out ${THREADED}/$*.${O}
+ ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c
+ -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} -o a.out && \
+ ${LDS} mv a.out $*.${O}
distclean: clean
clean: FRC
rm -f .depend a.out core ${LIB} tags
rm -f *.${O} *.BAK *.CKP *~
+ rm -f ${THREADED}/*.${O}
+ -rmdir ${THREADED}
+
depend: FRC
mkdep -I${INCL} -I${PORTINCL} ${CPPFLAGS} ${SRCS}
diff --git a/contrib/bind/lib/inet/inet_addr.c b/contrib/bind/lib/inet/inet_addr.c
index 1d3943b..3b54aa8 100644
--- a/contrib/bind/lib/inet/inet_addr.c
+++ b/contrib/bind/lib/inet/inet_addr.c
@@ -1,6 +1,4 @@
/*
- * ++Copyright++ 1983, 1990, 1993
- * -
* Copyright (c) 1983, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -31,7 +29,9 @@
* 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
@@ -49,33 +49,48 @@
* PROFITS, WHETHER 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--
+ */
+
+/*
+ * 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 char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
-static char rcsid[] = "$Id: inet_addr.c,v 8.7 1996/11/18 09:09:07 vixie Exp $";
+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 <sys/types.h>
#include <sys/param.h>
+
#include <netinet/in.h>
#include <arpa/inet.h>
+
#include <ctype.h>
-#include "port_after.h"
-/* these are compatibility routines, not needed on recent BSD releases */
+#include "port_after.h"
/*
* Ascii internet address interpretation routine.
* The value returned is in network order.
*/
u_long
-inet_addr(cp)
- register const char *cp;
-{
+inet_addr(const char *cp) {
struct in_addr val;
if (inet_aton(cp, &val))
@@ -91,15 +106,13 @@ inet_addr(cp)
* cannot distinguish between failure and a local broadcast address.
*/
int
-inet_aton(cp, addr)
- register const char *cp;
- struct in_addr *addr;
-{
- register u_long val;
- register int base, n;
- register char c;
- u_int parts[4];
- register u_int *pp = parts;
+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 (;;) {
@@ -110,22 +123,28 @@ inet_aton(cp, addr)
*/
if (!isdigit(c))
return (0);
- val = 0; base = 10;
+ val = 0; base = 10; digit = 0;
if (c == '0') {
c = *++cp;
if (c == 'x' || c == 'X')
base = 16, c = *++cp;
- else
+ 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;
}
@@ -136,7 +155,7 @@ inet_aton(cp, addr)
* a.b.c (with c treated as 16 bits)
* a.b (with b treated as 24 bits)
*/
- if (pp >= parts + 3)
+ if (pp >= parts + 3 || val > 0xff)
return (0);
*pp++ = val;
c = *++cp;
@@ -149,15 +168,16 @@ inet_aton(cp, addr)
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 0:
- return (0); /* initial nondigit */
-
case 1: /* a -- 32 bits */
break;
@@ -179,7 +199,7 @@ inet_aton(cp, addr)
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
break;
}
- if (addr)
+ if (addr != NULL)
addr->s_addr = htonl(val);
return (1);
}
diff --git a/contrib/bind/lib/inet/inet_cidr_ntop.c b/contrib/bind/lib/inet/inet_cidr_ntop.c
new file mode 100644
index 0000000..08352ab
--- /dev/null
+++ b/contrib/bind/lib/inet/inet_cidr_ntop.c
@@ -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 <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#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);
+}
diff --git a/contrib/bind/lib/inet/inet_cidr_pton.c b/contrib/bind/lib/inet/inet_cidr_pton.c
new file mode 100644
index 0000000..4fae2c6
--- /dev/null
+++ b/contrib/bind/lib/inet/inet_cidr_pton.c
@@ -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 <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <isc/assertions.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#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);
+}
diff --git a/contrib/bind/lib/inet/inet_lnaof.c b/contrib/bind/lib/inet/inet_lnaof.c
index 9562024..97b80cf 100644
--- a/contrib/bind/lib/inet/inet_lnaof.c
+++ b/contrib/bind/lib/inet/inet_lnaof.c
@@ -32,7 +32,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)inet_lnaof.c 8.1 (Berkeley) 6/4/93";
+static const char sccsid[] = "@(#)inet_lnaof.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include "port_before.h"
diff --git a/contrib/bind/lib/inet/inet_makeaddr.c b/contrib/bind/lib/inet/inet_makeaddr.c
index 8a4b082..49ea023 100644
--- a/contrib/bind/lib/inet/inet_makeaddr.c
+++ b/contrib/bind/lib/inet/inet_makeaddr.c
@@ -32,7 +32,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)inet_makeaddr.c 8.1 (Berkeley) 6/4/93";
+static const char sccsid[] = "@(#)inet_makeaddr.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include "port_before.h"
diff --git a/contrib/bind/lib/inet/inet_net_ntop.c b/contrib/bind/lib/inet/inet_net_ntop.c
index 7f6526f..4e2f91f 100644
--- a/contrib/bind/lib/inet/inet_net_ntop.c
+++ b/contrib/bind/lib/inet/inet_net_ntop.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.4 1996/11/18 09:09:08 vixie Exp $";
+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"
@@ -78,7 +78,7 @@ inet_net_ntop(af, src, bits, dst, size)
* pointer to dst, or NULL if an error occurred (check errno).
* note:
* network byte order assumed. this means 192.5.5.240/28 has
- * 0x11110000 in its fourth octet.
+ * 0b11110000 in its fourth octet.
* author:
* Paul Vixie (ISC), July 1996
*/
@@ -102,6 +102,7 @@ inet_net_ntop_ipv4(src, bits, dst, size)
if (size < sizeof "0")
goto emsgsize;
*dst++ = '0';
+ size--;
*dst = '\0';
}
diff --git a/contrib/bind/lib/inet/inet_net_pton.c b/contrib/bind/lib/inet/inet_net_pton.c
index 5f381c5..4d265b2 100644
--- a/contrib/bind/lib/inet/inet_net_pton.c
+++ b/contrib/bind/lib/inet/inet_net_pton.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: inet_net_pton.c,v 1.8 1996/11/21 10:28:12 vixie Exp $";
+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"
@@ -26,7 +26,7 @@ static const char rcsid[] = "$Id: inet_net_pton.c,v 1.8 1996/11/21 10:28:12 vixi
#include <netinet/in.h>
#include <arpa/inet.h>
-#include <assert.h>
+#include <isc/assertions.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
@@ -85,7 +85,7 @@ inet_net_pton(af, src, dst, size)
* not an IPv4 network specification.
* note:
* network byte order assumed. this means 192.5.5.240/28 has
- * 0x11110000 in its fourth octet.
+ * 0b11110000 in its fourth octet.
* author:
* Paul Vixie (ISC), June 1996
*/
@@ -107,31 +107,36 @@ inet_net_pton_ipv4(src, dst, size)
/* Hexadecimal: Eat nybble string. */
if (size <= 0)
goto emsgsize;
- *dst = 0, dirty = 0;
+ dirty = 0;
src++; /* skip x or X. */
- while ((ch = *src++) != '\0' &&
- isascii(ch) && isxdigit(ch)) {
+ while ((ch = *src++) != '\0' && isascii(ch) && isxdigit(ch)) {
if (isupper(ch))
ch = tolower(ch);
n = strchr(xdigits, ch) - xdigits;
- assert(n >= 0 && n <= 15);
- *dst |= n;
- if (!dirty++)
- *dst <<= 4;
- else if (size-- > 0)
- *++dst = 0, dirty = 0;
+ 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);
}
- if (dirty)
- size--;
} else if (isascii(ch) && isdigit(ch)) {
/* Decimal: eat dotted digit string. */
for (;;) {
tmp = 0;
do {
n = strchr(digits, ch) - digits;
- assert(n >= 0 && n <= 9);
+ INSIST(n >= 0 && n <= 9);
tmp *= 10;
tmp += n;
if (tmp > 255)
@@ -159,7 +164,7 @@ inet_net_pton_ipv4(src, dst, size)
bits = 0;
do {
n = strchr(digits, ch) - digits;
- assert(n >= 0 && n <= 9);
+ INSIST(n >= 0 && n <= 9);
bits *= 10;
bits += n;
} while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
@@ -167,8 +172,6 @@ inet_net_pton_ipv4(src, dst, size)
goto enoent;
if (bits > 32)
goto emsgsize;
- if (bits > 32)
- goto emsgsize;
}
/* Firey death and destruction unless we prefetched EOS. */
diff --git a/contrib/bind/lib/inet/inet_neta.c b/contrib/bind/lib/inet/inet_neta.c
index 96c24f3..8665a9a 100644
--- a/contrib/bind/lib/inet/inet_neta.c
+++ b/contrib/bind/lib/inet/inet_neta.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: inet_neta.c,v 1.5 1997/09/26 17:56:01 halley Exp $";
+static const char rcsid[] = "$Id: inet_neta.c,v 1.6 1999/01/08 19:23:45 vixie Exp $";
#endif
#include "port_before.h"
diff --git a/contrib/bind/lib/inet/inet_netof.c b/contrib/bind/lib/inet/inet_netof.c
index 54b700c..e887530 100644
--- a/contrib/bind/lib/inet/inet_netof.c
+++ b/contrib/bind/lib/inet/inet_netof.c
@@ -32,7 +32,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)inet_netof.c 8.1 (Berkeley) 6/4/93";
+static const char sccsid[] = "@(#)inet_netof.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include "port_before.h"
diff --git a/contrib/bind/lib/inet/inet_network.c b/contrib/bind/lib/inet/inet_network.c
index 485b0b9..d26369c 100644
--- a/contrib/bind/lib/inet/inet_network.c
+++ b/contrib/bind/lib/inet/inet_network.c
@@ -32,7 +32,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)inet_network.c 8.1 (Berkeley) 6/4/93";
+static const char sccsid[] = "@(#)inet_network.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include "port_before.h"
@@ -56,28 +56,35 @@ inet_network(cp)
register u_long val, base, n, i;
register char c;
u_long parts[4], *pp = parts;
+ int digit;
again:
- val = 0; base = 10;
+ val = 0; base = 10; digit = 0;
if (*cp == '0')
- base = 8, cp++;
+ 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)
+ if (pp >= parts + 4 || val > 0xff)
return (INADDR_NONE);
*pp++ = val, cp++;
goto again;
diff --git a/contrib/bind/lib/inet/inet_ntoa.c b/contrib/bind/lib/inet/inet_ntoa.c
index 6d1ec29..aaedcb6 100644
--- a/contrib/bind/lib/inet/inet_ntoa.c
+++ b/contrib/bind/lib/inet/inet_ntoa.c
@@ -32,8 +32,8 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)inet_ntoa.c 8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id: inet_ntoa.c,v 1.5 1997/09/26 17:56:01 halley Exp $";
+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"
@@ -52,7 +52,7 @@ static char rcsid[] = "$Id: inet_ntoa.c,v 1.5 1997/09/26 17:56:01 halley Exp $";
* Convert network-format internet address
* to base 256 d.d.d.d representation.
*/
-char *
+/*const*/ char *
inet_ntoa(struct in_addr in) {
static char ret[18];
diff --git a/contrib/bind/lib/inet/inet_ntop.c b/contrib/bind/lib/inet/inet_ntop.c
index f575fce..0b85e70 100644
--- a/contrib/bind/lib/inet/inet_ntop.c
+++ b/contrib/bind/lib/inet/inet_ntop.c
@@ -1,4 +1,5 @@
-/* Copyright (c) 1996 by Internet Software Consortium.
+/*
+ * 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
@@ -15,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$Id: inet_ntop.c,v 1.4 1996/11/18 09:09:10 vixie Exp $";
+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"
@@ -77,7 +78,7 @@ inet_ntop(af, src, dst, size)
/* const char *
* inet_ntop4(src, dst, size)
- * format an IPv4 address, more or less like inet_ntoa()
+ * format an IPv4 address
* return:
* `dst' (as a const)
* notes:
diff --git a/contrib/bind/lib/inet/inet_pton.c b/contrib/bind/lib/inet/inet_pton.c
index 021e840..0a2927d 100644
--- a/contrib/bind/lib/inet/inet_pton.c
+++ b/contrib/bind/lib/inet/inet_pton.c
@@ -1,4 +1,5 @@
-/* Copyright (c) 1996 by Internet Software Consortium.
+/*
+ * 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
@@ -15,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$Id: inet_pton.c,v 1.4 1996/11/18 09:09:11 vixie Exp $";
+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"
@@ -171,6 +172,8 @@ inet_pton6(src, dst)
return (0);
colonp = tp;
continue;
+ } else if (*src == '\0') {
+ return (0);
}
if (tp + NS_INT16SZ > endp)
return (0);
@@ -202,6 +205,8 @@ inet_pton6(src, dst)
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;
diff --git a/contrib/bind/lib/inet/nsap_addr.c b/contrib/bind/lib/inet/nsap_addr.c
index e8dec96..b28acec 100644
--- a/contrib/bind/lib/inet/nsap_addr.c
+++ b/contrib/bind/lib/inet/nsap_addr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$Id: nsap_addr.c,v 8.8 1998/02/13 01:11:12 halley Exp $";
+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"
diff --git a/contrib/bind/lib/irs/Makefile b/contrib/bind/lib/irs/Makefile
index 55130d0..3421b8b 100644
--- a/contrib/bind/lib/irs/Makefile
+++ b/contrib/bind/lib/irs/Makefile
@@ -1,4 +1,4 @@
-# Copyright (c) 1996 by Internet Software Consortium
+# 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
@@ -13,7 +13,7 @@
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
# SOFTWARE.
-# $Id: Makefile,v 8.6 1997/05/21 19:23:18 halley Exp $
+# $Id: Makefile,v 8.16 1999/02/22 02:47:58 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
@@ -26,29 +26,48 @@ A=a
CC= cc
LD= ld
SHELL= /bin/sh
-CDEBUG= -g
+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 cruv
+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 gen.c \
- gen_gr.c gen_ho.c gen_ng.c gen_nw.c gen_pr.c gen_pw.c gen_sv.c \
- getgrent.c gethostent.c getnetent.c getnetgrent.c getprotoent.c \
- getpwent.c getservent.c hesiod.c irs_data.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
+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} gen.${O} gen_gr.${O} gen_ho.${O} gen_ng.${O} gen_nw.${O} \
- gen_pr.${O} gen_pw.${O} gen_sv.${O} getgrent.${O} gethostent.${O} \
- getnetent.${O} getnetgrent.${O} getprotoent.${O} getpwent.${O} \
- getservent.${O} hesiod.${O} irs_data.${O} lcl.${O} lcl_gr.${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}
@@ -56,18 +75,29 @@ OBJS= dns.${O} dns_gr.${O} dns_ho.${O} dns_nw.${O} dns_pr.${O} dns_pw.${O} \
all: ${LIBBIND}
${LIBBIND}: ${OBJS}
+ -( cd ${THREADED} ; \
+ ${AR} ${LIBBINDR} ${ARPREF} ${OBJS} ${ARSUFF} ; \
+ ${RANLIB} ${LIBBINDR} )
${AR} ${LIBBIND} ${ARPREF} ${OBJS} ${ARSUFF}
${RANLIB} ${LIBBIND}
.c.${O}:
- ${CC} ${CPPFLAGS} ${CFLAGS} -c $*.c
- -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} && ${LDS} mv a.out $*.${O}
+ if test ! -d ${THREADED} ; then mkdir ${THREADED} ; fi
+ -(${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} ${REENTRANT} -c $*.c \
+ -o ${THREADED}/$*.${O} ; \
+ ${LDS} ${LD} ${LD_LIBFLAGS} ${THREADED}/$*.${O} && \
+ ${LDS} mv a.out ${THREADED}/$*.${O})
+ ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c
+ -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} -o a.out && \
+ ${LDS} mv a.out $*.${O}
distclean: clean
clean: FRC
rm -f .depend a.out core ${LIB} tags
rm -f *.${O} *.BAK *.CKP *~
+ rm -f ${THREADED}/*.${O}
+ -rmdir ${THREADED}
depend: FRC
mkdep -I${INCL} -I${PORTINCL} ${CPPFLAGS} ${SRCS}
@@ -75,6 +105,10 @@ depend: FRC
links: FRC
@set -e; ln -s SRC/*.[ch] .
+testirpd: testirpd.o ${LIBBIND}
+ ${CC} ${CDEBUG} ${LDFLAGS} -o testirpd testirpd.o ${LIBBIND} ${SYSLIBS}
+
+
install:
FRC:
diff --git a/contrib/bind/lib/irs/Makefile.BSD b/contrib/bind/lib/irs/Makefile.BSD
index 197e739..d30c417 100644
--- a/contrib/bind/lib/irs/Makefile.BSD
+++ b/contrib/bind/lib/irs/Makefile.BSD
@@ -1,4 +1,4 @@
-# BSDI $Id: Makefile.BSD,v 1.4 1996/10/25 07:22:55 vixie Exp $
+# BSDI $Id: Makefile.BSD,v 1.5 1999/01/18 07:46:47 vixie Exp $
#
# @(#)Makefile 5.12 (Berkeley) 7/15/92
@@ -15,7 +15,8 @@ SRCS= lcl.c lcl_gr.c lcl_pw.c lcl_sv.c lcl_pr.c lcl_ho.c lcl_nw.c lcl_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 \
+ 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=
diff --git a/contrib/bind/lib/irs/README b/contrib/bind/lib/irs/README
index d6b8792..cb81a9a 100644
--- a/contrib/bind/lib/irs/README
+++ b/contrib/bind/lib/irs/README
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -18,7 +18,7 @@
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.4 1996/10/25 07:22:56 vixie Exp $
+$Id: README,v 1.5 1999/01/08 19:23:52 vixie Exp $
Introduction:
diff --git a/contrib/bind/lib/irs/dns.c b/contrib/bind/lib/irs/dns.c
index e7aa125..7ba7eec 100644
--- a/contrib/bind/lib/irs/dns.c
+++ b/contrib/bind/lib/irs/dns.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: dns.c,v 1.11 1998/03/21 00:59:45 halley Exp $";
+static const char rcsid[] = "$Id: dns.c,v 1.14 1999/01/18 07:46:47 vixie Exp $";
#endif
/*
@@ -29,6 +29,14 @@ static const char rcsid[] = "$Id: dns.c,v 1.11 1998/03/21 00:59:45 halley Exp $"
#include <string.h>
#include <errno.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <resolv.h>
+
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -40,6 +48,9 @@ static const char rcsid[] = "$Id: dns.c,v 1.11 1998/03/21 00:59:45 halley Exp $"
/* 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 */
@@ -48,17 +59,19 @@ irs_dns_acc(const char *options) {
struct irs_acc *acc;
struct dns_p *dns;
- if (!(acc = malloc(sizeof *acc))) {
+ if (!(acc = memget(sizeof *acc))) {
errno = ENOMEM;
return (NULL);
}
memset(acc, 0x5e, sizeof *acc);
- if (!(dns = malloc(sizeof *dns))) {
+ if (!(dns = memget(sizeof *dns))) {
errno = ENOMEM;
- free(acc);
+ 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
@@ -83,20 +96,56 @@ irs_dns_acc(const char *options) {
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);
- free(dns);
- free(this);
+ memput(dns, sizeof *dns);
+ memput(this, sizeof *this);
}
diff --git a/contrib/bind/lib/irs/dns_gr.c b/contrib/bind/lib/irs/dns_gr.c
index 9c91719..64cbe9b 100644
--- a/contrib/bind/lib/irs/dns_gr.c
+++ b/contrib/bind/lib/irs/dns_gr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: dns_gr.c,v 1.15 1998/03/21 00:59:46 halley Exp $";
+static const char rcsid[] = "$Id: dns_gr.c,v 1.19 1999/01/18 07:46:48 vixie Exp $";
#endif
/*
@@ -39,6 +39,13 @@ static int __bind_irs_gr_unneeded;
#include <errno.h>
#include <unistd.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <isc/memcluster.h>
+
#include <irs.h>
#include "port_after.h"
@@ -53,7 +60,7 @@ struct pvt {
/*
* This is our private accessor data. It has a shared hesiod context.
*/
- struct dns_p *dns;
+ 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
@@ -77,6 +84,10 @@ 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,
@@ -94,14 +105,14 @@ irs_dns_gr(struct irs_acc *this) {
errno = ENODEV;
return (NULL);
}
- if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) {
+ if (!(pvt = memget(sizeof *pvt))) {
errno = ENOMEM;
return (NULL);
}
memset(pvt, 0, sizeof *pvt);
pvt->dns = dns;
- if (!(gr = (struct irs_gr *)malloc(sizeof *gr))) {
- free(pvt);
+ if (!(gr = memget(sizeof *gr))) {
+ memput(pvt, sizeof *pvt);
errno = ENOMEM;
return (NULL);
}
@@ -114,6 +125,8 @@ irs_dns_gr(struct irs_acc *this) {
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);
}
@@ -127,8 +140,8 @@ gr_close(struct irs_gr *this) {
free(pvt->group.gr_mem);
if (pvt->membuf)
free(pvt->membuf);
- free(pvt);
- free(this);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
static struct group *
@@ -247,4 +260,21 @@ get_hes_group(struct irs_gr *this, const char *name, const char *type) {
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 */
diff --git a/contrib/bind/lib/irs/dns_ho.c b/contrib/bind/lib/irs/dns_ho.c
index 3a8c402..e319f96 100644
--- a/contrib/bind/lib/irs/dns_ho.c
+++ b/contrib/bind/lib/irs/dns_ho.c
@@ -32,7 +32,7 @@
*/
/*
- * Portions Copyright (c) 1996,1997 by Internet Software Consortium.
+ * 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
@@ -52,7 +52,7 @@
/* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */
#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$Id: dns_ho.c,v 1.18 1998/01/26 23:08:22 halley Exp $";
+static const char rcsid[] = "$Id: dns_ho.c,v 1.26 1999/10/15 19:49:09 vixie Exp $";
#endif /* LIBC_SCCS and not lint */
/* Imports. */
@@ -75,6 +75,7 @@ static char rcsid[] = "$Id: dns_ho.c,v 1.18 1998/01/26 23:08:22 halley Exp $";
#include <stdio.h>
#include <string.h>
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -88,8 +89,6 @@ static char rcsid[] = "$Id: dns_ho.c,v 1.18 1998/01/26 23:08:22 halley Exp $";
# define SPRINTF(x) sprintf x
#endif
-extern int h_errno;
-
/* Definitions. */
#define MAXALIASES 35
@@ -113,6 +112,8 @@ struct pvt {
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 {
@@ -122,6 +123,8 @@ typedef union {
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. */
@@ -134,14 +137,19 @@ static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr,
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(char **, int);
+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. */
@@ -150,13 +158,14 @@ irs_dns_ho(struct irs_acc *this) {
struct irs_ho *ho;
struct pvt *pvt;
- if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) {
+ if (!(pvt = memget(sizeof *pvt))) {
errno = ENOMEM;
return (NULL);
}
memset(pvt, 0, sizeof *pvt);
- if (!(ho = (struct irs_ho *)malloc(sizeof *ho))) {
- free(pvt);
+
+ if (!(ho = memget(sizeof *ho))) {
+ memput(pvt, sizeof *pvt);
errno = ENOMEM;
return (NULL);
}
@@ -169,6 +178,8 @@ irs_dns_ho(struct irs_acc *this) {
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);
}
@@ -178,18 +189,23 @@ 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)
- free(pvt);
- free(this);
+ 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 ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ if (init(this) == -1)
return (NULL);
- if (_res.options & RES_USE_INET6) {
+
+ if (pvt->res->options & RES_USE_INET6) {
hp = ho_byname2(this, name, AF_INET6);
if (hp)
return (hp);
@@ -200,11 +216,12 @@ ho_byname(struct irs_ho *this, const char *name) {
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, len;
+ int n, size, type;
u_char buf[MAXPACKET];
+ char tmp[NS_MAXDNAME];
const char *cp;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ if (init(this) == -1)
return (NULL);
switch (af) {
@@ -217,20 +234,22 @@ ho_byname2(struct irs_ho *this, const char *name, int af) {
type = T_AAAA;
break;
default:
- h_errno = NETDB_INTERNAL;
+ 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_query() since we are not the only
+ * this is also done in res_nquery() since we are not the only
* function that looks up host names.
*/
- if (!strchr(name, '.') && (cp = hostalias(name)))
+ if (!strchr(name, '.') && (cp = res_hostalias(pvt->res, name,
+ tmp, sizeof tmp)))
name = cp;
- if ((n = res_search(name, C_IN, type, buf, sizeof buf)) < 0)
+ 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));
}
@@ -244,11 +263,13 @@ ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) {
struct hostent *hp;
int n, size;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ if (init(this) == -1)
return (NULL);
+
if (af == AF_INET6 && len == IN6ADDRSZ &&
(!memcmp(uaddr, mapped, sizeof mapped) ||
- !memcmp(uaddr, tunnelled, sizeof tunnelled))) {
+ (!memcmp(uaddr, tunnelled, sizeof tunnelled) &&
+ memcmp(&uaddr[sizeof tunnelled], v6local, sizeof(v6local))))) {
/* Unmap. */
addr = (char *)addr + sizeof mapped;
uaddr += sizeof mapped;
@@ -264,12 +285,12 @@ ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) {
break;
default:
errno = EAFNOSUPPORT;
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
return (NULL);
}
if (size > len) {
errno = EINVAL;
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
return (NULL);
}
switch (af) {
@@ -292,21 +313,21 @@ ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) {
default:
abort();
}
- n = res_query(qbuf, C_IN, T_PTR, buf, sizeof buf);
+ 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() */
+ 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 && (_res.options & RES_USE_INET6)) {
+ 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;
}
- h_errno = NETDB_SUCCESS;
+ RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS);
return (hp);
}
@@ -322,7 +343,42 @@ ho_rewind(struct irs_ho *this) {
static void
ho_minimize(struct irs_ho *this) {
- /* NOOP */
+ 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. */
@@ -364,7 +420,7 @@ gethostans(struct irs_ho *this,
* Find first satisfactory answer.
*/
if (ansbuf + HFIXEDSZ > eom) {
- h_errno = NO_RECOVERY;
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
return (NULL);
}
hp = (HEADER *)ansbuf;
@@ -374,27 +430,27 @@ gethostans(struct irs_ho *this,
buflen = sizeof pvt->hostbuf;
cp = ansbuf + HFIXEDSZ;
if (qdcount != 1) {
- h_errno = NO_RECOVERY;
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
return (NULL);
}
n = dn_expand(ansbuf, eom, cp, bp, buflen);
- if ((n < 0) || !(*name_ok)(bp)) {
- h_errno = NO_RECOVERY;
+ 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) {
- h_errno = NO_RECOVERY;
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
return (NULL);
}
if (qtype == T_A || qtype == T_AAAA) {
- /* res_send() has already verified that the query name is the
+ /* 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) {
- h_errno = NO_RECOVERY;
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
return (NULL);
}
pvt->host.h_name = bp;
@@ -413,7 +469,7 @@ gethostans(struct irs_ho *this,
had_error = 0;
while (ancount-- > 0 && cp < eom && !had_error) {
n = dn_expand(ansbuf, eom, cp, bp, buflen);
- if ((n < 0) || !(*name_ok)(bp)) {
+ if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) {
had_error++;
continue;
}
@@ -434,7 +490,7 @@ gethostans(struct irs_ho *this,
if (ap >= &pvt->host_aliases[MAXALIASES-1])
continue;
n = dn_expand(ansbuf, eom, cp, tbuf, sizeof tbuf);
- if ((n < 0) || !(*name_ok)(tbuf)) {
+ if (n < 0 || !maybe_ok(pvt->res, tbuf, name_ok)) {
had_error++;
continue;
}
@@ -458,7 +514,7 @@ gethostans(struct irs_ho *this,
}
if (qtype == T_PTR && type == T_CNAME) {
n = dn_expand(ansbuf, eom, cp, tbuf, sizeof tbuf);
- if (n < 0 || !res_dnok(tbuf)) {
+ if (n < 0 || !maybe_dnok(pvt->res, tbuf)) {
had_error++;
continue;
}
@@ -481,12 +537,13 @@ gethostans(struct irs_ho *this,
}
switch (type) {
case T_PTR:
- if (strcasecmp(tname, bp) != 0) {
+ if (ns_samename(tname, bp) != 1) {
cp += n;
continue;
}
n = dn_expand(ansbuf, eom, cp, bp, buflen);
- if (n < 0 || !res_hnok(bp) || n >= MAXHOSTNAMELEN) {
+ if (n < 0 || !maybe_hnok(pvt->res, bp) ||
+ n >= MAXHOSTNAMELEN) {
had_error++;
break;
}
@@ -505,7 +562,7 @@ gethostans(struct irs_ho *this,
break;
case T_A:
case T_AAAA:
- if (strcasecmp(pvt->host.h_name, bp) != 0) {
+ if (ns_samename(pvt->host.h_name, bp) != 1) {
cp += n;
continue;
}
@@ -551,8 +608,8 @@ gethostans(struct irs_ho *this,
*ap = NULL;
*hap = NULL;
- if (_res.nsort && haveanswer > 1 && qtype == T_A)
- addrsort(pvt->h_addr_ptrs, haveanswer);
+ 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)
@@ -562,13 +619,13 @@ gethostans(struct irs_ho *this,
bp += n;
buflen -= n;
}
- if (_res.options & RES_USE_INET6)
+ if (pvt->res->options & RES_USE_INET6)
map_v4v6_hostent(&pvt->host, &bp, &buflen);
- h_errno = NETDB_SUCCESS;
+ RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS);
return (&pvt->host);
}
no_recovery:
- h_errno = NO_RECOVERY;
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
return (NULL);
}
@@ -598,16 +655,16 @@ map_v4v6_hostent(struct hostent *hp, char **bpp, int *lenp) {
}
static void
-addrsort(char **ap, int num) {
+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 < _res.nsort; j++)
- if (_res.sort_list[j].addr.s_addr ==
+ for (j = 0 ; (unsigned)j < statp->nsort; j++)
+ if (statp->sort_list[j].addr.s_addr ==
(((struct in_addr *)(*p))->s_addr &
- _res.sort_list[j].mask))
+ statp->sort_list[j].mask))
break;
aval[i] = j;
if (needsort == 0 && i > 0 && j < aval[i-1])
@@ -635,3 +692,15 @@ addrsort(char **ap, int num) {
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);
+}
diff --git a/contrib/bind/lib/irs/dns_nw.c b/contrib/bind/lib/irs/dns_nw.c
index 30767e7..66ef664 100644
--- a/contrib/bind/lib/irs/dns_nw.c
+++ b/contrib/bind/lib/irs/dns_nw.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: dns_nw.c,v 1.13 1998/02/13 01:10:40 halley Exp $";
+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. */
@@ -38,6 +38,7 @@ static const char rcsid[] = "$Id: dns_nw.c,v 1.13 1998/02/13 01:10:40 halley Exp
#include <stdlib.h>
#include <string.h>
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -51,8 +52,6 @@ static const char rcsid[] = "$Id: dns_nw.c,v 1.13 1998/02/13 01:10:40 halley Exp
# define SPRINTF(x) sprintf x
#endif
-extern int h_errno;
-
/* Definitions. */
#define MAXALIASES 35
@@ -67,6 +66,8 @@ struct pvt {
struct nwent net;
char * ali[MAXALIASES];
char buf[BUFSIZ+1];
+ struct __res_state * res;
+ void (*free_res)(void *);
};
typedef union {
@@ -84,6 +85,10 @@ 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 *);
@@ -92,9 +97,10 @@ static struct nwent * get1101answer(struct irs_nw *,
enum by_what by_what,
int af, const char *name,
const u_char *addr, int addrlen);
-static struct nwent * get1101mask(struct nwent *);
+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. */
@@ -103,13 +109,13 @@ irs_dns_nw(struct irs_acc *this) {
struct irs_nw *nw;
struct pvt *pvt;
- if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) {
+ if (!(pvt = memget(sizeof *pvt))) {
errno = ENOMEM;
return (NULL);
}
memset(pvt, 0, sizeof *pvt);
- if (!(nw = (struct irs_nw *)malloc(sizeof *nw))) {
- free(pvt);
+ if (!(nw = memget(sizeof *nw))) {
+ memput(pvt, sizeof *pvt);
errno = ENOMEM;
return (NULL);
}
@@ -121,6 +127,8 @@ irs_dns_nw(struct irs_acc *this) {
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);
}
@@ -130,32 +138,47 @@ static void
nw_close(struct irs_nw *this) {
struct pvt *pvt = (struct pvt *)this->private;
- free(pvt);
- free(this);
+ 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;
}
- h_errno = NETDB_INTERNAL;
+ 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;
}
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
errno = EAFNOSUPPORT;
return (NULL);
}
@@ -172,43 +195,80 @@ nw_rewind(struct irs_nw *this) {
static void
nw_minimize(struct irs_nw *this) {
- /* NOOP */
+ 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;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1)
- return (NULL);
- anslen = res_search(name, C_IN, T_PTR, ansbuf, sizeof ansbuf);
+ anslen = res_nsearch(pvt->res, name, C_IN, T_PTR,
+ ansbuf, sizeof ansbuf);
if (anslen < 0)
return (NULL);
- return (get1101mask(get1101answer(this, ansbuf, anslen, by_name,
- AF_INET, name, NULL, 0)));
+ 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) {
- u_char ansbuf[MAXPACKET];
+ 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;
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
return (NULL);
}
if (make1101inaddr(net, len, qbuf, sizeof qbuf) < 0)
return (NULL);
- anslen = res_query(qbuf, C_IN, T_PTR, ansbuf, sizeof ansbuf);
+ anslen = res_nquery(pvt->res, qbuf, C_IN, T_PTR,
+ ansbuf, sizeof ansbuf);
if (anslen < 0)
return (NULL);
- return (get1101mask(get1101answer(this, ansbuf, anslen, by_addr,
- AF_INET, NULL, net, len)));
+ return (get1101mask(this, get1101answer(this, ansbuf, anslen, by_addr,
+ AF_INET, NULL, net, len)));
}
static struct nwent *
@@ -225,7 +285,7 @@ get1101answer(struct irs_nw *this,
/* Initialize, and parse header. */
eom = ansbuf + anslen;
if (ansbuf + HFIXEDSZ > eom) {
- h_errno = NO_RECOVERY;
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
return (NULL);
}
hp = (HEADER *)ansbuf;
@@ -235,16 +295,16 @@ get1101answer(struct irs_nw *this,
int n = dn_skipname(cp, eom);
cp += n + QFIXEDSZ;
if (n < 0 || cp > eom) {
- h_errno = NO_RECOVERY;
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
return (NULL);
}
}
ancount = ntohs(hp->ancount);
if (!ancount) {
if (hp->aa)
- h_errno = HOST_NOT_FOUND;
+ RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
else
- h_errno = TRY_AGAIN;
+ RES_SET_H_ERRNO(pvt->res, TRY_AGAIN);
return (NULL);
}
@@ -264,7 +324,7 @@ get1101answer(struct irs_nw *this,
int n = strlen(name) + 1;
if (n > buflen) {
- h_errno = NO_RECOVERY;
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
return (NULL);
}
pvt->net.n_name = strcpy(bp, name);
@@ -277,7 +337,7 @@ get1101answer(struct irs_nw *this,
int n = addrlen / 8 + ((addrlen % 8) != 0);
if (INADDRSZ > buflen) {
- h_errno = NO_RECOVERY;
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
return (NULL);
}
memset(bp, 0, INADDRSZ);
@@ -298,9 +358,9 @@ get1101answer(struct irs_nw *this,
int n = dn_expand(ansbuf, eom, cp, bp, buflen);
cp += n; /* Owner */
- if (n < 0 || !res_dnok(bp) ||
+ if (n < 0 || !maybe_dnok(pvt->res, bp) ||
cp + 3 * INT16SZ + INT32SZ > eom) {
- h_errno = NO_RECOVERY;
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
return (NULL);
}
GETSHORT(type, cp); /* Type */
@@ -311,8 +371,8 @@ get1101answer(struct irs_nw *this,
int nn;
nn = dn_expand(ansbuf, eom, cp, bp, buflen);
- if (nn < 0 || !res_hnok(bp) || nn != n) {
- h_errno = NO_RECOVERY;
+ if (nn < 0 || !maybe_hnok(pvt->res, bp) || nn != n) {
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
return (NULL);
}
normalize_name(bp);
@@ -320,7 +380,7 @@ get1101answer(struct irs_nw *this,
case by_addr: {
if (pvt->net.n_name == NULL)
pvt->net.n_name = bp;
- else if (strcasecmp(pvt->net.n_name, bp) == 0)
+ else if (ns_samename(pvt->net.n_name, bp) == 1)
break;
else
*ap++ = bp;
@@ -338,7 +398,7 @@ get1101answer(struct irs_nw *this,
&b1, &b2, &b3, &b4) != 4)
break;
if (buflen < INADDRSZ) {
- h_errno = NO_RECOVERY;
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
return (NULL);
}
pvt->net.n_addr = bp;
@@ -355,7 +415,7 @@ get1101answer(struct irs_nw *this,
cp += n; /* RDATA */
}
if (!haveanswer) {
- h_errno = TRY_AGAIN;
+ RES_SET_H_ERRNO(pvt->res, TRY_AGAIN);
return (NULL);
}
*ap = NULL;
@@ -364,7 +424,8 @@ get1101answer(struct irs_nw *this,
}
static struct nwent *
-get1101mask(struct nwent *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;
@@ -379,7 +440,7 @@ get1101mask(struct nwent *nwent) {
}
/* Query for the A RR that would hold this network's mask. */
- anslen = res_query(qbuf, C_IN, T_A, ansbuf, sizeof ansbuf);
+ anslen = res_nquery(pvt->res, qbuf, C_IN, T_A, ansbuf, sizeof ansbuf);
if (anslen < HFIXEDSZ)
return (nwent);
@@ -400,7 +461,7 @@ get1101mask(struct nwent *nwent) {
while (--ancount >= 0 && cp < eom) {
int n = dn_expand(ansbuf, eom, cp, owner, sizeof owner);
- if (n < 0 || !res_dnok(owner))
+ if (n < 0 || !maybe_dnok(pvt->res, owner))
break;
cp += n; /* Owner */
if (cp + 3 * INT16SZ + INT32SZ > eom)
@@ -412,7 +473,7 @@ get1101mask(struct nwent *nwent) {
if (cp + n > eom)
break;
if (n == INADDRSZ && class == C_IN && type == T_A &&
- !strcasecmp(qbuf, owner)) {
+ ns_samename(qbuf, owner) == 1) {
/* This A RR indicates the actual netmask. */
int nn, mm;
@@ -485,3 +546,15 @@ normalize_name(char *name) {
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);
+}
diff --git a/contrib/bind/lib/irs/dns_p.h b/contrib/bind/lib/irs/dns_p.h
index 5a4ef84..6b5fe11 100644
--- a/contrib/bind/lib/irs/dns_p.h
+++ b/contrib/bind/lib/irs/dns_p.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,17 +16,24 @@
*/
/*
- * $Id: dns_p.h,v 1.7 1996/10/25 07:22:59 vixie Exp $
+ * $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;
+ void *hes_ctx;
+ struct __res_state *res;
+ void (*free_res) __P((void *));
};
/*
diff --git a/contrib/bind/lib/irs/dns_pr.c b/contrib/bind/lib/irs/dns_pr.c
index 2ca6aaf..77c6a93 100644
--- a/contrib/bind/lib/irs/dns_pr.c
+++ b/contrib/bind/lib/irs/dns_pr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: dns_pr.c,v 1.9 1997/12/04 04:57:48 halley Exp $";
+static const char rcsid[] = "$Id: dns_pr.c,v 1.14 1999/09/04 22:06:14 vixie Exp $";
#endif
/* Imports */
@@ -25,6 +25,8 @@ static const char rcsid[] = "$Id: dns_pr.c,v 1.9 1997/12/04 04:57:48 halley Exp
#include <sys/types.h>
#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
#include <stdio.h>
#include <string.h>
@@ -33,6 +35,7 @@ static const char rcsid[] = "$Id: dns_pr.c,v 1.9 1997/12/04 04:57:48 halley Exp
#include <stdlib.h>
#include <errno.h>
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -44,7 +47,7 @@ static const char rcsid[] = "$Id: dns_pr.c,v 1.9 1997/12/04 04:57:48 halley Exp
/* Types. */
struct pvt {
- struct dns_p * dns;
+ struct dns_p * dns;
struct protoent proto;
char * prbuf;
};
@@ -57,6 +60,10 @@ 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 **);
@@ -72,13 +79,13 @@ irs_dns_pr(struct irs_acc *this) {
errno = ENODEV;
return (NULL);
}
- if (!(pvt = malloc(sizeof *pvt))) {
+ if (!(pvt = memget(sizeof *pvt))) {
errno = ENOMEM;
return (NULL);
}
memset(pvt, 0, sizeof *pvt);
- if (!(pr = malloc(sizeof *pr))) {
- free(pvt);
+ if (!(pr = memget(sizeof *pr))) {
+ memput(pvt, sizeof *pvt);
errno = ENOMEM;
return (NULL);
}
@@ -91,6 +98,8 @@ irs_dns_pr(struct irs_acc *this) {
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);
}
@@ -104,7 +113,9 @@ pr_close(struct irs_pr *this) {
free(pvt->proto.p_aliases);
if (pvt->prbuf)
free(pvt->prbuf);
- free(this);
+
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
static struct protoent *
@@ -155,6 +166,23 @@ 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 *
diff --git a/contrib/bind/lib/irs/dns_pw.c b/contrib/bind/lib/irs/dns_pw.c
index 97612d1..5344c6e 100644
--- a/contrib/bind/lib/irs/dns_pw.c
+++ b/contrib/bind/lib/irs/dns_pw.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: dns_pw.c,v 1.13 1997/12/04 04:57:48 halley Exp $";
+static const char rcsid[] = "$Id: dns_pw.c,v 1.18 1999/09/04 22:06:14 vixie Exp $";
#endif
#include "port_before.h"
@@ -30,6 +30,13 @@ static int __bind_irs_pw_unneeded;
#include <errno.h>
#include <string.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <isc/memcluster.h>
+
#include <irs.h>
#include "port_after.h"
@@ -41,7 +48,7 @@ static int __bind_irs_pw_unneeded;
/* Types. */
struct pvt {
- struct dns_p *dns;
+ struct dns_p * dns;
struct passwd passwd;
char * pwbuf;
};
@@ -54,6 +61,10 @@ 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 *);
@@ -70,14 +81,14 @@ irs_dns_pw(struct irs_acc *this) {
errno = ENODEV;
return (NULL);
}
- if (!(pvt = malloc(sizeof *pvt))) {
+ if (!(pvt = memget(sizeof *pvt))) {
errno = ENOMEM;
return (NULL);
}
memset(pvt, 0, sizeof *pvt);
pvt->dns = dns;
- if (!(pw = malloc(sizeof *pw))) {
- free(pvt);
+ if (!(pw = memget(sizeof *pw))) {
+ memput(pvt, sizeof *pvt);
errno = ENOMEM;
return (NULL);
}
@@ -89,6 +100,8 @@ irs_dns_pw(struct irs_acc *this) {
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);
}
@@ -100,7 +113,9 @@ pw_close(struct irs_pw *this) {
if (pvt->pwbuf)
free(pvt->pwbuf);
- free(this);
+
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
static struct passwd *
@@ -132,6 +147,23 @@ 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 *
diff --git a/contrib/bind/lib/irs/dns_sv.c b/contrib/bind/lib/irs/dns_sv.c
index 064e80a..ea0ba70 100644
--- a/contrib/bind/lib/irs/dns_sv.c
+++ b/contrib/bind/lib/irs/dns_sv.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: dns_sv.c,v 1.12 1997/12/04 04:57:49 halley Exp $";
+static const char rcsid[] = "$Id: dns_sv.c,v 1.17 1999/09/04 22:06:14 vixie Exp $";
#endif
/* Imports */
@@ -33,6 +33,12 @@ static const char rcsid[] = "$Id: dns_sv.c,v 1.12 1997/12/04 04:57:49 halley Exp
#include <stdlib.h>
#include <errno.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -44,9 +50,11 @@ static const char rcsid[] = "$Id: dns_sv.c,v 1.12 1997/12/04 04:57:49 halley Exp
/* Definitions */
struct pvt {
- struct dns_p * dns;
+ struct dns_p * dns;
struct servent serv;
char * svbuf;
+ struct __res_state * res;
+ void (*free_res)(void *);
};
/* Forward. */
@@ -58,6 +66,10 @@ 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 *);
@@ -74,14 +86,14 @@ irs_dns_sv(struct irs_acc *this) {
errno = ENODEV;
return (NULL);
}
- if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) {
+ if (!(pvt = memget(sizeof *pvt))) {
errno = ENOMEM;
return (NULL);
}
memset(pvt, 0, sizeof *pvt);
pvt->dns = dns;
- if (!(sv = malloc(sizeof *sv))) {
- free(pvt);
+ if (!(sv = memget(sizeof *sv))) {
+ memput(pvt, sizeof *pvt);
errno = ENOMEM;
return (NULL);
}
@@ -93,6 +105,8 @@ irs_dns_sv(struct irs_acc *this) {
sv->rewind = sv_rewind;
sv->close = sv_close;
sv->minimize = sv_minimize;
+ sv->res_get = sv_res_get;
+ sv->res_set = sv_res_set;
return (sv);
}
@@ -106,7 +120,11 @@ sv_close(struct irs_sv *this) {
free(pvt->serv.s_aliases);
if (pvt->svbuf)
free(pvt->svbuf);
- free(this);
+
+ if (pvt->res && pvt->free_res)
+ (*pvt->free_res)(pvt->res);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
static struct servent *
@@ -248,3 +266,20 @@ 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);
+}
diff --git a/contrib/bind/lib/irs/gai_strerror.c b/contrib/bind/lib/irs/gai_strerror.c
new file mode 100644
index 0000000..f56c6f5
--- /dev/null
+++ b/contrib/bind/lib/irs/gai_strerror.c
@@ -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 <license@inner.net>.
+
+*/
+
+#include <port_before.h>
+#include <netdb.h>
+#include <errno.h>
+#include <port_after.h>
+
+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";
+ };
+}
diff --git a/contrib/bind/lib/irs/gen.c b/contrib/bind/lib/irs/gen.c
index 325a526..fe41088 100644
--- a/contrib/bind/lib/irs/gen.c
+++ b/contrib/bind/lib/irs/gen.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: gen.c,v 1.18 1998/03/21 00:59:46 halley Exp $";
+static const char rcsid[] = "$Id: gen.c,v 1.25 1999/10/13 16:39:29 vixie Exp $";
#endif
/*
@@ -35,13 +35,19 @@ static char rcsid[] = "$Id: gen.c,v 1.18 1998/03/21 00:59:46 halley Exp $";
#include "port_before.h"
-#include <assert.h>
+#include <isc/assertions.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -60,6 +66,7 @@ static const struct nameval acc_names[irs_nacc+1] = {
{ "local", irs_lcl },
{ "dns", irs_dns },
{ "nis", irs_nis },
+ { "irp", irs_irp },
{ NULL, irs_nacc }
};
@@ -73,6 +80,7 @@ static const accinit accs[irs_nacc+1] = {
#else
NULL,
#endif
+ irs_irp_acc,
NULL
};
@@ -96,8 +104,11 @@ static const struct nameval option_names[] = {
/* 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 *);
+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,
@@ -106,25 +117,27 @@ static int add_rule(struct gen_p *,
/* Public */
struct irs_acc *
-irs_gen_acc(const char *options) {
+irs_gen_acc(const char *options, const char *conf_file) {
struct irs_acc *acc;
struct gen_p *irs;
- if (!(acc = malloc(sizeof *acc))) {
+ if (!(acc = memget(sizeof *acc))) {
errno = ENOMEM;
return (NULL);
}
memset(acc, 0x5e, sizeof *acc);
- if (!(irs = malloc(sizeof *irs))) {
+ if (!(irs = memget(sizeof *irs))) {
errno = ENOMEM;
- free(acc);
+ 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);
+ init_map_rules(irs, conf_file);
acc->private = irs;
#ifdef WANT_IRS_GR
acc->gr_map = irs_gen_gr;
@@ -141,12 +154,65 @@ irs_gen_acc(const char *options) {
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;
@@ -182,11 +248,14 @@ gen_close(struct irs_acc *this) {
/* 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. */
- free(irs);
+ memput(irs, sizeof *irs);
/* The object. */
- free(this);
+ memput(this, sizeof *this);
}
/* Private */
@@ -205,7 +274,7 @@ static struct irs_rule *
release_rule(struct irs_rule *rule) {
struct irs_rule *next = rule->next;
- free(rule);
+ memput(rule, sizeof *rule);
return (next);
}
@@ -231,7 +300,7 @@ add_rule(struct gen_p *irs,
if (acc == irs_nis)
return (-1);
#endif
- new = (struct irs_rule *)malloc(sizeof *new);
+ new = memget(sizeof *new);
if (new == NULL)
return (-1);
memset(new, 0x5e, sizeof *new);
@@ -310,11 +379,15 @@ default_map_rules(struct gen_p *irs) {
}
static void
-init_map_rules(struct gen_p *irs) {
+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 = fopen(_PATH_IRS_CONF, "r")) == NULL) {
+ 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;
}
@@ -337,13 +410,13 @@ init_map_rules(struct gen_p *irs) {
options[0] = '\0';
n = find_name(mapname, map_names);
- assert(n < irs_nmap);
+ INSIST(n < irs_nmap);
if (n < 0)
continue;
map = (enum irs_map_id) n;
n = find_name(accname, acc_names);
- assert(n < irs_nacc);
+ INSIST(n < irs_nacc);
if (n < 0)
continue;
acc = (enum irs_acc_id) n;
diff --git a/contrib/bind/lib/irs/gen_gr.c b/contrib/bind/lib/irs/gen_gr.c
index b0c61a8..ae23d2c 100644
--- a/contrib/bind/lib/irs/gen_gr.c
+++ b/contrib/bind/lib/irs/gen_gr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: gen_gr.c,v 1.16 1998/03/21 00:59:47 halley Exp $";
+static const char rcsid[] = "$Id: gen_gr.c,v 1.21 1999/10/13 16:39:29 vixie Exp $";
#endif
/* Imports */
@@ -29,12 +29,17 @@ static int __bind_irs_gr_unneeded;
#include <sys/types.h>
-#include <assert.h>
+#include <isc/assertions.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -59,6 +64,8 @@ struct pvt {
size_t nmemb; /* Malloc'd max index of gr_mem[]. */
char * membuf;
size_t membufsize;
+ struct __res_state * res;
+ void (*free_res)(void *);
};
/* Forward */
@@ -71,6 +78,10 @@ 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);
@@ -89,13 +100,13 @@ irs_gen_gr(struct irs_acc *this) {
struct irs_gr *gr;
struct pvt *pvt;
- if (!(gr = malloc(sizeof *gr))) {
+ if (!(gr = memget(sizeof *gr))) {
errno = ENOMEM;
return (NULL);
}
memset(gr, 0x5e, sizeof *gr);
- if (!(pvt = malloc(sizeof *pvt))) {
- free(gr);
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(gr, sizeof *gr);
errno = ENOMEM;
return (NULL);
}
@@ -110,6 +121,8 @@ irs_gen_gr(struct irs_acc *this) {
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);
}
@@ -119,8 +132,8 @@ static void
gr_close(struct irs_gr *this) {
struct pvt *pvt = (struct pvt *)this->private;
- free(pvt);
- free(this);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
static struct group *
@@ -266,6 +279,46 @@ gr_minimize(struct irs_gr *this) {
}
}
+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
@@ -310,7 +363,7 @@ grmerge(struct irs_gr *this, const struct group *src, int preserve) {
* Enlarge destination membuf; cp points at new portion.
*/
n = sizenew(pvt->group.gr_mem, src->gr_mem);
- assert((nnew == 0) == (n == 0));
+ INSIST((nnew == 0) == (n == 0));
if (!preserve) {
n += strlen(src->gr_name) + 1;
n += strlen(src->gr_passwd) + 1;
@@ -346,7 +399,7 @@ grmerge(struct irs_gr *this, const struct group *src, int preserve) {
strcpy(cp, src->gr_passwd);
cp += strlen(src->gr_passwd) + 1;
}
- assert(cp >= pvt->membuf && cp <= &pvt->membuf[pvt->membufsize]);
+ INSIST(cp >= pvt->membuf && cp <= &pvt->membuf[pvt->membufsize]);
}
static int
diff --git a/contrib/bind/lib/irs/gen_ho.c b/contrib/bind/lib/irs/gen_ho.c
index 7da829d..9e7a429 100644
--- a/contrib/bind/lib/irs/gen_ho.c
+++ b/contrib/bind/lib/irs/gen_ho.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,19 +16,26 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$Id: gen_ho.c,v 1.9 1997/12/04 04:57:50 halley Exp $";
+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 <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
#include <errno.h>
#include <stdlib.h>
#include <netdb.h>
+#include <resolv.h>
#include <stdio.h>
#include <string.h>
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -36,14 +43,14 @@ static char rcsid[] = "$Id: gen_ho.c,v 1.9 1997/12/04 04:57:50 halley Exp $";
#include "irs_p.h"
#include "gen_p.h"
-extern int h_errno;
-
/* Definitions */
struct pvt {
struct irs_rule * rules;
struct irs_rule * rule;
struct irs_ho * ho;
+ struct __res_state * res;
+ void (*free_res)(void *);
};
/* Forwards */
@@ -57,6 +64,12 @@ static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr,
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 */
@@ -66,17 +79,17 @@ irs_gen_ho(struct irs_acc *this) {
struct irs_ho *ho;
struct pvt *pvt;
- if (!(ho = malloc(sizeof *ho))) {
+ if (!(pvt = memget(sizeof *pvt))) {
errno = ENOMEM;
return (NULL);
}
- memset(ho, 0x5e, sizeof *ho);
- if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) {
- free(ho);
+ memset(pvt, 0, sizeof *pvt);
+ if (!(ho = memget(sizeof *ho))) {
+ memput(pvt, sizeof *pvt);
errno = ENOMEM;
return (NULL);
}
- memset(pvt, 0, sizeof *pvt);
+ memset(ho, 0x5e, sizeof *ho);
pvt->rules = accpvt->map_rules[irs_ho];
pvt->rule = pvt->rules;
ho->private = pvt;
@@ -87,6 +100,8 @@ irs_gen_ho(struct irs_acc *this) {
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);
}
@@ -96,8 +111,11 @@ static void
ho_close(struct irs_ho *this) {
struct pvt *pvt = (struct pvt *)this->private;
- free(pvt);
- free(this);
+ 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 *
@@ -106,14 +124,25 @@ ho_byname(struct irs_ho *this, const char *name) {
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;
- h_errno = NETDB_INTERNAL;
+ 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;
/*
@@ -121,12 +150,14 @@ ho_byname(struct irs_ho *this, const char *name) {
* 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
+ * H_ERRNO is TRY_AGAIN, we continue to try other lookup
* functions, otherwise we return the TRY_AGAIN error.
*/
- if (h_errno != TRY_AGAIN || errno != 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);
}
@@ -136,23 +167,36 @@ ho_byname2(struct irs_ho *this, const char *name, int af) {
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;
- h_errno = NETDB_INTERNAL;
+ 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 (h_errno != TRY_AGAIN || errno != 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);
}
@@ -162,23 +206,38 @@ ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) {
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;
- h_errno = NETDB_INTERNAL;
+ 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 (h_errno != TRY_AGAIN || errno != 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);
}
@@ -221,9 +280,64 @@ 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);
+}
diff --git a/contrib/bind/lib/irs/gen_ng.c b/contrib/bind/lib/irs/gen_ng.c
index 3958380..064d616 100644
--- a/contrib/bind/lib/irs/gen_ng.c
+++ b/contrib/bind/lib/irs/gen_ng.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: gen_ng.c,v 1.9 1997/12/04 04:57:50 halley Exp $";
+static const char rcsid[] = "$Id: gen_ng.c,v 1.14 1999/10/13 16:39:29 vixie Exp $";
#endif
/* Imports */
@@ -25,10 +25,15 @@ static char rcsid[] = "$Id: gen_ng.c,v 1.9 1997/12/04 04:57:50 halley Exp $";
#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -62,13 +67,13 @@ irs_gen_ng(struct irs_acc *this) {
struct irs_ng *ng;
struct pvt *pvt;
- if (!(ng = malloc(sizeof *ng))) {
+ if (!(ng = memget(sizeof *ng))) {
errno = ENOMEM;
return (NULL);
}
memset(ng, 0x5e, sizeof *ng);
- if (!(pvt = malloc(sizeof *pvt))) {
- free(ng);
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(ng, sizeof *ng);
errno = ENOMEM;
return (NULL);
}
@@ -90,10 +95,11 @@ static void
ng_close(struct irs_ng *this) {
struct pvt *pvt = (struct pvt *)this->private;
+ ng_minimize(this);
if (pvt->curgroup)
free(pvt->curgroup);
- free(pvt);
- free(this);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
static int
diff --git a/contrib/bind/lib/irs/gen_nw.c b/contrib/bind/lib/irs/gen_nw.c
index 8ae8074..fad436c 100644
--- a/contrib/bind/lib/irs/gen_nw.c
+++ b/contrib/bind/lib/irs/gen_nw.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: gen_nw.c,v 1.8 1997/12/04 04:57:50 halley Exp $";
+static const char rcsid[] = "$Id: gen_nw.c,v 1.13 1999/10/13 16:39:29 vixie Exp $";
#endif
/* Imports */
@@ -25,10 +25,15 @@ static char rcsid[] = "$Id: gen_nw.c,v 1.8 1997/12/04 04:57:50 halley Exp $";
#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
#include <errno.h>
+#include <resolv.h>
#include <stdlib.h>
#include <string.h>
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -41,6 +46,8 @@ static char rcsid[] = "$Id: gen_nw.c,v 1.8 1997/12/04 04:57:50 halley Exp $";
struct pvt {
struct irs_rule * rules;
struct irs_rule * rule;
+ struct __res_state * res;
+ void (*free_res)(void *);
};
/* Forward */
@@ -51,6 +58,12 @@ 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 */
@@ -60,17 +73,17 @@ irs_gen_nw(struct irs_acc *this) {
struct irs_nw *nw;
struct pvt *pvt;
- if (!(nw = (struct irs_nw *)malloc(sizeof *nw))) {
+ if (!(pvt = memget(sizeof *pvt))) {
errno = ENOMEM;
return (NULL);
}
- memset(nw, 0x5e, sizeof *nw);
- if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) {
- free(nw);
+ memset(pvt, 0, sizeof *pvt);
+ if (!(nw = memget(sizeof *nw))) {
+ memput(pvt, sizeof *pvt);
errno = ENOMEM;
return (NULL);
}
- memset(pvt, 0, sizeof *pvt);
+ memset(nw, 0x5e, sizeof *nw);
pvt->rules = accpvt->map_rules[irs_nw];
pvt->rule = pvt->rules;
nw->private = pvt;
@@ -80,6 +93,8 @@ irs_gen_nw(struct irs_acc *this) {
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);
}
@@ -89,8 +104,13 @@ static void
nw_close(struct irs_nw *this) {
struct pvt *pvt = (struct pvt *)this->private;
- free(pvt);
- free(this);
+ 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 *
@@ -99,6 +119,9 @@ nw_next(struct irs_nw *this) {
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);
@@ -122,13 +145,17 @@ nw_byname(struct irs_nw *this, const char *name, int type) {
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;
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
rval = (*nw->byname)(nw, name, type);
if (rval != NULL)
return (rval);
- if (h_errno != TRY_AGAIN && !(rule->flags & IRS_CONTINUE))
+ if (pvt->res->res_h_errno != TRY_AGAIN &&
+ !(rule->flags & IRS_CONTINUE))
break;
}
return (NULL);
@@ -141,13 +168,17 @@ nw_byaddr(struct irs_nw *this, void *net, int length, int type) {
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;
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
rval = (*nw->byaddr)(nw, net, length, type);
if (rval != NULL)
return (rval);
- if (h_errno != TRY_AGAIN && !(rule->flags & IRS_CONTINUE))
+ if (pvt->res->res_h_errno != TRY_AGAIN &&
+ !(rule->flags & IRS_CONTINUE))
break;
}
return (NULL);
@@ -170,9 +201,62 @@ 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);
+}
diff --git a/contrib/bind/lib/irs/gen_p.h b/contrib/bind/lib/irs/gen_p.h
index 92e115d..b8210b0 100644
--- a/contrib/bind/lib/irs/gen_p.h
+++ b/contrib/bind/lib/irs/gen_p.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
/*
- * $Id: gen_p.h,v 1.7 1996/11/21 10:28:15 vixie Exp $
+ * $Id: gen_p.h,v 1.10 1999/01/18 07:46:50 vixie Exp $
*/
/* Notes:
@@ -43,6 +43,7 @@ enum irs_acc_id {
irs_lcl, /* Local. */
irs_dns, /* DNS or Hesiod. */
irs_nis, /* Sun NIS ("YP"). */
+ irs_irp, /* IR protocol. */
irs_nacc
};
@@ -92,13 +93,15 @@ 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 *));
+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 *));
diff --git a/contrib/bind/lib/irs/gen_pr.c b/contrib/bind/lib/irs/gen_pr.c
index 096be51..de09571 100644
--- a/contrib/bind/lib/irs/gen_pr.c
+++ b/contrib/bind/lib/irs/gen_pr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: gen_pr.c,v 1.8 1997/12/04 04:57:51 halley Exp $";
+static const char rcsid[] = "$Id: gen_pr.c,v 1.12 1999/10/13 16:39:30 vixie Exp $";
#endif
/* Imports */
@@ -24,11 +24,15 @@ static char rcsid[] = "$Id: gen_pr.c,v 1.8 1997/12/04 04:57:51 halley Exp $";
#include "port_before.h"
#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
#include <errno.h>
+#include <resolv.h>
#include <stdlib.h>
#include <string.h>
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -41,6 +45,8 @@ static char rcsid[] = "$Id: gen_pr.c,v 1.8 1997/12/04 04:57:51 halley Exp $";
struct pvt {
struct irs_rule * rules;
struct irs_rule * rule;
+ struct __res_state * res;
+ void (*free_res)(void *);
};
/* Forward */
@@ -51,6 +57,10 @@ 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 */
@@ -60,13 +70,13 @@ irs_gen_pr(struct irs_acc *this) {
struct irs_pr *pr;
struct pvt *pvt;
- if (!(pr = (struct irs_pr *)malloc(sizeof *pr))) {
+ if (!(pr = memget(sizeof *pr))) {
errno = ENOMEM;
return (NULL);
}
memset(pr, 0x5e, sizeof *pr);
- if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) {
- free(pr);
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(pr, sizeof *pr);
errno = ENOMEM;
return (NULL);
}
@@ -80,6 +90,8 @@ irs_gen_pr(struct irs_acc *this) {
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);
}
@@ -89,8 +101,8 @@ static void
pr_close(struct irs_pr *this) {
struct pvt *pvt = (struct pvt *)this->private;
- free(pvt);
- free(this);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
static struct protoent *
@@ -172,3 +184,43 @@ pr_minimize(struct irs_pr *this) {
(*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);
+ }
+}
diff --git a/contrib/bind/lib/irs/gen_pw.c b/contrib/bind/lib/irs/gen_pw.c
index aaa82df..d80a64b 100644
--- a/contrib/bind/lib/irs/gen_pw.c
+++ b/contrib/bind/lib/irs/gen_pw.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: gen_pw.c,v 1.10 1997/12/04 04:57:51 halley Exp $";
+static const char rcsid[] = "$Id: gen_pw.c,v 1.14 1999/10/13 16:39:30 vixie Exp $";
#endif
/* Imports */
@@ -28,12 +28,16 @@ static int __bind_irs_pw_unneeded;
#else
#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
#include <errno.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -46,6 +50,8 @@ static int __bind_irs_pw_unneeded;
struct pvt {
struct irs_rule * rules;
struct irs_rule * rule;
+ struct __res_state * res;
+ void (*free_res)(void *);
};
/* Forward */
@@ -56,6 +62,10 @@ 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 */
@@ -65,13 +75,13 @@ irs_gen_pw(struct irs_acc *this) {
struct irs_pw *pw;
struct pvt *pvt;
- if (!(pw = (struct irs_pw *)malloc(sizeof *pw))) {
+ if (!(pw = memget(sizeof *pw))) {
errno = ENOMEM;
return (NULL);
}
memset(pw, 0x5e, sizeof *pw);
- if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) {
- free(pw);
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(pw, sizeof *pvt);
errno = ENOMEM;
return (NULL);
}
@@ -85,6 +95,8 @@ irs_gen_pw(struct irs_acc *this) {
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);
}
@@ -94,8 +106,8 @@ static void
pw_close(struct irs_pw *this) {
struct pvt *pvt = (struct pvt *)this->private;
- free(pvt);
- free(this);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
static struct passwd *
@@ -178,4 +190,44 @@ pw_minimize(struct irs_pw *this) {
}
}
+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 */
diff --git a/contrib/bind/lib/irs/gen_sv.c b/contrib/bind/lib/irs/gen_sv.c
index 22f0cde..e0c1cb6 100644
--- a/contrib/bind/lib/irs/gen_sv.c
+++ b/contrib/bind/lib/irs/gen_sv.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: gen_sv.c,v 1.8 1997/12/04 04:57:52 halley Exp $";
+static const char rcsid[] = "$Id: gen_sv.c,v 1.12 1999/10/13 16:39:30 vixie Exp $";
#endif
/* Imports */
@@ -24,11 +24,15 @@ static char rcsid[] = "$Id: gen_sv.c,v 1.8 1997/12/04 04:57:52 halley Exp $";
#include "port_before.h"
#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -41,6 +45,8 @@ static char rcsid[] = "$Id: gen_sv.c,v 1.8 1997/12/04 04:57:52 halley Exp $";
struct pvt {
struct irs_rule * rules;
struct irs_rule * rule;
+ struct __res_state * res;
+ void (*free_res)(void *);
};
/* Forward */
@@ -52,6 +58,10 @@ static struct servent * sv_byname(struct irs_sv *, 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 */
@@ -61,13 +71,13 @@ irs_gen_sv(struct irs_acc *this) {
struct irs_sv *sv;
struct pvt *pvt;
- if (!(sv = (struct irs_sv *)malloc(sizeof *sv))) {
+ if (!(sv = memget(sizeof *sv))) {
errno = ENOMEM;
return (NULL);
}
memset(sv, 0x5e, sizeof *sv);
- if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) {
- free(sv);
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(sv, sizeof *sv);
errno = ENOMEM;
return (NULL);
}
@@ -81,6 +91,8 @@ irs_gen_sv(struct irs_acc *this) {
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);
}
@@ -90,8 +102,8 @@ static void
sv_close(struct irs_sv *this) {
struct pvt *pvt = (struct pvt *)this->private;
- free(pvt);
- free(this);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
static struct servent *
@@ -173,3 +185,43 @@ sv_minimize(struct irs_sv *this) {
(*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);
+ }
+}
diff --git a/contrib/bind/lib/irs/getaddrinfo.c b/contrib/bind/lib/irs/getaddrinfo.c
new file mode 100644
index 0000000..f95a681
--- /dev/null
+++ b/contrib/bind/lib/irs/getaddrinfo.c
@@ -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 <port_before.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <arpa/inet.h>
+#include <port_after.h>
+
+#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);
+}
diff --git a/contrib/bind/lib/irs/getgrent.c b/contrib/bind/lib/irs/getgrent.c
index df34447fb0..866e8c5 100644
--- a/contrib/bind/lib/irs/getgrent.c
+++ b/contrib/bind/lib/irs/getgrent.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ * 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
@@ -16,21 +16,25 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: getgrent.c,v 1.13 1998/03/21 00:59:47 halley Exp $";
+static const char rcsid[] = "$Id: getgrent.c,v 1.19 1999/10/13 16:39:30 vixie Exp $";
#endif
/* Imports */
#include "port_before.h"
-#ifndef WANT_IRS_GR
+#if !defined(WANT_IRS_GR) || defined(__BIND_NOSTATIC)
static int __bind_irs_gr_unneeded;
#else
#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
#include <errno.h>
#include <grp.h>
+#include <resolv.h>
#include <stdio.h>
#include <irs.h>
@@ -41,87 +45,150 @@ static int __bind_irs_gr_unneeded;
/* Forward */
-static struct irs_gr * init(void);
+static struct net_data *init(void);
void endgrent(void);
/* Public */
struct group *
getgrent() {
- struct irs_gr *gr = init();
-
- if (!gr)
- return (NULL);
- net_data.gr_last = (*gr->next)(gr);
- return (net_data.gr_last);
+ struct net_data *net_data = init();
+
+ return (getgrent_p(net_data));
}
struct group *
getgrnam(const char *name) {
- struct irs_gr *gr = init();
-
- if (!gr)
+ 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)
+ 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);
+ return (net_data->gr_last);
}
struct group *
-getgrgid(gid_t gid) {
- struct irs_gr *gr = init();
-
- if (!gr)
+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)
+ 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);
+ return (net_data->gr_last);
}
int
-setgroupent(int stayopen) {
- struct irs_gr *gr = init();
-
- if (!gr)
+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);
+ net_data->gr_stayopen = (stayopen != 0);
+ if (stayopen == 0)
+ net_data_minimize(net_data);
return (1);
}
#ifdef SETGRENT_VOID
void
-setgrent() {
- (void)setgroupent(0);
+setgrent_p(struct net_data *net_data) {
+ (void)setgroupent_p(0, net_data);
}
#else
int
-setgrent() {
- return (setgroupent(0));
+setgrent_p(struct net_data *net_data) {
+ return (setgroupent_p(0, net_data));
}
#endif /* SETGRENT_VOID */
void
-endgrent() {
- struct irs_gr *gr = init();
+endgrent_p(struct net_data *net_data) {
+ struct irs_gr *gr;
- if (gr != NULL)
+ if ((net_data != NULL) && ((gr = net_data->gr) != NULL))
(*gr->minimize)(gr);
}
int
-getgrouplist(const char *name, gid_t basegid, gid_t *groups, int *ngroups) {
- struct irs_gr *gr = init();
-
- if (!gr) {
+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);
}
@@ -130,18 +197,25 @@ getgrouplist(const char *name, gid_t basegid, gid_t *groups, int *ngroups) {
/* Private */
-static struct irs_gr *
+static struct net_data *
init() {
- if (!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) {
+ 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);
+ errno = EIO;
+ return (NULL);
+ }
+ (*net_data->gr->res_set)(net_data->gr, net_data->res,
+ NULL);
}
- return (net_data.gr);
+
+ return (net_data);
}
#endif /* WANT_IRS_GR */
diff --git a/contrib/bind/lib/irs/getgrent_r.c b/contrib/bind/lib/irs/getgrent_r.c
new file mode 100644
index 0000000..df055db
--- /dev/null
+++ b/contrib/bind/lib/irs/getgrent_r.c
@@ -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 <port_before.h>
+#if !defined(_REENTRANT) || !defined(DO_PTHREADS) || !defined(WANT_IRS_PW)
+ static int getgrent_r_not_required = 0;
+#else
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <grp.h>
+#include <sys/param.h>
+#include <port_after.h>
+
+#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) */
diff --git a/contrib/bind/lib/irs/gethostent.c b/contrib/bind/lib/irs/gethostent.c
index 669cb95..ac66520 100644
--- a/contrib/bind/lib/irs/gethostent.c
+++ b/contrib/bind/lib/irs/gethostent.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996,1997 by Internet Software Consortium.
+ * 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
@@ -16,17 +16,21 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: gethostent.c,v 1.13 1997/12/04 04:57:52 halley Exp $";
+static const char rcsid[] = "$Id: gethostent.c,v 1.25 1999/10/19 22:27:20 cyarnell Exp $";
#endif
/* Imports */
#include "port_before.h"
+#if !defined(__BIND_NOSTATIC)
+
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
+#include <sys/ioctl.h>
#include <netinet/in.h>
+#include <net/if.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
@@ -37,8 +41,10 @@ static char rcsid[] = "$Id: gethostent.c,v 1.13 1997/12/04 04:57:52 halley Exp $
#include <resolv.h>
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
#include <irs.h>
+#include <isc/memcluster.h>
#include "port_after.h"
@@ -57,156 +63,747 @@ struct pvt {
/* Forward */
-static struct irs_ho * init(void);
-static void freepvt(void);
-static struct hostent * fakeaddr(const char *, int);
+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 ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ if (!net_data)
return (NULL);
- if (_res.options & RES_USE_INET6) {
- hp = gethostbyname2(name, AF_INET6);
+
+ if (net_data->res->options & RES_USE_INET6) {
+ hp = gethostbyname2_p(name, AF_INET6, net_data);
if (hp)
return (hp);
}
- return (gethostbyname2(name, AF_INET));
+ return (gethostbyname2_p(name, AF_INET, net_data));
}
struct hostent *
-gethostbyname2(const char *name, int af) {
- struct irs_ho *ho = init();
+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 (!ho)
+ if (!net_data || !(ho = net_data->ho))
return (NULL);
- if (net_data.ho_stayopen && net_data.ho_last) {
- if (!strcasecmp(name, net_data.ho_last->h_name))
- return (net_data.ho_last);
- for (hap = net_data.ho_last->h_aliases; hap && *hap; hap++)
- if (!strcasecmp(name, *hap))
- return (net_data.ho_last);
+ 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 = hostalias(name)))
+ if (!strchr(name, '.') && (cp = res_hostalias(net_data->res, name,
+ tmp, sizeof tmp)))
name = cp;
- if ((hp = fakeaddr(name, af)) != NULL)
+ if ((hp = fakeaddr(name, af, net_data)) != NULL)
return (hp);
- net_data.ho_last = (*ho->byname2)(ho, name, af);
- if (!net_data.ho_stayopen)
+ net_data->ho_last = (*ho->byname2)(ho, name, af);
+ if (!net_data->ho_stayopen)
endhostent();
- return (net_data.ho_last);
+ return (net_data->ho_last);
}
struct hostent *
-gethostbyaddr(const char *addr, int len, int af) {
- struct irs_ho *ho = init();
+gethostbyaddr_p(const char *addr, int len, int af, struct net_data *net_data) {
+ struct irs_ho *ho;
char **hap;
- if (!ho)
+ 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;
+ 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)
+ 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);
+ return (net_data->ho_last);
}
+
struct hostent *
-gethostent() {
- struct irs_ho *ho = init();
+gethostent_p(struct net_data *net_data) {
+ struct irs_ho *ho;
+ struct hostent *hp;
- if (!ho)
+ if (!net_data || !(ho = net_data->ho))
return (NULL);
- net_data.ho_last = (*ho->next)(ho);
- return (net_data.ho_last);
+ 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(int stayopen) {
- struct irs_ho *ho = init();
+sethostent_p(int stayopen, struct net_data *net_data) {
+ struct irs_ho *ho;
- if (!ho)
+ if (!net_data || !(ho = net_data->ho))
return;
- freepvt();
+ freepvt(net_data);
(*ho->rewind)(ho);
- net_data.ho_stayopen = (stayopen != 0);
+ net_data->ho_stayopen = (stayopen != 0);
+ if (stayopen == 0)
+ net_data_minimize(net_data);
}
void
-endhostent() {
- struct irs_ho *ho = init();
+endhostent_p(struct net_data *net_data) {
+ struct irs_ho *ho;
- if (ho != NULL)
+ if ((net_data != NULL) && ((ho = net_data->ho) != NULL))
(*ho->minimize)(ho);
}
-/* Private */
+#if !defined(HAS_INET6_STRUCTS) || defined(MISSING_IN6ADDR_ANY)
+static const struct in6_addr in6addr_any;
+#endif
-static struct irs_ho *
-init() {
- if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+#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 (!net_data_init())
- goto error;
- if (!net_data.ho)
- net_data.ho = (*net_data.irs->ho_map)(net_data.irs);
- if (!net_data.ho) {
- error: errno = EIO;
- h_errno = NETDB_INTERNAL;
+ }
+
+ /* 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);
}
- return (net_data.ho);
+
+ /* 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) {
+ struct ifconf ifc;
+ struct ifreq ifreq;
+ 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;
+ 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)
+ goto err_ret;
+
+ if (bufsiz > 1000000)
+ goto err_ret;
+
+ memput(buf, bufsiz);
+ bufsiz += 4096;
+ }
+
+ /* Parse system's interface list. */
+ cplim = buf + ifc.ifc_len; /* skip over if's with big ifr_addr's */
+ for (cp = buf;
+ (*have_v4 == 0 || *have_v6 == 0) && cp < cplim;
+ cp += cpsize) {
+ memcpy(&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
+ 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;
+ /* XXX maybe this should be a hard error? */
+ if (ioctl(s, SIOCGIFADDR, (char *)&ifreq) < 0)
+ continue;
+#endif
+ switch (ifreq.ifr_addr.sa_family) {
+ case AF_INET:
+ if (*have_v4 == 0) {
+ memcpy(&in4,
+ &((struct sockaddr_in *)
+ &ifreq.ifr_addr)->sin_addr, sizeof in4);
+ if (in4.s_addr == INADDR_ANY)
+ break;
+ n = ioctl(s, SIOCGIFFLAGS, (char *)&ifreq);
+ if (n < 0)
+ break;
+ if ((ifreq.ifr_flags & IFF_UP) == 0)
+ break;
+ *have_v4 = 1;
+ }
+ break;
+ case AF_INET6:
+ if (*have_v6 == 0) {
+ memcpy(&in6,
+ &((struct sockaddr_in6 *)
+ &ifreq.ifr_addr)->sin6_addr, sizeof in6);
+ if (memcmp(&in6, &in6addr_any, sizeof in6) == 0)
+ break;
+ n = ioctl(s, SIOCGIFFLAGS, (char *)&ifreq);
+ if (n < 0)
+ break;
+ if ((ifreq.ifr_flags & IFF_UP) == 0)
+ break;
+ *have_v6 = 1;
+ }
+ break;
+ }
+ }
+ if (buf != NULL)
+ memput(buf, bufsiz);
+ close(s);
+ return (0);
+ err_ret:
+ if (buf != NULL)
+ memput(buf, bufsiz);
+ if (s != -1)
+ close(s);
+ 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() {
- if (net_data.ho_data) {
- free(net_data.ho_data);
- net_data.ho_data = NULL;
+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) {
+fakeaddr(const char *name, int af, struct net_data *net_data) {
struct pvt *pvt;
- const char *cp;
- freepvt();
- net_data.ho_data = malloc(sizeof(struct pvt));
- if (!net_data.ho_data) {
+ freepvt(net_data);
+ net_data->ho_data = malloc(sizeof (struct pvt));
+ if (!net_data->ho_data) {
errno = ENOMEM;
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
return (NULL);
}
- pvt = net_data.ho_data;
+ pvt = net_data->ho_data;
/*
- * Unlike its forebear (inet_aton), our friendly inet_pton() is strict
+ * 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
+ * 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) {
- h_errno = HOST_NOT_FOUND;
+ 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) {
+ switch(af) {
case AF_INET:
pvt->host.h_length = NS_INADDRSZ;
break;
@@ -215,7 +812,7 @@ fakeaddr(const char *name, int af) {
break;
default:
errno = EAFNOSUPPORT;
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
return (NULL);
}
pvt->host.h_name = pvt->name;
@@ -224,9 +821,7 @@ fakeaddr(const char *name, int af) {
pvt->addrs[0] = (char *)pvt->addr;
pvt->addrs[1] = NULL;
pvt->host.h_addr_list = pvt->addrs;
- if (af == AF_INET && (_res.options & RES_USE_INET6))
- map_v4v6_address(pvt->addr, pvt->addr);
- h_errno = NETDB_SUCCESS;
+ RES_SET_H_ERRNO(net_data->res, NETDB_SUCCESS);
return (&pvt->host);
}
@@ -243,21 +838,23 @@ fakeaddr(const char *name, int af) {
*/
strncpy(hname2, hp->h_name, MAXDNAME);
hname2[MAXDNAME] = '\0';
- old_options = _res.options;
- _res.options &= ~RES_DNSRCH;
- _res.options |= RES_DEFNAMES;
+ old_options = net_data->res->options;
+ net_data->res->options &= ~RES_DNSRCH;
+ net_data->res->options |= RES_DEFNAMES;
if (!(rhp = gethostbyname(hname2))) {
- _res.options = old_options;
- h_errno = HOST_NOT_FOUND;
+ net_data->res->options = old_options;
+ RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND);
return (NULL);
}
- _res.options = old_options;
+ net_data->res->options = old_options;
for (haddr = rhp->h_addr_list; *haddr; haddr++)
if (!memcmp(*haddr, addr, INADDRSZ))
break;
if (!*haddr) {
- h_errno = HOST_NOT_FOUND;
+ RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND);
return (NULL);
}
}
#endif /* grot */
+
+#endif /*__BIND_NOSTATIC*/
diff --git a/contrib/bind/lib/irs/gethostent_r.c b/contrib/bind/lib/irs/gethostent_r.c
new file mode 100644
index 0000000..5da1a96
--- /dev/null
+++ b/contrib/bind/lib/irs/gethostent_r.c
@@ -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 <port_before.h>
+#if !defined(_REENTRANT) || !defined(DO_PTHREADS)
+ static int gethostent_r_not_required = 0;
+#else
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/param.h>
+#include <port_after.h>
+
+#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) */
diff --git a/contrib/bind/lib/irs/getnameinfo.c b/contrib/bind/lib/irs/getnameinfo.c
new file mode 100644
index 0000000..3157c66
--- /dev/null
+++ b/contrib/bind/lib/irs/getnameinfo.c
@@ -0,0 +1,230 @@
+/*
+ * 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 <port_before.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <netdb.h>
+#include <resolv.h>
+#include <string.h>
+
+#include <port_after.h>
+
+#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_long v4a;
+ 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:
+ v4a = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
+ if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+ flags |= NI_NUMERICHOST;
+ v4a >>= IN_CLASSA_NSHIFT;
+ if (v4a == 0 || v4a == IN_LOOPBACKNET)
+ flags |= NI_NUMERICHOST;
+ break;
+ case AF_INET6:
+ pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0];
+ 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;
+}
diff --git a/contrib/bind/lib/irs/getnetent.c b/contrib/bind/lib/irs/getnetent.c
index 17132f6..b63ddaf 100644
--- a/contrib/bind/lib/irs/getnetent.c
+++ b/contrib/bind/lib/irs/getnetent.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,15 +16,18 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: getnetent.c,v 1.10 1997/12/04 04:57:53 halley Exp $";
+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 <sys/types.h>
#include <sys/socket.h>
+
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
@@ -32,6 +35,7 @@ static char rcsid[] = "$Id: getnetent.c,v 1.10 1997/12/04 04:57:53 halley Exp $"
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
+#include <resolv.h>
#include <stdlib.h>
#include <string.h>
@@ -52,10 +56,10 @@ struct pvt {
/* Forward */
-static struct irs_nw * init(void);
-static struct netent * nw_to_net(struct nwent *);
-static void freepvt(void);
-static struct netent * fakeaddr(const char *, int af);
+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 */
@@ -67,118 +71,182 @@ static struct netent * fakeaddr(const char *, int af);
struct netent *
getnetent() {
- struct irs_nw *nw = init();
-
- if (!nw)
- return (NULL);
- net_data.nw_last = nw_to_net((*nw->next)(nw));
- return (net_data.nw_last);
+ struct net_data *net_data = init();
+
+ return (getnetent_p(net_data));
}
struct netent *
getnetbyname(const char *name) {
- struct irs_nw *nw = init();
+ 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 (!nw)
+
+ 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 (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);
+ return (net_data->nw_last);
}
- if ((np = fakeaddr(name, AF_INET)) != NULL)
+ if ((np = fakeaddr(name, AF_INET, net_data)) != NULL)
return (np);
- net_data.nw_last = nw_to_net((*nw->byname)(nw, name, AF_INET));
- if (!net_data.nw_stayopen)
+ 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);
+ return (net_data->nw_last);
}
struct netent *
-getnetbyaddr(unsigned long net, int type) {
- struct irs_nw *nw = init();
+getnetbyaddr_p(unsigned long net, int type, struct net_data *net_data) {
+ struct irs_nw *nw;
u_char addr[4];
int bits;
-
- if (!nw)
+
+ 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);
-
- addr[3] = (0xFF000000 & net) >> 24;
- addr[2] = (0x00FF0000 & net) >> 16;
- addr[1] = (0x0000FF00 & net) >> 8;
- addr[0] = (0x000000FF & net);
-
- /* Use the old class rules to figure out the network bits. */
- if (addr[3] >= 240)
- bits = 32;
- else if (addr[3] >= 224)
- bits = 4;
- else if (addr[3] >= 192)
- bits = 24;
- else if (addr[3] >= 128)
- bits = 16;
- else
+ 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;
-
- net_data.nw_last = nw_to_net((*nw->byaddr)(nw, addr, bits, AF_INET));
- if (!net_data.nw_stayopen)
+ } 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);
+ return (net_data->nw_last);
}
+
+
+
void
-setnetent(int stayopen) {
- struct irs_nw *nw = init();
-
- if (!nw)
+setnetent_p(int stayopen, struct net_data *net_data) {
+ struct irs_nw *nw;
+
+ if (!net_data || !(nw = net_data->nw))
return;
- freepvt();
+ freepvt(net_data);
(*nw->rewind)(nw);
- net_data.nw_stayopen = (stayopen != 0);
+ net_data->nw_stayopen = (stayopen != 0);
+ if (stayopen == 0)
+ net_data_minimize(net_data);
}
void
-endnetent() {
- struct irs_nw *nw = init();
+endnetent_p(struct net_data *net_data) {
+ struct irs_nw *nw;
- if (nw != NULL)
+ if ((net_data != NULL) && ((nw = net_data->nw) != NULL))
(*nw->minimize)(nw);
}
/* Private */
-static struct irs_nw *
+static struct net_data *
init() {
- if (!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) {
+ 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);
+ errno = EIO;
+ return (NULL);
+ }
+ (*net_data->nw->res_set)(net_data->nw, net_data->res, NULL);
}
- return (net_data.nw);
+
+ return (net_data);
}
static void
-freepvt() {
- if (net_data.nw_data) {
- free(net_data.nw_data);
- net_data.nw_data = NULL;
+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) {
+fakeaddr(const char *name, int af, struct net_data *net_data) {
struct pvt *pvt;
const char *cp;
u_long tmp;
@@ -186,7 +254,7 @@ fakeaddr(const char *name, int af) {
if (af != AF_INET) {
/* XXX should support IPv6 some day */
errno = EAFNOSUPPORT;
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
return (NULL);
}
if (!isascii(name[0]) || !isdigit(name[0]))
@@ -201,7 +269,7 @@ fakeaddr(const char *name, int af) {
tmp = inet_network(name);
if (tmp == INADDR_NONE) {
- h_errno = HOST_NOT_FOUND;
+ RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND);
return (NULL);
}
@@ -209,14 +277,14 @@ fakeaddr(const char *name, int af) {
* Fake up a netent as if we'd actually
* done a lookup.
*/
- freepvt();
- net_data.nw_data = malloc(sizeof(struct pvt));
- if (!net_data.nw_data) {
+ freepvt(net_data);
+ net_data->nw_data = malloc(sizeof (struct pvt));
+ if (!net_data->nw_data) {
errno = ENOMEM;
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
return (NULL);
}
- pvt = net_data.nw_data;
+ pvt = net_data->nw_data;
strncpy(pvt->name, name, MAXDNAME);
pvt->name[MAXDNAME] = '\0';
@@ -230,29 +298,29 @@ fakeaddr(const char *name, int af) {
}
static struct netent *
-nw_to_net(struct nwent *nwent) {
+nw_to_net(struct nwent *nwent, struct net_data *net_data) {
struct pvt *pvt;
u_long addr = 0;
- int i;
+ int i;
int msbyte;
if (!nwent || nwent->n_addrtype != AF_INET)
return (NULL);
- freepvt();
- net_data.nw_data = malloc(sizeof(struct pvt));
- if (!net_data.nw_data) {
+ freepvt(net_data);
+ net_data->nw_data = malloc(sizeof (struct pvt));
+ if (!net_data->nw_data) {
errno = ENOMEM;
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
return (NULL);
}
- pvt = net_data.nw_data;
+ 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
@@ -269,4 +337,4 @@ nw_to_net(struct nwent *nwent) {
return (&pvt->netent);
}
-
+#endif /*__BIND_NOSTATIC*/
diff --git a/contrib/bind/lib/irs/getnetent_r.c b/contrib/bind/lib/irs/getnetent_r.c
new file mode 100644
index 0000000..b78b45a
--- /dev/null
+++ b/contrib/bind/lib/irs/getnetent_r.c
@@ -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 <port_before.h>
+#if !defined(_REENTRANT) || !defined(DO_PTHREADS)
+ static int getnetent_r_not_required = 0;
+#else
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/param.h>
+#include <port_after.h>
+
+#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) */
diff --git a/contrib/bind/lib/irs/getnetgrent.c b/contrib/bind/lib/irs/getnetgrent.c
index 0acb776..8c5f5f8 100644
--- a/contrib/bind/lib/irs/getnetgrent.c
+++ b/contrib/bind/lib/irs/getnetgrent.c
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,14 +16,22 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: getnetgrent.c,v 1.9 1997/12/04 04:57:53 halley Exp $";
+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 <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
#include <errno.h>
+#include <resolv.h>
#include <stdio.h>
#include <irs.h>
@@ -34,60 +42,100 @@ static const char rcsid[] = "$Id: getnetgrent.c,v 1.9 1997/12/04 04:57:53 halley
/* Forward */
-static struct irs_ng * init(void);
+static struct net_data *init(void);
+
/* Public */
void
setnetgrent(const char *netgroup) {
- struct irs_ng *ng = init();
-
- if (ng != NULL)
- (*ng->rewind)(ng, netgroup);
+ struct net_data *net_data = init();
+
+ setnetgrent_p(netgroup, net_data);
}
-void
+void
endnetgrent(void) {
- struct irs_ng *ng = init();
-
- if (ng)
- (*ng->close)(ng);
- net_data.ng = NULL;
+ 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 irs_ng *ng = init();
-
- if (!ng)
+ 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(char **host, char **user, char **domain) {
- struct irs_ng *ng = init();
- struct netgrp *ngent;
-
- if (!ng)
+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 irs_ng *
+static struct net_data *
init(void) {
-
- if (!net_data_init())
+ 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);
+ 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.ng);
+
+ return (net_data);
}
+
+#endif /*__BIND_NOSTATIC*/
diff --git a/contrib/bind/lib/irs/getnetgrent_r.c b/contrib/bind/lib/irs/getnetgrent_r.c
new file mode 100644
index 0000000..e0c366c
--- /dev/null
+++ b/contrib/bind/lib/irs/getnetgrent_r.c
@@ -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 <port_before.h>
+#if !defined(_REENTRANT) || !defined(DO_PTHREADS)
+ static int getnetgrent_r_not_required = 0;
+#else
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <port_after.h>
+
+#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) */
diff --git a/contrib/bind/lib/irs/getprotoent.c b/contrib/bind/lib/irs/getprotoent.c
index f79a1c6..e3bfc37 100644
--- a/contrib/bind/lib/irs/getprotoent.c
+++ b/contrib/bind/lib/irs/getprotoent.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,16 +16,22 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: getprotoent.c,v 1.9 1997/12/04 04:57:53 halley Exp $";
+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 <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
#include <errno.h>
+#include <resolv.h>
#include <stdio.h>
#include <irs.h>
@@ -36,85 +42,132 @@ static char rcsid[] = "$Id: getprotoent.c,v 1.9 1997/12/04 04:57:53 halley Exp $
/* Forward */
-static struct irs_pr * init(void);
+static struct net_data *init(void);
/* Public */
struct protoent *
getprotoent() {
- struct irs_pr *pr = init();
-
- if (!pr)
- return (NULL);
- net_data.pr_last = (*pr->next)(pr);
- return (net_data.pr_last);
+ struct net_data *net_data = init();
+
+ return (getprotoent_p(net_data));
}
struct protoent *
getprotobyname(const char *name) {
- struct irs_pr *pr = init();
+ 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 (!pr)
+ 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 (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);
+ return (net_data->pr_last);
}
- net_data.pr_last = (*pr->byname)(pr, name);
- if (!net_data.pr_stayopen)
+ net_data->pr_last = (*pr->byname)(pr, name);
+ if (!net_data->pr_stayopen)
endprotoent();
- return (net_data.pr_last);
+ return (net_data->pr_last);
}
struct protoent *
-getprotobynumber(int proto) {
- struct irs_pr *pr = init();
+getprotobynumber_p(int proto, struct net_data *net_data) {
+ struct irs_pr *pr;
- if (!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)
+ 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);
+ return (net_data->pr_last);
}
void
-setprotoent(int stayopen) {
- struct irs_pr *pr = init();
+setprotoent_p(int stayopen, struct net_data *net_data) {
+ struct irs_pr *pr;
- if (!pr)
+ if (!net_data || !(pr = net_data->pr))
return;
(*pr->rewind)(pr);
- net_data.pr_stayopen = (stayopen != 0);
+ net_data->pr_stayopen = (stayopen != 0);
+ if (stayopen == 0)
+ net_data_minimize(net_data);
}
void
-endprotoent() {
- struct irs_pr *pr = init();
+endprotoent_p(struct net_data *net_data) {
+ struct irs_pr *pr;
- if (pr != NULL)
+ if ((net_data != NULL) && ((pr = net_data->pr) != NULL))
(*pr->minimize)(pr);
}
/* Private */
-static struct irs_pr *
+static struct net_data *
init() {
- if (!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) {
+ 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);
+ errno = EIO;
+ return (NULL);
+ }
+ (*net_data->pr->res_set)(net_data->pr, net_data->res, NULL);
}
- return (net_data.pr);
+
+ return (net_data);
}
+
+#endif /*__BIND_NOSTATIC*/
diff --git a/contrib/bind/lib/irs/getprotoent_r.c b/contrib/bind/lib/irs/getprotoent_r.c
new file mode 100644
index 0000000..e5c54d7
--- /dev/null
+++ b/contrib/bind/lib/irs/getprotoent_r.c
@@ -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 <port_before.h>
+#if !defined(_REENTRANT) || !defined(DO_PTHREADS)
+ static int getprotoent_r_not_required = 0;
+#else
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <port_after.h>
+
+#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) */
diff --git a/contrib/bind/lib/irs/getpwent.c b/contrib/bind/lib/irs/getpwent.c
index 8e4d897..94f2df5 100644
--- a/contrib/bind/lib/irs/getpwent.c
+++ b/contrib/bind/lib/irs/getpwent.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,21 +16,25 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: getpwent.c,v 1.13 1998/03/21 00:59:48 halley Exp $";
+static const char rcsid[] = "$Id: getpwent.c,v 1.20 1999/10/13 16:39:31 vixie Exp $";
#endif
/* Imports */
#include "port_before.h"
-#ifndef WANT_IRS_PW
+#if !defined(WANT_IRS_PW) || defined(__BIND_NOSTATIC)
static int __bind_irs_pw_unneeded;
#else
#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
#include <errno.h>
#include <pwd.h>
+#include <resolv.h>
#include <stdio.h>
#include <irs.h>
@@ -41,95 +45,155 @@ static int __bind_irs_pw_unneeded;
/* Forward */
-static struct irs_pw * init(void);
+static struct net_data * init(void);
/* Public */
struct passwd *
getpwent(void) {
- struct irs_pw *pw = init();
+ struct net_data *net_data = init();
- if (!pw)
- return (NULL);
- net_data.pw_last = (*pw->next)(pw);
- return (net_data.pw_last);
+ return (getpwent_p(net_data));
}
struct passwd *
getpwnam(const char *name) {
- struct irs_pw *pw = init();
-
- if (!pw)
+ 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();
+
+ return (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)
+ 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);
+ return (net_data->pw_last);
}
struct passwd *
-getpwuid(uid_t uid) {
- struct irs_pw *pw = init();
+getpwuid_p(uid_t uid, struct net_data *net_data) {
+ struct irs_pw *pw;
- if (!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)
+ 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);
+ return (net_data->pw_last);
}
int
-setpassent(int stayopen) {
- struct irs_pw *pw = init();
-
- if (!pw)
+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);
+ net_data->pw_stayopen = (stayopen != 0);
+ if (stayopen == 0)
+ net_data_minimize(net_data);
return (1);
}
#ifdef SETPWENT_VOID
void
-setpwent() {
- (void) setpassent(0);
+setpwent_p(struct net_data *net_data) {
+ (void) setpassent_p(0, net_data);
}
#else
-int
-setpwent() {
- return (setpassent(0));
+int
+setpwent_p(struct net_data *net_data) {
+ return (setpassent_p(0, net_data));
}
#endif
void
-endpwent() {
- struct irs_pw *pw = init();
+endpwent_p(struct net_data *net_data) {
+ struct irs_pw *pw;
- if (pw != NULL)
+ if ((net_data != NULL) && ((pw = net_data->pw) != NULL))
(*pw->minimize)(pw);
}
/* Private */
-static struct irs_pw *
+static struct net_data *
init() {
- if (!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) {
+ 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);
+ errno = EIO;
+ return (NULL);
+ }
+ (*net_data->pw->res_set)(net_data->pw, net_data->res, NULL);
}
- return (net_data.pw);
+
+ return (net_data);
}
#endif /* WANT_IRS_PW */
diff --git a/contrib/bind/lib/irs/getpwent_r.c b/contrib/bind/lib/irs/getpwent_r.c
new file mode 100644
index 0000000..761fa45
--- /dev/null
+++ b/contrib/bind/lib/irs/getpwent_r.c
@@ -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 <port_before.h>
+#if !defined(_REENTRANT) || !defined(DO_PTHREADS) || !defined(WANT_IRS_PW)
+ static int getpwent_r_not_required = 0;
+#else
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <port_after.h>
+
+#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) */
diff --git a/contrib/bind/lib/irs/getservent.c b/contrib/bind/lib/irs/getservent.c
index 64ac2dc..d2b8b50 100644
--- a/contrib/bind/lib/irs/getservent.c
+++ b/contrib/bind/lib/irs/getservent.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,16 +16,22 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: getservent.c,v 1.10 1997/12/04 04:57:54 halley Exp $";
+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 <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
#include <errno.h>
+#include <resolv.h>
#include <stdio.h>
#include <irs.h>
@@ -36,87 +42,135 @@ static char rcsid[] = "$Id: getservent.c,v 1.10 1997/12/04 04:57:54 halley Exp $
/* Forward */
-static struct irs_sv * init(void);
+static struct net_data *init(void);
/* Public */
struct servent *
getservent(void) {
- struct irs_sv *sv = init();
-
- if (!sv)
- return (NULL);
- net_data.sv_last = (*sv->next)(sv);
- return (net_data.sv_last);
+ struct net_data *net_data = init();
+
+ return (getservent_p(net_data));
}
struct servent *
getservbyname(const char *name, const char *proto) {
- struct irs_sv *sv = init();
+ 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 (!sv)
+
+ 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 (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);
+ return (net_data->sv_last);
}
- net_data.sv_last = (*sv->byname)(sv, name, proto);
- if (!net_data.sv_stayopen)
+ net_data->sv_last = (*sv->byname)(sv, name, proto);
+ if (!net_data->sv_stayopen)
endservent();
- return (net_data.sv_last);
+ return (net_data->sv_last);
}
struct servent *
-getservbyport(int port, const char *proto) {
- struct irs_sv *sv = init();
-
- if (!sv)
+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);
+ 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(int stayopen) {
- struct irs_sv *sv = init();
+setservent_p(int stayopen, struct net_data *net_data) {
+ struct irs_sv *sv;
- if (!sv)
+ if (!net_data || !(sv = net_data->sv))
return;
(*sv->rewind)(sv);
- net_data.sv_stayopen = (stayopen != 0);
+ net_data->sv_stayopen = (stayopen != 0);
+ if (stayopen == 0)
+ net_data_minimize(net_data);
}
void
-endservent() {
- struct irs_sv *sv = init();
+endservent_p(struct net_data *net_data) {
+ struct irs_sv *sv;
- if (sv != NULL)
+ if ((net_data != NULL) && ((sv = net_data->sv) != NULL))
(*sv->minimize)(sv);
}
/* Private */
-static struct irs_sv *
+static struct net_data *
init() {
- if (!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) {
+ 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);
+ errno = EIO;
+ return (NULL);
+ }
+ (*net_data->sv->res_set)(net_data->sv, net_data->res, NULL);
}
- return (net_data.sv);
+
+ return (net_data);
}
+
+#endif /*__BIND_NOSTATIC*/
diff --git a/contrib/bind/lib/irs/getservent_r.c b/contrib/bind/lib/irs/getservent_r.c
new file mode 100644
index 0000000..4da9dc2
--- /dev/null
+++ b/contrib/bind/lib/irs/getservent_r.c
@@ -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 <port_before.h>
+#if !defined(_REENTRANT) || !defined(DO_PTHREADS)
+ static int getservent_r_not_required = 0;
+#else
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/param.h>
+#include <port_after.h>
+
+#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) */
diff --git a/contrib/bind/lib/irs/hesiod.c b/contrib/bind/lib/irs/hesiod.c
index a56d213..54a6657 100644
--- a/contrib/bind/lib/irs/hesiod.c
+++ b/contrib/bind/lib/irs/hesiod.c
@@ -1,9 +1,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: hesiod.c,v 1.15 1998/01/26 23:08:24 halley Exp $";
+static const char rcsid[] = "$Id: hesiod.c,v 1.20 1999/02/22 04:09:06 vixie Exp $";
#endif
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -65,6 +65,7 @@ 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 */
@@ -131,15 +132,16 @@ hesiod_init(void **context) {
goto cleanup;
}
+#if 0
+ if (res_ninit(ctx->res) < 0)
+ goto cleanup;
+#endif
+
*context = ctx;
return (0);
cleanup:
- if (ctx->LHS)
- free(ctx->LHS);
- if (ctx->RHS)
- free(ctx->RHS);
- free(ctx);
+ hesiod_end(ctx);
return (-1);
}
@@ -149,12 +151,18 @@ hesiod_init(void **context) {
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;
}
/*
@@ -226,11 +234,17 @@ hesiod_resolve(void *context, const char *name, const char *type) {
char *bindname = hesiod_to_bind(context, name, type);
char **retvec;
- if (!bindname)
+ if (bindname == NULL)
+ return (NULL);
+ if (init(ctx) == -1) {
+ free(bindname);
return (NULL);
+ }
- if ((retvec = get_txt_records(ctx, C_IN, bindname)))
+ if ((retvec = get_txt_records(ctx, C_IN, bindname))) {
+ free(bindname);
return (retvec);
+ }
if (errno != ENOENT)
return (NULL);
@@ -322,8 +336,6 @@ parse_config_file(struct hesiod_p *ctx, const char *filename) {
/*
* Given a DNS class and a DNS name, do a lookup for TXT records, and
* return a list of them.
- *
- * XXX we're still using the non-thread safe res_* routines.
*/
static char **
get_txt_records(struct hesiod_p *ctx, int class, const char *name) {
@@ -333,7 +345,6 @@ get_txt_records(struct hesiod_p *ctx, int class, const char *name) {
int dlen; /* len of data section */
u_char *data; /* pointer to data */
} rr;
- struct __res_state save_res;
HEADER *hp;
u_char qbuf[MAX_HESRESP], abuf[MAX_HESRESP];
u_char *cp, *erdata, *eom;
@@ -342,22 +353,15 @@ get_txt_records(struct hesiod_p *ctx, int class, const char *name) {
int i, j, n, skip;
/*
- * Construct the query and send it. We play games with _res
- * since we don't have our own resolver state. Once the
- * resolver routines are rewritten to use their own context
- * variable, we'll use it here.
+ * Construct the query and send it.
*/
- if ((_res.options & RES_INIT) == 0 && res_init() == -1)
- return (NULL);
- save_res = _res;
- n = res_mkquery(QUERY, name, class, T_TXT, NULL, 0,
- NULL, qbuf, MAX_HESRESP);
+ 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_send(qbuf, n, abuf, MAX_HESRESP);
- _res = save_res;
+ n = res_nsend(ctx->res, qbuf, n, abuf, MAX_HESRESP);
if (n < 0) {
errno = ECONNREFUSED;
return (NULL);
@@ -452,3 +456,48 @@ get_txt_records(struct hesiod_p *ctx, int class, const char *name) {
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);
+}
diff --git a/contrib/bind/lib/irs/hesiod_p.h b/contrib/bind/lib/irs/hesiod_p.h
index d2204db..eb32166 100644
--- a/contrib/bind/lib/irs/hesiod_p.h
+++ b/contrib/bind/lib/irs/hesiod_p.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -20,7 +20,7 @@
*/
/*
- * $Id: hesiod_p.h,v 1.6 1996/11/18 09:09:32 vixie Exp $
+ * $Id: hesiod_p.h,v 1.9 1999/01/08 19:24:39 vixie Exp $
*/
/*
@@ -36,6 +36,11 @@
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
diff --git a/contrib/bind/lib/irs/irp.c b/contrib/bind/lib/irs/irp.c
new file mode 100644
index 0000000..c2b64ab
--- /dev/null
+++ b/contrib/bind/lib/irs/irp.c
@@ -0,0 +1,583 @@
+/*
+ * 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.5 1999/10/13 17:11:18 vixie Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#include <syslog.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#include <isc/memcluster.h>
+
+#include <irs.h>
+#include <irp.h>
+
+#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;
+ struct sockaddr_un uaddr;
+ long ipaddr;
+ const char *irphost;
+ int code;
+ char text[256];
+ int socklen = 0;
+
+ if (pvt->fdCxn != -1) {
+ perror("fd != 1");
+ return (-1);
+ }
+
+ memset(&uaddr, 0, sizeof uaddr);
+ memset(&iaddr, 0, sizeof iaddr);
+
+ irphost = getenv(IRPD_HOST_ENV);
+ if (irphost == NULL) {
+ irphost = "127.0.0.1";
+ }
+
+ 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 {
+ 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);
+}
+
+
+
diff --git a/contrib/bind/lib/irs/irp_gr.c b/contrib/bind/lib/irs/irp_gr.c
new file mode 100644
index 0000000..4e2a28c
--- /dev/null
+++ b/contrib/bind/lib/irs/irp_gr.c
@@ -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 <syslog.h>
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <syslog.h>
+
+#include <irs.h>
+#include <irp.h>
+#include <isc/memcluster.h>
+#include <isc/irpmarshall.h>
+
+#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 */
diff --git a/contrib/bind/lib/irs/irp_ho.c b/contrib/bind/lib/irs/irp_ho.c
new file mode 100644
index 0000000..7bfd0e2
--- /dev/null
+++ b/contrib/bind/lib/irs/irp_ho.c
@@ -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 <syslog.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
+#include <irs.h>
+#include <irp.h>
+#include <isc/irpmarshall.h>
+#include <isc/memcluster.h>
+
+#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);
+ }
+}
+
diff --git a/contrib/bind/lib/irs/irp_ng.c b/contrib/bind/lib/irs/irp_ng.c
new file mode 100644
index 0000000..e96f66c
--- /dev/null
+++ b/contrib/bind/lib/irs/irp_ng.c
@@ -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 <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <syslog.h>
+
+#include <irs.h>
+#include <irp.h>
+#include <isc/memcluster.h>
+#include <isc/irpmarshall.h>
+
+#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 */
+
diff --git a/contrib/bind/lib/irs/irp_nw.c b/contrib/bind/lib/irs/irp_nw.c
new file mode 100644
index 0000000..c0bcbfa
--- /dev/null
+++ b/contrib/bind/lib/irs/irp_nw.c
@@ -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 <syslog.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
+#include <irs.h>
+#include <irp.h>
+#include <isc/irpmarshall.h>
+
+#include <isc/memcluster.h>
+#include <isc/misc.h>
+
+#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);
+}
diff --git a/contrib/bind/lib/irs/irp_p.h b/contrib/bind/lib/irs/irp_p.h
new file mode 100644
index 0000000..adf8174
--- /dev/null
+++ b/contrib/bind/lib/irs/irp_p.h
@@ -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 <stdio.h>
+
+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
diff --git a/contrib/bind/lib/irs/irp_pr.c b/contrib/bind/lib/irs/irp_pr.c
new file mode 100644
index 0000000..1de304e
--- /dev/null
+++ b/contrib/bind/lib/irs/irp_pr.c
@@ -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 <syslog.h>
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <syslog.h>
+
+#include <irs.h>
+#include <irp.h>
+#include <isc/memcluster.h>
+#include <isc/irpmarshall.h>
+
+#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);
+}
diff --git a/contrib/bind/lib/irs/irp_pw.c b/contrib/bind/lib/irs/irp_pw.c
new file mode 100644
index 0000000..f23cb73
--- /dev/null
+++ b/contrib/bind/lib/irs/irp_pw.c
@@ -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 <syslog.h>
+#include <sys/param.h>
+
+#include <db.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <utmp.h>
+#include <unistd.h>
+
+#include <irs.h>
+#include <irp.h>
+#include <isc/memcluster.h>
+#include <isc/irpmarshall.h>
+
+#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 */
diff --git a/contrib/bind/lib/irs/irp_sv.c b/contrib/bind/lib/irs/irp_sv.c
new file mode 100644
index 0000000..6a12c5b
--- /dev/null
+++ b/contrib/bind/lib/irs/irp_sv.c
@@ -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 <syslog.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#ifdef IRS_LCL_SV_DB
+#include <db.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslog.h>
+
+#include <irs.h>
+#include <irp.h>
+#include <isc/irpmarshall.h>
+#include <isc/memcluster.h>
+
+#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);
+ }
+}
+
+
diff --git a/contrib/bind/lib/irs/irpmarshall.c b/contrib/bind/lib/irs/irpmarshall.c
new file mode 100644
index 0000000..8f7c330
--- /dev/null
+++ b/contrib/bind/lib/irs/irpmarshall.c
@@ -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 <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <utmp.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <irs.h>
+#include <isc/memcluster.h>
+#include <isc/irpmarshall.h>
+
+#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
diff --git a/contrib/bind/lib/irs/irs_data.c b/contrib/bind/lib/irs/irs_data.c
index 7f23751..f31fe69 100644
--- a/contrib/bind/lib/irs/irs_data.c
+++ b/contrib/bind/lib/irs/irs_data.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,24 +16,179 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: irs_data.c,v 1.7 1997/12/04 04:57:54 halley Exp $";
+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 <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <resolv.h>
#include <stdio.h>
+#include <isc/memcluster.h>
+
+#ifdef DO_PTHREADS
+#include <pthread.h>
+#endif
#include <irs.h>
#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;
+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
-int
-net_data_init() {
- if (!net_data.irs)
- net_data.irs = irs_gen_acc("");
- return (net_data.irs != NULL);
+ 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*/
diff --git a/contrib/bind/lib/irs/irs_data.h b/contrib/bind/lib/irs/irs_data.h
index 4356b57..c82d767 100644
--- a/contrib/bind/lib/irs/irs_data.h
+++ b/contrib/bind/lib/irs/irs_data.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,10 +16,11 @@
*/
/*
- * $Id: irs_data.h,v 1.7 1997/12/04 04:57:55 halley Exp $
+ * $Id: irs_data.h,v 1.12 1999/01/18 07:46:55 vixie Exp $
*/
-#define net_data __net_data
+#ifndef __BIND_NOSTATIC
+
#define net_data_init __net_data_init
struct net_data {
@@ -37,7 +38,8 @@ struct net_data {
struct passwd * pw_last;
struct servent * sv_last;
struct protoent * pr_last;
- struct netent * nw_last;
+ struct netent * nw_last; /* should have been ne_last */
+ struct nwent * nww_last;
struct hostent * ho_last;
unsigned int gr_stayopen :1;
@@ -50,8 +52,11 @@ struct net_data {
void * nw_data;
void * ho_data;
- char fill[512 - 68]; /* 68 = sizeof(above) */
+ struct __res_state * res; /* for gethostent.c */
+
};
-extern struct net_data net_data;
-extern int net_data_init(void);
+extern struct net_data * net_data_init(const char *conf_file);
+extern void net_data_minimize(struct net_data *);
+
+#endif /*__BIND_NOSTATIC*/
diff --git a/contrib/bind/lib/irs/irs_p.h b/contrib/bind/lib/irs/irs_p.h
index bc49665..d14f7d1 100644
--- a/contrib/bind/lib/irs/irs_p.h
+++ b/contrib/bind/lib/irs/irs_p.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,21 +16,34 @@
*/
/*
- * $Id: irs_p.h,v 1.6 1997/12/04 04:57:55 halley Exp $
+ * $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 <stdio.h>
+
#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
diff --git a/contrib/bind/lib/irs/lcl.c b/contrib/bind/lib/irs/lcl.c
index badbdfe..46c7743 100644
--- a/contrib/bind/lib/irs/lcl.c
+++ b/contrib/bind/lib/irs/lcl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: lcl.c,v 1.11 1998/03/21 00:59:49 halley Exp $";
+static const char rcsid[] = "$Id: lcl.c,v 1.15 1999/10/13 16:39:32 vixie Exp $";
#endif
/* Imports */
@@ -27,6 +27,13 @@ static char rcsid[] = "$Id: lcl.c,v 1.11 1998/03/21 00:59:49 halley Exp $";
#include <errno.h>
#include <string.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <isc/memcluster.h>
+
#include <irs.h>
#include "port_after.h"
@@ -37,6 +44,9 @@ static char rcsid[] = "$Id: lcl.c,v 1.11 1998/03/21 00:59:49 halley Exp $";
/* 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 */
@@ -45,17 +55,19 @@ irs_lcl_acc(const char *options) {
struct irs_acc *acc;
struct lcl_p *lcl;
- if (!(acc = malloc(sizeof *acc))) {
+ if (!(acc = memget(sizeof *acc))) {
errno = ENOMEM;
return (NULL);
}
memset(acc, 0x5e, sizeof *acc);
- if (!(lcl = malloc(sizeof *lcl))) {
+ 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;
@@ -72,17 +84,55 @@ irs_lcl_acc(const char *options) {
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)
- free(lcl);
- free(this);
+ if (lcl) {
+ if (lcl->free_res)
+ (*lcl->free_res)(lcl->res);
+ memput(lcl, sizeof *lcl);
+ }
+ memput(this, sizeof *this);
}
diff --git a/contrib/bind/lib/irs/lcl_gr.c b/contrib/bind/lib/irs/lcl_gr.c
index 5a5d503..acb85ee 100644
--- a/contrib/bind/lib/irs/lcl_gr.c
+++ b/contrib/bind/lib/irs/lcl_gr.c
@@ -32,7 +32,7 @@
*/
/*
- * Portions Copyright (c) 1996, 1998 by Internet Software Consortium.
+ * 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
@@ -49,7 +49,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: lcl_gr.c,v 1.20 1998/03/21 00:59:49 halley Exp $";
+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 */
@@ -64,6 +64,9 @@ static int __bind_irs_gr_unneeded;
#include <sys/param.h>
#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
#include <errno.h>
#include <fcntl.h>
@@ -74,11 +77,14 @@ static int __bind_irs_gr_unneeded;
#include <unistd.h>
#include <irs.h>
-
-#include "port_after.h"
+#include <isc/memcluster.h>
#include "irs_p.h"
#include "lcl_p.h"
+#include "irp_p.h"
+
+#include "port_after.h"
+
/* Types. */
@@ -123,13 +129,13 @@ irs_lcl_gr(struct irs_acc *this) {
struct irs_gr *gr;
struct pvt *pvt;
- if (!(gr = malloc(sizeof *gr))) {
+ if (!(gr = memget(sizeof *gr))) {
errno = ENOMEM;
return (NULL);
}
memset(gr, 0x5e, sizeof *gr);
- if (!(pvt = malloc(sizeof *pvt))) {
- free(gr);
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(gr, sizeof *gr);
errno = ENOMEM;
return (NULL);
}
@@ -142,6 +148,8 @@ irs_lcl_gr(struct irs_acc *this) {
gr->rewind = gr_rewind;
gr->list = make_group_list;
gr->minimize = gr_minimize;
+ gr->res_get = NULL;
+ gr->res_set = NULL;
return (gr);
}
@@ -157,8 +165,8 @@ gr_close(struct irs_gr *this) {
free(pvt->group.gr_mem);
if (pvt->membuf)
free(pvt->membuf);
- free(pvt);
- free(this);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
static struct group *
@@ -271,13 +279,12 @@ grnext(struct pvt *pvt) {
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 linelen, n;
+ size_t n;
char *bp, **m, *p;
/* Read lines until we find one that matches our search criteria. */
for (;;) {
- bp = grnext(pvt);
- if (bp == NULL)
+ if ((bp = grnext(pvt)) == NULL)
return (NULL);
/* Optimize the usual case of searching for a name. */
@@ -320,8 +327,10 @@ grscan(struct irs_gr *this, int search, gid_t gid, const char *name) {
* to account for the NULL terminator. As above, allocate
* largest of INITIAL_NMEMB, or 2*n.
*/
- for (n = 2, p = bp; (p = strpbrk(p, ", ")) != NULL; ++p, ++n)
- (void)NULL;
+ 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;
diff --git a/contrib/bind/lib/irs/lcl_ho.c b/contrib/bind/lib/irs/lcl_ho.c
index b285d1c..5939207 100644
--- a/contrib/bind/lib/irs/lcl_ho.c
+++ b/contrib/bind/lib/irs/lcl_ho.c
@@ -32,7 +32,7 @@
*/
/*
- * Portions Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -52,7 +52,7 @@
/* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */
#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$Id: lcl_ho.c,v 1.15 1997/12/04 04:57:56 halley Exp $";
+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. */
@@ -77,6 +77,7 @@ static char rcsid[] = "$Id: lcl_ho.c,v 1.15 1997/12/04 04:57:56 halley Exp $";
#include <string.h>
#include <irs.h>
+#include <isc/memcluster.h>
#include "port_after.h"
@@ -89,8 +90,6 @@ static char rcsid[] = "$Id: lcl_ho.c,v 1.15 1997/12/04 04:57:56 halley Exp $";
# define SPRINTF(x) sprintf x
#endif
-extern int h_errno;
-
/* Definitions. */
#define MAXALIASES 35
@@ -110,6 +109,8 @@ struct pvt {
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 {
@@ -131,8 +132,13 @@ static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr,
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. */
@@ -147,12 +153,13 @@ irs_lcl_ho(struct irs_acc *this) {
struct irs_ho *ho;
struct pvt *pvt;
- if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) {
+ if (!(pvt = memget(sizeof *pvt))) {
errno = ENOMEM;
return (NULL);
}
memset(pvt, 0, sizeof *pvt);
- if (!(ho = malloc(sizeof *ho))) {
+ if (!(ho = memget(sizeof *ho))) {
+ memput(pvt, sizeof *pvt);
errno = ENOMEM;
return (NULL);
}
@@ -165,6 +172,8 @@ irs_lcl_ho(struct irs_acc *this) {
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);
}
@@ -174,19 +183,24 @@ 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);
- free(pvt);
- free(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 hostent *hp;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ if (init(this) == -1)
return (NULL);
- if (_res.options & RES_USE_INET6) {
+
+ if (pvt->res->options & RES_USE_INET6) {
hp = ho_byname2(this, name, AF_INET6);
if (hp)
return (hp);
@@ -196,12 +210,14 @@ ho_byname(struct irs_ho *this, const char *name) {
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 ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ if (init(this) == -1)
return (NULL);
+
ho_rewind(this);
n = ns_namelen(name);
while ((hp = ho_next(this)) != NULL) {
@@ -220,21 +236,23 @@ ho_byname2(struct irs_ho *this, const char *name, int af) {
}
found:
if (!hp) {
- h_errno = HOST_NOT_FOUND;
+ RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
return (NULL);
}
- h_errno = NETDB_SUCCESS;
+ 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 ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ if (init(this) == -1)
return (NULL);
+
if (af == AF_INET6 && len == IN6ADDRSZ &&
(!memcmp(uaddr, mapped, sizeof mapped) ||
!memcmp(uaddr, tunnelled, sizeof tunnelled))) {
@@ -253,12 +271,12 @@ ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) {
break;
default:
errno = EAFNOSUPPORT;
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
return (NULL);
}
if (size > len) {
errno = EINVAL;
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
return (NULL);
}
@@ -289,10 +307,10 @@ ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) {
}
found:
if (!hp) {
- h_errno = HOST_NOT_FOUND;
+ RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
return (NULL);
}
- h_errno = NETDB_SUCCESS;
+ RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS);
return (hp);
}
@@ -300,33 +318,67 @@ static struct hostent *
ho_next(struct irs_ho *this) {
struct pvt *pvt = (struct pvt *)this->private;
char *cp, **q, *p;
- int af, len;
+ 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) {
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
return (NULL);
}
+ bufp = pvt->hostbuf;
+ bufsiz = sizeof pvt->hostbuf;
+ offset = 0;
again:
- if (!(p = fgets(pvt->hostbuf, sizeof pvt->hostbuf, pvt->fp))) {
- h_errno = HOST_NOT_FOUND;
+ 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 (*p == '#')
+ 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;
- if (!(cp = strpbrk(p, "#\n")))
+ }
+
+ p -= offset;
+ offset = 0;
+
+ if (*p == '#')
goto again;
- *cp = '\0';
+ if ((cp = strpbrk(p, "#\n")) != NULL)
+ *cp = '\0';
if (!(cp = strpbrk(p, " \t")))
goto again;
*cp++ = '\0';
- if ((_res.options & RES_USE_INET6) &&
- inet_pton(AF_INET6, p, pvt->host_addr) > 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 (_res.options & RES_USE_INET6) {
+ if (pvt->res->options & RES_USE_INET6) {
map_v4v6_address((char*)pvt->host_addr,
(char*)pvt->host_addr);
af = AF_INET6;
@@ -360,7 +412,9 @@ ho_next(struct irs_ho *this) {
*cp++ = '\0';
}
*q = NULL;
- h_errno = NETDB_SUCCESS;
+ if (dbuf)
+ free(dbuf);
+ RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS);
return (&pvt->host);
}
@@ -389,6 +443,40 @@ ho_minimize(struct irs_ho *this) {
(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. */
@@ -401,3 +489,15 @@ ns_namelen(const char *s) {
(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);
+}
diff --git a/contrib/bind/lib/irs/lcl_ng.c b/contrib/bind/lib/irs/lcl_ng.c
index ca7e7e2..03acbf6 100644
--- a/contrib/bind/lib/irs/lcl_ng.c
+++ b/contrib/bind/lib/irs/lcl_ng.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ * 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
@@ -16,13 +16,17 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: lcl_ng.c,v 1.12 1998/02/13 01:10:41 halley Exp $";
+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 <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -30,6 +34,7 @@ static char rcsid[] = "$Id: lcl_ng.c,v 1.12 1998/02/13 01:10:41 halley Exp $";
#include <unistd.h>
#include <irs.h>
+#include <isc/memcluster.h>
#include "port_after.h"
@@ -100,13 +105,13 @@ irs_lcl_ng(struct irs_acc *this) {
struct irs_ng *ng;
struct pvt *pvt;
- if (!(ng = malloc(sizeof *ng))) {
+ if (!(ng = memget(sizeof *ng))) {
errno = ENOMEM;
return (NULL);
}
memset(ng, 0x5e, sizeof *ng);
- if (!(pvt = malloc(sizeof *pvt))) {
- free(ng);
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(ng, sizeof *ng);
errno = ENOMEM;
return (NULL);
}
@@ -129,8 +134,8 @@ ng_close(struct irs_ng *this) {
if (pvt->fp != NULL)
fclose(pvt->fp);
freelists(this);
- free(pvt);
- free(this);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
/*
diff --git a/contrib/bind/lib/irs/lcl_nw.c b/contrib/bind/lib/irs/lcl_nw.c
index 09a324c..0d41ec4 100644
--- a/contrib/bind/lib/irs/lcl_nw.c
+++ b/contrib/bind/lib/irs/lcl_nw.c
@@ -32,7 +32,7 @@
*/
/*
- * Portions Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -49,7 +49,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: lcl_nw.c,v 1.13 1997/12/04 04:57:57 halley Exp $";
+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 */
@@ -59,18 +59,21 @@ static const char rcsid[] = "$Id: lcl_nw.c,v 1.13 1997/12/04 04:57:57 halley Exp
#include "port_before.h"
#include <sys/types.h>
+#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-#include <sys/socket.h>
+#include <arpa/nameser.h>
#include <errno.h>
#include <fcntl.h>
+#include <resolv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <irs.h>
+#include <isc/memcluster.h>
#include "port_after.h"
@@ -87,6 +90,8 @@ struct pvt {
struct nwent net;
char * aliases[MAXALIASES];
char addr[MAXADDRSIZE];
+ struct __res_state * res;
+ void (*free_res)(void *);
};
/* Forward */
@@ -97,6 +102,12 @@ 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. */
@@ -111,17 +122,17 @@ irs_lcl_nw(struct irs_acc *this) {
struct irs_nw *nw;
struct pvt *pvt;
- if (!(nw = (struct irs_nw *)malloc(sizeof *nw))) {
+ if (!(pvt = memget(sizeof *pvt))) {
errno = ENOMEM;
return (NULL);
}
- memset(nw, 0x5e, sizeof *nw);
- if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) {
- free(nw);
+ memset(pvt, 0, sizeof *pvt);
+ if (!(nw = memget(sizeof *nw))) {
+ memput(pvt, sizeof *pvt);
errno = ENOMEM;
return (NULL);
}
- memset(pvt, 0, sizeof *pvt);
+ memset(nw, 0x5e, sizeof *nw);
nw->private = pvt;
nw->close = nw_close;
nw->byname = nw_byname;
@@ -129,6 +140,8 @@ irs_lcl_nw(struct irs_acc *this) {
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);
}
@@ -138,16 +151,22 @@ 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);
- free(pvt);
- free(this);
+ 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)
@@ -161,13 +180,16 @@ 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 (strcasecmp(p->n_name, name) == 0 &&
+ if (ns_samename(p->n_name, name) == 1 &&
p->n_addrtype == type)
break;
for (ap = p->n_aliases; *ap; ap++)
- if ((strcasecmp(*ap, name) == 0) &&
+ if ((ns_samename(*ap, name) == 1) &&
(p->n_addrtype == type))
goto found;
}
@@ -195,24 +217,60 @@ nw_rewind(struct irs_nw *this) {
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) {
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
return (NULL);
}
+ bufp = pvt->line;
+ bufsiz = sizeof(pvt->line);
+
again:
- p = fgets(pvt->line, BUFSIZ, pvt->fp);
+ p = fgets(bufp + offset, bufsiz - offset, pvt->fp);
if (p == NULL)
- return (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)
- goto again;
- *cp = '\0';
+ if (cp != NULL)
+ *cp = '\0';
pvt->net.n_name = p;
cp = strpbrk(p, " \t");
if (cp == NULL)
@@ -245,15 +303,67 @@ nw_next(struct irs_nw *this) {
}
}
*q = NULL;
- return (&pvt->net);
+ 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);
+}
diff --git a/contrib/bind/lib/irs/lcl_p.h b/contrib/bind/lib/irs/lcl_p.h
index 058aeaa..b9e3b3e 100644
--- a/contrib/bind/lib/irs/lcl_p.h
+++ b/contrib/bind/lib/irs/lcl_p.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
/*
- * $Id: lcl_p.h,v 1.5 1996/10/25 07:23:19 vixie Exp $
+ * $Id: lcl_p.h,v 1.7 1999/01/08 19:24:51 vixie Exp $
*/
/*
@@ -30,7 +30,8 @@
* Object state.
*/
struct lcl_p {
- void *placeholder;
+ struct __res_state * res;
+ void (*free_res) __P((void *));
};
/*
diff --git a/contrib/bind/lib/irs/lcl_pr.c b/contrib/bind/lib/irs/lcl_pr.c
index 101f99d..5162115 100644
--- a/contrib/bind/lib/irs/lcl_pr.c
+++ b/contrib/bind/lib/irs/lcl_pr.c
@@ -32,7 +32,7 @@
*/
/*
- * Portions Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -49,7 +49,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: lcl_pr.c,v 1.11 1997/12/04 04:57:57 halley Exp $";
+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 */
@@ -57,6 +57,9 @@ static const char rcsid[] = "$Id: lcl_pr.c,v 1.11 1997/12/04 04:57:57 halley Exp
#include "port_before.h"
#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
#include <errno.h>
#include <fcntl.h>
@@ -65,6 +68,7 @@ static const char rcsid[] = "$Id: lcl_pr.c,v 1.11 1997/12/04 04:57:57 halley Exp
#include <stdlib.h>
#include <irs.h>
+#include <isc/memcluster.h>
#include "port_after.h"
@@ -79,10 +83,10 @@ static const char rcsid[] = "$Id: lcl_pr.c,v 1.11 1997/12/04 04:57:57 halley Exp
/* Types */
struct pvt {
- FILE *fp;
- char line[BUFSIZ+1];
- struct protoent proto;
- char *proto_aliases[MAXALIASES];
+ FILE * fp;
+ char line[BUFSIZ+1];
+ struct protoent proto;
+ char * proto_aliases[MAXALIASES];
};
/* Forward */
@@ -107,12 +111,12 @@ irs_lcl_pr(struct irs_acc *this) {
struct irs_pr *pr;
struct pvt *pvt;
- if (!(pr = (struct irs_pr *)malloc(sizeof *pr))) {
+ if (!(pr = memget(sizeof *pr))) {
errno = ENOMEM;
return (NULL);
}
- if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) {
- free(pr);
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(pr, sizeof *this);
errno = ENOMEM;
return (NULL);
}
@@ -124,6 +128,8 @@ irs_lcl_pr(struct irs_acc *this) {
pr->next = pr_next;
pr->rewind = pr_rewind;
pr->minimize = pr_minimize;
+ pr->res_get = NULL;
+ pr->res_set = NULL;
return (pr);
}
@@ -135,8 +141,8 @@ pr_close(struct irs_pr *this) {
if (pvt->fp)
(void) fclose(pvt->fp);
- free(pvt);
- free(this);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
static struct protoent *
@@ -189,20 +195,54 @@ 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(pvt->line, BUFSIZ, pvt->fp)) == NULL)
+ 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)
- goto again;
- *cp = '\0';
+ if (cp != NULL)
+ *cp = '\0';
pvt->proto.p_name = p;
cp = strpbrk(p, " \t");
if (cp == NULL)
diff --git a/contrib/bind/lib/irs/lcl_pw.c b/contrib/bind/lib/irs/lcl_pw.c
index 1f3e870..2655677 100644
--- a/contrib/bind/lib/irs/lcl_pw.c
+++ b/contrib/bind/lib/irs/lcl_pw.c
@@ -32,7 +32,7 @@
*/
/*
- * Portions Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -49,7 +49,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: lcl_pw.c,v 1.16 1998/02/13 01:10:42 halley Exp $";
+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 */
@@ -61,6 +61,10 @@ static int __bind_irs_pw_unneeded;
#else
#include <sys/param.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
#include <db.h>
#include <errno.h>
@@ -73,6 +77,7 @@ static int __bind_irs_pw_unneeded;
#include <utmp.h>
#include <unistd.h>
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -115,12 +120,12 @@ irs_lcl_pw(struct irs_acc *this) {
struct irs_pw *pw;
struct pvt *pvt;
- if (!(pw = malloc(sizeof *pw))) {
+ if (!(pw = memget(sizeof *pw))) {
errno = ENOMEM;
return (NULL);
}
memset(pw, 0x5e, sizeof *pw);
- if (!(pvt = malloc(sizeof *pvt))) {
+ if (!(pvt = memget(sizeof *pvt))) {
free(pw);
errno = ENOMEM;
return (NULL);
@@ -133,6 +138,8 @@ irs_lcl_pw(struct irs_acc *this) {
pw->byuid = pw_byuid;
pw->rewind = pw_rewind;
pw->minimize = pw_minimize;
+ pw->res_get = NULL;
+ pw->res_set = NULL;
return (pw);
}
@@ -147,9 +154,9 @@ pw_close(struct irs_pw *this) {
pvt->pw_db = NULL;
}
if (pvt->line)
- free(pvt->line);
- free(pvt);
- free(this);
+ memput(pvt->line, pvt->max);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
static struct passwd *
@@ -262,9 +269,20 @@ hashpw(struct irs_pw *this, DBT *key) {
if ((pvt->pw_db->get)(pvt->pw_db, key, &data, 0))
return (0);
p = (char *)data.data;
- if (data.size > pvt->max &&
- (pvt->line = realloc(pvt->line, pvt->max += 1024)) == NULL)
- return (0);
+ 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;
diff --git a/contrib/bind/lib/irs/lcl_sv.c b/contrib/bind/lib/irs/lcl_sv.c
index 0da9984..7e5bec9 100644
--- a/contrib/bind/lib/irs/lcl_sv.c
+++ b/contrib/bind/lib/irs/lcl_sv.c
@@ -32,7 +32,7 @@
*/
/*
- * Portions Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -49,7 +49,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: lcl_sv.c,v 1.11 1997/12/04 04:57:58 halley Exp $";
+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 */
@@ -58,31 +58,42 @@ static const char rcsid[] = "$Id: lcl_sv.c,v 1.11 1997/12/04 04:57:58 halley Exp
#include <sys/types.h>
#include <sys/socket.h>
-
#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#ifdef IRS_LCL_SV_DB
+#include <db.h>
+#endif
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <irs.h>
+#include <isc/memcluster.h>
#include "port_after.h"
#include "irs_p.h"
#include "lcl_p.h"
-#define MAXALIASES 35
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
/* Types */
struct pvt {
- FILE * fp;
- char line[BUFSIZ+1];
- struct servent serv;
- char * serv_aliases[MAXALIASES];
+#ifdef IRS_LCL_SV_DB
+ DB * dbh;
+ int dbf;
+#endif
+ struct lcl_sv sv;
};
/* Forward */
@@ -94,6 +105,10 @@ static struct servent * sv_byname(struct irs_sv *, 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 */
@@ -108,13 +123,13 @@ irs_lcl_sv(struct irs_acc *this) {
struct irs_sv *sv;
struct pvt *pvt;
- if (!(sv = (struct irs_sv *)malloc(sizeof *sv))) {
+ if ((sv = memget(sizeof *sv)) == NULL) {
errno = ENOMEM;
return (NULL);
}
memset(sv, 0x5e, sizeof *sv);
- if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) {
- free(sv);
+ if ((pvt = memget(sizeof *pvt)) == NULL) {
+ memput(sv, sizeof *sv);
errno = ENOMEM;
return (NULL);
}
@@ -126,6 +141,11 @@ irs_lcl_sv(struct irs_acc *this) {
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);
}
@@ -135,120 +155,278 @@ static void
sv_close(struct irs_sv *this) {
struct pvt *pvt = (struct pvt *)this->private;
- if (pvt->fp)
- fclose(pvt->fp);
- free(pvt);
- free(this);
+#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) {
- register struct servent *p;
- register char **cp;
-
- sv_rewind(this);
- 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;
+#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;
+ 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) {
- register struct servent *p;
-
- sv_rewind(this);
- while ((p = sv_next(this))) {
- if (p->s_port != port)
- continue;
- if (proto == NULL || strcmp(p->s_proto, proto) == 0)
- break;
- }
- return (p);
+#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->fp) {
- if (fseek(pvt->fp, 0L, SEEK_SET) == 0)
+ if (pvt->sv.fp) {
+ if (fseek(pvt->sv.fp, 0L, SEEK_SET) == 0)
return;
- (void)fclose(pvt->fp);
+ (void)fclose(pvt->sv.fp);
+ pvt->sv.fp = NULL;
}
- if (!(pvt->fp = fopen(_PATH_SERVICES, "r" )))
+#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;
- if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) {
- (void)fclose(pvt->fp);
- pvt->fp = NULL;
+ }
+#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;
- char *p;
- register char *cp, **q;
- if (!pvt->fp)
+#ifdef IRS_LCL_SV_DB
+ if (pvt->dbh != NULL)
+ NULL;
+ else
+#endif
+ if (pvt->sv.fp != NULL)
+ NULL;
+ else
sv_rewind(this);
- if (!pvt->fp)
+
+#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(pvt->line, BUFSIZ, pvt->fp)) == NULL)
+ if ((p = fgets(sv->line, BUFSIZ, sv->fp)) == NULL)
return (NULL);
if (*p == '#')
goto again;
- cp = strpbrk(p, "#\n");
- if (cp == NULL)
- goto again;
- *cp = '\0';
- pvt->serv.s_name = p;
- p = strpbrk(p, " \t");
- if (p == NULL)
+ 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++;
- cp = strpbrk(p, ",/");
- if (cp == NULL)
+ if (*p == '\0' || *p == '#' || *p == '\n')
goto again;
- *cp++ = '\0';
- pvt->serv.s_port = htons((u_short)atoi(p));
- pvt->serv.s_proto = cp;
- q = pvt->serv.s_aliases = pvt->serv_aliases;
- cp = strpbrk(cp, " \t");
- if (cp != NULL)
- *cp++ = '\0';
- while (cp && *cp) {
- if (*cp == ' ' || *cp == '\t') {
- cp++;
- continue;
- }
- if (q < &pvt->serv_aliases[MAXALIASES - 1])
- *q++ = cp;
- cp = strpbrk(cp, " \t");
- if (cp != NULL)
- *cp++ = '\0';
+ 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 (&pvt->serv);
+ return (&sv->serv);
}
-static void
-sv_minimize(struct irs_sv *this) {
- struct pvt *pvt = (struct pvt *)this->private;
+/* Private. */
- if (pvt->fp != NULL) {
- (void)fclose(pvt->fp);
- pvt->fp = NULL;
+#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
diff --git a/contrib/bind/lib/irs/nis.c b/contrib/bind/lib/irs/nis.c
index d53bde9..fcd9b79 100644
--- a/contrib/bind/lib/irs/nis.c
+++ b/contrib/bind/lib/irs/nis.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: nis.c,v 1.10 1998/03/21 00:59:50 halley Exp $";
+static const char rcsid[] = "$Id: nis.c,v 1.13 1999/01/18 07:46:58 vixie Exp $";
#endif
/* Imports */
@@ -34,6 +34,12 @@ static const char rcsid[] = "$Id: nis.c,v 1.10 1998/03/21 00:59:50 halley Exp $"
#include <string.h>
#include <errno.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -45,6 +51,9 @@ static const char rcsid[] = "$Id: nis.c,v 1.10 1998/03/21 00:59:50 halley Exp $"
/* 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 */
@@ -56,13 +65,13 @@ irs_nis_acc(const char *options) {
if (yp_get_default_domain(&domain) != 0)
return (NULL);
- if (!(nis = malloc(sizeof *nis))) {
+ if (!(nis = memget(sizeof *nis))) {
errno = ENOMEM;
return (NULL);
}
memset(nis, 0, sizeof *nis);
- if (!(acc = malloc(sizeof *acc))) {
- free(nis);
+ if (!(acc = memget(sizeof *acc))) {
+ memput(nis, sizeof *nis);
errno = ENOMEM;
return (NULL);
}
@@ -84,19 +93,57 @@ irs_nis_acc(const char *options) {
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);
- free(nis);
- free(this);
+ memput(nis, sizeof *nis);
+ memput(this, sizeof *this);
}
#endif /*WANT_IRS_NIS*/
diff --git a/contrib/bind/lib/irs/nis_gr.c b/contrib/bind/lib/irs/nis_gr.c
index aa2f30c..713437a 100644
--- a/contrib/bind/lib/irs/nis_gr.c
+++ b/contrib/bind/lib/irs/nis_gr.c
@@ -32,7 +32,7 @@
*/
/*
- * Portions Copyright (c) 1996, 1997, 1998 by Internet Software Consortium.
+ * 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
@@ -49,7 +49,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: nis_gr.c,v 1.13 1998/03/21 00:59:50 halley Exp $";
+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 */
@@ -64,6 +64,10 @@ static int __bind_irs_gr_unneeded;
#include <sys/param.h>
#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <isc/memcluster.h>
#include <rpc/rpc.h>
#include <rpc/xdr.h>
@@ -77,6 +81,8 @@ static int __bind_irs_gr_unneeded;
#include <string.h>
#include <unistd.h>
+#include <isc/memcluster.h>
+
#include <irs.h>
#include "port_after.h"
@@ -130,13 +136,13 @@ irs_nis_gr(struct irs_acc *this) {
struct irs_gr *gr;
struct pvt *pvt;
- if (!(gr = malloc(sizeof *gr))) {
+ if (!(gr = memget(sizeof *gr))) {
errno = ENOMEM;
return (NULL);
}
memset(gr, 0x5e, sizeof *gr);
- if (!(pvt = malloc(sizeof *pvt))) {
- free(gr);
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(gr, sizeof *gr);
errno = ENOMEM;
return (NULL);
}
@@ -151,6 +157,8 @@ irs_nis_gr(struct irs_acc *this) {
gr->rewind = gr_rewind;
gr->list = make_group_list;
gr->minimize = gr_minimize;
+ gr->res_get = NULL;
+ gr->res_set = NULL;
return (gr);
}
@@ -164,8 +172,8 @@ gr_close(struct irs_gr *this) {
free(pvt->group.gr_mem);
if (pvt->membuf)
free(pvt->membuf);
- free(pvt);
- free(this);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
static struct group *
@@ -286,6 +294,9 @@ makegroupent(struct irs_gr *this) {
goto cleanup;
cp++;
+ if (*cp && cp[strlen(cp)-1] == '\n')
+ cp[strlen(cp)-1] = '\0';
+
/*
* Parse the members out.
*/
diff --git a/contrib/bind/lib/irs/nis_ho.c b/contrib/bind/lib/irs/nis_ho.c
index 65bdb4b..07d2274 100644
--- a/contrib/bind/lib/irs/nis_ho.c
+++ b/contrib/bind/lib/irs/nis_ho.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$Id: nis_ho.c,v 1.10 1997/12/04 04:57:59 halley Exp $";
+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 */
@@ -46,6 +46,7 @@ static int __bind_irs_nis_unneeded;
#include <stdio.h>
#include <string.h>
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -53,8 +54,6 @@ static int __bind_irs_nis_unneeded;
#include "irs_p.h"
#include "nis_p.h"
-extern int h_errno;
-
/* Definitions */
#define MAXALIASES 35
@@ -78,6 +77,8 @@ struct pvt {
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 };
@@ -98,9 +99,14 @@ static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr,
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 */
@@ -109,17 +115,17 @@ irs_nis_ho(struct irs_acc *this) {
struct irs_ho *ho;
struct pvt *pvt;
- if (!(ho = malloc(sizeof *ho))) {
+ if (!(pvt = memget(sizeof *pvt))) {
errno = ENOMEM;
return (NULL);
}
- memset(ho, 0x5e, sizeof *ho);
- if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) {
- free(ho);
+ memset(pvt, 0, sizeof *pvt);
+ if (!(ho = memget(sizeof *ho))) {
+ memput(pvt, sizeof *pvt);
errno = ENOMEM;
return (NULL);
}
- memset(pvt, 0, sizeof *pvt);
+ memset(ho, 0x5e, sizeof *ho);
pvt->needrewind = 1;
pvt->nis_domain = ((struct nis_p *)this->private)->domain;
ho->private = pvt;
@@ -130,6 +136,8 @@ irs_nis_ho(struct irs_acc *this) {
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);
}
@@ -139,18 +147,23 @@ static void
ho_close(struct irs_ho *this) {
struct pvt *pvt = (struct pvt *)this->private;
+ ho_minimize(this);
nisfree(pvt, do_all);
- free(pvt);
- free(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 hostent *hp;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ if (init(this) == -1)
return (NULL);
- if (_res.options & RES_USE_INET6) {
+
+ if (pvt->res->options & RES_USE_INET6) {
hp = ho_byname2(this, name, AF_INET6);
if (hp)
return (hp);
@@ -163,11 +176,14 @@ 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) {
- h_errno = HOST_NOT_FOUND;
+ RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
return (NULL);
}
return (makehostent(this));
@@ -180,6 +196,9 @@ ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) {
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))) {
@@ -190,14 +209,14 @@ ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) {
len = INADDRSZ;
}
if (inet_ntop(af, uaddr, tmp, sizeof tmp) == NULL) {
- h_errno = NETDB_INTERNAL;
+ 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) {
- h_errno = HOST_NOT_FOUND;
+ RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
return (NULL);
}
return (makehostent(this));
@@ -209,6 +228,9 @@ ho_next(struct irs_ho *this) {
struct hostent *rval;
int r;
+ if (init(this) == -1)
+ return (NULL);
+
do {
if (pvt->needrewind) {
nisfree(pvt, do_all);
@@ -230,7 +252,7 @@ ho_next(struct irs_ho *this) {
pvt->curkey_len = newkey_len;
}
if (r != 0) {
- h_errno = HOST_NOT_FOUND;
+ RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
return (NULL);
}
rval = makehostent(this);
@@ -247,7 +269,42 @@ ho_rewind(struct irs_ho *this) {
static void
ho_minimize(struct irs_ho *this) {
- /* NOOP */
+ 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 */
@@ -260,17 +317,17 @@ makehostent(struct irs_ho *this) {
int af, len;
p = pvt->curval_data;
- if ((cp = strchr(p, '#')) != NULL)
+ if ((cp = strpbrk(p, "#\n")) != NULL)
*cp = '\0';
if (!(cp = strpbrk(p, spaces)))
return (NULL);
*cp++ = '\0';
- if ((_res.options & RES_USE_INET6) &&
+ 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 (_res.options & RES_USE_INET6) {
+ if (pvt->res->options & RES_USE_INET6) {
map_v4v6_address((char*)pvt->host_addr,
(char*)pvt->host_addr);
af = AF_INET6;
@@ -303,7 +360,7 @@ makehostent(struct irs_ho *this) {
*cp++ = '\0';
}
*q = NULL;
- h_errno = NETDB_SUCCESS;
+ RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS);
return (&pvt->host);
}
@@ -319,4 +376,15 @@ nisfree(struct pvt *pvt, enum do_what do_what) {
}
}
+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*/
diff --git a/contrib/bind/lib/irs/nis_ng.c b/contrib/bind/lib/irs/nis_ng.c
index 1667ca6..88d97ff 100644
--- a/contrib/bind/lib/irs/nis_ng.c
+++ b/contrib/bind/lib/irs/nis_ng.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: nis_ng.c,v 1.10 1997/12/04 04:58:00 halley Exp $";
+static const char rcsid[] = "$Id: nis_ng.c,v 1.16 1999/01/18 07:46:58 vixie Exp $";
#endif
/* Imports */
@@ -34,7 +34,7 @@ static int __bind_irs_nis_unneeded;
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
-#include <assert.h>
+#include <isc/assertions.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
@@ -42,6 +42,11 @@ static int __bind_irs_nis_unneeded;
#include <stdlib.h>
#include <string.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -91,13 +96,13 @@ irs_nis_ng(struct irs_acc *this) {
struct irs_ng *ng;
struct pvt *pvt;
- if (!(ng = malloc(sizeof *ng))) {
+ if (!(ng = memget(sizeof *ng))) {
errno = ENOMEM;
return (NULL);
}
memset(ng, 0x5e, sizeof *ng);
- if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) {
- free(ng);
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(ng, sizeof *ng);
errno = ENOMEM;
return (NULL);
}
@@ -119,14 +124,13 @@ ng_close(struct irs_ng *this) {
struct pvt *pvt = (struct pvt *)this->private;
tmpfree(pvt);
- free(pvt);
- free(this);
+ 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 netgrp *rval;
if (!pvt->cur)
return (0);
@@ -159,7 +163,6 @@ ng_test(struct irs_ng *this, const char *name,
static void
ng_rewind(struct irs_ng *this, const char *name) {
struct pvt *pvt = (struct pvt *)this->private;
- struct netgrp *rval;
/* Either hand back or free the existing list. */
if (pvt->tmpgroup) {
@@ -194,7 +197,10 @@ add_group_to_list(struct pvt *pvt, const char *name, int len) {
r = yp_match(pvt->nis_domain, netgroup_map, (char *)name, len,
&vdata, &vlen);
if (r == 0) {
- for (cp = vdata; cp; cp = np) {
+ 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';
@@ -212,7 +218,7 @@ add_tuple_to_list(struct pvt *pvt, const char *name, char *cp) {
struct tmpgrp *tmp;
char *tp, *np;
- assert(*cp++ == '(');
+ INSIST(*cp++ == '(');
tmp = malloc(sizeof *tmp + strlen(name) + sizeof '\0' +
strlen(cp) - sizeof ')');
diff --git a/contrib/bind/lib/irs/nis_nw.c b/contrib/bind/lib/irs/nis_nw.c
index b9e9e79..72ec391 100644
--- a/contrib/bind/lib/irs/nis_nw.c
+++ b/contrib/bind/lib/irs/nis_nw.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: nis_nw.c,v 1.10 1997/12/04 04:58:00 halley Exp $";
+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 */
@@ -28,20 +28,24 @@ static int __bind_irs_nis_unneeded;
#else
#include <sys/types.h>
+#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-#include <sys/socket.h>
+#include <arpa/nameser.h>
+
#include <rpc/rpc.h>
#include <rpc/xdr.h>
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#include <errno.h>
+#include <resolv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -67,6 +71,9 @@ struct pvt {
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 };
@@ -82,9 +89,14 @@ 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 */
@@ -93,17 +105,17 @@ irs_nis_nw(struct irs_acc *this) {
struct irs_nw *nw;
struct pvt *pvt;
- if (!(nw = (struct irs_nw *)malloc(sizeof *nw))) {
+ if (!(pvt = memget(sizeof *pvt))) {
errno = ENOMEM;
return (NULL);
}
- memset(nw, 0x5e, sizeof *nw);
- if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) {
- free(nw);
+ memset(pvt, 0, sizeof *pvt);
+ if (!(nw = memget(sizeof *nw))) {
+ memput(pvt, sizeof *pvt);
errno = ENOMEM;
return (NULL);
}
- memset(pvt, 0, sizeof *pvt);
+ memset(nw, 0x5e, sizeof *nw);
pvt->needrewind = 1;
pvt->nis_domain = ((struct nis_p *)this->private)->domain;
nw->private = pvt;
@@ -113,6 +125,8 @@ irs_nis_nw(struct irs_acc *this) {
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);
}
@@ -122,10 +136,13 @@ 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);
- free(pvt);
- free(this);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
static struct nwent *
@@ -134,15 +151,18 @@ nw_byaddr(struct irs_nw *this, void *net, int length, int af) {
char tmp[sizeof "255.255.255.255/32"], *t;
int r;
+ if (init(this) == -1)
+ return (NULL);
+
if (af != AF_INET) {
- h_errno = NETDB_INTERNAL;
+ 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) {
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
return (NULL);
}
r = yp_match(pvt->nis_domain, networks_byaddr, tmp, strlen(tmp),
@@ -156,7 +176,7 @@ nw_byaddr(struct irs_nw *this, void *net, int length, int af) {
&pvt->curval_data, &pvt->curval_len);
}
if (r != 0) {
- h_errno = HOST_NOT_FOUND;
+ RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
return (NULL);
}
}
@@ -168,8 +188,11 @@ 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) {
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
errno = EAFNOSUPPORT;
return (NULL);
}
@@ -177,7 +200,7 @@ nw_byname(struct irs_nw *this, const char *name, int af) {
r = yp_match(pvt->nis_domain, networks_byname, (char *)name,
strlen(name), &pvt->curval_data, &pvt->curval_len);
if (r != 0) {
- h_errno = HOST_NOT_FOUND;
+ RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
return (NULL);
}
return (makenwent(this));
@@ -196,6 +219,9 @@ nw_next(struct irs_nw *this) {
struct nwent *rval;
int r;
+ if (init(this) == -1)
+ return (NULL);
+
do {
if (pvt->needrewind) {
nisfree(pvt, do_all);
@@ -217,7 +243,7 @@ nw_next(struct irs_nw *this) {
pvt->curkey_len = newkey_len;
}
if (r != 0) {
- h_errno = HOST_NOT_FOUND;
+ RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
return (NULL);
}
rval = makenwent(this);
@@ -227,15 +253,50 @@ nw_next(struct irs_nw *this) {
static void
nw_minimize(struct irs_nw *this) {
- /* NOOP */
+ 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) {
- static const char spaces[] = " \t";
struct pvt *pvt = (struct pvt *)this->private;
+ static const char spaces[] = " \t";
char *t, *cp, **ap;
if (pvt->nwbuf)
@@ -243,7 +304,7 @@ makenwent(struct irs_nw *this) {
pvt->nwbuf = pvt->curval_data;
pvt->curval_data = NULL;
- if ((cp = strchr(pvt->nwbuf, '#')) != NULL)
+ if ((cp = strpbrk(pvt->nwbuf, "#\n")) != NULL)
*cp = '\0';
cp = pvt->nwbuf;
@@ -303,4 +364,16 @@ nisfree(struct pvt *pvt, enum do_what do_what) {
}
}
+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*/
diff --git a/contrib/bind/lib/irs/nis_p.h b/contrib/bind/lib/irs/nis_p.h
index 92d2647..d3dc126 100644
--- a/contrib/bind/lib/irs/nis_p.h
+++ b/contrib/bind/lib/irs/nis_p.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
/*
- * $Id: nis_p.h,v 1.4 1996/10/25 07:23:24 vixie Exp $
+ * $Id: nis_p.h,v 1.6 1999/01/08 19:25:03 vixie Exp $
*/
/*
@@ -27,7 +27,9 @@
* Object state.
*/
struct nis_p {
- char * domain;
+ char * domain;
+ struct __res_state * res;
+ void (*free_res) __P((void *));
};
diff --git a/contrib/bind/lib/irs/nis_pr.c b/contrib/bind/lib/irs/nis_pr.c
index 1653692..8dff084 100644
--- a/contrib/bind/lib/irs/nis_pr.c
+++ b/contrib/bind/lib/irs/nis_pr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: nis_pr.c,v 1.9 1997/12/04 04:58:00 halley Exp $";
+static const char rcsid[] = "$Id: nis_pr.c,v 1.13 1999/01/18 07:46:59 vixie Exp $";
#endif
/* Imports */
@@ -29,6 +29,8 @@ static int __bind_irs_nis_unneeded;
#include <sys/types.h>
#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
#include <rpc/rpc.h>
#include <rpc/xdr.h>
#include <rpcsvc/yp_prot.h>
@@ -41,6 +43,7 @@ static int __bind_irs_nis_unneeded;
#include <stdlib.h>
#include <errno.h>
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -85,13 +88,13 @@ irs_nis_pr(struct irs_acc *this) {
struct irs_pr *pr;
struct pvt *pvt;
- if (!(pr = malloc(sizeof *pr))) {
+ if (!(pr = memget(sizeof *pr))) {
errno = ENOMEM;
return (NULL);
}
memset(pr, 0x5e, sizeof *pr);
- if (!(pvt = malloc(sizeof *pvt))) {
- free(pr);
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(pr, sizeof *pr);
errno = ENOMEM;
return (NULL);
}
@@ -105,6 +108,8 @@ irs_nis_pr(struct irs_acc *this) {
pr->rewind = pr_rewind;
pr->close = pr_close;
pr->minimize = pr_minimize;
+ pr->res_get = NULL;
+ pr->res_set = NULL;
return (pr);
}
@@ -119,8 +124,8 @@ pr_close(struct irs_pr *this) {
free(pvt->proto.p_aliases);
if (pvt->prbuf)
free(pvt->prbuf);
- free(pvt);
- free(this);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
static struct protoent *
@@ -182,7 +187,7 @@ pr_next(struct irs_pr *this) {
pvt->curkey_len = newkey_len;
}
if (r != 0) {
- h_errno = HOST_NOT_FOUND;
+ errno = ENOENT;
return (NULL);
}
rval = makeprotoent(this);
diff --git a/contrib/bind/lib/irs/nis_pw.c b/contrib/bind/lib/irs/nis_pw.c
index f06f796..ce90f20 100644
--- a/contrib/bind/lib/irs/nis_pw.c
+++ b/contrib/bind/lib/irs/nis_pw.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: nis_pw.c,v 1.10 1997/12/04 04:58:01 halley Exp $";
+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 */
@@ -28,6 +28,11 @@ static int __bind_irs_pw_unneeded;
#else
#include <sys/param.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <isc/memcluster.h>
#include <rpc/rpc.h>
#include <rpc/xdr.h>
#include <rpcsvc/yp_prot.h>
@@ -41,6 +46,8 @@ static int __bind_irs_pw_unneeded;
#include <string.h>
#include <unistd.h>
+#include <isc/memcluster.h>
+
#include <irs.h>
#include "port_after.h"
@@ -85,13 +92,13 @@ irs_nis_pw(struct irs_acc *this) {
struct irs_pw *pw;
struct pvt *pvt;
- if (!(pw = malloc(sizeof *pw))) {
+ if (!(pw = memget(sizeof *pw))) {
errno = ENOMEM;
return (NULL);
}
memset(pw, 0x5e, sizeof *pw);
- if (!(pvt = malloc(sizeof *pvt))) {
- free(pw);
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(pw, sizeof *pw);
errno = ENOMEM;
return (NULL);
}
@@ -99,13 +106,15 @@ irs_nis_pw(struct irs_acc *this) {
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->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);
+ pw->res_get = NULL;
+ pw->res_set = NULL;
+ return (pw);
}
/* Methods */
@@ -117,8 +126,8 @@ pw_close(struct irs_pw *this) {
if (pvt->pwbuf)
free(pvt->pwbuf);
nisfree(pvt, do_all);
- free(pvt);
- free(this);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
static struct passwd *
@@ -155,7 +164,7 @@ pw_next(struct irs_pw *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;
@@ -170,7 +179,7 @@ pw_byname(struct irs_pw *this, const char *name) {
}
return (makepasswdent(this));
}
-
+
static struct passwd *
pw_byuid(struct irs_pw *this, uid_t uid) {
struct pvt *pvt = (struct pvt *)this->private;
@@ -246,6 +255,10 @@ makepasswdent(struct irs_pw *this) {
*cp++ = '\0';
pvt->passwd.pw_shell = cp;
+
+ if ((cp = strchr(cp, '\n')) != NULL)
+ *cp = '\0';
+
return (&pvt->passwd);
cleanup:
diff --git a/contrib/bind/lib/irs/nis_sv.c b/contrib/bind/lib/irs/nis_sv.c
index 1dacc2f..8810fd2 100644
--- a/contrib/bind/lib/irs/nis_sv.c
+++ b/contrib/bind/lib/irs/nis_sv.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: nis_sv.c,v 1.10 1997/12/04 04:58:01 halley Exp $";
+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 */
@@ -28,6 +28,9 @@ static int __bind_irs_nis_unneeded;
#else
#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
#include <sys/socket.h>
#include <rpc/rpc.h>
#include <rpc/xdr.h>
@@ -40,6 +43,7 @@ static int __bind_irs_nis_unneeded;
#include <stdlib.h>
#include <string.h>
+#include <isc/memcluster.h>
#include <irs.h>
#include "port_after.h"
@@ -85,13 +89,13 @@ irs_nis_sv(struct irs_acc *this) {
struct irs_sv *sv;
struct pvt *pvt;
- if (!(sv = (struct irs_sv *)malloc(sizeof *sv))) {
+ if (!(sv = memget(sizeof *sv))) {
errno = ENOMEM;
return (NULL);
}
memset(sv, 0x5e, sizeof *sv);
- if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) {
- free(sv);
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(sv, sizeof *sv);
errno = ENOMEM;
return (NULL);
}
@@ -105,6 +109,8 @@ irs_nis_sv(struct irs_acc *this) {
sv->byport = sv_byport;
sv->rewind = sv_rewind;
sv->minimize = sv_minimize;
+ sv->res_get = NULL;
+ sv->res_set = NULL;
return (sv);
}
@@ -119,8 +125,8 @@ sv_close(struct irs_sv *this) {
free(pvt->serv.s_aliases);
if (pvt->svbuf)
free(pvt->svbuf);
- free(pvt);
- free(this);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
static struct servent *
@@ -221,7 +227,7 @@ makeservent(struct irs_sv *this) {
pvt->serv.s_aliases = NULL;
}
- if ((p = strchr(pvt->svbuf, '#')))
+ if ((p = strpbrk(pvt->svbuf, "#\n")))
*p = '\0';
p = pvt->svbuf;
diff --git a/contrib/bind/lib/irs/nul_ng.c b/contrib/bind/lib/irs/nul_ng.c
index 0910d57..cc5c801 100644
--- a/contrib/bind/lib/irs/nul_ng.c
+++ b/contrib/bind/lib/irs/nul_ng.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: nul_ng.c,v 1.7 1997/12/04 04:58:01 halley Exp $";
+static const char rcsid[] = "$Id: nul_ng.c,v 1.10 1999/01/18 07:46:59 vixie Exp $";
#endif
/*
@@ -27,6 +27,8 @@ static const char rcsid[] = "$Id: nul_ng.c,v 1.7 1997/12/04 04:58:01 halley Exp
#include <sys/types.h>
#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
#include <stdio.h>
#include <string.h>
@@ -36,6 +38,7 @@ static const char rcsid[] = "$Id: nul_ng.c,v 1.7 1997/12/04 04:58:01 halley Exp
#include <errno.h>
#include <irs.h>
+#include <isc/memcluster.h>
#include "port_after.h"
@@ -59,7 +62,7 @@ struct irs_ng *
irs_nul_ng(struct irs_acc *this) {
struct irs_ng *ng;
- if (!(ng = malloc(sizeof *ng))) {
+ if (!(ng = memget(sizeof *ng))) {
errno = ENOMEM;
return (NULL);
}
@@ -77,7 +80,7 @@ irs_nul_ng(struct irs_acc *this) {
static void
ng_close(struct irs_ng *this) {
- free(this);
+ memput(this, sizeof *this);
}
/* ARGSUSED */
diff --git a/contrib/bind/lib/irs/pathnames.h b/contrib/bind/lib/irs/pathnames.h
index 40a0472..1a225e5 100644
--- a/contrib/bind/lib/irs/pathnames.h
+++ b/contrib/bind/lib/irs/pathnames.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
/*
- * $Id: pathnames.h,v 1.5 1996/10/25 07:23:28 vixie Exp $
+ * $Id: pathnames.h,v 1.7 1999/01/08 19:25:10 vixie Exp $
*/
#ifndef _PATH_IRS_CONF
@@ -39,6 +39,12 @@
#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
diff --git a/contrib/bind/lib/irs/util.c b/contrib/bind/lib/irs/util.c
index f58f5ca2..8965af5 100644
--- a/contrib/bind/lib/irs/util.c
+++ b/contrib/bind/lib/irs/util.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: util.c,v 1.7 1997/12/04 04:58:02 halley Exp $";
+static const char rcsid[] = "$Id: util.c,v 1.10 1999/01/08 19:25:11 vixie Exp $";
#endif
#include "port_before.h"
@@ -25,8 +25,8 @@ static const char rcsid[] = "$Id: util.c,v 1.7 1997/12/04 04:58:02 halley Exp $"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
+#include <resolv.h>
-#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
diff --git a/contrib/bind/lib/isc/Makefile b/contrib/bind/lib/isc/Makefile
index cdcac69..87e20f2 100644
--- a/contrib/bind/lib/isc/Makefile
+++ b/contrib/bind/lib/isc/Makefile
@@ -1,4 +1,4 @@
-# Copyright (c) 1996 by Internet Software Consortium
+# 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
@@ -13,7 +13,7 @@
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
# SOFTWARE.
-# $Id: Makefile,v 8.15 1997/12/03 22:36:08 halley Exp $
+# $Id: Makefile,v 8.22 1999/02/22 02:47:58 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
@@ -31,37 +31,55 @@ 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 cruv
+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}:
- ${CC} ${CPPFLAGS} ${CFLAGS} -c $*.c
- -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} && ${LDS} mv a.out $*.${O}
+ if test ! -d ${THREADED} ; then mkdir ${THREADED} ; fi
+ ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} ${REENTRANT} -c $*.c \
+ -o ${THREADED}/$*.${O}
+ -${LDS} ${LD} ${LD_LIBFLAGS} ${THREADED}/$*.${O} -o a.out && \
+ ${LDS} mv a.out ${THREADED}/$*.${O}
+ ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c
+ -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} -o a.out && \
+ ${LDS} mv a.out $*.${O}
distclean: clean
clean: FRC
rm -f .depend a.out core ${LIB} tags
rm -f *.${O} *.BAK *.CKP *~
+ rm -f ${THREADED}/*.${O}
+ -rmdir ${THREADED}
depend: FRC
mkdep -I${INCL} -I${PORTINCL} ${CPPFLAGS} ${SRCS}
diff --git a/contrib/bind/lib/isc/assertions.c b/contrib/bind/lib/isc/assertions.c
index 949d4d2..b53cc0a 100644
--- a/contrib/bind/lib/isc/assertions.c
+++ b/contrib/bind/lib/isc/assertions.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static const char rcsid[] = "$Id: assertions.c,v 8.2 1997/12/08 21:29:05 halley Exp $";
+static const char rcsid[] = "$Id: assertions.c,v 8.3 1999/01/08 19:25:14 vixie Exp $";
#endif
#include "port_before.h"
diff --git a/contrib/bind/lib/isc/assertions.mdoc b/contrib/bind/lib/isc/assertions.mdoc
index e82d9f9..3d8d103 100644
--- a/contrib/bind/lib/isc/assertions.mdoc
+++ b/contrib/bind/lib/isc/assertions.mdoc
@@ -1,6 +1,6 @@
-.\" $Id: assertions.mdoc,v 8.1 1997/12/03 22:33:30 halley Exp $
+.\" $Id: assertions.mdoc,v 8.2 1999/01/08 19:25:15 vixie Exp $
.\"
-.\"Copyright (c) 1997 by Internet Software Consortium.
+.\"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
diff --git a/contrib/bind/lib/isc/base64.c b/contrib/bind/lib/isc/base64.c
index 58e700e..c1eebe6 100644
--- a/contrib/bind/lib/isc/base64.c
+++ b/contrib/bind/lib/isc/base64.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ * 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
@@ -41,7 +41,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: base64.c,v 8.5 1998/03/27 00:17:46 halley Exp $";
+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"
diff --git a/contrib/bind/lib/isc/bitncmp.c b/contrib/bind/lib/isc/bitncmp.c
index 473f4f7..8dadca0 100644
--- a/contrib/bind/lib/isc/bitncmp.c
+++ b/contrib/bind/lib/isc/bitncmp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: bitncmp.c,v 1.5 1996/11/18 09:09:48 vixie Exp $";
+static const char rcsid[] = "$Id: bitncmp.c,v 1.6 1999/01/08 19:25:20 vixie Exp $";
#endif
#include "port_before.h"
diff --git a/contrib/bind/lib/isc/bitncmp.mdoc b/contrib/bind/lib/isc/bitncmp.mdoc
index 99c6c25..4fa12e8 100644
--- a/contrib/bind/lib/isc/bitncmp.mdoc
+++ b/contrib/bind/lib/isc/bitncmp.mdoc
@@ -1,6 +1,6 @@
-.\" $Id: bitncmp.mdoc,v 8.1 1997/01/30 20:27:23 vixie Exp $
+.\" $Id: bitncmp.mdoc,v 8.2 1999/01/08 19:25:21 vixie Exp $
.\"
-.\"Copyright (c) 1996 by Internet Software Consortium.
+.\"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
diff --git a/contrib/bind/lib/isc/ctl_clnt.c b/contrib/bind/lib/isc/ctl_clnt.c
new file mode 100644
index 0000000..66f32f8
--- /dev/null
+++ b/contrib/bind/lib/isc/ctl_clnt.c
@@ -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 <sys/param.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/assertions.h>
+#include <isc/ctl.h>
+#include <isc/eventlib.h>
+#include <isc/list.h>
+#include <isc/memcluster.h>
+
+#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);
+}
diff --git a/contrib/bind/lib/isc/ctl_p.c b/contrib/bind/lib/isc/ctl_p.c
new file mode 100644
index 0000000..d70a05f
--- /dev/null
+++ b/contrib/bind/lib/isc/ctl_p.c
@@ -0,0 +1,156 @@
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: ctl_p.c,v 8.6 1999/10/13 16:39:34 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 <sys/param.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <isc/assertions.h>
+#include <isc/eventlib.h>
+#include <isc/logging.h>
+#include <isc/memcluster.h>
+#include <isc/ctl.h>
+
+#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);
+ }
+ 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);
+ }
+ 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;
+ case AF_UNIX:
+ *((struct sockaddr_un *)dst) = *((struct sockaddr_un *)src);
+ break;
+ default:
+ *dst = *src;
+ break;
+ }
+}
diff --git a/contrib/bind/lib/isc/ctl_p.h b/contrib/bind/lib/isc/ctl_p.h
new file mode 100644
index 0000000..1ebb254
--- /dev/null
+++ b/contrib/bind/lib/isc/ctl_p.h
@@ -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 *);
diff --git a/contrib/bind/lib/isc/ctl_srvr.c b/contrib/bind/lib/isc/ctl_srvr.c
new file mode 100644
index 0000000..0bdc8c8
--- /dev/null
+++ b/contrib/bind/lib/isc/ctl_srvr.c
@@ -0,0 +1,744 @@
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: ctl_srvr.c,v 8.21 1999/10/17 08:41:57 cyarnell 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 <sys/param.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <isc/assertions.h>
+#include <isc/ctl.h>
+#include <isc/eventlib.h>
+#include <isc/list.h>
+#include <isc/logging.h>
+#include <isc/memcluster.h>
+
+#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;
+ struct sockaddr_un un;
+};
+
+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) {
+ save_errno = errno;
+ (*ctx->logger)(ctl_error, "%s: bind: %s", me, strerror(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, 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;
+ }
+}
diff --git a/contrib/bind/lib/isc/ev_connects.c b/contrib/bind/lib/isc/ev_connects.c
index 1cf7291..237bcb1 100644
--- a/contrib/bind/lib/isc/ev_connects.c
+++ b/contrib/bind/lib/isc/ev_connects.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 1996, 1997, 1998 by Internet Software Consortium
+ * 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
@@ -20,7 +20,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static const char rcsid[] = "$Id: ev_connects.c,v 8.19 1998/03/20 23:26:22 halley Exp $";
+static const char rcsid[] = "$Id: ev_connects.c,v 8.25 1999/10/07 20:44:04 vixie Exp $";
#endif
/* Import. */
@@ -39,6 +39,18 @@ static const char rcsid[] = "$Id: ev_connects.c,v 8.19 1998/03/20 23:26:22 halle
#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);
@@ -64,8 +76,8 @@ evListen(evContext opaqueCtx, int fd, int maxconn,
* are not met, then we might restore the old nonblocking status
* incorrectly.
*/
- if ((mode & O_NONBLOCK) == 0) {
- OK(fcntl(fd, F_SETFL, mode | O_NONBLOCK));
+ if ((mode & PORT_NONBLOCK) == 0) {
+ OK(fcntl(fd, F_SETFL, mode | PORT_NONBLOCK));
new->flags |= EV_CONN_BLOCK;
}
OK(listen(fd, maxconn));
@@ -149,7 +161,7 @@ evCancelConn(evContext opaqueCtx, evConnID id) {
if (errno != EBADF)
return (-1);
} else
- OK(fcntl(this->fd, F_SETFL, mode | O_NONBLOCK));
+ OK(fcntl(this->fd, F_SETFL, mode | PORT_NONBLOCK));
}
/* Unlink from ctx->conns. */
@@ -224,9 +236,14 @@ evTryAccept(evContext opaqueCtx, evConnID id, int *sys_errno) {
new->conn = conn;
new->ralen = sizeof new->ra;
new->fd = accept(conn->fd, &new->ra, &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 (getsockname(new->fd, &new->la, &new->lalen) < 0) {
+ if (GETXXXNAME(getsockname, new->fd, new->la, new->lalen) < 0) {
new->ioErrno = errno;
(void) close(new->fd);
new->fd = -1;
@@ -256,9 +273,14 @@ listener(evContext opaqueCtx, void *uap, int fd, int evmask) {
REQUIRE((evmask & EV_READ) != 0);
ralen = sizeof ra;
new = accept(fd, &ra, &ralen);
+ if (new > ctx->highestFD) {
+ close(new);
+ new = -1;
+ errno = ENOTSOCK;
+ }
if (new >= 0) {
lalen = sizeof la;
- if (getsockname(new, &la, &lalen) < 0) {
+ if (GETXXXNAME(getsockname, new, la, lalen) < 0) {
int save = errno;
(void) close(new);
@@ -272,7 +294,6 @@ listener(evContext opaqueCtx, void *uap, int fd, int evmask) {
static void
connector(evContext opaqueCtx, void *uap, int fd, int evmask) {
- evContext_p *ctx = opaqueCtx.opaque;
evConn *conn = uap;
struct sockaddr la, ra;
int lalen, ralen;
@@ -304,8 +325,8 @@ connector(evContext opaqueCtx, void *uap, int fd, int evmask) {
#else
read(fd, buf, 0) < 0 ||
#endif
- getsockname(fd, &la, &lalen) < 0 ||
- getpeername(fd, &ra, &ralen) < 0) {
+ GETXXXNAME(getsockname, fd, la, lalen) < 0 ||
+ GETXXXNAME(getpeername, fd, ra, ralen) < 0) {
int save = errno;
(void) close(fd); /* XXX closing caller's fd */
diff --git a/contrib/bind/lib/isc/ev_files.c b/contrib/bind/lib/isc/ev_files.c
index 6cd1d41..434385c 100644
--- a/contrib/bind/lib/isc/ev_files.c
+++ b/contrib/bind/lib/isc/ev_files.c
@@ -1,4 +1,5 @@
-/* Copyright (c) 1995, 1996, 1997, 1998 by Internet Software Consortium
+/*
+ * 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
@@ -19,7 +20,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static const char rcsid[] = "$Id: ev_files.c,v 1.15 1998/02/06 01:53:52 halley Exp $";
+static const char rcsid[] = "$Id: ev_files.c,v 1.19 1999/10/07 20:44:04 vixie Exp $";
#endif
#include "port_before.h"
@@ -56,7 +57,7 @@ evSelectFD(evContext opaqueCtx,
ctx, fd, eventmask, func, uap);
if (eventmask == 0 || (eventmask & ~EV_MASK_ALL) != 0)
ERR(EINVAL);
- if (fd >= FD_SETSIZE)
+ if (fd > ctx->highestFD)
ERR(EINVAL);
OK(mode = fcntl(fd, F_GETFL, NULL)); /* side effect: validate fd. */
@@ -68,10 +69,10 @@ evSelectFD(evContext opaqueCtx,
*/
id = FindFD(ctx, fd, EV_MASK_ALL);
if (id == NULL) {
- if (mode & O_NONBLOCK)
+ if (mode & PORT_NONBLOCK)
FD_SET(fd, &ctx->nonblockBefore);
else {
- OK(fcntl(fd, F_SETFL, mode | O_NONBLOCK));
+ OK(fcntl(fd, F_SETFL, mode | PORT_NONBLOCK));
FD_CLR(fd, &ctx->nonblockBefore);
}
}
@@ -150,7 +151,7 @@ int
evDeselectFD(evContext opaqueCtx, evFileID opaqueID) {
evContext_p *ctx = opaqueCtx.opaque;
evFile *del = opaqueID.opaque;
- evFile *old, *cur;
+ evFile *cur;
int mode, eventmask;
if (!del) {
@@ -196,7 +197,7 @@ evDeselectFD(evContext opaqueCtx, evFileID opaqueID) {
* 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 & ~O_NONBLOCK);
+ (void) fcntl(del->fd, F_SETFL, mode & ~PORT_NONBLOCK);
}
/*
diff --git a/contrib/bind/lib/isc/ev_streams.c b/contrib/bind/lib/isc/ev_streams.c
index aa4270b..b25a666 100644
--- a/contrib/bind/lib/isc/ev_streams.c
+++ b/contrib/bind/lib/isc/ev_streams.c
@@ -1,4 +1,5 @@
-/* Copyright (c) 1996, 1997, 1998 by Internet Software Consortium
+/*
+ * 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
@@ -19,7 +20,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static const char rcsid[] = "$Id: ev_streams.c,v 8.18 1998/03/20 23:26:22 halley Exp $";
+static const char rcsid[] = "$Id: ev_streams.c,v 8.21 1999/10/07 20:44:04 vixie Exp $";
#endif
#include "port_before.h"
@@ -83,7 +84,6 @@ evWrite(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt,
save = errno;
FREE(new);
errno = save;
- err:
return (-1);
}
@@ -118,13 +118,11 @@ evRead(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt,
save = errno;
FREE(new);
errno = save;
- err:
return (-1);
}
int
evTimeRW(evContext opaqueCtx, evStreamID id, evTimerID timer) /*ARGSUSED*/ {
- evContext_p *ctx = opaqueCtx.opaque;
evStream *str = id.opaque;
str->timer = timer;
@@ -134,7 +132,6 @@ evTimeRW(evContext opaqueCtx, evStreamID id, evTimerID timer) /*ARGSUSED*/ {
int
evUntimeRW(evContext opaqueCtx, evStreamID id) /*ARGSUSED*/ {
- evContext_p *ctx = opaqueCtx.opaque;
evStream *str = id.opaque;
str->flags &= ~EV_STR_TIMEROK;
diff --git a/contrib/bind/lib/isc/ev_timers.c b/contrib/bind/lib/isc/ev_timers.c
index 198f27c..0db770c 100644
--- a/contrib/bind/lib/isc/ev_timers.c
+++ b/contrib/bind/lib/isc/ev_timers.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 1996, 1997, 1998 by Internet Software Consortium
+ * 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
@@ -20,7 +20,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static const char rcsid[] = "$Id: ev_timers.c,v 1.23 1998/03/20 23:26:23 halley Exp $";
+static const char rcsid[] = "$Id: ev_timers.c,v 1.25 1999/10/07 20:44:04 vixie Exp $";
#endif
/* Import. */
@@ -107,7 +107,6 @@ evCmpTime(struct timespec a, struct timespec b) {
struct timespec
evNowTime() {
struct timeval now;
- struct timespec ret;
if (gettimeofday(&now, NULL) < 0)
return (evConsTime(0, 0));
@@ -288,7 +287,6 @@ evSetIdleTimer(evContext opaqueCtx,
int
evClearIdleTimer(evContext opaqueCtx, evTimerID id) {
- evContext_p *ctx = opaqueCtx.opaque;
evTimer *del = id.opaque;
idle_timer *tt = del->uap;
diff --git a/contrib/bind/lib/isc/ev_waits.c b/contrib/bind/lib/isc/ev_waits.c
index a45adf1..c336dcb 100644
--- a/contrib/bind/lib/isc/ev_waits.c
+++ b/contrib/bind/lib/isc/ev_waits.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1997, 1998 by Internet Software Consortium
+ * 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
@@ -20,7 +20,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static const char rcsid[] = "$Id: ev_waits.c,v 8.6 1998/03/20 23:26:23 halley Exp $";
+static const char rcsid[] = "$Id: ev_waits.c,v 8.9 1999/10/13 17:11:20 vixie Exp $";
#endif
#include "port_before.h"
@@ -117,7 +117,7 @@ evUnwait(evContext opaqueCtx, evWaitID id) {
for (prev = NULL, this = wl->first;
this != NULL;
prev = this, this = this->next)
- if (this == id.opaque) {
+ if (this == (evWait *)id.opaque) {
found = 1;
if (prev != NULL)
prev->next = this->next;
@@ -136,7 +136,7 @@ evUnwait(evContext opaqueCtx, evWaitID id) {
for (prev = NULL, this = ctx->waitDone.first;
this != NULL;
prev = this, this = this->next)
- if (this == id.opaque) {
+ if (this == (evWait *)id.opaque) {
found = 1;
if (prev != NULL)
prev->next = this->next;
@@ -218,7 +218,6 @@ evNewWaitList(evContext_p *ctx) {
static void
evFreeWaitList(evContext_p *ctx, evWaitList *this) {
- evWaitList *prev;
INSIST(this != NULL);
diff --git a/contrib/bind/lib/isc/eventlib.c b/contrib/bind/lib/isc/eventlib.c
index afb9d9d..6cb227b 100644
--- a/contrib/bind/lib/isc/eventlib.c
+++ b/contrib/bind/lib/isc/eventlib.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 1996, 1997, 1998 by Internet Software Consortium
+ * 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
@@ -20,7 +20,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static const char rcsid[] = "$Id: eventlib.c,v 1.38 1998/03/20 23:26:24 halley Exp $";
+static const char rcsid[] = "$Id: eventlib.c,v 1.44 1999/10/13 17:11:20 vixie Exp $";
#endif
#include "port_before.h"
@@ -31,6 +31,7 @@ static const char rcsid[] = "$Id: eventlib.c,v 1.38 1998/03/20 23:26:24 halley E
#include <sys/stat.h>
#include <errno.h>
+#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
@@ -44,7 +45,9 @@ static const char rcsid[] = "$Id: eventlib.c,v 1.38 1998/03/20 23:26:24 halley E
/* Forward. */
#ifdef NEED_PSELECT
-static int pselect(int, void *, void *, void *, struct timespec*);
+static int pselect(int, void *, void *, void *,
+ struct timespec *,
+ const sigset_t *);
#endif
/* Public. */
@@ -52,7 +55,6 @@ static int pselect(int, void *, void *, void *, struct timespec*);
int
evCreate(evContext *opaqueCtx) {
evContext_p *ctx;
- int i;
/* Make sure the memory heap is initialized. */
if (meminit(0, 0) < 0 && errno != EEXIST)
@@ -76,14 +78,15 @@ evCreate(evContext *opaqueCtx) {
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
- for (i = 0; i < FD_SETSIZE; i++)
- ctx->fdTable[i] = NULL;
+ memset(ctx->fdTable, 0, sizeof ctx->fdTable);
/* Streams. */
ctx->streams = NULL;
@@ -299,7 +302,7 @@ evGetNext(evContext opaqueCtx, evEvent *opaqueEv, int options) {
/* XXX should predict system's earliness and adjust. */
x = pselect(ctx->fdMax+1,
&ctx->rdLast, &ctx->wrLast, &ctx->exLast,
- tp);
+ tp, NULL);
pselect_errno = errno;
evPrintf(ctx, 4, "select() returns %d (err: %s)\n",
@@ -625,6 +628,13 @@ evMainLoop(evContext opaqueCtx) {
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;
@@ -638,9 +648,14 @@ evPrintf(const evContext_p *ctx, int level, const char *fmt, ...) {
}
#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) {
+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) {
@@ -648,7 +663,11 @@ pselect(int nfds, void *rfds, void *wfds, void *efds, struct timespec *tsp) {
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);
diff --git a/contrib/bind/lib/isc/eventlib.mdoc b/contrib/bind/lib/isc/eventlib.mdoc
index f0e31e1..202b1cb 100644
--- a/contrib/bind/lib/isc/eventlib.mdoc
+++ b/contrib/bind/lib/isc/eventlib.mdoc
@@ -1,6 +1,6 @@
-.\" $Id: eventlib.mdoc,v 1.18 1998/01/26 23:00:56 halley Exp $
+.\" $Id: eventlib.mdoc,v 1.20 1999/08/18 22:09:04 vixie Exp $
.\"
-.\"Copyright (c) 1995, 1996, 1997 by Internet Software Consortium
+.\"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
@@ -63,7 +63,9 @@
.Nm evTryAccept ,
.Nm evConsIovec ,
.Nm evSetDebug ,
-.Nm evPrintf
+.Nm evPrintf ,
+.Nm evInitID ,
+.Nm evTestID
.Nd event handling library
.Sh SYNOPSIS
.Fd #include <isc/eventlib.h>
@@ -171,6 +173,10 @@
.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
@@ -769,6 +775,25 @@ with the event context pointed to by
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
diff --git a/contrib/bind/lib/isc/eventlib_p.h b/contrib/bind/lib/isc/eventlib_p.h
index 2606333..80dc160 100644
--- a/contrib/bind/lib/isc/eventlib_p.h
+++ b/contrib/bind/lib/isc/eventlib_p.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 1996, 1997, 1998 by Internet Software Consortium
+ * 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
@@ -18,7 +18,7 @@
/* eventlib_p.h - private interfaces for eventlib
* vix 09sep95 [initial]
*
- * $Id: eventlib_p.h,v 1.25 1998/02/06 01:53:54 halley Exp $
+ * $Id: eventlib_p.h,v 1.27 1999/06/03 20:36:05 vixie Exp $
*/
#ifndef _EVENTLIB_P_H
@@ -165,7 +165,7 @@ typedef struct {
fd_set wrLast, wrNext;
fd_set exLast, exNext;
fd_set nonblockBefore;
- int fdMax, fdCount;
+ int fdMax, fdCount, highestFD;
evFile *fdTable[FD_SETSIZE];
#ifdef EVENTLIB_TIME_CHECKS
struct timespec lastSelectTime;
diff --git a/contrib/bind/lib/isc/heap.c b/contrib/bind/lib/isc/heap.c
index 821d323..ba9c503 100644
--- a/contrib/bind/lib/isc/heap.c
+++ b/contrib/bind/lib/isc/heap.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997 by Internet Software Consortium.
+ * 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
@@ -26,7 +26,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: heap.c,v 8.5 1998/03/27 00:17:47 halley Exp $";
+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"
diff --git a/contrib/bind/lib/isc/heap.mdoc b/contrib/bind/lib/isc/heap.mdoc
index 2c22bc2..516490b 100644
--- a/contrib/bind/lib/isc/heap.mdoc
+++ b/contrib/bind/lib/isc/heap.mdoc
@@ -1,6 +1,6 @@
-.\" $Id: heap.mdoc,v 8.4 1997/04/26 04:00:55 vixie Exp $
+.\" $Id: heap.mdoc,v 8.5 1999/01/08 19:25:38 vixie Exp $
.\"
-.\"Copyright (c) 1997 by Internet Software Consortium.
+.\"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
diff --git a/contrib/bind/lib/isc/logging.c b/contrib/bind/lib/isc/logging.c
index e5264ff..a3988e4 100644
--- a/contrib/bind/lib/isc/logging.c
+++ b/contrib/bind/lib/isc/logging.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1997, 1998 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: logging.c,v 8.18 1998/03/27 00:17:47 halley Exp $";
+static const char rcsid[] = "$Id: logging.c,v 8.24 1999/10/13 16:39:34 vixie Exp $";
#endif /* not lint */
#include "port_before.h"
@@ -115,9 +115,7 @@ log_open_stream(log_channel chan) {
regular = (sb.st_mode & S_IFREG);
if (chan->out.file.versions) {
- if (regular)
- version_rename(chan);
- else {
+ if (!regular) {
syslog(LOG_ERR,
"log_open_stream: want versions but %s isn't a regular file",
chan->out.file.name);
@@ -265,7 +263,6 @@ log_vwrite(log_context lc, int category, int level, const char *format,
int pri, debugging, did_vsprintf = 0;
int original_category;
FILE *stream;
- int chan_level;
log_channel chan;
struct timeval tv;
struct tm *local_tm;
@@ -300,7 +297,11 @@ log_vwrite(log_context lc, int category, int level, const char *format,
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],
@@ -378,8 +379,19 @@ log_vwrite(log_context lc, int category, int level, const char *format,
pos = ftell(stream);
if (pos >= 0 &&
(unsigned long)pos >
- chan->out.file.max_size)
- break;
+ 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 : "",
diff --git a/contrib/bind/lib/isc/logging.mdoc b/contrib/bind/lib/isc/logging.mdoc
index 6fdb618..6b48943 100644
--- a/contrib/bind/lib/isc/logging.mdoc
+++ b/contrib/bind/lib/isc/logging.mdoc
@@ -1,6 +1,6 @@
-.\" $Id: logging.mdoc,v 8.2 1998/02/06 01:54:34 halley Exp $
+.\" $Id: logging.mdoc,v 8.3 1999/01/08 19:25:41 vixie Exp $
.\"
-.\"Copyright (c) 1995, 1996, 1997, 1998 by Internet Software Consortium
+.\"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
diff --git a/contrib/bind/lib/isc/logging_p.h b/contrib/bind/lib/isc/logging_p.h
index 317582d..e94102e 100644
--- a/contrib/bind/lib/isc/logging_p.h
+++ b/contrib/bind/lib/isc/logging_p.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * 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
diff --git a/contrib/bind/lib/isc/memcluster.c b/contrib/bind/lib/isc/memcluster.c
index 761fe98..b775fa7 100644
--- a/contrib/bind/lib/isc/memcluster.c
+++ b/contrib/bind/lib/isc/memcluster.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997 by Internet Software Consortium.
+ * 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
@@ -15,8 +15,15 @@
* 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 char rcsid[] = "$Id: memcluster.c,v 8.10 1998/05/05 19:00:52 halley Exp $";
+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"
@@ -41,15 +48,34 @@ static char rcsid[] = "$Id: memcluster.c,v 8.10 1998/05/05 19:00:52 halley Exp $
#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
@@ -70,6 +96,9 @@ 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
@@ -78,13 +107,18 @@ 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) {
- int i;
+#if defined(DEBUGGING_MEMCLUSTER)
+ INSIST(sizeof(fence_t) == FENCEPOST_SIZE);
+#endif
if (freelists != NULL) {
errno = EEXIST;
return (-1);
@@ -108,6 +142,15 @@ meminit(size_t init_max_size, size_t target_size) {
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
@@ -116,7 +159,17 @@ meminit(size_t init_max_size, size_t target_size) {
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)
@@ -130,7 +183,27 @@ __memget(size_t 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
}
/*
@@ -186,18 +259,50 @@ __memget(size_t 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": */
+ /* 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
@@ -208,7 +313,11 @@ __memget(size_t size) {
stats[size].gets++;
stats[size].totalgets++;
stats[new_size].freefrags--;
+#if defined(DEBUGGING_MEMCLUSTER)
+ return ((char *)e + sizeof *e);
+#else
return (ret);
+#endif
}
/*
@@ -217,25 +326,83 @@ __memget(size_t size) {
*/
void
__memput(void *mem, size_t size) {
- size_t new_size = quantize(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
@@ -251,7 +418,7 @@ __memput(void *mem, size_t size) {
void *
__memget_debug(size_t size, const char *file, int line) {
void *ptr;
- ptr = __memget(size);
+ ptr = __memget_record(size, file, line);
fprintf(stderr, "%s:%d: memget(%lu) -> %p\n", file, line,
(u_long)size, ptr);
return (ptr);
@@ -261,7 +428,7 @@ 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);
+ __memput_record(ptr, size, file, line);
}
/*
@@ -270,6 +437,9 @@ __memput_debug(void *ptr, size_t size, const char *file, int line) {
void
memstats(FILE *out) {
size_t i;
+#ifdef MEMCLUSTER_RECORD
+ memcluster_element *e;
+#endif
if (freelists == NULL)
return;
@@ -286,6 +456,19 @@ memstats(FILE *out) {
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 :
+ "<UNKNOWN>", e->line,
+ (char *)e + sizeof *e, e->size);
+ e = e->next;
+ }
+ }
+#endif
}
/* Private. */
@@ -295,7 +478,7 @@ memstats(FILE *out) {
* 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
+static size_t
quantize(size_t size) {
int remainder;
/*
@@ -309,7 +492,19 @@ quantize(size_t size) {
*/
remainder = size % P_SIZE;
if (remainder != 0)
- size += P_SIZE - remainder;
+ 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
diff --git a/contrib/bind/lib/isc/memcluster.mdoc b/contrib/bind/lib/isc/memcluster.mdoc
index c076972..82bfd71 100644
--- a/contrib/bind/lib/isc/memcluster.mdoc
+++ b/contrib/bind/lib/isc/memcluster.mdoc
@@ -1,6 +1,6 @@
-.\" $Id: memcluster.mdoc,v 8.1 1997/09/26 17:56:10 halley Exp $
+.\" $Id: memcluster.mdoc,v 8.2 1999/01/08 19:25:46 vixie Exp $
.\"
-.\"Copyright (c) 1995, 1996 by Internet Software Consortium
+.\"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
diff --git a/contrib/bind/lib/isc/tree.c b/contrib/bind/lib/isc/tree.c
index ce500ec..90ba146 100644
--- a/contrib/bind/lib/isc/tree.c
+++ b/contrib/bind/lib/isc/tree.c
@@ -1,5 +1,5 @@
#ifndef LINT
-static char RCSid[] = "$Id: tree.c,v 8.6 1997/09/26 17:56:11 halley Exp $";
+static const char rcsid[] = "$Id: tree.c,v 8.9 1999/01/08 19:25:47 vixie Exp $";
#endif
/*
@@ -22,7 +22,7 @@ static char RCSid[] = "$Id: tree.c,v 8.6 1997/09/26 17:56:11 halley Exp $";
*/
/*
- * Portions Copyright (c) 1996,1997 by Internet Software Consortium.
+ * 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
@@ -56,7 +56,7 @@ static char *debugFuncs[256];
# define ENTER(proc) { \
debugFuncs[debugDepth] = proc; \
fprintf(stderr, "ENTER(%d:%s.%s)\n", \
- debugDepth, DEBUG,
+ debugDepth, DEBUG, \
debugFuncs[debugDepth]); \
debugDepth++; \
}
diff --git a/contrib/bind/lib/isc/tree.mdoc b/contrib/bind/lib/isc/tree.mdoc
index 2406219..422344e 100644
--- a/contrib/bind/lib/isc/tree.mdoc
+++ b/contrib/bind/lib/isc/tree.mdoc
@@ -1,6 +1,6 @@
-.\" $Id: tree.mdoc,v 8.1 1997/01/30 20:27:25 vixie Exp $
+.\" $Id: tree.mdoc,v 8.2 1999/01/08 19:25:48 vixie Exp $
.\"
-.\"Copyright (c) 1995, 1996 by Internet Software Consortium
+.\"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
diff --git a/contrib/bind/lib/nameser/Makefile b/contrib/bind/lib/nameser/Makefile
index d86dc74..52a102f 100644
--- a/contrib/bind/lib/nameser/Makefile
+++ b/contrib/bind/lib/nameser/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1996 by Internet Software Consortium
+# 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
@@ -15,7 +15,7 @@
# SOFTWARE.
#
-# $Id: Makefile,v 8.7 1997/05/21 19:32:08 halley Exp $
+# $Id: Makefile,v 8.16 1999/09/07 08:47:28 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
@@ -33,31 +33,48 @@ 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 cruv
+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
+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}
+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}
+all: ${LIBBIND}
${LIBBIND}: ${OBJS}
+ ( cd ${THREADED} ; \
+ ${AR} ${LIBBINDR} ${ARPREF} ${OBJS} ${ARSUFF} ; \
+ ${RANLIB} ${LIBBINDR} )
${AR} ${LIBBIND} ${ARPREF} ${OBJS} ${ARSUFF}
${RANLIB} ${LIBBIND}
.c.${O}:
- ${CC} ${CPPFLAGS} ${CFLAGS} -c $*.c
- -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} && ${LDS} mv a.out $*.${O}
+ if test ! -d ${THREADED} ; then mkdir ${THREADED} ; fi
+ ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} ${REENTRANT} -c $*.c \
+ -o ${THREADED}/$*.${O}
+ -${LDS} ${LD} ${LD_LIBFLAGS} ${THREADED}/$*.${O} -o a.out && \
+ ${LDS} mv a.out ${THREADED}/$*.${O}
+ ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c
+ -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} -o a.out && \
+ ${LDS} mv a.out $*.${O}
distclean: clean
clean: FRC
rm -f .depend a.out core ${LIB} tags
rm -f *.${O} *.BAK *.CKP *~
+ rm -f ${THREADED}/*.${O}
+ -rmdir ${THREADED}
depend: FRC
mkdep -I${INCL} -I${PORTINCL} ${CPPFLAGS} ${SRCS}
diff --git a/contrib/bind/lib/nameser/ns_date.c b/contrib/bind/lib/nameser/ns_date.c
new file mode 100644
index 0000000..da593a5
--- /dev/null
+++ b/contrib/bind/lib/nameser/ns_date.c
@@ -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 <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#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);
+}
diff --git a/contrib/bind/lib/nameser/ns_name.c b/contrib/bind/lib/nameser/ns_name.c
index 86c0bbb..6bd668d 100644
--- a/contrib/bind/lib/nameser/ns_name.c
+++ b/contrib/bind/lib/nameser/ns_name.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: ns_name.c,v 8.3 1997/04/24 22:10:54 vixie Exp $";
+static const char rcsid[] = "$Id: ns_name.c,v 8.12 1999/10/13 17:11:23 vixie Exp $";
#endif
#include "port_before.h"
@@ -29,12 +29,13 @@ static char rcsid[] = "$Id: ns_name.c,v 8.3 1997/04/24 22:10:54 vixie Exp $";
#include <errno.h>
#include <resolv.h>
#include <string.h>
+#include <ctype.h>
#include "port_after.h"
/* Data. */
-static char digits[] = "0123456789";
+static const char digits[] = "0123456789";
/* Forward. */
@@ -199,7 +200,7 @@ ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
}
return (1);
}
- if (c == 0) {
+ if (c == 0 || *src == '.') {
errno = EMSGSIZE;
return (-1);
}
@@ -237,6 +238,49 @@ ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
}
/*
+ * 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:
@@ -248,7 +292,7 @@ ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
{
const u_char *srcp, *dstlim;
u_char *dstp;
- int n, c, len, checked;
+ int n, len, checked;
len = -1;
checked = 0;
@@ -366,6 +410,7 @@ ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
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. */
@@ -375,8 +420,7 @@ ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
(const u_char * const *)lpp);
if (l >= 0) {
if (dstp + 1 >= eob) {
- errno = EMSGSIZE;
- return (-1);
+ goto cleanup;
}
*dstp++ = (l >> 8) | NS_CMPRSFLGS;
*dstp++ = l % 256;
@@ -391,12 +435,10 @@ ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
}
/* copy label to buffer */
if (n & NS_CMPRSFLGS) { /* Should not happen. */
- errno = EMSGSIZE;
- return (-1);
+ goto cleanup;
}
if (dstp + 1 + n >= eob) {
- errno = EMSGSIZE;
- return (-1);
+ goto cleanup;
}
memcpy(dstp, srcp, n + 1);
srcp += n + 1;
@@ -404,6 +446,7 @@ ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
} while (n != 0);
if (dstp > eob) {
+cleanup:
if (msg != NULL)
*lpp = NULL;
errno = EMSGSIZE;
diff --git a/contrib/bind/lib/nameser/ns_netint.c b/contrib/bind/lib/nameser/ns_netint.c
index 1f640a5..030a2d0 100644
--- a/contrib/bind/lib/nameser/ns_netint.c
+++ b/contrib/bind/lib/nameser/ns_netint.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,21 +16,19 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: ns_netint.c,v 8.1 1996/11/18 09:09:57 vixie Exp $";
+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 <sys/types.h>*/
-/*#include <sys/socket.h>*/
-
-/*#include <netinet/in.h>*/
#include <arpa/nameser.h>
#include "port_after.h"
+/* Public. */
+
u_int
ns_get16(const u_char *src) {
u_int dst;
diff --git a/contrib/bind/lib/nameser/ns_parse.c b/contrib/bind/lib/nameser/ns_parse.c
index 800ea19..35f7f40 100644
--- a/contrib/bind/lib/nameser/ns_parse.c
+++ b/contrib/bind/lib/nameser/ns_parse.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,9 +16,11 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: ns_parse.c,v 8.8 1998/02/17 17:20:33 vixie Exp $";
+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 <sys/types.h>
@@ -32,6 +34,16 @@ static char rcsid[] = "$Id: ns_parse.c,v 8.8 1998/02/17 17:20:33 vixie Exp $";
#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. */
@@ -52,8 +64,8 @@ struct _ns_flagdata _ns_flagdata[16] = {
{ 0x0000, 0 }, /* expansion (6/6). */
};
-static int
-skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) {
+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--) {
@@ -61,24 +73,19 @@ skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) {
b = dn_skipname(ptr, eom);
if (b < 0)
- goto emsgsize;
+ RETERR(EMSGSIZE);
ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/;
if (section != ns_s_qd) {
- if (ptr + NS_INT32SZ > eom)
- goto emsgsize;
+ if (ptr + NS_INT32SZ + NS_INT16SZ > eom)
+ RETERR(EMSGSIZE);
ptr += NS_INT32SZ/*TTL*/;
- if (ptr + NS_INT16SZ > eom)
- goto emsgsize;
NS_GET16(rdlength, ptr);
ptr += rdlength/*RData*/;
}
}
if (ptr > eom)
- goto emsgsize;
+ RETERR(EMSGSIZE);
return (ptr - optr);
- emsgsize:
- errno = EMSGSIZE;
- return (-1);
}
int
@@ -90,22 +97,22 @@ ns_initparse(const u_char *msg, int msglen, ns_msg *handle) {
handle->_msg = msg;
handle->_eom = eom;
if (msg + NS_INT16SZ > eom)
- goto emsgsize;
+ RETERR(EMSGSIZE);
NS_GET16(handle->_id, msg);
if (msg + NS_INT16SZ > eom)
- goto emsgsize;
+ RETERR(EMSGSIZE);
NS_GET16(handle->_flags, msg);
for (i = 0; i < ns_s_max; i++) {
if (msg + NS_INT16SZ > eom)
- goto emsgsize;
+ 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 = skiprr(msg, eom, (ns_sect)i,
- handle->_counts[i]);
+ int b = ns_skiprr(msg, eom, (ns_sect)i,
+ handle->_counts[i]);
if (b < 0)
return (-1);
@@ -113,14 +120,9 @@ ns_initparse(const u_char *msg, int msglen, ns_msg *handle) {
msg += b;
}
if (msg != eom)
- goto emsgsize;
- handle->_sect = ns_s_max;
- handle->_rrnum = -1;
- handle->_ptr = NULL;
+ RETERR(EMSGSIZE);
+ setsection(handle, ns_s_max);
return (0);
- emsgsize:
- errno = EMSGSIZE;
- return (-1);
}
int
@@ -129,29 +131,26 @@ ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
/* Make section right. */
if (section < 0 || section >= ns_s_max)
- goto enodev;
- if ((int)section != (int)handle->_sect) {
- handle->_sect = section;
- handle->_rrnum = 0;
- handle->_ptr = handle->_sections[(int)section];
- }
+ 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])
- goto enodev;
- if (rrnum < handle->_rrnum) {
- handle->_rrnum = 0;
- handle->_ptr = handle->_sections[(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;
}
-
- b = skiprr(handle->_msg, 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,
@@ -159,36 +158,41 @@ ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
if (b < 0)
return (-1);
handle->_ptr += b;
- if (handle->_ptr + NS_INT16SZ > handle->_eom)
- goto emsgsize;
+ if (handle->_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom)
+ RETERR(EMSGSIZE);
NS_GET16(rr->type, handle->_ptr);
- if (handle->_ptr + NS_INT16SZ > handle->_eom)
- goto emsgsize;
- NS_GET16(rr->class, 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 > handle->_eom)
- goto emsgsize;
+ if (handle->_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom)
+ RETERR(EMSGSIZE);
NS_GET32(rr->ttl, handle->_ptr);
- if (handle->_ptr + NS_INT16SZ > handle->_eom)
- goto emsgsize;
NS_GET16(rr->rdlength, handle->_ptr);
if (handle->_ptr + rr->rdlength > handle->_eom)
- goto emsgsize;
+ RETERR(EMSGSIZE);
rr->rdata = handle->_ptr;
handle->_ptr += rr->rdlength;
}
- handle->_rrnum++;
+ if (++handle->_rrnum > handle->_counts[(int)section])
+ setsection(handle, (ns_sect)((int)section + 1));
/* All done. */
return (0);
- enodev:
- errno = ENODEV;
- return (-1);
- emsgsize:
- errno = EMSGSIZE;
- return (-1);
+}
+
+/* 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];
+ }
}
diff --git a/contrib/bind/lib/nameser/ns_print.c b/contrib/bind/lib/nameser/ns_print.c
index 8ab4766..93f1e91 100644
--- a/contrib/bind/lib/nameser/ns_print.c
+++ b/contrib/bind/lib/nameser/ns_print.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: ns_print.c,v 8.4 1998/02/13 01:16:37 halley Exp $";
+static const char rcsid[] = "$Id: ns_print.c,v 8.17 1999/10/19 02:06:54 gson Exp $";
#endif
/* Import. */
@@ -30,7 +30,7 @@ static char rcsid[] = "$Id: ns_print.c,v 8.4 1998/02/13 01:16:37 halley Exp $";
#include <arpa/nameser.h>
#include <arpa/inet.h>
-#include <assert.h>
+#include <isc/assertions.h>
#include <errno.h>
#include <resolv.h>
#include <string.h>
@@ -58,6 +58,10 @@ static int addstr(const char *src, size_t len,
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) \
@@ -115,7 +119,7 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
/*
* Owner.
*/
- if (name_ctx != NULL && strcasecmp(name_ctx, name) == 0) {
+ if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
T(addstr("\t\t\t", 3, &buf, &buflen));
} else {
len = prune_origin(name, origin);
@@ -171,7 +175,11 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
rdata += len;
T(addstr(" ", 1, &buf, &buflen));
- /* Second word. */
+
+ /* 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;
@@ -439,7 +447,7 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
case ns_t_key: {
char base64_key[NS_MD5RSA_MAX_BASE64];
- u_int keyflags, protocol, algorithm;
+ u_int keyflags, protocol, algorithm, key_id;
const char *leader;
int n;
@@ -447,6 +455,7 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
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++;
@@ -472,6 +481,8 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
}
if (len > 15)
T(addstr(" )", 2, &buf, &buflen));
+ n = SPRINTF((tmp, " ; key_tag= %u", key_id));
+ T(addstr(tmp, n, &buf, &buflen));
break;
}
@@ -491,10 +502,10 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
algorithm = *rdata++;
labels = *rdata++;
t = ns_get32(rdata); rdata += NS_INT32SZ;
- len = SPRINTF((tmp, " %s %d %lu ",
- p_type(type), algorithm, t));
+ 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))
+ if (labels > (u_int)dn_count_labels(name))
goto formerr;
/* Signature expiry. */
@@ -533,7 +544,6 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
}
if (len > 15)
T(addstr(" )", 2, &buf, &buflen));
-
break;
}
@@ -553,6 +563,63 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
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;
@@ -608,7 +675,7 @@ prune_origin(const char *name, const char *origin) {
const char *oname = name;
while (*name != '\0') {
- if (origin != NULL && strcasecmp(name, origin) == 0)
+ if (origin != NULL && ns_samename(name, origin) == 1)
return (name - oname - (name > oname));
while (*name != '\0') {
if (*name == '\\') {
@@ -712,14 +779,14 @@ addname(const u_char *msg, size_t msglen,
static void
addlen(size_t len, char **buf, size_t *buflen) {
- assert(len <= *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) {
+ if (len >= *buflen) {
errno = ENOSPC;
return (-1);
}
diff --git a/contrib/bind/lib/nameser/ns_samedomain.c b/contrib/bind/lib/nameser/ns_samedomain.c
new file mode 100644
index 0000000..c847924
--- /dev/null
+++ b/contrib/bind/lib/nameser/ns_samedomain.c
@@ -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 <sys/types.h>
+#include <arpa/nameser.h>
+#include <errno.h>
+#include <string.h>
+
+#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);
+}
diff --git a/contrib/bind/lib/nameser/ns_sign.c b/contrib/bind/lib/nameser/ns_sign.c
new file mode 100644
index 0000000..75af894
--- /dev/null
+++ b/contrib/bind/lib/nameser/ns_sign.c
@@ -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 <sys/types.h>
+#include <sys/param.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/dst.h>
+
+#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);
+}
diff --git a/contrib/bind/lib/nameser/ns_ttl.c b/contrib/bind/lib/nameser/ns_ttl.c
index a71d3c7..67cd976 100644
--- a/contrib/bind/lib/nameser/ns_ttl.c
+++ b/contrib/bind/lib/nameser/ns_ttl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -16,7 +16,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: ns_ttl.c,v 8.5 1998/02/13 01:16:38 halley Exp $";
+static const char rcsid[] = "$Id: ns_ttl.c,v 8.8 1999/10/13 16:39:36 vixie Exp $";
#endif
/* Import. */
@@ -52,7 +52,7 @@ int
ns_format_ttl(u_long src, char *dst, size_t dstlen) {
char *odst = dst;
int secs, mins, hours, days, weeks, x;
- char tmp[50], *p;
+ char *p;
secs = src % 60; src /= 60;
mins = src % 60; src /= 60;
diff --git a/contrib/bind/lib/nameser/ns_verify.c b/contrib/bind/lib/nameser/ns_verify.c
new file mode 100644
index 0000000..316da13
--- /dev/null
+++ b/contrib/bind/lib/nameser/ns_verify.c
@@ -0,0 +1,471 @@
+/*
+ * 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.11 1999/10/15 21:06:51 vixie Exp $";
+#endif
+
+/* Import. */
+
+#include "port_before.h"
+#include "fd_setsize.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/dst.h>
+
+#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];
+
+ /* 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_ntol(recstart, buf, sizeof(buf));
+ 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_ntol(rdatastart, buf, sizeof(buf));
+ 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, &timesigned, 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_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);
+}
diff --git a/contrib/bind/lib/resolv/Makefile b/contrib/bind/lib/resolv/Makefile
index 5be600d..243e69b 100644
--- a/contrib/bind/lib/resolv/Makefile
+++ b/contrib/bind/lib/resolv/Makefile
@@ -1,4 +1,4 @@
-# Copyright (c) 1996 by Internet Software Consortium
+# 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
@@ -13,7 +13,7 @@
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
# SOFTWARE.
-# $Id: Makefile,v 8.17 1997/05/21 19:32:09 halley Exp $
+# $Id: Makefile,v 8.30 1999/10/07 08:24:15 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
@@ -31,35 +31,53 @@ 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 cruv
+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_mkupdate.c \
- res_update.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_mkupdate.${O} \
- res_update.${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}:
- ${CC} ${CPPFLAGS} ${CFLAGS} -c $*.c
- -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} && ${LDS} mv a.out $*.${O}
+ if test ! -d ${THREADED} ; then mkdir ${THREADED} ; fi
+ ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} ${REENTRANT} -c $*.c \
+ -o ${THREADED}/$*.${O}
+ -${LDS} ${LD} ${LD_LIBFLAGS} ${THREADED}/$*.${O} -o a.out && \
+ ${LDS} mv a.out ${THREADED}/$*.${O}
+ ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c
+ -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} -o a.out && \
+ ${LDS} mv a.out $*.${O}
distclean: clean
clean: FRC
rm -f .depend a.out core ${LIB} tags
rm -f *.${O} *.BAK *.CKP *~
+ rm -f ${THREADED}/*.${O}
+ -rmdir ${THREADED}
depend: FRC
mkdep -I${INCL} -I${PORTINCL} ${CPPFLAGS} ${SRCS}
diff --git a/contrib/bind/lib/resolv/herror.c b/contrib/bind/lib/resolv/herror.c
index 38217db..bf4cce6 100644
--- a/contrib/bind/lib/resolv/herror.c
+++ b/contrib/bind/lib/resolv/herror.c
@@ -32,7 +32,7 @@
*/
/*
- * Portions Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -49,18 +49,27 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id: herror.c,v 8.7 1996/11/18 09:10:00 vixie Exp $";
+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 <sys/types.h>
#include <sys/param.h>
#include <sys/uio.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
#include <netdb.h>
+#include <resolv.h>
#include <string.h>
#include <unistd.h>
+#include <irs.h>
+
#include "port_after.h"
+#undef h_errno
const char *h_errlist[] = {
"Resolver Error 0 (no error)",
@@ -78,21 +87,19 @@ int h_errno;
* print the error indicated by the h_errno value.
*/
void
-herror(s)
- const char *s;
-{
- struct iovec iov[4];
- register struct iovec *v = iov;
+herror(const char *s) {
+ struct iovec iov[4], *v = iov;
+ extern int * __h_errno();
- if (s && *s) {
- v->iov_base = (char *)s;
+ 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_base = (char *)hstrerror(*__h_errno());
v->iov_len = strlen(v->iov_base);
v++;
v->iov_base = "\n";
@@ -100,10 +107,12 @@ herror(s)
writev(STDERR_FILENO, iov, (v - iov) + 1);
}
+/*
+ * hstrerror --
+ * return the string associated with a given "host" errno value.
+ */
const char *
-hstrerror(err)
- int err;
-{
+hstrerror(int err) {
if (err < 0)
return ("Resolver internal error");
else if (err < h_nerr)
diff --git a/contrib/bind/lib/resolv/res_comp.c b/contrib/bind/lib/resolv/res_comp.c
index c1f946e..d972848 100644
--- a/contrib/bind/lib/resolv/res_comp.c
+++ b/contrib/bind/lib/resolv/res_comp.c
@@ -52,7 +52,7 @@
*/
/*
- * Portions Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -69,8 +69,8 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id: res_comp.c,v 8.11 1997/05/21 19:31:04 halley Exp $";
+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"
@@ -244,6 +244,8 @@ res_dnok(const char *dn) {
*/
void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); }
void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); }
+#ifndef __ultrix__
u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); }
u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); }
+#endif /*__ultrix__*/
#endif /*BIND_4_COMPAT*/
diff --git a/contrib/bind/lib/resolv/res_data.c b/contrib/bind/lib/resolv/res_data.c
index ca06d64..7688637 100644
--- a/contrib/bind/lib/resolv/res_data.c
+++ b/contrib/bind/lib/resolv/res_data.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995,1996 by Internet Software Consortium.
+ * 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
@@ -16,24 +16,31 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$Id: res_data.c,v 8.5 1996/11/18 09:10:02 vixie Exp $";
+static const char rcsid[] = "$Id: res_data.c,v 8.17 1999/10/13 17:11:31 vixie Exp $";
#endif /* LIBC_SCCS and not lint */
#include "port_before.h"
+
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/time.h>
+
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
+
#include <ctype.h>
+#include <netdb.h>
#include <resolv.h>
+#include <res_update.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+
#include "port_after.h"
+#undef _res
const char *_res_opcodes[] = {
"QUERY",
@@ -54,25 +61,6 @@ const char *_res_opcodes[] = {
"ZONEREF",
};
-const char *_res_resultcodes[] = {
- "NOERROR",
- "FORMERR",
- "SERVFAIL",
- "NXDOMAIN",
- "NOTIMP",
- "REFUSED",
- "YXDOMAIN",
- "YXRRSET",
- "NXRRSET",
- "NOTAUTH",
- "ZONEERR",
- "11",
- "12",
- "13",
- "14",
- "NOCHANGE",
-};
-
#ifdef BIND_UPDATE
const char *_res_sectioncodes[] = {
"ZONE",
@@ -81,3 +69,224 @@ const char *_res_sectioncodes[] = {
"ADDITIONAL",
};
#endif
+
+#ifndef __BIND_NOSTATIC
+struct __res_state _res
+# if defined(__BIND_RES_TEXT)
+ = { RES_TIMEOUT, } /* Motorola, et al. */
+# endif
+ ;
+
+/* Proto. */
+
+int res_ourserver_p(const res_state, const struct sockaddr_in *);
+void res_pquery(const res_state, const u_char *, int, FILE *);
+
+int
+res_init(void) {
+ extern int __res_vinit(res_state, int);
+
+ /*
+ * These three fields used to be statically initialized. This made
+ * it hard to use this code in a shared library. It is necessary,
+ * now that we're doing dynamic initialization here, that we preserve
+ * the old semantics: if an application modifies one of these three
+ * fields of _res before res_init() is called, res_init() will not
+ * alter them. Of course, if an application is setting them to
+ * _zero_ before calling res_init(), hoping to override what used
+ * to be the static default, we can't detect it and unexpected results
+ * will follow. Zero for any of these fields would make no sense,
+ * so one can safely assume that the applications were already getting
+ * unexpected results.
+ *
+ * _res.options is tricky since some apps were known to diddle the bits
+ * before res_init() was first called. We can't replicate that semantic
+ * with dynamic initialization (they may have turned bits off that are
+ * set in RES_DEFAULT). Our solution is to declare such applications
+ * "broken". They could fool us by setting RES_INIT but none do (yet).
+ */
+ if (!_res.retrans)
+ _res.retrans = RES_TIMEOUT;
+ if (!_res.retry)
+ _res.retry = 4;
+ if (!(_res.options & RES_INIT))
+ _res.options = RES_DEFAULT;
+
+ /*
+ * This one used to initialize implicitly to zero, so unless the app
+ * has set it to something in particular, we can randomize it now.
+ */
+ if (!_res.id)
+ _res.id = res_randomid();
+
+ return (__res_vinit(&_res, 1));
+}
+
+void
+p_query(const u_char *msg) {
+ fp_query(msg, stdout);
+}
+
+void
+fp_query(const u_char *msg, FILE *file) {
+ fp_nquery(msg, PACKETSZ, file);
+}
+
+void
+fp_nquery(const u_char *msg, int len, FILE *file) {
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ return;
+
+ res_pquery(&_res, msg, len, file);
+}
+
+int
+res_mkquery(int op, /* opcode of query */
+ const char *dname, /* domain name */
+ int class, int type, /* class and type of query */
+ const u_char *data, /* resource record data */
+ int datalen, /* length of data */
+ const u_char *newrr_in, /* new rr for modify or append */
+ u_char *buf, /* buffer to put query */
+ int buflen) /* size of buffer */
+{
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+ return (res_nmkquery(&_res, op, dname, class, type,
+ data, datalen,
+ newrr_in, buf, buflen));
+}
+
+int
+res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nmkupdate(&_res, rrecp_in, buf, buflen));
+}
+
+int
+res_query(const char *name, /* domain name */
+ int class, int type, /* class and type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen) /* size of answer buffer */
+{
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+ return (res_nquery(&_res, name, class, type, answer, anslen));
+}
+
+void
+res_send_setqhook(res_send_qhook hook) {
+ _res.qhook = hook;
+}
+
+void
+res_send_setrhook(res_send_rhook hook) {
+ _res.rhook = hook;
+}
+
+int
+res_isourserver(const struct sockaddr_in *inp) {
+ return (res_ourserver_p(&_res, inp));
+}
+
+int
+res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ /* errno should have been set by res_init() in this case. */
+ return (-1);
+ }
+
+ return (res_nsend(&_res, buf, buflen, ans, anssiz));
+}
+
+int
+res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key,
+ u_char *ans, int anssiz)
+{
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ /* errno should have been set by res_init() in this case. */
+ return (-1);
+ }
+
+ return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz));
+}
+
+void
+res_close(void) {
+ res_nclose(&_res);
+}
+
+int
+res_update(ns_updrec *rrecp_in) {
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nupdate(&_res, rrecp_in, NULL));
+}
+
+int
+res_search(const char *name, /* domain name */
+ int class, int type, /* class and type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen) /* size of answer */
+{
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nsearch(&_res, name, class, type, answer, anslen));
+}
+
+int
+res_querydomain(const char *name,
+ const char *domain,
+ int class, int type, /* class and type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen) /* size of answer */
+{
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nquerydomain(&_res, name, domain,
+ class, type,
+ answer, anslen));
+}
+
+const char *
+hostalias(const char *name) {
+ static char abuf[MAXDNAME];
+
+ return (res_hostalias(&_res, name, abuf, sizeof abuf));
+}
+
+#ifdef ultrix
+int
+local_hostname_length(const char *hostname) {
+ int len_host, len_domain;
+
+ if (!*_res.defdname)
+ res_init();
+ len_host = strlen(hostname);
+ len_domain = strlen(_res.defdname);
+ if (len_host > len_domain &&
+ !strcasecmp(hostname + len_host - len_domain, _res.defdname) &&
+ hostname[len_host - len_domain - 1] == '.')
+ return (len_host - len_domain - 1);
+ return (0);
+}
+#endif /*ultrix*/
+
+#endif
diff --git a/contrib/bind/lib/resolv/res_debug.c b/contrib/bind/lib/resolv/res_debug.c
index 80d1477..39f5e9f 100644
--- a/contrib/bind/lib/resolv/res_debug.c
+++ b/contrib/bind/lib/resolv/res_debug.c
@@ -77,7 +77,7 @@
*/
/*
- * Portions Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -94,8 +94,8 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id: res_debug.c,v 8.20 1998/02/13 01:11:34 halley Exp $";
+static const char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_debug.c,v 8.32 1999/10/13 16:39:39 vixie Exp $";
#endif /* LIBC_SCCS and not lint */
#include "port_before.h"
@@ -127,19 +127,16 @@ static char rcsid[] = "$Id: res_debug.c,v 8.20 1998/02/13 01:11:34 halley Exp $"
#endif
extern const char *_res_opcodes[];
-extern const char *_res_resultcodes[];
extern const char *_res_sectioncodes[];
/*
* Print the current options.
*/
void
-fp_resstat(struct __res_state *statp, FILE *file) {
+fp_resstat(const res_state statp, FILE *file) {
u_long mask;
fprintf(file, ";; res options:");
- if (!statp)
- statp = &_res;
for (mask = 1; mask != 0; mask <<= 1)
if (statp->options & mask)
fprintf(file, " %s", p_option(mask));
@@ -147,7 +144,10 @@ fp_resstat(struct __res_state *statp, FILE *file) {
}
static void
-do_section(ns_msg *handle, ns_sect section, int pflag, FILE *file) {
+do_section(const res_state statp,
+ ns_msg *handle, ns_sect section,
+ int pflag, FILE *file)
+{
int n, sflag, rrnum;
char buf[2048]; /* XXX need to malloc */
ns_opcode opcode;
@@ -156,11 +156,11 @@ do_section(ns_msg *handle, ns_sect section, int pflag, FILE *file) {
/*
* Print answer records.
*/
- sflag = (_res.pfcode & pflag);
- if (_res.pfcode && !sflag)
+ sflag = (statp->pfcode & pflag);
+ if (statp->pfcode && !sflag)
return;
- opcode = ns_msg_getflag(*handle, ns_f_opcode);
+ opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode);
rrnum = 0;
for (;;) {
if (ns_parserr(handle, section, rrnum, &rr)) {
@@ -168,11 +168,11 @@ do_section(ns_msg *handle, ns_sect section, int pflag, FILE *file) {
fprintf(file, ";; ns_parserr: %s\n",
strerror(errno));
else if (rrnum > 0 && sflag != 0 &&
- (_res.pfcode & RES_PRF_HEAD1))
+ (statp->pfcode & RES_PRF_HEAD1))
putc('\n', file);
return;
}
- if (rrnum == 0 && sflag != 0 && (_res.pfcode & RES_PRF_HEAD1))
+ if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1))
fprintf(file, ";; %s SECTION:\n",
p_section(section, opcode));
if (section == ns_s_qd)
@@ -195,29 +195,16 @@ do_section(ns_msg *handle, ns_sect section, int pflag, FILE *file) {
}
}
-void
-p_query(const u_char *msg) {
- fp_query(msg, stdout);
-}
-
-void
-fp_query(const u_char *msg, FILE *file) {
- fp_nquery(msg, PACKETSZ, file);
-}
-
/*
* Print the contents of a query.
* This is intended to be primarily a debugging routine.
*/
void
-fp_nquery(const u_char *msg, int len, FILE *file) {
+res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
ns_msg handle;
- int n, qdcount, ancount, nscount, arcount;
+ int qdcount, ancount, nscount, arcount;
u_int opcode, rcode, id;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1)
- return;
-
if (ns_initparse(msg, len, &handle) < 0) {
fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
return;
@@ -233,13 +220,13 @@ fp_nquery(const u_char *msg, int len, FILE *file) {
/*
* Print header fields.
*/
- if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || rcode)
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode)
fprintf(file,
";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
- _res_opcodes[opcode], _res_resultcodes[rcode], id);
- if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX))
+ _res_opcodes[opcode], p_rcode(rcode), id);
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX))
putc(';', file);
- if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) {
fprintf(file, "; flags:");
if (ns_msg_getflag(handle, ns_f_qr))
fprintf(file, " qr");
@@ -258,7 +245,7 @@ fp_nquery(const u_char *msg, int len, FILE *file) {
if (ns_msg_getflag(handle, ns_f_cd))
fprintf(file, " cd");
}
- if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) {
fprintf(file, "; %s: %d",
p_section(ns_s_qd, opcode), qdcount);
fprintf(file, ", %s: %d",
@@ -268,17 +255,17 @@ fp_nquery(const u_char *msg, int len, FILE *file) {
fprintf(file, ", %s: %d",
p_section(ns_s_ar, opcode), arcount);
}
- if ((!_res.pfcode) || (_res.pfcode &
+ if ((!statp->pfcode) || (statp->pfcode &
(RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
putc('\n',file);
}
/*
* Print the various sections.
*/
- do_section(&handle, ns_s_qd, RES_PRF_QUES, file);
- do_section(&handle, ns_s_an, RES_PRF_ANS, file);
- do_section(&handle, ns_s_ns, RES_PRF_AUTH, file);
- do_section(&handle, ns_s_ar, RES_PRF_ADD, file);
+ 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);
@@ -375,55 +362,99 @@ const struct res_sym __p_update_section_syms[] = {
{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[] = {
- {T_A, "A", "address"},
- {T_NS, "NS", "name server"},
- {T_MD, "MD", "mail destination (deprecated)"},
- {T_MF, "MF", "mail forwarder (deprecated)"},
- {T_CNAME, "CNAME", "canonical name"},
- {T_SOA, "SOA", "start of authority"},
- {T_MB, "MB", "mailbox"},
- {T_MG, "MG", "mail group member"},
- {T_MR, "MR", "mail rename"},
- {T_NULL, "NULL", "null"},
- {T_WKS, "WKS", "well-known service (deprecated)"},
- {T_PTR, "PTR", "domain name pointer"},
- {T_HINFO, "HINFO", "host information"},
- {T_MINFO, "MINFO", "mailbox information"},
- {T_MX, "MX", "mail exchanger"},
- {T_TXT, "TXT", "text"},
- {T_RP, "RP", "responsible person"},
- {T_AFSDB, "AFSDB", "DCE or AFS server"},
- {T_X25, "X25", "X25 address"},
- {T_ISDN, "ISDN", "ISDN address"},
- {T_RT, "RT", "router"},
- {T_NSAP, "NSAP", "nsap address"},
- {T_NSAP_PTR, "NSAP_PTR", "domain name pointer"},
- {T_SIG, "SIG", "signature"},
- {T_KEY, "KEY", "key"},
- {T_PX, "PX", "mapping information"},
- {T_GPOS, "GPOS", "geographical position (withdrawn)"},
- {T_AAAA, "AAAA", "IPv6 address"},
- {T_LOC, "LOC", "location"},
- {T_NXT, "NXT", "next valid name (unimplemented)"},
- {T_EID, "EID", "endpoint identifier (unimplemented)"},
- {T_NIMLOC, "NIMLOC", "NIMROD locator (unimplemented)"},
- {T_SRV, "SRV", "server selection"},
- {T_ATMA, "ATMA", "ATM address (unimplemented)"},
- {T_IXFR, "IXFR", "incremental zone transfer"},
- {T_AXFR, "AXFR", "zone transfer"},
- {T_MAILB, "MAILB", "mailbox-related data (deprecated)"},
- {T_MAILA, "MAILA", "mail agent (deprecated)"},
- {T_NAPTR, "NAPTR", "URN Naming Authority"},
- {T_ANY, "ANY", "\"any\""},
+ {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++) {
@@ -450,7 +481,7 @@ sym_ntos(const struct res_sym *syms, int number, int *success) {
}
}
- sprintf(unname, "%d", number);
+ sprintf(unname, "%d", number); /* XXX nonreentrant */
if (success)
*success = 0;
return (unname);
@@ -467,7 +498,7 @@ sym_ntop(const struct res_sym *syms, int number, int *success) {
return (syms->humanname);
}
}
- sprintf(unname, "%d", number);
+ sprintf(unname, "%d", number); /* XXX nonreentrant */
if (success)
*success = 0;
return (unname);
@@ -527,6 +558,7 @@ p_option(u_long option) {
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);
}
@@ -537,13 +569,20 @@ p_option(u_long option) {
*/
const char *
p_time(u_int32_t value) {
- static char nbuf[40];
+ 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.
@@ -559,7 +598,7 @@ static const char *
precsize_ntoa(prec)
u_int8_t prec;
{
- static char retbuf[sizeof "90000000.00"];
+ static char retbuf[sizeof "90000000.00"]; /* XXX nonreentrant */
unsigned long val;
int mantissa, exponent;
@@ -831,6 +870,8 @@ loc_ntoa(binary, ascii)
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;
@@ -848,6 +889,9 @@ loc_ntoa(binary, ascii)
versionval = *cp++;
+ if (ascii == NULL)
+ ascii = tmpbuf;
+
if (versionval) {
(void) sprintf(ascii, "; error: unknown LOC RR version");
return (ascii);
@@ -960,11 +1004,16 @@ dn_count_labels(const char *name) {
*/
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",
diff --git a/contrib/bind/lib/resolv/res_debug.h b/contrib/bind/lib/resolv/res_debug.h
new file mode 100644
index 0000000..1150551
--- /dev/null
+++ b/contrib/bind/lib/resolv/res_debug.h
@@ -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(file, string, error, address) /*empty*/
+# define Perror(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_ */
diff --git a/contrib/bind/lib/resolv/res_findzonecut.c b/contrib/bind/lib/resolv/res_findzonecut.c
new file mode 100644
index 0000000..73a42a2
--- /dev/null
+++ b/contrib/bind/lib/resolv/res_findzonecut.c
@@ -0,0 +1,596 @@
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: res_findzonecut.c,v 8.8 1999/10/15 19:49:11 vixie 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 <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/list.h>
+
+#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 <dname,class>, 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<dname,class>. if we get one as an
+ * answer, that just means <dname,class> 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), n));
+ return (-1);
+ }
+ 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);
+}
diff --git a/contrib/bind/lib/resolv/res_init.c b/contrib/bind/lib/resolv/res_init.c
index f374d51..85dc7e3 100644
--- a/contrib/bind/lib/resolv/res_init.c
+++ b/contrib/bind/lib/resolv/res_init.c
@@ -52,7 +52,7 @@
*/
/*
- * Portions Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -69,24 +69,28 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
-static char rcsid[] = "$Id: res_init.c,v 8.7 1996/11/18 09:10:04 vixie Exp $";
+static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
+static const char rcsid[] = "$Id: res_init.c,v 8.13 1999/10/13 16:39:40 vixie Exp $";
#endif /* LIBC_SCCS and not lint */
#include "port_before.h"
+
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/time.h>
+
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
+
#include <ctype.h>
#include <resolv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+
#include "port_after.h"
/* Options. Should all be left alone. */
@@ -94,7 +98,7 @@ static char rcsid[] = "$Id: res_init.c,v 8.7 1996/11/18 09:10:04 vixie Exp $";
#define RFC1535
#define DEBUG
-static void res_setoptions __P((char *, char *));
+static void res_setoptions __P((res_state, const char *, const char *));
#ifdef RESOLVSORT
static const char sort_mask[] = "/&";
@@ -110,13 +114,6 @@ static u_int32_t net_mask __P((struct in_addr));
* Resolver state default settings.
*/
-struct __res_state _res
-# if defined(__BIND_RES_TEXT)
- = { RES_TIMEOUT, } /* Motorola, et al. */
-# endif
- ;
-
-
/*
* Set up default settings. If the configuration file exist, the values
* there will have precedence. Otherwise, the server address is set to
@@ -139,7 +136,15 @@ struct __res_state _res
* Return 0 if completes successfully, -1 on error
*/
int
-res_init() {
+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;
@@ -155,53 +160,32 @@ res_init() {
int dots;
#endif
- /*
- * These three fields used to be statically initialized. This made
- * it hard to use this code in a shared library. It is necessary,
- * now that we're doing dynamic initialization here, that we preserve
- * the old semantics: if an application modifies one of these three
- * fields of _res before res_init() is called, res_init() will not
- * alter them. Of course, if an application is setting them to
- * _zero_ before calling res_init(), hoping to override what used
- * to be the static default, we can't detect it and unexpected results
- * will follow. Zero for any of these fields would make no sense,
- * so one can safely assume that the applications were already getting
- * unexpected results.
- *
- * _res.options is tricky since some apps were known to diddle the bits
- * before res_init() was first called. We can't replicate that semantic
- * with dynamic initialization (they may have turned bits off that are
- * set in RES_DEFAULT). Our solution is to declare such applications
- * "broken". They could fool us by setting RES_INIT but none do (yet).
- */
- if (!_res.retrans)
- _res.retrans = RES_TIMEOUT;
- if (!_res.retry)
- _res.retry = 4;
- if (!(_res.options & RES_INIT))
- _res.options = RES_DEFAULT;
-
- /*
- * This one used to initialize implicitly to zero, so unless the app
- * has set it to something in particular, we can randomize it now.
- */
- if (!_res.id)
- _res.id = res_randomid();
+ if (!preinit) {
+ statp->retrans = RES_TIMEOUT;
+ statp->retry = RES_DFLRETRY;
+ statp->options = RES_DEFAULT;
+ statp->id = res_randomid();
+ }
#ifdef USELOOPBACK
- _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
+ statp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
#else
- _res.nsaddr.sin_addr.s_addr = INADDR_ANY;
+ statp->nsaddr.sin_addr.s_addr = INADDR_ANY;
#endif
- _res.nsaddr.sin_family = AF_INET;
- _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
- _res.nscount = 1;
- _res.ndots = 1;
- _res.pfcode = 0;
+ statp->nsaddr.sin_family = AF_INET;
+ statp->nsaddr.sin_port = htons(NAMESERVER_PORT);
+ statp->nscount = 1;
+ statp->ndots = 1;
+ statp->pfcode = 0;
+ statp->_sock = -1;
+ statp->_flags = 0;
+ statp->qhook = NULL;
+ statp->rhook = NULL;
/* Allow user to override the local domain definition */
if ((cp = getenv("LOCALDOMAIN")) != NULL) {
- (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
+ (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
+ statp->defdname[sizeof(statp->defdname) - 1] = '\0';
haveenv++;
/*
@@ -211,10 +195,10 @@ res_init() {
* one that they want to use as an individual (even more
* important now that the rfc1535 stuff restricts searches)
*/
- cp = _res.defdname;
- pp = _res.dnsrch;
+ cp = statp->defdname;
+ pp = statp->dnsrch;
*pp++ = cp;
- for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
+ for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
if (*cp == '\n') /* silly backwards compat */
break;
else if (*cp == ' ' || *cp == '\t') {
@@ -253,8 +237,9 @@ res_init() {
cp++;
if ((*cp == '\0') || (*cp == '\n'))
continue;
- strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
- if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
+ 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;
@@ -268,17 +253,18 @@ res_init() {
cp++;
if ((*cp == '\0') || (*cp == '\n'))
continue;
- strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
- if ((cp = strchr(_res.defdname, '\n')) != NULL)
+ 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 = _res.defdname;
- pp = _res.dnsrch;
+ cp = statp->defdname;
+ pp = statp->dnsrch;
*pp++ = cp;
- for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
+ for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
if (*cp == ' ' || *cp == '\t') {
*cp = 0;
n = 1;
@@ -303,9 +289,9 @@ res_init() {
while (*cp == ' ' || *cp == '\t')
cp++;
if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
- _res.nsaddr_list[nserv].sin_addr = a;
- _res.nsaddr_list[nserv].sin_family = AF_INET;
- _res.nsaddr_list[nserv].sin_port =
+ 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++;
}
@@ -328,7 +314,7 @@ res_init() {
n = *cp;
*cp = 0;
if (inet_aton(net, &a)) {
- _res.sort_list[nsort].addr = a;
+ statp->sort_list[nsort].addr = a;
if (ISSORTMASK(n)) {
*cp++ = n;
net = cp;
@@ -338,14 +324,14 @@ res_init() {
n = *cp;
*cp = 0;
if (inet_aton(net, &a)) {
- _res.sort_list[nsort].mask = a.s_addr;
+ statp->sort_list[nsort].mask = a.s_addr;
} else {
- _res.sort_list[nsort].mask =
- net_mask(_res.sort_list[nsort].addr);
+ statp->sort_list[nsort].mask =
+ net_mask(statp->sort_list[nsort].addr);
}
} else {
- _res.sort_list[nsort].mask =
- net_mask(_res.sort_list[nsort].addr);
+ statp->sort_list[nsort].mask =
+ net_mask(statp->sort_list[nsort].addr);
}
nsort++;
}
@@ -355,35 +341,35 @@ res_init() {
}
#endif
if (MATCH(buf, "options")) {
- res_setoptions(buf + sizeof("options") - 1, "conf");
+ res_setoptions(statp, buf + sizeof("options") - 1, "conf");
continue;
}
}
if (nserv > 1)
- _res.nscount = nserv;
+ statp->nscount = nserv;
#ifdef RESOLVSORT
- _res.nsort = nsort;
+ statp->nsort = nsort;
#endif
(void) fclose(fp);
}
- if (_res.defdname[0] == 0 &&
- gethostname(buf, sizeof(_res.defdname) - 1) == 0 &&
+ if (statp->defdname[0] == 0 &&
+ gethostname(buf, sizeof(statp->defdname) - 1) == 0 &&
(cp = strchr(buf, '.')) != NULL)
- strcpy(_res.defdname, cp + 1);
+ strcpy(statp->defdname, cp + 1);
/* find components of local domain that might be searched */
if (havesearch == 0) {
- pp = _res.dnsrch;
- *pp++ = _res.defdname;
+ pp = statp->dnsrch;
+ *pp++ = statp->defdname;
*pp = NULL;
#ifndef RFC1535
dots = 0;
- for (cp = _res.defdname; *cp; cp++)
+ for (cp = statp->defdname; *cp; cp++)
dots += (*cp == '.');
- cp = _res.defdname;
- while (pp < _res.dnsrch + MAXDFLSRCH) {
+ cp = statp->defdname;
+ while (pp < statp->dnsrch + MAXDFLSRCH) {
if (dots < LOCALDOMAINPARTS)
break;
cp = strchr(cp, '.') + 1; /* we know there is one */
@@ -392,9 +378,9 @@ res_init() {
}
*pp = NULL;
#ifdef DEBUG
- if (_res.options & RES_DEBUG) {
+ if (statp->options & RES_DEBUG) {
printf(";; res_init()... default dnsrch list:\n");
- for (pp = _res.dnsrch; *pp; pp++)
+ for (pp = statp->dnsrch; *pp; pp++)
printf(";;\t%s\n", *pp);
printf(";;\t..END..\n");
}
@@ -403,20 +389,18 @@ res_init() {
}
if ((cp = getenv("RES_OPTIONS")) != NULL)
- res_setoptions(cp, "env");
- _res.options |= RES_INIT;
+ res_setoptions(statp, cp, "env");
+ statp->options |= RES_INIT;
return (0);
}
static void
-res_setoptions(options, source)
- char *options, *source;
-{
- char *cp = options;
+res_setoptions(res_state statp, const char *options, const char *source) {
+ const char *cp = options;
int i;
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
+ if (statp->options & RES_DEBUG)
printf(";; res_setoptions(\"%s\", \"%s\")...\n",
options, source);
#endif
@@ -428,24 +412,41 @@ res_setoptions(options, source)
if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
i = atoi(cp + sizeof("ndots:") - 1);
if (i <= RES_MAXNDOTS)
- _res.ndots = i;
+ statp->ndots = i;
else
- _res.ndots = RES_MAXNDOTS;
+ statp->ndots = RES_MAXNDOTS;
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
- printf(";;\tndots=%d\n", _res.ndots);
+ 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 (!(_res.options & RES_DEBUG)) {
+ if (!(statp->options & RES_DEBUG)) {
printf(";; res_setoptions(\"%s\", \"%s\")..\n",
options, source);
- _res.options |= RES_DEBUG;
+ statp->options |= RES_DEBUG;
}
printf(";;\tdebug\n");
#endif
} else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
- _res.options |= RES_USE_INET6;
+ 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? */
}
@@ -472,8 +473,7 @@ net_mask(in) /* XXX - should really use system's version of this */
#endif
u_int
-res_randomid()
-{
+res_randomid(void) {
struct timeval now;
gettimeofday(&now, NULL);
diff --git a/contrib/bind/lib/resolv/res_mkquery.c b/contrib/bind/lib/resolv/res_mkquery.c
index 74be28b..17b1ccf 100644
--- a/contrib/bind/lib/resolv/res_mkquery.c
+++ b/contrib/bind/lib/resolv/res_mkquery.c
@@ -52,7 +52,7 @@
*/
/*
- * Portions Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -69,8 +69,8 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id: res_mkquery.c,v 8.9 1997/04/24 22:22:36 vixie Exp $";
+static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_mkquery.c,v 8.12 1999/10/13 16:39:40 vixie Exp $";
#endif /* LIBC_SCCS and not lint */
#include "port_before.h"
@@ -87,34 +87,32 @@ static char rcsid[] = "$Id: res_mkquery.c,v 8.9 1997/04/24 22:22:36 vixie Exp $"
/* Options. Leave them on. */
#define DEBUG
+extern const char *_res_opcodes[];
+
/*
* Form all types of queries.
* Returns the size of the result or -1.
*/
int
-res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
- int op; /* opcode of query */
- const char *dname; /* domain name */
- int class, type; /* class and type of query */
- const u_char *data; /* resource record data */
- int datalen; /* length of data */
- const u_char *newrr_in; /* new rr for modify or append */
- u_char *buf; /* buffer to put query */
- int buflen; /* size of buffer */
+res_nmkquery(res_state statp,
+ int op, /* opcode of query */
+ const char *dname, /* domain name */
+ int class, int type, /* class and type of query */
+ const u_char *data, /* resource record data */
+ int datalen, /* length of data */
+ const u_char *newrr_in, /* new rr for modify or append */
+ u_char *buf, /* buffer to put query */
+ int buflen) /* size of buffer */
{
register HEADER *hp;
register u_char *cp;
register int n;
u_char *dnptrs[20], **dpp, **lastdnptr;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
- h_errno = NETDB_INTERNAL;
- return (-1);
- }
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
- printf(";; res_mkquery(%d, %s, %d, %d)\n",
- op, dname, class, type);
+ if (statp->options & RES_DEBUG)
+ printf(";; res_nmkquery(%s, %s, %s, %s)\n",
+ _res_opcodes[op], dname, p_class(class), p_type(type));
#endif
/*
* Initialize header fields.
@@ -123,9 +121,9 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
return (-1);
memset(buf, 0, HFIXEDSZ);
hp = (HEADER *) buf;
- hp->id = htons(++_res.id);
+ hp->id = htons(++statp->id);
hp->opcode = op;
- hp->rd = (_res.options & RES_RECURSE) != 0;
+ hp->rd = (statp->options & RES_RECURSE) != 0;
hp->rcode = NOERROR;
cp = buf + HFIXEDSZ;
buflen -= HFIXEDSZ;
diff --git a/contrib/bind/lib/resolv/res_mkupdate.c b/contrib/bind/lib/resolv/res_mkupdate.c
index c6e7f4a1..14e1a60 100644
--- a/contrib/bind/lib/resolv/res_mkupdate.c
+++ b/contrib/bind/lib/resolv/res_mkupdate.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -21,7 +21,7 @@
*/
#if !defined(lint) && !defined(SABER)
-static char rcsid[] = "$Id: res_mkupdate.c,v 1.11 1998/01/26 23:08:45 halley Exp $";
+static const char rcsid[] = "$Id: res_mkupdate.c,v 1.24 1999/10/13 17:11:32 vixie Exp $";
#endif /* not lint */
#include "port_before.h"
@@ -37,6 +37,7 @@ static char rcsid[] = "$Id: res_mkupdate.c,v 1.11 1998/01/26 23:08:45 halley Exp
#include <limits.h>
#include <netdb.h>
#include <resolv.h>
+#include <res_update.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -47,12 +48,20 @@ static char rcsid[] = "$Id: res_mkupdate.c,v 1.11 1998/01/26 23:08:45 halley Exp
/* Options. Leave them on. */
#define DEBUG
+#define MAXPORT 1024
static int getnum_str(u_char **, u_char *);
+static int gethexnum_str(u_char **, u_char *);
static int getword_str(char *, int, u_char **, u_char *);
+static int getstr_str(char *, int, u_char **, u_char *);
#define ShrinkBuffer(x) if ((buflen -= x) < 0) return (-2);
+/* Forward. */
+
+int res_protocolnumber(const char *);
+int res_servicenumber(const char *);
+
/*
* Form update packets.
* Returns the size of the resulting packet if no error
@@ -66,23 +75,21 @@ static int getword_str(char *, int, u_char **, u_char *);
* -5 unknown operation or no records
*/
int
-res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
+res_nmkupdate(res_state statp, ns_updrec *rrecp_in, u_char *buf, int buflen) {
ns_updrec *rrecp_start = rrecp_in;
HEADER *hp;
- u_char c, *cp, *cp1, *sp1, *sp2, *startp, *endp;
- int n, i, j, found, soanum, multiline;
- ns_updrec *rrecp, *tmprrecp, *recptr = NULL;
+ u_char *cp, *sp1, *sp2, *startp, *endp;
+ int n, i, soanum, multiline;
+ ns_updrec *rrecp;
struct in_addr ina;
+ struct in6_addr in6a;
char buf2[MAXDNAME];
+ u_char buf3[MAXDNAME];
int section, numrrs = 0, counts[ns_s_max];
u_int16_t rtype, rclass;
u_int32_t n1, rttl;
u_char *dnptrs[20], **dpp, **lastdnptr;
-
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
- h_errno = NETDB_INTERNAL;
- return (-1);
- }
+ int siglen, keylen, certlen;
/*
* Initialize header fields.
@@ -91,7 +98,7 @@ res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
return (-1);
memset(buf, 0, HFIXEDSZ);
hp = (HEADER *) buf;
- hp->id = htons(++_res.id);
+ hp->id = htons(++statp->id);
hp->opcode = ns_o_update;
hp->rcode = NOERROR;
sp1 = buf + 2*INT16SZ; /* save pointer to zocount */
@@ -108,7 +115,7 @@ res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
return (-3);
memset(counts, 0, sizeof counts);
- for (rrecp = rrecp_start; rrecp; rrecp = rrecp->r_grpnext) {
+ for (rrecp = rrecp_start; rrecp; rrecp = NEXT(rrecp, r_glink)) {
numrrs++;
section = rrecp->r_section;
if (section < 0 || section >= ns_s_max)
@@ -264,8 +271,35 @@ res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
n = getnum_str(&startp, endp);
if (n < 0)
return (-1);
+ ShrinkBuffer(INT16SZ);
PUTSHORT(n, cp);
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ break;
+ case T_SRV:
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+
if (!getword_str(buf2, sizeof buf2, &startp, endp))
return (-1);
n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
@@ -292,17 +326,315 @@ res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
ShrinkBuffer(n);
}
break;
- case T_WKS:
+ case T_WKS: {
+ char bm[MAXPORT/8];
+ int maxbm = 0;
+
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ if (!inet_aton(buf2, &ina))
+ return (-1);
+ n1 = ntohl(ina.s_addr);
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(n1, cp);
+
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ if ((i = res_protocolnumber(buf2)) < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = i & 0xff;
+
+ for (i = 0; i < MAXPORT/8 ; i++)
+ bm[i] = 0;
+
+ while (getword_str(buf2, sizeof buf2, &startp, endp)) {
+ if ((n1 = res_servicenumber(buf2)) <= 0)
+ return (-1);
+
+ if (n1 < MAXPORT) {
+ bm[n1/8] |= (0x80>>(n1%8));
+ if (n1 > maxbm)
+ maxbm = n1;
+ } else
+ return (-1);
+ }
+ maxbm = maxbm/8 + 1;
+ ShrinkBuffer(maxbm);
+ memcpy(cp, bm, maxbm);
+ cp += maxbm;
+ break;
+ }
case T_HINFO:
+ for (i = 0; i < 2; i++) {
+ if ((n = getstr_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ }
+ break;
case T_TXT:
+ while (1) {
+ if ((n = getstr_str(buf2, sizeof buf2,
+ &startp, endp)) < 0) {
+ if (cp != (sp2 + INT16SZ))
+ break;
+ return (-1);
+ }
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ }
+ break;
case T_X25:
+ /* RFC 1183 */
+ if ((n = getstr_str(buf2, sizeof buf2, &startp,
+ endp)) < 0)
+ return (-1);
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ break;
case T_ISDN:
+ /* RFC 1183 */
+ if ((n = getstr_str(buf2, sizeof buf2, &startp,
+ endp)) < 0)
+ return (-1);
+ if ((n > 255) || (n == 0))
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ if ((n = getstr_str(buf2, sizeof buf2, &startp,
+ endp)) < 0)
+ n = 0;
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ break;
case T_NSAP:
+ if ((n = inet_nsap_addr((char *)startp, (u_char *)buf2, sizeof(buf2))) != 0) {
+ ShrinkBuffer(n);
+ memcpy(cp, buf2, n);
+ cp += n;
+ } else {
+ return (-1);
+ }
+ break;
case T_LOC:
- /* XXX - more fine tuning needed here */
- ShrinkBuffer(rrecp->r_size);
- memcpy(cp, rrecp->r_data, rrecp->r_size);
- cp += rrecp->r_size;
+ if ((n = loc_aton((char *)startp, (u_char *)buf2)) != 0) {
+ ShrinkBuffer(n);
+ memcpy(cp, buf2, n);
+ cp += n;
+ } else
+ return (-1);
+ break;
+ case ns_t_sig:
+ {
+ int sig_type, success, dateerror;
+ u_int32_t exptime, timesigned;
+
+ /* type */
+ if ((n = getword_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ sig_type = sym_ston(__p_type_syms, buf2, &success);
+ if (!success || sig_type == ns_t_any)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(sig_type, cp);
+ /* alg */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* labels */
+ n = getnum_str(&startp, endp);
+ if (n <= 0 || n > 255)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* ottl & expire */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ exptime = ns_datetosecs(buf2, &dateerror);
+ if (!dateerror) {
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(rttl, cp);
+ }
+ else {
+ char *ulendp;
+ u_int32_t ottl;
+
+ ottl = strtoul(buf2, &ulendp, 10);
+ if (ulendp != NULL && *ulendp != '\0')
+ return (-1);
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(ottl, cp);
+ if (!getword_str(buf2, sizeof buf2, &startp,
+ endp))
+ return (-1);
+ exptime = ns_datetosecs(buf2, &dateerror);
+ if (dateerror)
+ return (-1);
+ }
+ /* expire */
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(exptime, cp);
+ /* timesigned */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ timesigned = ns_datetosecs(buf2, &dateerror);
+ if (!dateerror) {
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(timesigned, cp);
+ }
+ else
+ return (-1);
+ /* footprint */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* signer name */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ /* sig */
+ if ((n = getword_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ siglen = b64_pton(buf2, buf3, sizeof(buf3));
+ if (siglen < 0)
+ return (-1);
+ ShrinkBuffer(siglen);
+ memcpy(cp, buf3, siglen);
+ cp += siglen;
+ break;
+ }
+ case ns_t_key:
+ /* flags */
+ n = gethexnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* proto */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* alg */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* key */
+ if ((n = getword_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ keylen = b64_pton(buf2, buf3, sizeof(buf3));
+ if (keylen < 0)
+ return (-1);
+ ShrinkBuffer(keylen);
+ memcpy(cp, buf3, keylen);
+ cp += keylen;
+ break;
+ case ns_t_nxt:
+ {
+ int success, nxt_type;
+ u_char data[32];
+ int maxtype;
+
+ /* next name */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ maxtype = 0;
+ memset(data, 0, sizeof data);
+ while (1) {
+ if (!getword_str(buf2, sizeof buf2, &startp,
+ endp))
+ break;
+ nxt_type = sym_ston(__p_type_syms, buf2,
+ &success);
+ if (!success || !ns_t_rr_p(nxt_type))
+ return (-1);
+ NS_NXT_BIT_SET(nxt_type, data);
+ if (nxt_type > maxtype)
+ maxtype = nxt_type;
+ }
+ n = maxtype/NS_NXT_BITS+1;
+ ShrinkBuffer(n);
+ memcpy(cp, data, n);
+ cp += n;
+ break;
+ }
+ case ns_t_cert:
+ /* type */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* key tag */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* alg */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* cert */
+ if ((n = getword_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ certlen = b64_pton(buf2, buf3, sizeof(buf3));
+ if (certlen < 0)
+ return (-1);
+ ShrinkBuffer(certlen);
+ memcpy(cp, buf3, certlen);
+ cp += certlen;
+ break;
+ case ns_t_aaaa:
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ if (inet_pton(AF_INET6, buf2, &in6a) <= 0)
+ return (-1);
+ ShrinkBuffer(NS_IN6ADDRSZ);
+ memcpy(cp, &in6a, NS_IN6ADDRSZ);
+ cp += NS_IN6ADDRSZ;
break;
default:
return (-1);
@@ -348,14 +680,140 @@ getword_str(char *buf, int size, u_char **startpp, u_char *endp) {
}
/*
- * Get a whitespace delimited number from a string (not file) into buf
+ * get a white spae delimited string from memory. Process quoted strings
+ * and \DDD escapes. Return length or -1 on error. Returned string may
+ * contain nulls.
+ */
+static char digits[] = "0123456789";
+static int
+getstr_str(char *buf, int size, u_char **startpp, u_char *endp) {
+ char *cp;
+ int c, c1 = 0;
+ int inquote = 0;
+ int seen_quote = 0;
+ int escape = 0;
+ int dig = 0;
+
+ for (cp = buf; *startpp <= endp; ) {
+ if ((c = **startpp) == '\0')
+ break;
+ /* leading white space */
+ if ((cp == buf) && !seen_quote && isspace(c)) {
+ (*startpp)++;
+ continue;
+ }
+
+ switch (c) {
+ case '\\':
+ if (!escape) {
+ escape = 1;
+ dig = 0;
+ c1 = 0;
+ (*startpp)++;
+ continue;
+ }
+ goto do_escape;
+ case '"':
+ if (!escape) {
+ inquote = !inquote;
+ seen_quote = 1;
+ (*startpp)++;
+ continue;
+ }
+ /* fall through */
+ default:
+ do_escape:
+ if (escape) {
+ switch (c) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ c1 = c1 * 10 +
+ (strchr(digits, c) - digits);
+
+ if (++dig == 3) {
+ c = c1 &0xff;
+ break;
+ }
+ (*startpp)++;
+ continue;
+ }
+ escape = 0;
+ } else if (!inquote && isspace(c))
+ goto done;
+ if (cp >= buf+size-1)
+ goto done;
+ *cp++ = (u_char)c;
+ (*startpp)++;
+ }
+ }
+ done:
+ *cp = '\0';
+ return ((cp == buf)? (seen_quote? 0: -1): (cp - buf));
+}
+/*
+ * Get a whitespace delimited base 16 number from a string (not file) into buf
+ * update the start pointer to point after the number in the string.
+ */
+static int
+gethexnum_str(u_char **startpp, u_char *endp) {
+ int c, n;
+ int seendigit = 0;
+ int m = 0;
+
+ if (*startpp + 2 >= endp || strncasecmp((char *)*startpp, "0x", 2) != 0)
+ return getnum_str(startpp, endp);
+ (*startpp)+=2;
+ for (n = 0; *startpp <= endp; ) {
+ c = **startpp;
+ if (isspace(c) || c == '\0') {
+ if (seendigit) /* trailing whitespace */
+ break;
+ else { /* leading whitespace */
+ (*startpp)++;
+ continue;
+ }
+ }
+ if (c == ';') {
+ while ((*startpp <= endp) &&
+ ((c = **startpp) != '\n'))
+ (*startpp)++;
+ if (seendigit)
+ break;
+ continue;
+ }
+ if (!isxdigit(c)) {
+ if (c == ')' && seendigit) {
+ (*startpp)--;
+ break;
+ }
+ return (-1);
+ }
+ (*startpp)++;
+ if (isdigit(c))
+ n = n * 16 + (c - '0');
+ else
+ n = n * 16 + (tolower(c) - 'a' + 10);
+ seendigit = 1;
+ }
+ return (n + m);
+}
+
+/*
+ * Get a whitespace delimited base 16 number from a string (not file) into buf
* update the start pointer to point after the number in the string.
*/
static int
getnum_str(u_char **startpp, u_char *endp) {
int c, n;
int seendigit = 0;
- int seendecimal = 0;
int m = 0;
for (n = 0; *startpp <= endp; ) {
@@ -398,8 +856,11 @@ res_mkupdrec(int section, const char *dname,
u_int class, u_int type, u_long ttl) {
ns_updrec *rrecp = (ns_updrec *)calloc(1, sizeof(ns_updrec));
- if (!rrecp || !(rrecp->r_dname = strdup(dname)))
+ if (!rrecp || !(rrecp->r_dname = strdup(dname))) {
+ if (rrecp)
+ free((char *)rrecp);
return (NULL);
+ }
rrecp->r_class = class;
rrecp->r_type = type;
rrecp->r_ttl = ttl;
@@ -417,3 +878,221 @@ res_freeupdrec(ns_updrec *rrecp) {
free(rrecp->r_dname);
free(rrecp);
}
+
+struct valuelist {
+ struct valuelist * next;
+ struct valuelist * prev;
+ char * name;
+ char * proto;
+ int port;
+};
+static struct valuelist *servicelist, *protolist;
+
+void
+res_buildservicelist() {
+ struct servent *sp;
+ struct valuelist *slp;
+
+#ifdef MAYBE_HESIOD
+ setservent(0);
+#else
+ setservent(1);
+#endif
+ while ((sp = getservent()) != NULL) {
+ slp = (struct valuelist *)malloc(sizeof(struct valuelist));
+ if (!slp)
+ break;
+ slp->name = strdup(sp->s_name);
+ slp->proto = strdup(sp->s_proto);
+ if ((slp->name == NULL) || (slp->proto == NULL)) {
+ if (slp->name) free(slp->name);
+ if (slp->proto) free(slp->proto);
+ free(slp);
+ break;
+ }
+ slp->port = ntohs((u_int16_t)sp->s_port); /* host byt order */
+ slp->next = servicelist;
+ slp->prev = NULL;
+ if (servicelist)
+ servicelist->prev = slp;
+ servicelist = slp;
+ }
+ endservent();
+}
+
+void
+res_destroyservicelist() {
+ struct valuelist *slp, *slp_next;
+
+ for (slp = servicelist; slp != NULL; slp = slp_next) {
+ slp_next = slp->next;
+ free(slp->name);
+ free(slp->proto);
+ free(slp);
+ }
+ servicelist = (struct valuelist *)0;
+}
+
+void
+res_buildprotolist() {
+ struct protoent *pp;
+ struct valuelist *slp;
+
+#ifdef MAYBE_HESIOD
+ setprotoent(0);
+#else
+ setprotoent(1);
+#endif
+ while ((pp = getprotoent()) != NULL) {
+ slp = (struct valuelist *)malloc(sizeof(struct valuelist));
+ if (!slp)
+ break;
+ slp->name = strdup(pp->p_name);
+ if (slp->name == NULL) {
+ free(slp);
+ break;
+ }
+ slp->port = pp->p_proto; /* host byte order */
+ slp->next = protolist;
+ slp->prev = NULL;
+ if (protolist)
+ protolist->prev = slp;
+ protolist = slp;
+ }
+ endprotoent();
+}
+
+void
+res_destroyprotolist() {
+ struct valuelist *plp, *plp_next;
+
+ for (plp = protolist; plp != NULL; plp = plp_next) {
+ plp_next = plp->next;
+ free(plp->name);
+ free(plp);
+ }
+ protolist = (struct valuelist *)0;
+}
+
+static int
+findservice(const char *s, struct valuelist **list) {
+ struct valuelist *lp = *list;
+ int n;
+
+ for (; lp != NULL; lp = lp->next)
+ if (strcasecmp(lp->name, s) == 0) {
+ if (lp != *list) {
+ lp->prev->next = lp->next;
+ if (lp->next)
+ lp->next->prev = lp->prev;
+ (*list)->prev = lp;
+ lp->next = *list;
+ *list = lp;
+ }
+ return (lp->port); /* host byte order */
+ }
+ if (sscanf(s, "%d", &n) != 1 || n <= 0)
+ n = -1;
+ return (n);
+}
+
+/*
+ * Convert service name or (ascii) number to int.
+ */
+int
+res_servicenumber(const char *p) {
+ if (servicelist == (struct valuelist *)0)
+ res_buildservicelist();
+ return (findservice(p, &servicelist));
+}
+
+/*
+ * Convert protocol name or (ascii) number to int.
+ */
+int
+res_protocolnumber(const char *p) {
+ if (protolist == (struct valuelist *)0)
+ res_buildprotolist();
+ return (findservice(p, &protolist));
+}
+
+static struct servent *
+cgetservbyport(u_int16_t port, const char *proto) { /* Host byte order. */
+ struct valuelist **list = &servicelist;
+ struct valuelist *lp = *list;
+ static struct servent serv;
+
+ port = ntohs(port);
+ for (; lp != NULL; lp = lp->next) {
+ if (port != (u_int16_t)lp->port) /* Host byte order. */
+ continue;
+ if (strcasecmp(lp->proto, proto) == 0) {
+ if (lp != *list) {
+ lp->prev->next = lp->next;
+ if (lp->next)
+ lp->next->prev = lp->prev;
+ (*list)->prev = lp;
+ lp->next = *list;
+ *list = lp;
+ }
+ serv.s_name = lp->name;
+ serv.s_port = htons((u_int16_t)lp->port);
+ serv.s_proto = lp->proto;
+ return (&serv);
+ }
+ }
+ return (0);
+}
+
+static struct protoent *
+cgetprotobynumber(int proto) { /* Host byte order. */
+ struct valuelist **list = &protolist;
+ struct valuelist *lp = *list;
+ static struct protoent prot;
+
+ for (; lp != NULL; lp = lp->next)
+ if (lp->port == proto) { /* Host byte order. */
+ if (lp != *list) {
+ lp->prev->next = lp->next;
+ if (lp->next)
+ lp->next->prev = lp->prev;
+ (*list)->prev = lp;
+ lp->next = *list;
+ *list = lp;
+ }
+ prot.p_name = lp->name;
+ prot.p_proto = lp->port; /* Host byte order. */
+ return (&prot);
+ }
+ return (0);
+}
+
+const char *
+res_protocolname(int num) {
+ static char number[8];
+ struct protoent *pp;
+
+ if (protolist == (struct valuelist *)0)
+ res_buildprotolist();
+ pp = cgetprotobynumber(num);
+ if (pp == 0) {
+ (void) sprintf(number, "%d", num);
+ return (number);
+ }
+ return (pp->p_name);
+}
+
+const char *
+res_servicename(u_int16_t port, const char *proto) { /* Host byte order. */
+ static char number[8];
+ struct servent *ss;
+
+ if (servicelist == (struct valuelist *)0)
+ res_buildservicelist();
+ ss = cgetservbyport(htons(port), proto);
+ if (ss == 0) {
+ (void) sprintf(number, "%d", port);
+ return (number);
+ }
+ return (ss->s_name);
+}
diff --git a/contrib/bind/lib/resolv/res_mkupdate.h b/contrib/bind/lib/resolv/res_mkupdate.h
index eb2be3f..48edf63 100644
--- a/contrib/bind/lib/resolv/res_mkupdate.h
+++ b/contrib/bind/lib/resolv/res_mkupdate.h
@@ -1,3 +1,20 @@
+/*
+ * 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.
+ */
+
#ifndef _RES_MKUPDATE_H_
#define _RES_MKUPDATE_H_
diff --git a/contrib/bind/lib/resolv/res_query.c b/contrib/bind/lib/resolv/res_query.c
index aeef49d..26c1a60 100644
--- a/contrib/bind/lib/resolv/res_query.c
+++ b/contrib/bind/lib/resolv/res_query.c
@@ -52,7 +52,7 @@
*/
/*
- * Portions Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -69,8 +69,8 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id: res_query.c,v 8.14 1997/06/09 17:47:05 halley Exp $";
+static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_query.c,v 8.19 1999/10/15 19:49:11 vixie Exp $";
#endif /* LIBC_SCCS and not lint */
#include "port_before.h"
@@ -103,16 +103,16 @@ static char rcsid[] = "$Id: res_query.c,v 8.14 1997/06/09 17:47:05 halley Exp $"
* 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.
+ * Error number is left in H_ERRNO.
*
* Caller must parse answer and determine whether it answers the question.
*/
int
-res_query(name, class, type, answer, anslen)
- const char *name; /* domain name */
- int class, type; /* class and type of query */
- u_char *answer; /* buffer to put answer */
- int anslen; /* size of answer buffer */
+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;
@@ -120,56 +120,52 @@ res_query(name, class, type, answer, anslen)
hp->rcode = NOERROR; /* default */
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
- h_errno = NETDB_INTERNAL;
- return (-1);
- }
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
+ if (statp->options & RES_DEBUG)
printf(";; res_query(%s, %d, %d)\n", name, class, type);
#endif
- n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
- buf, sizeof(buf));
+ n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
+ buf, sizeof(buf));
if (n <= 0) {
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
+ if (statp->options & RES_DEBUG)
printf(";; res_query: mkquery failed\n");
#endif
- h_errno = NO_RECOVERY;
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
return (n);
}
- n = res_send(buf, n, answer, anslen);
+ n = res_nsend(statp, buf, n, answer, anslen);
if (n < 0) {
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
+ if (statp->options & RES_DEBUG)
printf(";; res_query: send error\n");
#endif
- h_errno = TRY_AGAIN;
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
return (n);
}
if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
+ if (statp->options & RES_DEBUG)
printf(";; rcode = %d, ancount=%d\n", hp->rcode,
ntohs(hp->ancount));
#endif
switch (hp->rcode) {
case NXDOMAIN:
- h_errno = HOST_NOT_FOUND;
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
break;
case SERVFAIL:
- h_errno = TRY_AGAIN;
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
break;
case NOERROR:
- h_errno = NO_DATA;
+ RES_SET_H_ERRNO(statp, NO_DATA);
break;
case FORMERR:
case NOTIMP:
case REFUSED:
default:
- h_errno = NO_RECOVERY;
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
break;
}
return (-1);
@@ -181,50 +177,43 @@ res_query(name, class, type, answer, anslen)
* 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.
+ * is detected. Error code, if any, is left in H_ERRNO.
*/
int
-res_search(name, class, type, answer, anslen)
- const char *name; /* domain name */
- int class, type; /* class and type of query */
- u_char *answer; /* buffer to put answer */
- int anslen; /* size of answer */
+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, tried_as_is = 0;
+ int trailing_dot, ret;
+ int got_nodata = 0, got_servfail = 0, root_on_list = 0;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
- h_errno = NETDB_INTERNAL;
- return (-1);
- }
errno = 0;
- h_errno = HOST_NOT_FOUND; /* default, if we never query */
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /* True if we never query. */
+
dots = 0;
- for (cp = name; *cp; cp++)
+ 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 = hostalias(name)) != NULL)
- return (res_query(cp, class, type, answer, anslen));
+ if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL)
+ return (res_nquery(statp, cp, class, type, answer, anslen));
/*
- * 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 there are enough dots in the name, do no searching.
+ * (The threshold can be set with the "ndots" option.)
*/
- saved_herrno = -1;
- if (dots >= _res.ndots) {
- ret = res_querydomain(name, NULL, class, type, answer, anslen);
- if (ret > 0)
- return (ret);
- saved_herrno = h_errno;
- tried_as_is++;
- }
+ if (dots >= statp->ndots || trailing_dot)
+ return (res_nquerydomain(statp, name, NULL, class, type,
+ answer, anslen));
/*
* We do at least one level of search if
@@ -232,16 +221,21 @@ res_search(name, class, type, answer, anslen)
* - there is at least one dot, there is no trailing dot,
* and RES_DNSRCH is set.
*/
- if ((!dots && (_res.options & RES_DEFNAMES)) ||
- (dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
+ if ((!dots && (statp->options & RES_DEFNAMES) != 0) ||
+ (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0)) {
int done = 0;
- for (domain = (const char * const *)_res.dnsrch;
+ for (domain = (const char * const *)statp->dnsrch;
*domain && !done;
domain++) {
- ret = res_querydomain(name, *domain, class, type,
- answer, anslen);
+ 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);
@@ -259,11 +253,11 @@ res_search(name, class, type, answer, anslen)
* fully-qualified.
*/
if (errno == ECONNREFUSED) {
- h_errno = TRY_AGAIN;
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
return (-1);
}
- switch (h_errno) {
+ switch (statp->res_h_errno) {
case NO_DATA:
got_nodata++;
/* FALLTHROUGH */
@@ -285,35 +279,33 @@ res_search(name, class, type, answer, anslen)
/* if we got here for some reason other than DNSRCH,
* we only wanted one iteration of the loop, so stop.
*/
- if (!(_res.options & RES_DNSRCH))
+ if ((statp->options & RES_DNSRCH) == 0)
done++;
}
}
/*
- * 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 the name has any dots at all, and "." is not on the search
+ * list, then try an as-is query now.
*/
- if (!tried_as_is) {
- ret = res_querydomain(name, NULL, class, type, answer, anslen);
+ if (statp->ndots) {
+ 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
+ * 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
+ * else send back meaningless H_ERRNO, that being the one from
* the last DNSRCH we did.
*/
- if (saved_herrno != -1)
- h_errno = saved_herrno;
- else if (got_nodata)
- h_errno = NO_DATA;
+ if (got_nodata)
+ RES_SET_H_ERRNO(statp, NO_DATA);
else if (got_servfail)
- h_errno = TRY_AGAIN;
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
return (-1);
}
@@ -322,23 +314,20 @@ res_search(name, class, type, answer, anslen)
* removing a trailing dot from name if domain is NULL.
*/
int
-res_querydomain(name, domain, class, type, answer, anslen)
- const char *name, *domain;
- int class, type; /* class and type of query */
- u_char *answer; /* buffer to put answer */
- int anslen; /* size of answer */
+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;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
- h_errno = NETDB_INTERNAL;
- return (-1);
- }
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
- printf(";; res_querydomain(%s, %s, %d, %d)\n",
+ if (statp->options & RES_DEBUG)
+ printf(";; res_nquerydomain(%s, %s, %d, %d)\n",
name, domain?domain:"<Nil>", class, type);
#endif
if (domain == NULL) {
@@ -348,7 +337,7 @@ res_querydomain(name, domain, class, type, answer, anslen)
*/
n = strlen(name);
if (n >= MAXDNAME) {
- h_errno = NO_RECOVERY;
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
return (-1);
}
n--;
@@ -361,23 +350,21 @@ res_querydomain(name, domain, class, type, answer, anslen)
n = strlen(name);
d = strlen(domain);
if (n + d + 1 >= MAXDNAME) {
- h_errno = NO_RECOVERY;
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
return (-1);
}
sprintf(nbuf, "%s.%s", name, domain);
}
- return (res_query(longname, class, type, answer, anslen));
+ return (res_nquery(statp, longname, class, type, answer, anslen));
}
const char *
-hostalias(const char *name) {
- char *cp1, *cp2;
- FILE *fp;
- char *file;
+res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) {
+ char *file, *cp1, *cp2;
char buf[BUFSIZ];
- static char abuf[MAXDNAME];
+ FILE *fp;
- if (_res.options & RES_NOALIASES)
+ if (statp->options & RES_NOALIASES)
return (NULL);
file = getenv("HOSTALIASES");
if (file == NULL || (fp = fopen(file, "r")) == NULL)
@@ -390,17 +377,18 @@ hostalias(const char *name) {
if (!*cp1)
break;
*cp1 = '\0';
- if (!strcasecmp(buf, name)) {
+ if (ns_samename(buf, name) == 1) {
while (isspace(*++cp1))
;
if (!*cp1)
break;
for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
;
- abuf[sizeof(abuf) - 1] = *cp2 = '\0';
- strncpy(abuf, cp1, sizeof(abuf) - 1);
+ *cp2 = '\0';
+ strncpy(dst, cp1, siz - 1);
+ dst[siz - 1] = '\0';
fclose(fp);
- return (abuf);
+ return (dst);
}
}
fclose(fp);
diff --git a/contrib/bind/lib/resolv/res_send.c b/contrib/bind/lib/resolv/res_send.c
index f8ac77b..80c9e44 100644
--- a/contrib/bind/lib/resolv/res_send.c
+++ b/contrib/bind/lib/resolv/res_send.c
@@ -52,7 +52,7 @@
*/
/*
- * Portions Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -69,8 +69,8 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id: res_send.c,v 8.20 1998/04/06 23:27:51 halley Exp $";
+static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_send.c,v 8.36 1999/10/15 19:49:11 vixie Exp $";
#endif /* LIBC_SCCS and not lint */
/*
@@ -93,78 +93,60 @@ static char rcsid[] = "$Id: res_send.c,v 8.20 1998/04/06 23:27:51 halley Exp $";
#include <errno.h>
#include <netdb.h>
#include <resolv.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <isc/eventlib.h>
+
#include "port_after.h"
/* Options. Leave them on. */
#define DEBUG
-#define CHECK_SRVR_ADDR
-
-static int s = -1; /* socket used for communications */
-static int connected = 0; /* is the socket connected */
-static int vc = 0; /* is the socket a virtual circuit? */
-static res_send_qhook Qhook = NULL;
-static res_send_rhook Rhook = NULL;
+#include "res_debug.h"
+#ifdef NEED_PSELECT
+static int pselect(int, void *, void *, void *,
+ struct timespec *,
+ const sigset_t *);
+#endif
-#ifndef DEBUG
-# define Dprint(cond, args) /*empty*/
-# define DprintQ(cond, args, query, size) /*empty*/
-# define Aerror(file, string, error, address) /*empty*/
-# define Perror(file, string, error) /*empty*/
-#else
-# define Dprint(cond, args) if (cond) {fprintf args;} else {}
-# define DprintQ(cond, args, query, size) if (cond) {\
- fprintf args;\
- __fp_nquery(query, size, stdout);\
- } else {}
+#define CHECK_SRVR_ADDR
+
+#ifdef DEBUG
static void
- Aerror(file, string, error, address)
- FILE *file;
- char *string;
- int error;
- struct sockaddr_in address;
+ Aerror(const res_state statp, FILE *file, const char *string, int error,
+ struct sockaddr_in address)
{
int save = errno;
- if (_res.options & RES_DEBUG) {
+ if ((statp->options & RES_DEBUG) != 0) {
+ char tmp[sizeof "255.255.255.255"];
+
fprintf(file, "res_send: %s ([%s].%u): %s\n",
string,
- inet_ntoa(address.sin_addr),
+ inet_ntop(address.sin_family, &address.sin_addr,
+ tmp, sizeof tmp),
ntohs(address.sin_port),
strerror(error));
}
errno = save;
}
static void
- Perror(file, string, error)
- FILE *file;
- char *string;
- int error;
- {
+ Perror(const res_state statp, FILE *file, const char *string, int error) {
int save = errno;
- if (_res.options & RES_DEBUG) {
+ if ((statp->options & RES_DEBUG) != 0)
fprintf(file, "res_send: %s: %s\n",
string, strerror(error));
- }
errno = save;
}
#endif
-void
-res_send_setqhook(res_send_qhook hook) {
- Qhook = hook;
-}
-
-void
-res_send_setrhook(res_send_rhook hook) {
- Rhook = hook;
-}
+static int cmpsock(struct sockaddr_in *a1, struct sockaddr_in *a2);
+void res_pquery(const res_state, const u_char *, int, FILE *);
/* int
* res_isourserver(ina)
@@ -176,24 +158,21 @@ res_send_setrhook(res_send_rhook hook) {
* paul vixie, 29may94
*/
int
-res_isourserver(const struct sockaddr_in *inp) {
+res_ourserver_p(const res_state statp, const struct sockaddr_in *inp) {
struct sockaddr_in ina;
- int ns, ret;
+ int ns;
ina = *inp;
- ret = 0;
- for (ns = 0; ns < _res.nscount; ns++) {
- const struct sockaddr_in *srv = &_res.nsaddr_list[ns];
+ 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)) {
- ret++;
- break;
- }
+ srv->sin_addr.s_addr == ina.sin_addr.s_addr))
+ return (1);
}
- return (ret);
+ return (0);
}
/* int
@@ -227,9 +206,8 @@ res_nameinquery(const char *name, int type, int class,
return (-1);
ttype = ns_get16(cp); cp += INT16SZ;
tclass = ns_get16(cp); cp += INT16SZ;
- if (ttype == type &&
- tclass == class &&
- strcasecmp(tname, name) == 0)
+ if (ttype == type && tclass == class &&
+ ns_samename(tname, name) == 1)
return (1);
}
return (0);
@@ -285,54 +263,66 @@ res_queriesmatch(const u_char *buf1, const u_char *eom1,
}
int
-res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
+res_nsend(res_state statp,
+ const u_char *buf, int buflen, u_char *ans, int anssiz)
+{
HEADER *hp = (HEADER *) buf;
HEADER *anhp = (HEADER *) ans;
int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns, n;
u_int badns; /* XXX NSMAX can't exceed #/bits in this variable */
+ static int highestFD = FD_SETSIZE - 1;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
- /* errno should have been set by res_init() in this case. */
- return (-1);
- }
if (anssiz < HFIXEDSZ) {
errno = EINVAL;
return (-1);
}
- DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY),
+ DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
(stdout, ";; res_send()\n"), buf, buflen);
- v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
+ v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
gotsomewhere = 0;
connreset = 0;
terrno = ETIMEDOUT;
badns = 0;
/*
+ * Some callers want to even out the load on their resolver list.
+ */
+ if (statp->nscount > 0 && (statp->options & RES_ROTATE) != 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 < _res.retry; try++) {
- for (ns = 0; ns < _res.nscount; ns++) {
- struct sockaddr_in *nsap = &_res.nsaddr_list[ns];
+ 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 (badns & (1 << ns)) {
- res_close();
+ res_nclose(statp);
goto next_ns;
}
- if (Qhook) {
+ if (statp->qhook) {
int done = 0, loops = 0;
do {
res_sendhookact act;
- act = (*Qhook)(&nsap, &buf, &buflen,
- ans, anssiz, &resplen);
+ act = (*statp->qhook)(&nsap, &buf, &buflen,
+ ans, anssiz, &resplen);
switch (act) {
case res_goahead:
done = 1;
break;
case res_nextns:
- res_close();
+ res_nclose(statp);
goto next_ns;
case res_done:
return (resplen);
@@ -349,7 +339,7 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
} while (!done);
}
- Dprint(_res.options & RES_DEBUG,
+ Dprint(statp->options & RES_DEBUG,
(stdout, ";; Querying server (# %d) address = %s\n",
ns + 1, inet_ntoa(nsap->sin_addr)));
@@ -359,33 +349,53 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
u_short len;
u_char *cp;
- /*
- * Use virtual circuit;
- * at most one attempt per server.
- */
- try = _res.retry;
+ /* Use VC; at most one attempt per server. */
+ try = statp->retry;
truncated = 0;
- if (s < 0 || !vc || hp->opcode == ns_o_update) {
- if (s >= 0)
- res_close();
- s = socket(PF_INET, SOCK_STREAM, 0);
- if (s < 0) {
+ /* Are we still talking to whom we want to talk to? */
+ if (statp->_sock >= 0 &&
+ (statp->_flags & RES_F_VC) != 0) {
+ struct sockaddr_in peer;
+ int size = sizeof(peer);
+
+ if (getpeername(statp->_sock,
+ (struct sockaddr *)&peer,
+ &size) < 0) {
+ res_nclose(statp);
+ statp->_flags &= ~RES_F_VC;
+ } else if (!cmpsock(&peer, nsap)) {
+ res_nclose(statp);
+ statp->_flags &= ~RES_F_VC;
+ }
+ }
+
+ if (statp->_sock < 0 ||
+ (statp->_flags & RES_F_VC) == 0) {
+ if (statp->_sock >= 0)
+ res_nclose(statp);
+
+ statp->_sock = socket(PF_INET,
+ SOCK_STREAM, 0);
+ if (statp->_sock < 0 ||
+ statp->_sock > highestFD) {
terrno = errno;
- Perror(stderr, "socket(vc)", errno);
+ Perror(statp, stderr,
+ "socket(vc)", errno);
return (-1);
}
errno = 0;
- if (connect(s, (struct sockaddr *)nsap,
+ if (connect(statp->_sock,
+ (struct sockaddr *)nsap,
sizeof *nsap) < 0) {
terrno = errno;
- Aerror(stderr, "connect/vc",
+ Aerror(statp, stderr, "connect/vc",
errno, *nsap);
badns |= (1 << ns);
- res_close();
+ res_nclose(statp);
goto next_ns;
}
- vc = 1;
+ statp->_flags |= RES_F_VC;
}
/*
* Send length & message
@@ -395,11 +405,12 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
iov[0].iov_len = INT16SZ;
iov[1].iov_base = (caddr_t)buf;
iov[1].iov_len = buflen;
- if (writev(s, iov, 2) != (INT16SZ + buflen)) {
+ if (writev(statp->_sock, iov, 2) !=
+ (INT16SZ + buflen)) {
terrno = errno;
- Perror(stderr, "write failed", errno);
+ Perror(statp, stderr, "write failed", errno);
badns |= (1 << ns);
- res_close();
+ res_nclose(statp);
goto next_ns;
}
/*
@@ -408,15 +419,16 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
read_len:
cp = ans;
len = INT16SZ;
- while ((n = read(s, (char *)cp, (int)len)) > 0) {
+ while ((n = read(statp->_sock,
+ (char *)cp, (int)len)) > 0) {
cp += n;
if ((len -= n) <= 0)
break;
}
if (n <= 0) {
terrno = errno;
- Perror(stderr, "read failed", errno);
- res_close();
+ Perror(statp, stderr, "read failed", errno);
+ res_nclose(statp);
/*
* A long running process might get its TCP
* connection reset if the remote server was
@@ -428,15 +440,15 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
*/
if (terrno == ECONNRESET && !connreset) {
connreset = 1;
- res_close();
+ res_nclose(statp);
goto same_ns;
}
- res_close();
+ res_nclose(statp);
goto next_ns;
}
resplen = ns_get16(ans);
if (resplen > anssiz) {
- Dprint(_res.options & RES_DEBUG,
+ Dprint(statp->options & RES_DEBUG,
(stdout, ";; response truncated\n")
);
truncated = 1;
@@ -447,23 +459,24 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
/*
* Undersized message.
*/
- Dprint(_res.options & RES_DEBUG,
+ Dprint(statp->options & RES_DEBUG,
(stdout, ";; undersized: %d\n", len));
terrno = EMSGSIZE;
badns |= (1 << ns);
- res_close();
+ res_nclose(statp);
goto next_ns;
}
cp = ans;
while (len != 0 &&
- (n = read(s, (char *)cp, (int)len)) > 0) {
+ (n = read(statp->_sock, (char *)cp, (int)len))
+ > 0) {
cp += n;
len -= n;
}
if (n <= 0) {
terrno = errno;
- Perror(stderr, "read(vc)", errno);
- res_close();
+ Perror(statp, stderr, "read(vc)", errno);
+ res_nclose(statp);
goto next_ns;
}
if (truncated) {
@@ -479,7 +492,8 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
n = (len > sizeof(junk)
? sizeof(junk)
: len);
- if ((n = read(s, junk, n)) > 0)
+ n = read(statp->_sock, junk, n);
+ if (n > 0)
len -= n;
else
break;
@@ -493,8 +507,8 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
* wait for the correct one.
*/
if (hp->id != anhp->id) {
- DprintQ((_res.options & RES_DEBUG) ||
- (_res.pfcode & RES_PRF_REPLY),
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
(stdout, ";; old answer (unexpected):\n"),
ans, (resplen>anssiz)?anssiz:resplen);
goto read_len;
@@ -503,24 +517,27 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
/*
* Use datagrams.
*/
- struct timeval timeout;
+ struct timespec start, timeout, finish;
fd_set dsmask;
struct sockaddr_in from;
- int fromlen;
-
- if ((s < 0) || vc) {
- if (vc)
- res_close();
- s = socket(PF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
+ int fromlen, seconds;
+
+ if (statp->_sock < 0 ||
+ (statp->_flags & RES_F_VC) != 0) {
+ if ((statp->_flags & RES_F_VC) != 0)
+ res_nclose(statp);
+ statp->_sock = socket(PF_INET, SOCK_DGRAM, 0);
+ if (statp->_sock < 0 ||
+ statp->_sock > highestFD) {
#ifndef CAN_RECONNECT
bad_dg_sock:
#endif
terrno = errno;
- Perror(stderr, "socket(dg)", errno);
+ Perror(statp, stderr,
+ "socket(dg)", errno);
return (-1);
}
- connected = 0;
+ statp->_flags &= ~RES_F_CONN;
}
#ifndef CANNOT_CONNECT_DGRAM
/*
@@ -538,28 +555,29 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
* as we wish to receive answers from the first
* server to respond.
*/
- if (_res.nscount == 1 || (try == 0 && ns == 0)) {
+ if (statp->nscount == 1 || (try == 0 && ns == 0)) {
/*
* Connect only if we are sure we won't
* receive a response from another server.
*/
- if (!connected) {
- if (connect(s, (struct sockaddr *)nsap,
- sizeof *nsap
- ) < 0) {
- Aerror(stderr,
+ if ((statp->_flags & RES_F_CONN) == 0) {
+ if (connect(statp->_sock,
+ (struct sockaddr *)nsap,
+ sizeof *nsap) < 0) {
+ Aerror(statp, stderr,
"connect(dg)",
errno, *nsap);
badns |= (1 << ns);
- res_close();
+ res_nclose(statp);
goto next_ns;
}
- connected = 1;
+ statp->_flags |= RES_F_CONN;
}
- if (send(s, (char*)buf, buflen, 0) != buflen) {
- Perror(stderr, "send", errno);
+ if (send(statp->_sock, (char*)buf, buflen, 0)
+ != buflen) {
+ Perror(statp, stderr, "send", errno);
badns |= (1 << ns);
- res_close();
+ res_nclose(statp);
goto next_ns;
}
} else {
@@ -567,86 +585,115 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
* Disconnect if we want to listen
* for responses from more than one server.
*/
- if (connected) {
+ if ((statp->_flags & RES_F_CONN) != 0) {
#ifdef CAN_RECONNECT
struct sockaddr_in no_addr;
no_addr.sin_family = AF_INET;
no_addr.sin_addr.s_addr = INADDR_ANY;
no_addr.sin_port = 0;
- (void) connect(s,
+ (void) connect(statp->_sock,
(struct sockaddr *)
&no_addr,
sizeof no_addr);
#else
- int s1 = socket(PF_INET, SOCK_DGRAM,0);
+ struct sockaddr_in local_addr;
+ int len, result, s1;
+
+ len = sizeof(local_addr);
+ s1 = socket(PF_INET, SOCK_DGRAM, 0);
+ result = getsockname(statp->_sock,
+ (struct sockaddr *)&local_addr,
+ &len);
if (s1 < 0)
goto bad_dg_sock;
- (void) dup2(s1, s);
+ (void) dup2(s1, statp->_sock);
(void) close(s1);
- Dprint(_res.options & RES_DEBUG,
+ if (result == 0) {
+ /*
+ * Attempt to rebind to old
+ * port. Note connected socket
+ * has an sin_addr set.
+ */
+ local_addr.sin_addr.s_addr =
+ htonl(0);
+ (void)bind(statp->_sock,
+ (struct sockaddr *)
+ &local_addr, len);
+ }
+ Dprint(statp->options & RES_DEBUG,
(stdout, ";; new DG socket\n"))
#endif /* CAN_RECONNECT */
- connected = 0;
+ statp->_flags &= ~RES_F_CONN;
errno = 0;
}
#endif /* !CANNOT_CONNECT_DGRAM */
- if (sendto(s, (char*)buf, buflen, 0,
+ if (sendto(statp->_sock,
+ (char*)buf, buflen, 0,
(struct sockaddr *)nsap,
sizeof *nsap)
!= buflen) {
- Aerror(stderr, "sendto", errno, *nsap);
+ Aerror(statp, stderr, "sendto", errno, *nsap);
badns |= (1 << ns);
- res_close();
+ res_nclose(statp);
goto next_ns;
}
#ifndef CANNOT_CONNECT_DGRAM
}
#endif /* !CANNOT_CONNECT_DGRAM */
+ if (statp->_sock < 0 || statp->_sock > highestFD) {
+ Perror(statp, stderr,
+ "fd out-of-bounds", EMFILE);
+ res_nclose(statp);
+ goto next_ns;
+ }
+
/*
* Wait for reply
*/
- timeout.tv_sec = (_res.retrans << try);
+ seconds = (statp->retrans << try);
if (try > 0)
- timeout.tv_sec /= _res.nscount;
- if ((long) timeout.tv_sec <= 0)
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
+ seconds /= statp->nscount;
+ if (seconds <= 0)
+ seconds = 1;
+ start = evNowTime();
+ timeout = evConsTime(seconds, 0);
+ finish = evAddTime(start, timeout);
wait:
- if (s < 0 || s >= FD_SETSIZE) {
- Perror(stderr, "s out-of-bounds", EMFILE);
- res_close();
- goto next_ns;
- }
FD_ZERO(&dsmask);
- FD_SET(s, &dsmask);
- n = select(s+1, &dsmask, (fd_set *)NULL,
- (fd_set *)NULL, &timeout);
- if (n < 0) {
- if (errno == EINTR)
- goto wait;
- Perror(stderr, "select", errno);
- res_close();
- goto next_ns;
- }
+ FD_SET(statp->_sock, &dsmask);
+ n = pselect(statp->_sock + 1,
+ &dsmask, NULL, NULL,
+ &timeout, NULL);
if (n == 0) {
- /*
- * timeout
- */
- Dprint(_res.options & RES_DEBUG,
+ Dprint(statp->options & RES_DEBUG,
(stdout, ";; timeout\n"));
gotsomewhere = 1;
- res_close();
+ goto next_ns;
+ }
+ if (n < 0) {
+ if (errno == EINTR) {
+ struct timespec now;
+
+ now = evNowTime();
+ if (evCmpTime(finish, now) >= 0) {
+ timeout = evSubTime(finish,
+ now);
+ goto wait;
+ }
+ }
+ Perror(statp, stderr, "select", errno);
+ res_nclose(statp);
goto next_ns;
}
errno = 0;
fromlen = sizeof(struct sockaddr_in);
- resplen = recvfrom(s, (char*)ans, anssiz, 0,
+ resplen = recvfrom(statp->_sock, (char*)ans, anssiz,0,
(struct sockaddr *)&from, &fromlen);
if (resplen <= 0) {
- Perror(stderr, "recvfrom", errno);
- res_close();
+ Perror(statp, stderr, "recvfrom", errno);
+ res_nclose(statp);
goto next_ns;
}
gotsomewhere = 1;
@@ -654,12 +701,12 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
/*
* Undersized message.
*/
- Dprint(_res.options & RES_DEBUG,
+ Dprint(statp->options & RES_DEBUG,
(stdout, ";; undersized: %d\n",
resplen));
terrno = EMSGSIZE;
badns |= (1 << ns);
- res_close();
+ res_nclose(statp);
goto next_ns;
}
if (hp->id != anhp->id) {
@@ -668,28 +715,28 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
* XXX - potential security hazard could
* be detected here.
*/
- DprintQ((_res.options & RES_DEBUG) ||
- (_res.pfcode & RES_PRF_REPLY),
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
(stdout, ";; old answer:\n"),
ans, (resplen>anssiz)?anssiz:resplen);
goto wait;
}
#ifdef CHECK_SRVR_ADDR
- if (!(_res.options & RES_INSECURE1) &&
- !res_isourserver(&from)) {
+ 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((_res.options & RES_DEBUG) ||
- (_res.pfcode & RES_PRF_REPLY),
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
(stdout, ";; not our server:\n"),
ans, (resplen>anssiz)?anssiz:resplen);
goto wait;
}
#endif
- if (!(_res.options & RES_INSECURE2) &&
+ if (!(statp->options & RES_INSECURE2) &&
!res_queriesmatch(buf, buf + buflen,
ans, ans + anssiz)) {
/*
@@ -697,8 +744,8 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
* XXX - potential security hazard could
* be detected here.
*/
- DprintQ((_res.options & RES_DEBUG) ||
- (_res.pfcode & RES_PRF_REPLY),
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
(stdout, ";; wrong query name:\n"),
ans, (resplen>anssiz)?anssiz:resplen);
goto wait;
@@ -706,33 +753,33 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
if (anhp->rcode == SERVFAIL ||
anhp->rcode == NOTIMP ||
anhp->rcode == REFUSED) {
- DprintQ(_res.options & RES_DEBUG,
+ DprintQ(statp->options & RES_DEBUG,
(stdout, "server rejected query:\n"),
ans, (resplen>anssiz)?anssiz:resplen);
badns |= (1 << ns);
- res_close();
+ res_nclose(statp);
/* don't retry if called from dig */
- if (!_res.pfcode)
+ if (!statp->pfcode)
goto next_ns;
}
- if (!(_res.options & RES_IGNTC) && anhp->tc) {
+ if (!(statp->options & RES_IGNTC) && anhp->tc) {
/*
* get rest of answer;
* use TCP with same server.
*/
- Dprint(_res.options & RES_DEBUG,
+ Dprint(statp->options & RES_DEBUG,
(stdout, ";; truncated answer\n"));
v_circuit = 1;
- res_close();
+ res_nclose(statp);
goto same_ns;
}
} /*if vc/dg*/
- Dprint((_res.options & RES_DEBUG) ||
- ((_res.pfcode & RES_PRF_REPLY) &&
- (_res.pfcode & RES_PRF_HEAD1)),
+ Dprint((statp->options & RES_DEBUG) ||
+ ((statp->pfcode & RES_PRF_REPLY) &&
+ (statp->pfcode & RES_PRF_HEAD1)),
(stdout, ";; got answer:\n"));
- DprintQ((_res.options & RES_DEBUG) ||
- (_res.pfcode & RES_PRF_REPLY),
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
(stdout, ""),
ans, (resplen>anssiz)?anssiz:resplen);
/*
@@ -743,25 +790,25 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
* or if we haven't been asked to keep a socket open,
* close the socket.
*/
- if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) ||
- !(_res.options & RES_STAYOPEN)) {
- res_close();
+ if ((v_circuit && (!(statp->options & RES_USEVC) || ns != 0)) ||
+ !(statp->options & RES_STAYOPEN)) {
+ res_nclose(statp);
}
- if (Rhook) {
+ if (statp->rhook) {
int done = 0, loops = 0;
do {
res_sendhookact act;
- act = (*Rhook)(nsap, buf, buflen,
- ans, anssiz, &resplen);
+ act = (*statp->rhook)(nsap, buf, buflen,
+ ans, anssiz, &resplen);
switch (act) {
case res_goahead:
case res_done:
done = 1;
break;
case res_nextns:
- res_close();
+ res_nclose(statp);
goto next_ns;
case res_modified:
/* give the hook another try */
@@ -780,7 +827,7 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
next_ns: ;
} /*foreach ns*/
} /*foreach retry*/
- res_close();
+ res_nclose(statp);
if (!v_circuit) {
if (!gotsomewhere)
errno = ECONNREFUSED; /* no nameservers found */
@@ -799,11 +846,45 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
* This routine is not expected to be user visible.
*/
void
-res_close() {
- if (s >= 0) {
- (void) close(s);
- s = -1;
- connected = 0;
- vc = 0;
+res_nclose(res_state statp) {
+ if (statp->_sock >= 0) {
+ (void) close(statp->_sock);
+ statp->_sock = -1;
+ statp->_flags &= ~(RES_F_VC | RES_F_CONN);
}
}
+
+/* Private */
+static int
+cmpsock(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
diff --git a/contrib/bind/lib/resolv/res_sendsigned.c b/contrib/bind/lib/resolv/res_sendsigned.c
new file mode 100644
index 0000000..efa463c
--- /dev/null
+++ b/contrib/bind/lib/resolv/res_sendsigned.c
@@ -0,0 +1,130 @@
+#include "port_before.h"
+#include "fd_setsize.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <isc/dst.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "port_after.h"
+
+#define DEBUG
+#include "res_debug.h"
+
+
+/* res_nsendsigned */
+int
+res_nsendsigned(res_state statp, const u_char *msg, int msglen,
+ ns_tsig_key *key, u_char *answer, int anslen)
+{
+ res_state nstatp;
+ DST_KEY *dstkey;
+ int usingTCP = 0;
+ u_char *newmsg;
+ int newmsglen, bufsize, siglen;
+ u_char sig[64];
+ HEADER *hp;
+ time_t tsig_time;
+ int ret;
+
+ dst_init();
+
+ nstatp = (res_state) malloc(sizeof(*statp));
+ if (nstatp == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ memcpy(nstatp, statp, sizeof(*statp));
+
+ bufsize = msglen + 1024;
+ newmsg = (u_char *) malloc(bufsize);
+ if (newmsg == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ memcpy(newmsg, msg, msglen);
+ newmsglen = msglen;
+
+ if (ns_samename(key->alg, NS_TSIG_ALG_HMAC_MD5) != 1)
+ dstkey = NULL;
+ else
+ dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5,
+ NS_KEY_TYPE_AUTH_ONLY,
+ NS_KEY_PROT_ANY,
+ key->data, key->len);
+ if (dstkey == NULL) {
+ errno = EINVAL;
+ free(nstatp);
+ free(newmsg);
+ return (-1);
+ }
+
+ nstatp->nscount = 1;
+ siglen = sizeof(sig);
+ ret = ns_sign(newmsg, &newmsglen, bufsize, NOERROR, dstkey, NULL, 0,
+ sig, &siglen, 0);
+ if (ret < 0) {
+ free (nstatp);
+ free (newmsg);
+ if (ret == NS_TSIG_ERROR_NO_SPACE)
+ errno = EMSGSIZE;
+ else if (ret == -1)
+ errno = EINVAL;
+ return (ret);
+ }
+
+ if (newmsglen > PACKETSZ || (nstatp->options & RES_IGNTC))
+ usingTCP = 1;
+ if (usingTCP == 0)
+ nstatp->options |= RES_IGNTC;
+ else
+ nstatp->options |= RES_USEVC;
+
+retry:
+
+ ret = res_nsend(nstatp, newmsg, newmsglen, answer, anslen);
+ if (ret < 0) {
+ free (nstatp);
+ free (newmsg);
+ return (ret);
+ }
+
+ anslen = ret;
+ ret = ns_verify(answer, &anslen, dstkey, sig, siglen,
+ NULL, NULL, &tsig_time, nstatp->options & RES_KEEPTSIG);
+ if (ret != 0) {
+ Dprint(nstatp->pfcode & RES_PRF_REPLY,
+ (stdout, ";; TSIG invalid (%s)\n", p_rcode(ret)));
+ free (nstatp);
+ free (newmsg);
+ if (ret == -1)
+ errno = EINVAL;
+ else
+ errno = ENOTTY;
+ return (-1);
+ }
+ Dprint(nstatp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG ok\n"));
+
+ hp = (HEADER *) answer;
+ if (hp->tc && usingTCP == 0) {
+ nstatp->options &= ~RES_IGNTC;
+ usingTCP = 1;
+ goto retry;
+ }
+
+ free (nstatp);
+ free (newmsg);
+ return (anslen);
+}
diff --git a/contrib/bind/lib/resolv/res_update.c b/contrib/bind/lib/resolv/res_update.c
index 8e6c448..bb2456e 100644
--- a/contrib/bind/lib/resolv/res_update.c
+++ b/contrib/bind/lib/resolv/res_update.c
@@ -1,9 +1,9 @@
#if !defined(lint) && !defined(SABER)
-static char rcsid[] = "$Id: res_update.c,v 1.14 1998/03/10 22:04:48 halley Exp $";
+static const char rcsid[] = "$Id: res_update.c,v 1.24 1999/10/15 19:49:12 vixie Exp $";
#endif /* not lint */
/*
- * Copyright (c) 1996 by Internet Software Consortium.
+ * 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
@@ -25,19 +25,27 @@ static char rcsid[] = "$Id: res_update.c,v 1.14 1998/03/10 22:04:48 halley Exp $
*/
#include "port_before.h"
+
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/time.h>
+
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
+
#include <errno.h>
#include <limits.h>
#include <netdb.h>
#include <resolv.h>
+#include <res_update.h>
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+
+#include <isc/list.h>
+
#include "port_after.h"
/*
@@ -54,465 +62,166 @@ static char rcsid[] = "$Id: res_update.c,v 1.14 1998/03/10 22:04:48 halley Exp $
* was encountered while updating the reverse zone.
*/
-#define NSMAX 16
-
-struct ns1 {
- char nsname[MAXDNAME];
- struct in_addr nsaddr1;
-};
-
struct zonegrp {
- char z_origin[MAXDNAME];
- int16_t z_class;
- char z_soardata[MAXDNAME + 5 * INT32SZ];
- struct ns1 z_ns[NSMAX];
- int z_nscount;
- ns_updrec * z_rr;
- struct zonegrp *z_next;
+ char z_origin[MAXDNAME];
+ ns_class z_class;
+ struct in_addr z_nsaddrs[MAXNS];
+ int z_nscount;
+ int z_flags;
+ LIST(ns_updrec) z_rrlist;
+ LINK(struct zonegrp) z_link;
};
+#define ZG_F_ZONESECTADDED 0x0001
-int
-res_update(ns_updrec *rrecp_in) {
- ns_updrec *rrecp, *tmprrecp;
- u_char buf[PACKETSZ], answer[PACKETSZ], packet[2*PACKETSZ];
- char name[MAXDNAME], zname[MAXDNAME], primary[MAXDNAME],
- mailaddr[MAXDNAME];
- u_char soardata[2*MAXCDNAME+5*INT32SZ];
- char *dname, *svdname, *cp1, *target;
- u_char *cp, *eom;
- HEADER *hp = (HEADER *) answer;
- struct zonegrp *zptr = NULL, *tmpzptr, *prevzptr, *zgrp_start = NULL;
- int i, j, k = 0, n, ancount, nscount, arcount, rcode, rdatasize,
- newgroup, done, myzone, seen_before, numzones = 0;
- u_int16_t dlen, class, qclass, type, qtype;
- u_int32_t ttl;
+/* Forward. */
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
- h_errno = NETDB_INTERNAL;
- return (-1);
- }
+static int nscopy(struct sockaddr_in *, const struct sockaddr_in *, int);
+static int nsprom(struct sockaddr_in *, const struct in_addr *, int);
+static void dprintf(const char *, ...);
- for (rrecp = rrecp_in; rrecp; rrecp = rrecp->r_next) {
- dname = rrecp->r_dname;
- n = strlen(dname);
- if (dname[n-1] == '.')
- dname[n-1] = '\0';
- qtype = T_SOA;
- qclass = rrecp->r_class;
- done = 0;
- seen_before = 0;
+/* Macros. */
- while (!done && dname) {
- if (qtype == T_SOA) {
- for (tmpzptr = zgrp_start;
- tmpzptr && !seen_before;
- tmpzptr = tmpzptr->z_next) {
- if (strcasecmp(dname,
- tmpzptr->z_origin) == 0 &&
- tmpzptr->z_class == qclass)
- seen_before++;
- for (tmprrecp = tmpzptr->z_rr;
- tmprrecp && !seen_before;
- tmprrecp = tmprrecp->r_grpnext)
- if (strcasecmp(dname, tmprrecp->r_dname) == 0
- && tmprrecp->r_class == qclass) {
- seen_before++;
- break;
- }
- if (seen_before) {
- /*
- * Append to the end of
- * current group.
- */
- for (tmprrecp = tmpzptr->z_rr;
- tmprrecp->r_grpnext;
- tmprrecp = tmprrecp->r_grpnext)
- (void)NULL;
- tmprrecp->r_grpnext = rrecp;
- rrecp->r_grpnext = NULL;
- done = 1;
- break;
- }
- }
- } else if (qtype == T_A) {
- for (tmpzptr = zgrp_start;
- tmpzptr && !done;
- tmpzptr = tmpzptr->z_next)
- for (i = 0; i < tmpzptr->z_nscount; i++)
- if (tmpzptr->z_class == qclass &&
- strcasecmp(tmpzptr->z_ns[i].nsname,
- dname) == 0 &&
- tmpzptr->z_ns[i].nsaddr1.s_addr != 0) {
- zptr->z_ns[k].nsaddr1.s_addr =
- tmpzptr->z_ns[i].nsaddr1.s_addr;
- done = 1;
- break;
- }
- }
- if (done)
- break;
- n = res_mkquery(QUERY, dname, qclass, qtype, NULL,
- 0, NULL, buf, sizeof buf);
- if (n <= 0) {
- fprintf(stderr, "res_update: mkquery failed\n");
- return (n);
- }
- n = res_send(buf, n, answer, sizeof answer);
- if (n < 0) {
- fprintf(stderr, "res_update: send error for %s\n",
- rrecp->r_dname);
- return (n);
- }
- if (n < HFIXEDSZ)
- return (-1);
- ancount = ntohs(hp->ancount);
- nscount = ntohs(hp->nscount);
- arcount = ntohs(hp->arcount);
- rcode = hp->rcode;
- cp = answer + HFIXEDSZ;
- eom = answer + n;
- /* skip the question section */
- n = dn_skipname(cp, eom);
- if (n < 0 || cp + n + 2 * INT16SZ > eom)
- return (-1);
- cp += n + 2 * INT16SZ;
+#define DPRINTF(x) do {\
+ int save_errno = errno; \
+ if ((statp->options & RES_DEBUG) != 0) dprintf x; \
+ errno = save_errno; \
+ } while (0)
- if (qtype == T_SOA) {
- if (ancount == 0 && nscount == 0 && arcount == 0) {
- /*
- * if (rcode == NOERROR) then the dname exists but
- * has no soa record associated with it.
- * if (rcode == NXDOMAIN) then the dname does not
- * exist and the server is replying out of NCACHE.
- * in either case, proceed with the next try
- */
- dname = strchr(dname, '.');
- if (dname != NULL)
- dname++;
- continue;
- } else if ((rcode == NOERROR || rcode == NXDOMAIN) &&
- ancount == 0 &&
- nscount == 1 && arcount == 0) {
- /*
- * name/data does not exist, soa record supplied in the
- * authority section
- */
- /* authority section must contain the soa record */
- if ((n = dn_expand(answer, eom, cp, zname,
- sizeof zname)) < 0)
- return (n);
- cp += n;
- if (cp + 2 * INT16SZ > eom)
- return (-1);
- GETSHORT(type, cp);
- GETSHORT(class, cp);
- if (type != T_SOA || class != qclass) {
- fprintf(stderr, "unknown answer\n");
- return (-1);
- }
- myzone = 0;
- svdname = dname;
- while (dname)
- if (strcasecmp(dname, zname) == 0) {
- myzone = 1;
- break;
- } else if ((dname = strchr(dname, '.')) != NULL)
- dname++;
- if (!myzone) {
- dname = strchr(svdname, '.');
- if (dname != NULL)
- dname++;
- continue;
- }
- nscount = 0;
- /* fallthrough */
- } else if (rcode == NOERROR && ancount == 1) {
- /*
- * found the zone name
- * new servers will supply NS records for the zone
- * in authority section and A records for those
- * nameservers in the additional section
- * older servers have to be explicitly queried for
- * NS records for the zone
- */
- /* answer section must contain the soa record */
- if ((n = dn_expand(answer, eom, cp, zname,
- sizeof zname)) < 0)
- return (n);
- else
- cp += n;
- if (cp + 2 * INT16SZ > eom)
- return (-1);
- GETSHORT(type, cp);
- GETSHORT(class, cp);
- if (type == T_CNAME) {
- dname = strchr(dname, '.');
- if (dname != NULL)
- dname++;
- continue;
- }
- if (strcasecmp(dname, zname) != 0 ||
- type != T_SOA ||
- class != rrecp->r_class) {
- fprintf(stderr, "unknown answer\n");
- return (-1);
- }
- /* FALLTHROUGH */
- } else {
- fprintf(stderr,
- "unknown response: ans=%d, auth=%d, add=%d, rcode=%d\n",
- ancount, nscount, arcount, hp->rcode);
- return (-1);
- }
- if (cp + INT32SZ + INT16SZ > eom)
- return (-1);
- /* continue processing the soa record */
- GETLONG(ttl, cp);
- GETSHORT(dlen, cp);
- if (cp + dlen > eom)
- return (-1);
- newgroup = 1;
- zptr = zgrp_start;
- prevzptr = NULL;
- while (zptr) {
- if (strcasecmp(zname, zptr->z_origin) == 0 &&
- type == T_SOA && class == qclass) {
- newgroup = 0;
- break;
- }
- prevzptr = zptr;
- zptr = zptr->z_next;
- }
- if (!newgroup) {
- for (tmprrecp = zptr->z_rr;
- tmprrecp->r_grpnext;
- tmprrecp = tmprrecp->r_grpnext)
- ;
- tmprrecp->r_grpnext = rrecp;
- rrecp->r_grpnext = NULL;
- done = 1;
- cp += dlen;
- break;
- } else {
- if ((n = dn_expand(answer, eom, cp, primary,
- sizeof primary)) < 0)
- return (n);
- cp += n;
- /*
- * We don't have to bounds check here because the
- * next use of 'cp' is in dn_expand().
- */
- cp1 = (char *)soardata;
- strcpy(cp1, primary);
- cp1 += strlen(cp1) + 1;
- if ((n = dn_expand(answer, eom, cp, mailaddr,
- sizeof mailaddr)) < 0)
- return (n);
- cp += n;
- strcpy(cp1, mailaddr);
- cp1 += strlen(cp1) + 1;
- if (cp + 5*INT32SZ > eom)
- return (-1);
- memcpy(cp1, cp, 5*INT32SZ);
- cp += 5*INT32SZ;
- cp1 += 5*INT32SZ;
- rdatasize = (u_char *)cp1 - soardata;
- zptr = calloc(1, sizeof(struct zonegrp));
- if (zptr == NULL)
- return (-1);
- if (zgrp_start == NULL)
- zgrp_start = zptr;
- else
- prevzptr->z_next = zptr;
- zptr->z_rr = rrecp;
- rrecp->r_grpnext = NULL;
- strcpy(zptr->z_origin, zname);
- zptr->z_class = class;
- memcpy(zptr->z_soardata, soardata, rdatasize);
- /* fallthrough to process NS and A records */
- }
- } else if (qtype == T_NS) {
- if (rcode == NOERROR && ancount > 0) {
- strcpy(zname, dname);
- for (zptr = zgrp_start; zptr; zptr = zptr->z_next) {
- if (strcasecmp(zname, zptr->z_origin) == 0)
- break;
- }
- if (zptr == NULL)
- /* should not happen */
- return (-1);
- if (nscount > 0) {
- /*
- * answer and authority sections contain
- * the same information, skip answer section
- */
- for (j = 0; j < ancount; j++) {
- n = dn_skipname(cp, eom);
- if (n < 0)
- return (-1);
- n += 2*INT16SZ + INT32SZ;
- if (cp + n + INT16SZ > eom)
- return (-1);
- cp += n;
- GETSHORT(dlen, cp);
- cp += dlen;
- }
- } else
- nscount = ancount;
- /* fallthrough to process NS and A records */
- } else {
- fprintf(stderr, "cannot determine nameservers for %s:\
-ans=%d, auth=%d, add=%d, rcode=%d\n",
- dname, ancount, nscount, arcount, hp->rcode);
- return (-1);
- }
- } else if (qtype == T_A) {
- if (rcode == NOERROR && ancount > 0) {
- arcount = ancount;
- ancount = nscount = 0;
- /* fallthrough to process A records */
- } else {
- fprintf(stderr, "cannot determine address for %s:\
-ans=%d, auth=%d, add=%d, rcode=%d\n",
- dname, ancount, nscount, arcount, hp->rcode);
- return (-1);
- }
- }
- /* process NS records for the zone */
- j = 0;
- for (i = 0; i < nscount; i++) {
- if ((n = dn_expand(answer, eom, cp, name,
- sizeof name)) < 0)
- return (n);
- cp += n;
- if (cp + 3 * INT16SZ + INT32SZ > eom)
- return (-1);
- GETSHORT(type, cp);
- GETSHORT(class, cp);
- GETLONG(ttl, cp);
- GETSHORT(dlen, cp);
- if (cp + dlen > eom)
- return (-1);
- if (strcasecmp(name, zname) == 0 &&
- type == T_NS && class == qclass) {
- if ((n = dn_expand(answer, eom, cp,
- name, sizeof name)) < 0)
- return (n);
- target = zptr->z_ns[j++].nsname;
- strcpy(target, name);
- }
- cp += dlen;
+/* Public. */
+
+int
+res_nupdate(res_state statp, ns_updrec *rrecp_in, ns_tsig_key *key) {
+ ns_updrec *rrecp;
+ u_char answer[PACKETSZ], packet[2*PACKETSZ];
+ struct zonegrp *zptr, tgrp;
+ LIST(struct zonegrp) zgrps;
+ int nzones = 0, nscount = 0, n;
+ struct sockaddr_in nsaddrs[MAXNS];
+
+ /* Thread all of the updates onto a list of groups. */
+ INIT_LIST(zgrps);
+ for (rrecp = rrecp_in; rrecp; rrecp = NEXT(rrecp, r_link)) {
+ /* Find the origin for it if there is one. */
+ tgrp.z_class = rrecp->r_class;
+ tgrp.z_nscount =
+ res_findzonecut(statp, rrecp->r_dname, tgrp.z_class,
+ RES_EXHAUSTIVE,
+ tgrp.z_origin,
+ sizeof tgrp.z_origin,
+ tgrp.z_nsaddrs, MAXNS);
+ if (tgrp.z_nscount <= 0) {
+ DPRINTF(("res_findzonecut failed (%d)",
+ tgrp.z_nscount));
+ goto done;
}
- if (zptr->z_nscount == 0)
- zptr->z_nscount = j;
- /* get addresses for the nameservers */
- for (i = 0; i < arcount; i++) {
- if ((n = dn_expand(answer, eom, cp, name,
- sizeof name)) < 0)
- return (n);
- cp += n;
- if (cp + 3 * INT16SZ + INT32SZ > eom)
- return (-1);
- GETSHORT(type, cp);
- GETSHORT(class, cp);
- GETLONG(ttl, cp);
- GETSHORT(dlen, cp);
- if (cp + dlen > eom)
- return (-1);
- if (type == T_A && dlen == INT32SZ && class == qclass) {
- for (j = 0; j < zptr->z_nscount; j++)
- if (strcasecmp(name, zptr->z_ns[j].nsname) == 0) {
- memcpy(&zptr->z_ns[j].nsaddr1.s_addr, cp,
- INT32SZ);
+ /* Find the group for it if there is one. */
+ for (zptr = HEAD(zgrps); zptr != NULL; zptr = NEXT(zptr, z_link))
+ if (ns_samename(tgrp.z_origin, zptr->z_origin) == 1 &&
+ tgrp.z_class == zptr->z_class)
break;
- }
- }
- cp += dlen;
- }
- if (zptr->z_nscount == 0) {
- dname = zname;
- qtype = T_NS;
- continue;
+ /* Make a group for it if there isn't one. */
+ if (zptr == NULL) {
+ zptr = malloc(sizeof *zptr);
+ if (zptr == NULL) {
+ DPRINTF(("malloc failed"));
+ goto done;
+ }
+ *zptr = tgrp;
+ zptr->z_flags = 0;
+ INIT_LIST(zptr->z_rrlist);
+ APPEND(zgrps, zptr, z_link);
}
- done = 1;
- for (k = 0; k < zptr->z_nscount; k++)
- if (zptr->z_ns[k].nsaddr1.s_addr == 0) {
- done = 0;
- dname = zptr->z_ns[k].nsname;
- qtype = T_A;
- }
-
- } /* while */
+ /* Thread this rrecp onto the right group. */
+ APPEND(zptr->z_rrlist, rrecp, r_glink);
}
- _res.options |= RES_DEBUG;
- for (zptr = zgrp_start; zptr; zptr = zptr->z_next) {
-
- /* append zone section */
+ for (zptr = HEAD(zgrps); zptr != NULL; zptr = NEXT(zptr, z_link)) {
+ /* Construct zone section and prepend it. */
rrecp = res_mkupdrec(ns_s_zn, zptr->z_origin,
zptr->z_class, ns_t_soa, 0);
if (rrecp == NULL) {
- fprintf(stderr, "saverrec error\n");
- fflush(stderr);
- return (-1);
+ DPRINTF(("res_mkupdrec failed"));
+ goto done;
}
- rrecp->r_grpnext = zptr->z_rr;
- zptr->z_rr = rrecp;
-
- n = res_mkupdate(zptr->z_rr, packet, sizeof packet);
+ PREPEND(zptr->z_rrlist, rrecp, r_glink);
+ zptr->z_flags |= ZG_F_ZONESECTADDED;
+
+ /* Marshall the update message. */
+ n = res_nmkupdate(statp, HEAD(zptr->z_rrlist),
+ packet, sizeof packet);
+ DPRINTF(("res_mkupdate -> %d", n));
+ if (n < 0)
+ goto done;
+
+ /* Temporarily replace the resolver's nameserver set. */
+ nscount = nscopy(nsaddrs, statp->nsaddr_list, statp->nscount);
+ statp->nscount = nsprom(statp->nsaddr_list,
+ zptr->z_nsaddrs, zptr->z_nscount);
+
+ /* Send the update and remember the result. */
+ if (key != NULL)
+ n = res_nsendsigned(statp, packet, n, key,
+ answer, sizeof answer);
+ else
+ n = res_nsend(statp, packet, n, answer, sizeof answer);
if (n < 0) {
- fprintf(stderr, "res_mkupdate error\n");
- fflush(stderr);
- return (-1);
- } else
- fprintf(stdout, "res_mkupdate: packet size = %d\n", n);
-
- /*
- * Override the list of NS records from res_init() with
- * the authoritative nameservers for the zone being updated.
- * Sort primary to be the first in the list of nameservers.
- */
- for (i = 0; i < zptr->z_nscount; i++) {
- if (strcasecmp(zptr->z_ns[i].nsname,
- zptr->z_soardata) == 0) {
- struct in_addr tmpaddr;
-
- if (i != 0) {
- strcpy(zptr->z_ns[i].nsname,
- zptr->z_ns[0].nsname);
- strcpy(zptr->z_ns[0].nsname,
- zptr->z_soardata);
- tmpaddr = zptr->z_ns[i].nsaddr1;
- zptr->z_ns[i].nsaddr1 =
- zptr->z_ns[0].nsaddr1;
- zptr->z_ns[0].nsaddr1 = tmpaddr;
- }
- break;
- }
- }
- for (i = 0; i < MAXNS; i++) {
- _res.nsaddr_list[i].sin_addr = zptr->z_ns[i].nsaddr1;
- _res.nsaddr_list[i].sin_family = AF_INET;
- _res.nsaddr_list[i].sin_port = htons(NAMESERVER_PORT);
+ DPRINTF(("res_nsend: send error, n=%d (%s)\n",
+ n, strerror(errno)));
+ goto done;
}
- _res.nscount = (zptr->z_nscount < MAXNS) ?
- zptr->z_nscount : MAXNS;
- n = res_send(packet, n, answer, sizeof(answer));
- if (n < 0) {
- fprintf(stderr, "res_send: send error, n=%d\n", n);
- break;
- } else
- numzones++;
+ if (((HEADER *)answer)->rcode == NOERROR)
+ nzones++;
+
+ /* Restore resolver's nameserver set. */
+ statp->nscount = nscopy(statp->nsaddr_list, nsaddrs, nscount);
+ nscount = 0;
+ }
+ done:
+ while (!EMPTY(zgrps)) {
+ zptr = HEAD(zgrps);
+ if ((zptr->z_flags & ZG_F_ZONESECTADDED) != 0)
+ res_freeupdrec(HEAD(zptr->z_rrlist));
+ UNLINK(zgrps, zptr, z_link);
+ free(zptr);
}
+ if (nscount != 0)
+ statp->nscount = nscopy(statp->nsaddr_list, nsaddrs, nscount);
+
+ return (nzones);
+}
+
+/* Private. */
- /* free malloc'ed memory */
- while(zgrp_start) {
- zptr = zgrp_start;
- zgrp_start = zgrp_start->z_next;
- res_freeupdrec(zptr->z_rr); /* Zone section we allocated. */
- free((char *)zptr);
+static int
+nscopy(struct sockaddr_in *dst, const struct sockaddr_in *src, int n) {
+ int i;
+
+ for (i = 0; i < n; i++)
+ dst[i] = src[i];
+ return (n);
+}
+
+static int
+nsprom(struct sockaddr_in *dst, const struct in_addr *src, int n) {
+ int i;
+
+ for (i = 0; i < n; i++) {
+ memset(&dst[i], 0, sizeof dst[i]);
+ dst[i].sin_family = AF_INET;
+ dst[i].sin_port = htons(NS_DEFAULTPORT);
+ dst[i].sin_addr = src[i];
}
+ return (n);
+}
+
+static void
+dprintf(const char *fmt, ...) {
+ va_list ap;
- return (numzones);
+ va_start(ap, fmt);
+ fputs(";; res_nupdate: ", stderr);
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ va_end(ap);
}
OpenPOWER on IntegriCloud