From d3809905480f2c382fc9f02db62e3fc2414fc933 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 29 Mar 2001 06:31:59 +0000 Subject: [PATCH] Initial pull over from BIND 8 --- lib/bind/Makefile.in | 20 + lib/bind/README | 4 + lib/bind/bsd/Makefile.in | 16 + lib/bind/bsd/daemon.c | 79 + lib/bind/bsd/ftruncate.c | 63 + lib/bind/bsd/gettimeofday.c | 64 + lib/bind/bsd/gettimeofday.h | 7 + lib/bind/bsd/mktemp.c | 154 + lib/bind/bsd/putenv.c | 25 + lib/bind/bsd/readv.c | 38 + lib/bind/bsd/setenv.c | 149 + lib/bind/bsd/setitimer.c | 27 + lib/bind/bsd/strcasecmp.c | 122 + lib/bind/bsd/strdup.c | 18 + lib/bind/bsd/strerror.c | 80 + lib/bind/bsd/strpbrk.c | 68 + lib/bind/bsd/strsep.c | 86 + lib/bind/bsd/strtoul.c | 117 + lib/bind/bsd/utimes.c | 39 + lib/bind/bsd/writev.c | 86 + lib/bind/config.h.in | 0 lib/bind/configure | 6825 ++++++++++++++++++++++++ lib/bind/configure.in | 1821 +++++++ lib/bind/cylink/Makefile.in | 12 + lib/bind/cylink/bits.c | 359 ++ lib/bind/cylink/bn.c | 131 + lib/bind/cylink/bn.h | 221 + lib/bind/cylink/bn00.c | 68 + lib/bind/cylink/bn16.c | 949 ++++ lib/bind/cylink/bn16.h | 92 + lib/bind/cylink/bn32.c | 949 ++++ lib/bind/cylink/bn32.h | 92 + lib/bind/cylink/bn68000.c | 62 + lib/bind/cylink/bn8086.c | 62 + lib/bind/cylink/bninit16.c | 56 + lib/bind/cylink/bninit32.c | 56 + lib/bind/cylink/bnsize00.h | 75 + lib/bind/cylink/c_asm.h | 133 + lib/bind/cylink/cencrint.h | 255 + lib/bind/cylink/ctk_endian.h | 212 + lib/bind/cylink/ctk_prime.c | 435 ++ lib/bind/cylink/cylink.h | 82 + lib/bind/cylink/dss.c | 1202 +++++ lib/bind/cylink/dssnum.h | 724 +++ lib/bind/cylink/funcs.h | 7 + lib/bind/cylink/kludge.h | 158 + lib/bind/cylink/lbn.h | 186 + lib/bind/cylink/lbn00.c | 65 + lib/bind/cylink/lbn16.c | 3644 +++++++++++++ lib/bind/cylink/lbn16.h | 181 + lib/bind/cylink/lbn32.c | 3643 +++++++++++++ lib/bind/cylink/lbn32.h | 181 + lib/bind/cylink/lbn68000.c | 500 ++ lib/bind/cylink/lbn68000.h | 74 + lib/bind/cylink/lbn68020.c | 349 ++ lib/bind/cylink/lbn68020.h | 69 + lib/bind/cylink/lbn80386.h | 169 + lib/bind/cylink/lbn8086.h | 113 + lib/bind/cylink/lbnmem.c | 195 + lib/bind/cylink/lbnmem.h | 102 + lib/bind/cylink/lbnppc.c | 358 ++ lib/bind/cylink/lbnppc.h | 98 + lib/bind/cylink/legal.c | 45 + lib/bind/cylink/legal.h | 47 + lib/bind/cylink/math.c | 1151 ++++ lib/bind/cylink/ppcasm.h | 575 ++ lib/bind/cylink/rand.c | 333 ++ lib/bind/cylink/sha.c | 698 +++ lib/bind/cylink/sha.h | 148 + lib/bind/cylink/sizetest.c | 51 + lib/bind/cylink/swap.c | 211 + lib/bind/cylink/toolkit.h | 393 ++ lib/bind/dnssafe/Makefile.in | 41 + lib/bind/dnssafe/ahcbcpad.c | 176 + lib/bind/dnssafe/ahcbcpad.h | 37 + lib/bind/dnssafe/ahchdig.c | 132 + lib/bind/dnssafe/ahchdig.h | 32 + lib/bind/dnssafe/ahchencr.c | 268 + lib/bind/dnssafe/ahchencr.h | 74 + lib/bind/dnssafe/ahchgen.c | 218 + lib/bind/dnssafe/ahchgen.h | 44 + lib/bind/dnssafe/ahchrand.c | 130 + lib/bind/dnssafe/ahchrand.h | 31 + lib/bind/dnssafe/ahdigest.c | 93 + lib/bind/dnssafe/ahdigest.h | 48 + lib/bind/dnssafe/ahencryp.c | 171 + lib/bind/dnssafe/ahencryp.h | 85 + lib/bind/dnssafe/ahgen.c | 92 + lib/bind/dnssafe/ahgen.h | 47 + lib/bind/dnssafe/ahrandom.c | 99 + lib/bind/dnssafe/ahrandom.h | 47 + lib/bind/dnssafe/ahrsaenc.c | 244 + lib/bind/dnssafe/ahrsaenc.h | 68 + lib/bind/dnssafe/ahrsaepr.c | 101 + lib/bind/dnssafe/ahrsaepr.h | 20 + lib/bind/dnssafe/ahrsaepu.c | 114 + lib/bind/dnssafe/ahrsaepu.h | 20 + lib/bind/dnssafe/aichdig.c | 38 + lib/bind/dnssafe/aichdig.h | 17 + lib/bind/dnssafe/aichenc8.c | 35 + lib/bind/dnssafe/aichenc8.h | 19 + lib/bind/dnssafe/aichencn.c | 19 + lib/bind/dnssafe/aichencn.h | 17 + lib/bind/dnssafe/aichencr.c | 33 + lib/bind/dnssafe/aichencr.h | 17 + lib/bind/dnssafe/aichgen.c | 33 + lib/bind/dnssafe/aichgen.h | 17 + lib/bind/dnssafe/aichrand.c | 38 + lib/bind/dnssafe/aichrand.h | 17 + lib/bind/dnssafe/aimd5.c | 27 + lib/bind/dnssafe/aimd5ran.c | 27 + lib/bind/dnssafe/ainfotyp.c | 32 + lib/bind/dnssafe/ainfotyp.h | 39 + lib/bind/dnssafe/ainull.c | 28 + lib/bind/dnssafe/ainull.h | 10 + lib/bind/dnssafe/airsaepr.c | 47 + lib/bind/dnssafe/airsaepu.c | 47 + lib/bind/dnssafe/airsakgn.c | 62 + lib/bind/dnssafe/airsaprv.c | 27 + lib/bind/dnssafe/airsapub.c | 27 + lib/bind/dnssafe/algae.h | 66 + lib/bind/dnssafe/algchoic.c | 169 + lib/bind/dnssafe/algchoic.h | 111 + lib/bind/dnssafe/algobj.c | 123 + lib/bind/dnssafe/algobj.h | 19 + lib/bind/dnssafe/amcrte.c | 119 + lib/bind/dnssafe/amdigest.h | 19 + lib/bind/dnssafe/amencdec.h | 21 + lib/bind/dnssafe/amgen.h | 19 + lib/bind/dnssafe/ammd5.c | 102 + lib/bind/dnssafe/ammd5r.c | 79 + lib/bind/dnssafe/amrandom.h | 17 + lib/bind/dnssafe/amrkg.c | 83 + lib/bind/dnssafe/amrsae.c | 117 + lib/bind/dnssafe/atypes.h | 60 + lib/bind/dnssafe/balg.c | 117 + lib/bind/dnssafe/balg.h | 116 + lib/bind/dnssafe/balgmeth.h | 18 + lib/bind/dnssafe/bgclrbit.c | 30 + lib/bind/dnssafe/bgmdmpyx.c | 28 + lib/bind/dnssafe/bgmdsqx.c | 26 + lib/bind/dnssafe/bgmodexp.c | 134 + lib/bind/dnssafe/bgpegcd.c | 80 + lib/bind/dnssafe/big2exp.c | 27 + lib/bind/dnssafe/bigabs.c | 24 + lib/bind/dnssafe/bigacc.c | 36 + lib/bind/dnssafe/bigarith.c | 140 + lib/bind/dnssafe/bigcmp.c | 36 + lib/bind/dnssafe/bigconst.c | 28 + lib/bind/dnssafe/biginv.c | 105 + lib/bind/dnssafe/biglen.c | 30 + lib/bind/dnssafe/bigmath.h | 71 + lib/bind/dnssafe/bigmaxes.h | 47 + lib/bind/dnssafe/bigmodx.c | 27 + lib/bind/dnssafe/bigmpy.c | 38 + lib/bind/dnssafe/bigpdiv.c | 161 + lib/bind/dnssafe/bigpmpy.c | 27 + lib/bind/dnssafe/bigpmpyh.c | 32 + lib/bind/dnssafe/bigpmpyl.c | 32 + lib/bind/dnssafe/bigpsq.c | 44 + lib/bind/dnssafe/bigqrx.c | 87 + lib/bind/dnssafe/bigsmod.c | 30 + lib/bind/dnssafe/bigtocan.c | 62 + lib/bind/dnssafe/bigu.c | 23 + lib/bind/dnssafe/bigunexp.c | 100 + lib/bind/dnssafe/binfocsh.c | 65 + lib/bind/dnssafe/binfocsh.h | 33 + lib/bind/dnssafe/bkey.c | 103 + lib/bind/dnssafe/bkey.h | 32 + lib/bind/dnssafe/bmempool.c | 273 + lib/bind/dnssafe/bmempool.h | 53 + lib/bind/dnssafe/bsafe2.h | 194 + lib/bind/dnssafe/btypechk.h | 25 + lib/bind/dnssafe/cantobig.c | 59 + lib/bind/dnssafe/crt2.c | 230 + lib/bind/dnssafe/crt2.h | 50 + lib/bind/dnssafe/digest.c | 69 + lib/bind/dnssafe/digrand.c | 90 + lib/bind/dnssafe/digrand.h | 53 + lib/bind/dnssafe/encrypt.c | 149 + lib/bind/dnssafe/generate.c | 80 + lib/bind/dnssafe/global.h | 63 + lib/bind/dnssafe/intbits.c | 34 + lib/bind/dnssafe/intitem.c | 56 + lib/bind/dnssafe/intitem.h | 11 + lib/bind/dnssafe/keyobj.c | 115 + lib/bind/dnssafe/keyobj.h | 16 + lib/bind/dnssafe/ki8byte.c | 72 + lib/bind/dnssafe/ki8byte.h | 9 + lib/bind/dnssafe/kifulprv.c | 153 + lib/bind/dnssafe/kifulprv.h | 12 + lib/bind/dnssafe/kiitem.c | 46 + lib/bind/dnssafe/kiitem.h | 9 + lib/bind/dnssafe/kinfotyp.c | 28 + lib/bind/dnssafe/kinfotyp.h | 57 + lib/bind/dnssafe/kipkcrpr.c | 102 + lib/bind/dnssafe/kipkcrpr.h | 13 + lib/bind/dnssafe/kirsacrt.c | 103 + lib/bind/dnssafe/kirsapub.c | 82 + lib/bind/dnssafe/kirsapub.h | 13 + lib/bind/dnssafe/md5.c | 283 + lib/bind/dnssafe/md5.h | 32 + lib/bind/dnssafe/md5rand.c | 71 + lib/bind/dnssafe/md5rand.h | 36 + lib/bind/dnssafe/prime.c | 166 + lib/bind/dnssafe/prime.h | 26 + lib/bind/dnssafe/random.c | 60 + lib/bind/dnssafe/rsa.c | 211 + lib/bind/dnssafe/rsa.h | 44 + lib/bind/dnssafe/rsakeygn.c | 244 + lib/bind/dnssafe/rsakeygn.h | 54 + lib/bind/dnssafe/seccbcd.c | 148 + lib/bind/dnssafe/seccbce.c | 99 + lib/bind/dnssafe/secrcbc.h | 36 + lib/bind/dnssafe/surrendr.c | 26 + lib/bind/dnssafe/surrendr.h | 22 + lib/bind/dst/Makefile.in | 16 + lib/bind/dst/bsafe_link.c | 1129 ++++ lib/bind/dst/cylink_link.c | 678 +++ lib/bind/dst/dst_api.c | 1069 ++++ lib/bind/dst/dst_internal.h | 168 + lib/bind/dst/eay_dss_link.c | 638 +++ lib/bind/dst/hmac_link.c | 495 ++ lib/bind/dst/md5.h | 101 + lib/bind/dst/md5_dgst.c | 368 ++ lib/bind/dst/md5_locl.h | 190 + lib/bind/dst/prandom.c | 855 +++ lib/bind/dst/rsaref_link.c | 767 +++ lib/bind/dst/support.c | 463 ++ lib/bind/include/Makefile.in | 2 + lib/bind/include/arpa/inet.h | 110 + lib/bind/include/arpa/nameser.h | 559 ++ lib/bind/include/arpa/nameser_compat.h | 230 + lib/bind/include/fd_setsize.h | 9 + lib/bind/include/hesiod.h | 40 + lib/bind/include/irp.h | 99 + lib/bind/include/irs.h | 330 ++ lib/bind/include/isc/assertions.h | 122 + lib/bind/include/isc/ctl.h | 104 + lib/bind/include/isc/dst.h | 141 + lib/bind/include/isc/eventlib.h | 196 + lib/bind/include/isc/heap.h | 47 + lib/bind/include/isc/irpmarshall.h | 116 + lib/bind/include/isc/list.h | 108 + lib/bind/include/isc/logging.h | 102 + lib/bind/include/isc/memcluster.h | 47 + lib/bind/include/isc/misc.h | 31 + lib/bind/include/isc/tree.h | 48 + lib/bind/include/netdb.h | 485 ++ lib/bind/include/netgroup.h | 17 + lib/bind/include/res_update.h | 65 + lib/bind/include/resolv.h | 447 ++ lib/bind/inet/Makefile.in | 16 + lib/bind/inet/inet_addr.c | 205 + lib/bind/inet/inet_cidr_ntop.c | 129 + lib/bind/inet/inet_cidr_pton.c | 154 + lib/bind/inet/inet_data.c | 54 + lib/bind/inet/inet_lnaof.c | 63 + lib/bind/inet/inet_makeaddr.c | 66 + lib/bind/inet/inet_net_ntop.c | 144 + lib/bind/inet/inet_net_pton.c | 215 + lib/bind/inet/inet_neta.c | 87 + lib/bind/inet/inet_netof.c | 62 + lib/bind/inet/inet_network.c | 103 + lib/bind/inet/inet_ntoa.c | 62 + lib/bind/inet/inet_ntop.c | 202 + lib/bind/inet/inet_pton.c | 220 + lib/bind/inet/nsap_addr.c | 101 + lib/bind/irs/Makefile.in | 49 + lib/bind/irs/dns.c | 153 + lib/bind/irs/dns_gr.c | 293 + lib/bind/irs/dns_ho.c | 1606 ++++++ lib/bind/irs/dns_nw.c | 566 ++ lib/bind/irs/dns_p.h | 50 + lib/bind/irs/dns_pr.c | 266 + lib/bind/irs/dns_pw.c | 231 + lib/bind/irs/dns_sv.c | 298 ++ lib/bind/irs/gai_strerror.c | 45 + lib/bind/irs/gen.c | 427 ++ lib/bind/irs/gen_gr.c | 454 ++ lib/bind/irs/gen_ho.c | 391 ++ lib/bind/irs/gen_ng.c | 172 + lib/bind/irs/gen_nw.c | 262 + lib/bind/irs/gen_p.h | 113 + lib/bind/irs/gen_pr.c | 226 + lib/bind/irs/gen_pw.c | 233 + lib/bind/irs/gen_sv.c | 227 + lib/bind/irs/getaddrinfo.c | 1254 +++++ lib/bind/irs/getgrent.c | 222 + lib/bind/irs/getgrent_r.c | 220 + lib/bind/irs/gethostent.c | 900 ++++ lib/bind/irs/gethostent_r.c | 228 + lib/bind/irs/getnameinfo.c | 226 + lib/bind/irs/getnetent.c | 342 ++ lib/bind/irs/getnetent_r.c | 192 + lib/bind/irs/getnetgrent.c | 141 + lib/bind/irs/getnetgrent_r.c | 142 + lib/bind/irs/getprotoent.c | 173 + lib/bind/irs/getprotoent_r.c | 186 + lib/bind/irs/getpwent.c | 199 + lib/bind/irs/getpwent_r.c | 263 + lib/bind/irs/getservent.c | 176 + lib/bind/irs/getservent_r.c | 207 + lib/bind/irs/hesiod.c | 506 ++ lib/bind/irs/hesiod_p.h | 48 + lib/bind/irs/irp.c | 592 ++ lib/bind/irs/irp_gr.c | 405 ++ lib/bind/irs/irp_ho.c | 429 ++ lib/bind/irs/irp_ng.c | 272 + lib/bind/irs/irp_nw.c | 375 ++ lib/bind/irs/irp_p.h | 61 + lib/bind/irs/irp_pr.c | 353 ++ lib/bind/irs/irp_pw.c | 356 ++ lib/bind/irs/irp_sv.c | 369 ++ lib/bind/irs/irpmarshall.c | 2344 ++++++++ lib/bind/irs/irs_data.c | 193 + lib/bind/irs/irs_data.h | 62 + lib/bind/irs/irs_p.h | 49 + lib/bind/irs/lcl.c | 140 + lib/bind/irs/lcl_gr.c | 354 ++ lib/bind/irs/lcl_ho.c | 576 ++ lib/bind/irs/lcl_ng.c | 444 ++ lib/bind/irs/lcl_nw.c | 371 ++ lib/bind/irs/lcl_p.h | 50 + lib/bind/irs/lcl_pr.c | 284 + lib/bind/irs/lcl_pw.c | 308 ++ lib/bind/irs/lcl_sv.c | 431 ++ lib/bind/irs/nis.c | 151 + lib/bind/irs/nis_gr.c | 353 ++ lib/bind/irs/nis_ho.c | 461 ++ lib/bind/irs/nis_ng.c | 297 ++ lib/bind/irs/nis_nw.c | 379 ++ lib/bind/irs/nis_p.h | 46 + lib/bind/irs/nis_pr.c | 295 + lib/bind/irs/nis_pw.c | 283 + lib/bind/irs/nis_sv.c | 305 ++ lib/bind/irs/nul_ng.c | 126 + lib/bind/irs/pathnames.h | 50 + lib/bind/irs/util.c | 107 + lib/bind/isc/Makefile.in | 16 + lib/bind/isc/assertions.c | 91 + lib/bind/isc/assertions.mdoc | 134 + lib/bind/isc/base64.c | 320 ++ lib/bind/isc/bitncmp.c | 66 + lib/bind/isc/bitncmp.mdoc | 82 + lib/bind/isc/ctl_clnt.c | 598 +++ lib/bind/isc/ctl_p.c | 186 + lib/bind/isc/ctl_p.h | 22 + lib/bind/isc/ctl_srvr.c | 778 +++ lib/bind/isc/ev_connects.c | 352 ++ lib/bind/isc/ev_files.c | 272 + lib/bind/isc/ev_streams.c | 306 ++ lib/bind/isc/ev_timers.c | 415 ++ lib/bind/isc/ev_waits.c | 245 + lib/bind/isc/eventlib.c | 676 +++ lib/bind/isc/eventlib.mdoc | 854 +++ lib/bind/isc/eventlib_p.h | 213 + lib/bind/isc/heap.c | 221 + lib/bind/isc/heap.mdoc | 368 ++ lib/bind/isc/logging.c | 702 +++ lib/bind/isc/logging.mdoc | 1052 ++++ lib/bind/isc/logging_p.h | 60 + lib/bind/isc/memcluster.c | 532 ++ lib/bind/isc/memcluster.mdoc | 375 ++ lib/bind/isc/movefile.c | 35 + lib/bind/isc/tree.c | 532 ++ lib/bind/isc/tree.mdoc | 154 + lib/bind/make/includes.in | 44 + lib/bind/make/mkdep.in | 147 + lib/bind/make/rules.in | 172 + lib/bind/nameser/Makefile.in | 12 + lib/bind/nameser/ns_date.c | 128 + lib/bind/nameser/ns_name.c | 934 ++++ lib/bind/nameser/ns_netint.c | 56 + lib/bind/nameser/ns_parse.c | 202 + lib/bind/nameser/ns_print.c | 901 ++++ lib/bind/nameser/ns_samedomain.c | 206 + lib/bind/nameser/ns_sign.c | 349 ++ lib/bind/nameser/ns_ttl.c | 159 + lib/bind/nameser/ns_verify.c | 480 ++ lib/bind/port_after.h.in | 11 + lib/bind/port_before.h.in | 110 + lib/bind/prand_conf.c | 219 + lib/bind/resolv/Makefile.in | 14 + lib/bind/resolv/herror.c | 126 + lib/bind/resolv/res_comp.c | 251 + lib/bind/resolv/res_data.c | 291 + lib/bind/resolv/res_debug.c | 1063 ++++ lib/bind/resolv/res_debug.h | 34 + lib/bind/resolv/res_findzonecut.c | 603 +++ lib/bind/resolv/res_init.c | 556 ++ lib/bind/resolv/res_mkquery.c | 250 + lib/bind/resolv/res_mkupdate.c | 1100 ++++ lib/bind/resolv/res_mkupdate.h | 24 + lib/bind/resolv/res_private.h | 2 + lib/bind/resolv/res_query.c | 426 ++ lib/bind/resolv/res_send.c | 1070 ++++ lib/bind/resolv/res_sendsigned.c | 134 + lib/bind/resolv/res_update.c | 240 + 399 files changed, 95578 insertions(+) create mode 100644 lib/bind/Makefile.in create mode 100644 lib/bind/README create mode 100644 lib/bind/bsd/Makefile.in create mode 100644 lib/bind/bsd/daemon.c create mode 100644 lib/bind/bsd/ftruncate.c create mode 100644 lib/bind/bsd/gettimeofday.c create mode 100644 lib/bind/bsd/gettimeofday.h create mode 100644 lib/bind/bsd/mktemp.c create mode 100644 lib/bind/bsd/putenv.c create mode 100644 lib/bind/bsd/readv.c create mode 100644 lib/bind/bsd/setenv.c create mode 100644 lib/bind/bsd/setitimer.c create mode 100644 lib/bind/bsd/strcasecmp.c create mode 100644 lib/bind/bsd/strdup.c create mode 100644 lib/bind/bsd/strerror.c create mode 100644 lib/bind/bsd/strpbrk.c create mode 100644 lib/bind/bsd/strsep.c create mode 100644 lib/bind/bsd/strtoul.c create mode 100644 lib/bind/bsd/utimes.c create mode 100644 lib/bind/bsd/writev.c create mode 100644 lib/bind/config.h.in create mode 100644 lib/bind/configure create mode 100644 lib/bind/configure.in create mode 100644 lib/bind/cylink/Makefile.in create mode 100644 lib/bind/cylink/bits.c create mode 100644 lib/bind/cylink/bn.c create mode 100644 lib/bind/cylink/bn.h create mode 100644 lib/bind/cylink/bn00.c create mode 100644 lib/bind/cylink/bn16.c create mode 100644 lib/bind/cylink/bn16.h create mode 100644 lib/bind/cylink/bn32.c create mode 100644 lib/bind/cylink/bn32.h create mode 100644 lib/bind/cylink/bn68000.c create mode 100644 lib/bind/cylink/bn8086.c create mode 100644 lib/bind/cylink/bninit16.c create mode 100644 lib/bind/cylink/bninit32.c create mode 100644 lib/bind/cylink/bnsize00.h create mode 100644 lib/bind/cylink/c_asm.h create mode 100644 lib/bind/cylink/cencrint.h create mode 100644 lib/bind/cylink/ctk_endian.h create mode 100644 lib/bind/cylink/ctk_prime.c create mode 100644 lib/bind/cylink/cylink.h create mode 100644 lib/bind/cylink/dss.c create mode 100644 lib/bind/cylink/dssnum.h create mode 100644 lib/bind/cylink/funcs.h create mode 100644 lib/bind/cylink/kludge.h create mode 100644 lib/bind/cylink/lbn.h create mode 100644 lib/bind/cylink/lbn00.c create mode 100644 lib/bind/cylink/lbn16.c create mode 100644 lib/bind/cylink/lbn16.h create mode 100644 lib/bind/cylink/lbn32.c create mode 100644 lib/bind/cylink/lbn32.h create mode 100644 lib/bind/cylink/lbn68000.c create mode 100644 lib/bind/cylink/lbn68000.h create mode 100644 lib/bind/cylink/lbn68020.c create mode 100644 lib/bind/cylink/lbn68020.h create mode 100644 lib/bind/cylink/lbn80386.h create mode 100644 lib/bind/cylink/lbn8086.h create mode 100644 lib/bind/cylink/lbnmem.c create mode 100644 lib/bind/cylink/lbnmem.h create mode 100644 lib/bind/cylink/lbnppc.c create mode 100644 lib/bind/cylink/lbnppc.h create mode 100644 lib/bind/cylink/legal.c create mode 100644 lib/bind/cylink/legal.h create mode 100644 lib/bind/cylink/math.c create mode 100644 lib/bind/cylink/ppcasm.h create mode 100644 lib/bind/cylink/rand.c create mode 100644 lib/bind/cylink/sha.c create mode 100644 lib/bind/cylink/sha.h create mode 100644 lib/bind/cylink/sizetest.c create mode 100644 lib/bind/cylink/swap.c create mode 100644 lib/bind/cylink/toolkit.h create mode 100644 lib/bind/dnssafe/Makefile.in create mode 100644 lib/bind/dnssafe/ahcbcpad.c create mode 100644 lib/bind/dnssafe/ahcbcpad.h create mode 100644 lib/bind/dnssafe/ahchdig.c create mode 100644 lib/bind/dnssafe/ahchdig.h create mode 100644 lib/bind/dnssafe/ahchencr.c create mode 100644 lib/bind/dnssafe/ahchencr.h create mode 100644 lib/bind/dnssafe/ahchgen.c create mode 100644 lib/bind/dnssafe/ahchgen.h create mode 100644 lib/bind/dnssafe/ahchrand.c create mode 100644 lib/bind/dnssafe/ahchrand.h create mode 100644 lib/bind/dnssafe/ahdigest.c create mode 100644 lib/bind/dnssafe/ahdigest.h create mode 100644 lib/bind/dnssafe/ahencryp.c create mode 100644 lib/bind/dnssafe/ahencryp.h create mode 100644 lib/bind/dnssafe/ahgen.c create mode 100644 lib/bind/dnssafe/ahgen.h create mode 100644 lib/bind/dnssafe/ahrandom.c create mode 100644 lib/bind/dnssafe/ahrandom.h create mode 100644 lib/bind/dnssafe/ahrsaenc.c create mode 100644 lib/bind/dnssafe/ahrsaenc.h create mode 100644 lib/bind/dnssafe/ahrsaepr.c create mode 100644 lib/bind/dnssafe/ahrsaepr.h create mode 100644 lib/bind/dnssafe/ahrsaepu.c create mode 100644 lib/bind/dnssafe/ahrsaepu.h create mode 100644 lib/bind/dnssafe/aichdig.c create mode 100644 lib/bind/dnssafe/aichdig.h create mode 100644 lib/bind/dnssafe/aichenc8.c create mode 100644 lib/bind/dnssafe/aichenc8.h create mode 100644 lib/bind/dnssafe/aichencn.c create mode 100644 lib/bind/dnssafe/aichencn.h create mode 100644 lib/bind/dnssafe/aichencr.c create mode 100644 lib/bind/dnssafe/aichencr.h create mode 100644 lib/bind/dnssafe/aichgen.c create mode 100644 lib/bind/dnssafe/aichgen.h create mode 100644 lib/bind/dnssafe/aichrand.c create mode 100644 lib/bind/dnssafe/aichrand.h create mode 100644 lib/bind/dnssafe/aimd5.c create mode 100644 lib/bind/dnssafe/aimd5ran.c create mode 100644 lib/bind/dnssafe/ainfotyp.c create mode 100644 lib/bind/dnssafe/ainfotyp.h create mode 100644 lib/bind/dnssafe/ainull.c create mode 100644 lib/bind/dnssafe/ainull.h create mode 100644 lib/bind/dnssafe/airsaepr.c create mode 100644 lib/bind/dnssafe/airsaepu.c create mode 100644 lib/bind/dnssafe/airsakgn.c create mode 100644 lib/bind/dnssafe/airsaprv.c create mode 100644 lib/bind/dnssafe/airsapub.c create mode 100644 lib/bind/dnssafe/algae.h create mode 100644 lib/bind/dnssafe/algchoic.c create mode 100644 lib/bind/dnssafe/algchoic.h create mode 100644 lib/bind/dnssafe/algobj.c create mode 100644 lib/bind/dnssafe/algobj.h create mode 100644 lib/bind/dnssafe/amcrte.c create mode 100644 lib/bind/dnssafe/amdigest.h create mode 100644 lib/bind/dnssafe/amencdec.h create mode 100644 lib/bind/dnssafe/amgen.h create mode 100644 lib/bind/dnssafe/ammd5.c create mode 100644 lib/bind/dnssafe/ammd5r.c create mode 100644 lib/bind/dnssafe/amrandom.h create mode 100644 lib/bind/dnssafe/amrkg.c create mode 100644 lib/bind/dnssafe/amrsae.c create mode 100644 lib/bind/dnssafe/atypes.h create mode 100644 lib/bind/dnssafe/balg.c create mode 100644 lib/bind/dnssafe/balg.h create mode 100644 lib/bind/dnssafe/balgmeth.h create mode 100644 lib/bind/dnssafe/bgclrbit.c create mode 100644 lib/bind/dnssafe/bgmdmpyx.c create mode 100644 lib/bind/dnssafe/bgmdsqx.c create mode 100644 lib/bind/dnssafe/bgmodexp.c create mode 100644 lib/bind/dnssafe/bgpegcd.c create mode 100644 lib/bind/dnssafe/big2exp.c create mode 100644 lib/bind/dnssafe/bigabs.c create mode 100644 lib/bind/dnssafe/bigacc.c create mode 100644 lib/bind/dnssafe/bigarith.c create mode 100644 lib/bind/dnssafe/bigcmp.c create mode 100644 lib/bind/dnssafe/bigconst.c create mode 100644 lib/bind/dnssafe/biginv.c create mode 100644 lib/bind/dnssafe/biglen.c create mode 100644 lib/bind/dnssafe/bigmath.h create mode 100644 lib/bind/dnssafe/bigmaxes.h create mode 100644 lib/bind/dnssafe/bigmodx.c create mode 100644 lib/bind/dnssafe/bigmpy.c create mode 100644 lib/bind/dnssafe/bigpdiv.c create mode 100644 lib/bind/dnssafe/bigpmpy.c create mode 100644 lib/bind/dnssafe/bigpmpyh.c create mode 100644 lib/bind/dnssafe/bigpmpyl.c create mode 100644 lib/bind/dnssafe/bigpsq.c create mode 100644 lib/bind/dnssafe/bigqrx.c create mode 100644 lib/bind/dnssafe/bigsmod.c create mode 100644 lib/bind/dnssafe/bigtocan.c create mode 100644 lib/bind/dnssafe/bigu.c create mode 100644 lib/bind/dnssafe/bigunexp.c create mode 100644 lib/bind/dnssafe/binfocsh.c create mode 100644 lib/bind/dnssafe/binfocsh.h create mode 100644 lib/bind/dnssafe/bkey.c create mode 100644 lib/bind/dnssafe/bkey.h create mode 100644 lib/bind/dnssafe/bmempool.c create mode 100644 lib/bind/dnssafe/bmempool.h create mode 100644 lib/bind/dnssafe/bsafe2.h create mode 100644 lib/bind/dnssafe/btypechk.h create mode 100644 lib/bind/dnssafe/cantobig.c create mode 100644 lib/bind/dnssafe/crt2.c create mode 100644 lib/bind/dnssafe/crt2.h create mode 100644 lib/bind/dnssafe/digest.c create mode 100644 lib/bind/dnssafe/digrand.c create mode 100644 lib/bind/dnssafe/digrand.h create mode 100644 lib/bind/dnssafe/encrypt.c create mode 100644 lib/bind/dnssafe/generate.c create mode 100644 lib/bind/dnssafe/global.h create mode 100644 lib/bind/dnssafe/intbits.c create mode 100644 lib/bind/dnssafe/intitem.c create mode 100644 lib/bind/dnssafe/intitem.h create mode 100644 lib/bind/dnssafe/keyobj.c create mode 100644 lib/bind/dnssafe/keyobj.h create mode 100644 lib/bind/dnssafe/ki8byte.c create mode 100644 lib/bind/dnssafe/ki8byte.h create mode 100644 lib/bind/dnssafe/kifulprv.c create mode 100644 lib/bind/dnssafe/kifulprv.h create mode 100644 lib/bind/dnssafe/kiitem.c create mode 100644 lib/bind/dnssafe/kiitem.h create mode 100644 lib/bind/dnssafe/kinfotyp.c create mode 100644 lib/bind/dnssafe/kinfotyp.h create mode 100644 lib/bind/dnssafe/kipkcrpr.c create mode 100644 lib/bind/dnssafe/kipkcrpr.h create mode 100644 lib/bind/dnssafe/kirsacrt.c create mode 100644 lib/bind/dnssafe/kirsapub.c create mode 100644 lib/bind/dnssafe/kirsapub.h create mode 100644 lib/bind/dnssafe/md5.c create mode 100644 lib/bind/dnssafe/md5.h create mode 100644 lib/bind/dnssafe/md5rand.c create mode 100644 lib/bind/dnssafe/md5rand.h create mode 100644 lib/bind/dnssafe/prime.c create mode 100644 lib/bind/dnssafe/prime.h create mode 100644 lib/bind/dnssafe/random.c create mode 100644 lib/bind/dnssafe/rsa.c create mode 100644 lib/bind/dnssafe/rsa.h create mode 100644 lib/bind/dnssafe/rsakeygn.c create mode 100644 lib/bind/dnssafe/rsakeygn.h create mode 100644 lib/bind/dnssafe/seccbcd.c create mode 100644 lib/bind/dnssafe/seccbce.c create mode 100644 lib/bind/dnssafe/secrcbc.h create mode 100644 lib/bind/dnssafe/surrendr.c create mode 100644 lib/bind/dnssafe/surrendr.h create mode 100644 lib/bind/dst/Makefile.in create mode 100644 lib/bind/dst/bsafe_link.c create mode 100644 lib/bind/dst/cylink_link.c create mode 100644 lib/bind/dst/dst_api.c create mode 100644 lib/bind/dst/dst_internal.h create mode 100644 lib/bind/dst/eay_dss_link.c create mode 100644 lib/bind/dst/hmac_link.c create mode 100644 lib/bind/dst/md5.h create mode 100644 lib/bind/dst/md5_dgst.c create mode 100644 lib/bind/dst/md5_locl.h create mode 100644 lib/bind/dst/prandom.c create mode 100644 lib/bind/dst/rsaref_link.c create mode 100644 lib/bind/dst/support.c create mode 100644 lib/bind/include/Makefile.in create mode 100644 lib/bind/include/arpa/inet.h create mode 100644 lib/bind/include/arpa/nameser.h create mode 100644 lib/bind/include/arpa/nameser_compat.h create mode 100644 lib/bind/include/fd_setsize.h create mode 100644 lib/bind/include/hesiod.h create mode 100644 lib/bind/include/irp.h create mode 100644 lib/bind/include/irs.h create mode 100644 lib/bind/include/isc/assertions.h create mode 100644 lib/bind/include/isc/ctl.h create mode 100644 lib/bind/include/isc/dst.h create mode 100644 lib/bind/include/isc/eventlib.h create mode 100644 lib/bind/include/isc/heap.h create mode 100644 lib/bind/include/isc/irpmarshall.h create mode 100644 lib/bind/include/isc/list.h create mode 100644 lib/bind/include/isc/logging.h create mode 100644 lib/bind/include/isc/memcluster.h create mode 100644 lib/bind/include/isc/misc.h create mode 100644 lib/bind/include/isc/tree.h create mode 100644 lib/bind/include/netdb.h create mode 100644 lib/bind/include/netgroup.h create mode 100644 lib/bind/include/res_update.h create mode 100644 lib/bind/include/resolv.h create mode 100644 lib/bind/inet/Makefile.in create mode 100644 lib/bind/inet/inet_addr.c create mode 100644 lib/bind/inet/inet_cidr_ntop.c create mode 100644 lib/bind/inet/inet_cidr_pton.c create mode 100644 lib/bind/inet/inet_data.c create mode 100644 lib/bind/inet/inet_lnaof.c create mode 100644 lib/bind/inet/inet_makeaddr.c create mode 100644 lib/bind/inet/inet_net_ntop.c create mode 100644 lib/bind/inet/inet_net_pton.c create mode 100644 lib/bind/inet/inet_neta.c create mode 100644 lib/bind/inet/inet_netof.c create mode 100644 lib/bind/inet/inet_network.c create mode 100644 lib/bind/inet/inet_ntoa.c create mode 100644 lib/bind/inet/inet_ntop.c create mode 100644 lib/bind/inet/inet_pton.c create mode 100644 lib/bind/inet/nsap_addr.c create mode 100644 lib/bind/irs/Makefile.in create mode 100644 lib/bind/irs/dns.c create mode 100644 lib/bind/irs/dns_gr.c create mode 100644 lib/bind/irs/dns_ho.c create mode 100644 lib/bind/irs/dns_nw.c create mode 100644 lib/bind/irs/dns_p.h create mode 100644 lib/bind/irs/dns_pr.c create mode 100644 lib/bind/irs/dns_pw.c create mode 100644 lib/bind/irs/dns_sv.c create mode 100644 lib/bind/irs/gai_strerror.c create mode 100644 lib/bind/irs/gen.c create mode 100644 lib/bind/irs/gen_gr.c create mode 100644 lib/bind/irs/gen_ho.c create mode 100644 lib/bind/irs/gen_ng.c create mode 100644 lib/bind/irs/gen_nw.c create mode 100644 lib/bind/irs/gen_p.h create mode 100644 lib/bind/irs/gen_pr.c create mode 100644 lib/bind/irs/gen_pw.c create mode 100644 lib/bind/irs/gen_sv.c create mode 100644 lib/bind/irs/getaddrinfo.c create mode 100644 lib/bind/irs/getgrent.c create mode 100644 lib/bind/irs/getgrent_r.c create mode 100644 lib/bind/irs/gethostent.c create mode 100644 lib/bind/irs/gethostent_r.c create mode 100644 lib/bind/irs/getnameinfo.c create mode 100644 lib/bind/irs/getnetent.c create mode 100644 lib/bind/irs/getnetent_r.c create mode 100644 lib/bind/irs/getnetgrent.c create mode 100644 lib/bind/irs/getnetgrent_r.c create mode 100644 lib/bind/irs/getprotoent.c create mode 100644 lib/bind/irs/getprotoent_r.c create mode 100644 lib/bind/irs/getpwent.c create mode 100644 lib/bind/irs/getpwent_r.c create mode 100644 lib/bind/irs/getservent.c create mode 100644 lib/bind/irs/getservent_r.c create mode 100644 lib/bind/irs/hesiod.c create mode 100644 lib/bind/irs/hesiod_p.h create mode 100644 lib/bind/irs/irp.c create mode 100644 lib/bind/irs/irp_gr.c create mode 100644 lib/bind/irs/irp_ho.c create mode 100644 lib/bind/irs/irp_ng.c create mode 100644 lib/bind/irs/irp_nw.c create mode 100644 lib/bind/irs/irp_p.h create mode 100644 lib/bind/irs/irp_pr.c create mode 100644 lib/bind/irs/irp_pw.c create mode 100644 lib/bind/irs/irp_sv.c create mode 100644 lib/bind/irs/irpmarshall.c create mode 100644 lib/bind/irs/irs_data.c create mode 100644 lib/bind/irs/irs_data.h create mode 100644 lib/bind/irs/irs_p.h create mode 100644 lib/bind/irs/lcl.c create mode 100644 lib/bind/irs/lcl_gr.c create mode 100644 lib/bind/irs/lcl_ho.c create mode 100644 lib/bind/irs/lcl_ng.c create mode 100644 lib/bind/irs/lcl_nw.c create mode 100644 lib/bind/irs/lcl_p.h create mode 100644 lib/bind/irs/lcl_pr.c create mode 100644 lib/bind/irs/lcl_pw.c create mode 100644 lib/bind/irs/lcl_sv.c create mode 100644 lib/bind/irs/nis.c create mode 100644 lib/bind/irs/nis_gr.c create mode 100644 lib/bind/irs/nis_ho.c create mode 100644 lib/bind/irs/nis_ng.c create mode 100644 lib/bind/irs/nis_nw.c create mode 100644 lib/bind/irs/nis_p.h create mode 100644 lib/bind/irs/nis_pr.c create mode 100644 lib/bind/irs/nis_pw.c create mode 100644 lib/bind/irs/nis_sv.c create mode 100644 lib/bind/irs/nul_ng.c create mode 100644 lib/bind/irs/pathnames.h create mode 100644 lib/bind/irs/util.c create mode 100644 lib/bind/isc/Makefile.in create mode 100644 lib/bind/isc/assertions.c create mode 100644 lib/bind/isc/assertions.mdoc create mode 100644 lib/bind/isc/base64.c create mode 100644 lib/bind/isc/bitncmp.c create mode 100644 lib/bind/isc/bitncmp.mdoc create mode 100644 lib/bind/isc/ctl_clnt.c create mode 100644 lib/bind/isc/ctl_p.c create mode 100644 lib/bind/isc/ctl_p.h create mode 100644 lib/bind/isc/ctl_srvr.c create mode 100644 lib/bind/isc/ev_connects.c create mode 100644 lib/bind/isc/ev_files.c create mode 100644 lib/bind/isc/ev_streams.c create mode 100644 lib/bind/isc/ev_timers.c create mode 100644 lib/bind/isc/ev_waits.c create mode 100644 lib/bind/isc/eventlib.c create mode 100644 lib/bind/isc/eventlib.mdoc create mode 100644 lib/bind/isc/eventlib_p.h create mode 100644 lib/bind/isc/heap.c create mode 100644 lib/bind/isc/heap.mdoc create mode 100644 lib/bind/isc/logging.c create mode 100644 lib/bind/isc/logging.mdoc create mode 100644 lib/bind/isc/logging_p.h create mode 100644 lib/bind/isc/memcluster.c create mode 100644 lib/bind/isc/memcluster.mdoc create mode 100644 lib/bind/isc/movefile.c create mode 100644 lib/bind/isc/tree.c create mode 100644 lib/bind/isc/tree.mdoc create mode 100644 lib/bind/make/includes.in create mode 100644 lib/bind/make/mkdep.in create mode 100644 lib/bind/make/rules.in create mode 100644 lib/bind/nameser/Makefile.in create mode 100644 lib/bind/nameser/ns_date.c create mode 100644 lib/bind/nameser/ns_name.c create mode 100644 lib/bind/nameser/ns_netint.c create mode 100644 lib/bind/nameser/ns_parse.c create mode 100644 lib/bind/nameser/ns_print.c create mode 100644 lib/bind/nameser/ns_samedomain.c create mode 100644 lib/bind/nameser/ns_sign.c create mode 100644 lib/bind/nameser/ns_ttl.c create mode 100644 lib/bind/nameser/ns_verify.c create mode 100644 lib/bind/port_after.h.in create mode 100644 lib/bind/port_before.h.in create mode 100644 lib/bind/prand_conf.c create mode 100644 lib/bind/resolv/Makefile.in create mode 100644 lib/bind/resolv/herror.c create mode 100644 lib/bind/resolv/res_comp.c create mode 100644 lib/bind/resolv/res_data.c create mode 100644 lib/bind/resolv/res_debug.c create mode 100644 lib/bind/resolv/res_debug.h create mode 100644 lib/bind/resolv/res_findzonecut.c create mode 100644 lib/bind/resolv/res_init.c create mode 100644 lib/bind/resolv/res_mkquery.c create mode 100644 lib/bind/resolv/res_mkupdate.c create mode 100644 lib/bind/resolv/res_mkupdate.h create mode 100644 lib/bind/resolv/res_private.h create mode 100644 lib/bind/resolv/res_query.c create mode 100644 lib/bind/resolv/res_send.c create mode 100644 lib/bind/resolv/res_sendsigned.c create mode 100644 lib/bind/resolv/res_update.c diff --git a/lib/bind/Makefile.in b/lib/bind/Makefile.in new file mode 100644 index 0000000000..d9ee853794 --- /dev/null +++ b/lib/bind/Makefile.in @@ -0,0 +1,20 @@ +BSDOBJS= daemon.o putenv.o strcasecmp.o strsep.o ftruncate.o \ + readv.o strdup.o strtoul.o gettimeofday.o setenv.o \ + strerror.o utimes.o mktemp.o setitimer.o strpbrk.o \ + writev.o + +SUBDIRS = bsd cylink dnssafe dst include inet irs isc nameser resolv + +OBJS= prand_conf.@O@ + +SRCS= prand_conf.c + +@BIND9_MAKE_RULES@ + +all depend: prand_conf.h + +prand_conf.h: prand_conf + ./prand_conf > $@ + +prand_conf: ${OBJS} + ${CC} -o $@ ${OBJS} diff --git a/lib/bind/README b/lib/bind/README new file mode 100644 index 0000000000..b89cff7095 --- /dev/null +++ b/lib/bind/README @@ -0,0 +1,4 @@ +--with-irs-gr=yes #define WANT_IRS_GR +--with-irs-nis=yes #define WANT_IRS_NIS +--with-irs-pw=yes #define WANT_IRS_PW + diff --git a/lib/bind/bsd/Makefile.in b/lib/bind/bsd/Makefile.in new file mode 100644 index 0000000000..4d1c74e5b9 --- /dev/null +++ b/lib/bind/bsd/Makefile.in @@ -0,0 +1,16 @@ +OBJS= daemon.@O@ ftruncate.@O@ gettimeofday.@O@ mktemp.@O@ putenv.@O@ \ + readv.@O@ setenv.@O@ setitimer.@O@ strcasecmp.@O@ strdup.@O@ \ + strerror.@O@ strpbrk.@O@ strsep.@O@ strtoul.@O@ utimes.@O@ \ + writev.@O@ + +SRCS= daemon.c ftruncate.c gettimeofday.c mktemp.c putenv.c \ + readv.c setenv.c setitimer.c strcasecmp.c strdup.c \ + strerror.c strpbrk.c strsep.c strtoul.c utimes.c \ + writev.c + +TARGETS= ${OBJS} + +CINCLUDES= -I.. -I../include +CWARNINGS= -Werror + +@BIND9_MAKE_RULES@ diff --git a/lib/bind/bsd/daemon.c b/lib/bind/bsd/daemon.c new file mode 100644 index 0000000000..a1472f969b --- /dev/null +++ b/lib/bind/bsd/daemon.c @@ -0,0 +1,79 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)daemon.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: daemon.c,v 1.1 2001/03/29 06:30:31 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "port_before.h" + +#include +#include +#include + +#include "port_after.h" + +#ifndef NEED_DAEMON +int __bind_daemon__; +#else + +int +daemon(int nochdir, int noclose) { + int fd; + + switch (fork()) { + case -1: + return (-1); + case 0: + break; + default: + _exit(0); + } + + if (setsid() == -1) + return (-1); + + if (!nochdir) + (void)chdir("/"); + + if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { + (void)dup2(fd, STDIN_FILENO); + (void)dup2(fd, STDOUT_FILENO); + (void)dup2(fd, STDERR_FILENO); + if (fd > 2) + (void)close (fd); + } + return (0); +} +#endif diff --git a/lib/bind/bsd/ftruncate.c b/lib/bind/bsd/ftruncate.c new file mode 100644 index 0000000000..56ce8d34a9 --- /dev/null +++ b/lib/bind/bsd/ftruncate.c @@ -0,0 +1,63 @@ +#ifndef LINT +static const char rcsid[] = "$Id: ftruncate.c,v 1.1 2001/03/29 06:30:32 marka Exp $"; +#endif + +/* + * ftruncate - set file size, BSD Style + * + * shortens or enlarges the file as neeeded + * uses some undocumented locking call. It is known to work on SCO unix, + * other vendors should try. + * The #error directive prevents unsupported OSes + */ + +#include "port_before.h" + +#if defined(M_UNIX) +#define OWN_FTRUNCATE +#include +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif +#ifdef _POSIX_SOURCE +#undef _POSIX_SOURCE +#endif + +#include + +#include "port_after.h" + +int +__ftruncate(int fd, long wantsize) { + long cursize; + + /* determine current file size */ + if ((cursize = lseek(fd, 0L, 2)) == -1) + return (-1); + + /* maybe lengthen... */ + if (cursize < wantsize) { + if (lseek(fd, wantsize - 1, 0) == -1 || + write(fd, "", 1) == -1) { + return (-1); + } + return (0); + } + + /* maybe shorten... */ + if (wantsize < cursize) { + struct flock fl; + + fl.l_whence = 0; + fl.l_len = 0; + fl.l_start = wantsize; + fl.l_type = F_WRLCK; + return (fcntl(fd, F_FREESP, &fl)); + } + return (0); +} +#endif + +#ifndef OWN_FTRUNCATE +int __bindcompat_ftruncate; +#endif diff --git a/lib/bind/bsd/gettimeofday.c b/lib/bind/bsd/gettimeofday.c new file mode 100644 index 0000000000..c6415aa934 --- /dev/null +++ b/lib/bind/bsd/gettimeofday.c @@ -0,0 +1,64 @@ +#ifndef LINT +static const char rcsid[] = "$Id: gettimeofday.c,v 1.1 2001/03/29 06:30:32 marka Exp $"; +#endif + +#include "port_before.h" +#undef gettimeofday +#include +#include +#include +#include "port_after.h" + +#if !defined(NEED_GETTIMEOFDAY) +/* + * gettimeofday() occasionally returns invalid tv_usec on some platforms. + */ +#define MILLION 1000000 + +#include "gettimeofday.h" + +int +isc__gettimeofday(struct timeval *tp, struct timezone *tzp) { + int res; + + res = gettimeofday(tp, tzp); + if (res < 0) + return (res); + if (tp == NULL) + return (res); + if (tp->tv_usec < 0) { + do { + tp->tv_usec += MILLION; + tp->tv_sec--; + } while (tp->tv_usec < 0); + goto log; + } else if (tp->tv_usec > MILLION) { + do { + tp->tv_usec -= MILLION; + tp->tv_sec++; + } while (tp->tv_usec > MILLION); + goto log; + } + return (res); + log: + syslog(LOG_ERR, "gettimeofday: tv_usec out of range\n"); + return (res); +} +#else +int +gettimeofday(struct timeval *tvp, struct _TIMEZONE *tzp) { + time_t clock, time(time_t *); + + if (time(&clock) == (time_t) -1) + return (-1); + if (tvp) { + tvp->tv_sec = clock; + tvp->tv_usec = 0; + } + if (tzp) { + tzp->tz_minuteswest = 0; + tzp->tz_dsttime = 0; + } + return (0); +} +#endif /*NEED_GETTIMEOFDAY*/ diff --git a/lib/bind/bsd/gettimeofday.h b/lib/bind/bsd/gettimeofday.h new file mode 100644 index 0000000000..e9975a2792 --- /dev/null +++ b/lib/bind/bsd/gettimeofday.h @@ -0,0 +1,7 @@ +#ifndef gettimeofday_h +#define gettimeofday_h +#include + +int isc__gettimeofday(struct timeval *tp, struct timezone *tzp); + +#endif diff --git a/lib/bind/bsd/mktemp.c b/lib/bind/bsd/mktemp.c new file mode 100644 index 0000000000..9852a356ac --- /dev/null +++ b/lib/bind/bsd/mktemp.c @@ -0,0 +1,154 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: mktemp.c,v 1.1 2001/03/29 06:30:33 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#if (!defined(NEED_MKTEMP)) && (!defined(NEED_MKSTEMP)) +int __mktemp_unneeded__; +#else + +static int gettemp(char *path, int *doopen); + +#ifdef NEED_MKSTEMP +mkstemp(char *path) { + int fd; + + return (gettemp(path, &fd) ? fd : -1); +} +#endif + +#ifdef NEED_MKTEMP +char * +mktemp(char *path) { + return(gettemp(path, (int *)NULL) ? path : (char *)NULL); +} +#endif + +static int +gettemp(char *path, int *doopen) { + char *start, *trv; + struct stat sbuf; + u_int pid; + + pid = getpid(); + for (trv = path; *trv; ++trv); /* extra X's get set to 0's */ + while (*--trv == 'X') { + *trv = (pid % 10) + '0'; + pid /= 10; + } + + /* + * check the target directory; if you have six X's and it + * doesn't exist this runs for a *very* long time. + */ + for (start = trv + 1;; --trv) { + if (trv <= path) + break; + if (*trv == '/') { + *trv = '\0'; + if (stat(path, &sbuf)) + return(0); + if (!S_ISDIR(sbuf.st_mode)) { + errno = ENOTDIR; + return(0); + } + *trv = '/'; + break; + } + } + + for (;;) { + if (doopen) { + if ((*doopen = + open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) + return(1); + if (errno != EEXIST) + return(0); + } + else if (stat(path, &sbuf)) + return(errno == ENOENT ? 1 : 0); + + /* tricky little algorithm for backward compatibility */ + for (trv = start;;) { + if (!*trv) + return(0); + if (*trv == 'z') + *trv++ = 'a'; + else { + if (isdigit(*trv)) + *trv = 'a'; + else + ++*trv; + break; + } + } + } + /*NOTREACHED*/ +} + +#endif /*NEED_MKTEMP*/ diff --git a/lib/bind/bsd/putenv.c b/lib/bind/bsd/putenv.c new file mode 100644 index 0000000000..abaa525d36 --- /dev/null +++ b/lib/bind/bsd/putenv.c @@ -0,0 +1,25 @@ +#ifndef LINT +static const char rcsid[] = "$Id: putenv.c,v 1.1 2001/03/29 06:30:33 marka Exp $"; +#endif + +#include "port_before.h" +#include "port_after.h" + +/* + * To give a little credit to Sun, SGI, + * and many vendors in the SysV world. + */ + +#if !defined(NEED_PUTENV) +int __bindcompat_putenv; +#else +int +putenv(char *str) { + char *tmp; + + for (tmp = str; *tmp && (*tmp != '='); tmp++) + ; + + return (setenv(str, tmp, 1)); +} +#endif diff --git a/lib/bind/bsd/readv.c b/lib/bind/bsd/readv.c new file mode 100644 index 0000000000..ccfcb5af33 --- /dev/null +++ b/lib/bind/bsd/readv.c @@ -0,0 +1,38 @@ +#ifndef LINT +static const char rcsid[] = "$Id: readv.c,v 1.1 2001/03/29 06:30:35 marka Exp $"; +#endif + +#include "port_before.h" + +#include +#include +#include +#include + +#include "port_after.h" + +#ifndef NEED_READV +int __bindcompat_readv; +#else + +int +__readv(fd, vp, vpcount) + int fd; + const struct iovec *vp; + int vpcount; +{ + int count = 0; + + while (vpcount-- > 0) { + int bytes = read(fd, vp->iov_base, vp->iov_len); + + if (bytes < 0) + return (-1); + count += bytes; + if (bytes != vp->iov_len) + break; + vp++; + } + return (count); +} +#endif /* NEED_READV */ diff --git a/lib/bind/bsd/setenv.c b/lib/bind/bsd/setenv.c new file mode 100644 index 0000000000..6a11c9db82 --- /dev/null +++ b/lib/bind/bsd/setenv.c @@ -0,0 +1,149 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)setenv.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: setenv.c,v 1.1 2001/03/29 06:30:35 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "port_before.h" + +#include +#include +#include + +#include "port_after.h" + +#if !defined(NEED_SETENV) +int __bindcompat_setenv; +#else + +extern char **environ; + +static char *findenv(const char *name, int *offset); + +/* + * setenv -- + * Set the value of the environmental variable "name" to be + * "value". If rewrite is set, replace any current value. + */ +setenv(const char *name, const char *value, int rewrite) { + extern char **environ; + static int alloced; /* if allocated space before */ + char *c; + int l_value, offset; + + if (*value == '=') /* no `=' in value */ + ++value; + l_value = strlen(value); + if ((c = findenv(name, &offset))) { /* find if already exists */ + if (!rewrite) + return (0); + if (strlen(c) >= l_value) { /* old larger; copy over */ + while (*c++ = *value++); + return (0); + } + } else { /* create new slot */ + int cnt; + char **p; + + for (p = environ, cnt = 0; *p; ++p, ++cnt); + if (alloced) { /* just increase size */ + environ = (char **)realloc((char *)environ, + (size_t)(sizeof(char *) * (cnt + 2))); + if (!environ) + return (-1); + } + else { /* get new space */ + alloced = 1; /* copy old entries into it */ + p = malloc((size_t)(sizeof(char *) * (cnt + 2))); + if (!p) + return (-1); + memcpy(p, environ, cnt * sizeof(char *)); + environ = p; + } + environ[cnt + 1] = NULL; + offset = cnt; + } + for (c = (char *)name; *c && *c != '='; ++c); /* no `=' in name */ + if (!(environ[offset] = /* name + `=' + value */ + malloc((size_t)((int)(c - name) + l_value + 2)))) + return (-1); + for (c = environ[offset]; (*c = *name++) && *c != '='; ++c); + for (*c++ = '='; *c++ = *value++;); + return (0); +} + +/* + * unsetenv(name) -- + * Delete environmental variable "name". + */ +void +unsetenv(const char *name) { + char **p; + int offset; + + while (findenv(name, &offset)) /* if set multiple times */ + for (p = &environ[offset];; ++p) + if (!(*p = *(p + 1))) + break; +} + +/* + * findenv -- + * Returns pointer to value associated with name, if any, else NULL. + * Sets offset to be the offset of the name/value combination in the + * environmental array, for use by setenv(3) and unsetenv(3). + * Explicitly removes '=' in argument name. + * + * This routine *should* be a static; don't use it. + */ +static char * +findenv(const char *name, int *offset) { + const char *np; + char **p, *c; + int len; + + if (name == NULL || environ == NULL) + return (NULL); + for (np = name; *np && *np != '='; ++np) + continue; + len = np - name; + for (p = environ; (c = *p) != NULL; ++p) + if (strncmp(c, name, len) == 0 && c[len] == '=') { + *offset = p - environ; + return (c + len + 1); + } + return (NULL); +} +#endif diff --git a/lib/bind/bsd/setitimer.c b/lib/bind/bsd/setitimer.c new file mode 100644 index 0000000000..791846a299 --- /dev/null +++ b/lib/bind/bsd/setitimer.c @@ -0,0 +1,27 @@ +#ifndef LINT +static const char rcsid[] = "$Id: setitimer.c,v 1.1 2001/03/29 06:30:35 marka Exp $"; +#endif + +#include "port_before.h" + +#include + +#include "port_after.h" + +/* + * Setitimer emulation routine. + */ +#ifndef NEED_SETITIMER +int __bindcompat_setitimer; +#else + +int +__setitimer(int which, const struct itimerval *value, + struct itimerval *ovalue) +{ + if (alarm(value->it_value.tv_sec) >= 0) + return (0); + else + return (-1); +} +#endif diff --git a/lib/bind/bsd/strcasecmp.c b/lib/bind/bsd/strcasecmp.c new file mode 100644 index 0000000000..c8c9d056bb --- /dev/null +++ b/lib/bind/bsd/strcasecmp.c @@ -0,0 +1,122 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: strcasecmp.c,v 1.1 2001/03/29 06:30:35 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "port_before.h" + +#include +#include +#include + +#include + +#include "port_after.h" + +#ifndef NEED_STRCASECMP +int __strcasecmp_unneeded__; +#else + +/* + * This array is designed for mapping upper and lower case letter + * together for a case independent comparison. The mappings are + * based upon ascii character sequences. + */ +static const u_char charmap[] = { + 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007, + 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017, + 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027, + 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037, + 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047, + 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057, + 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, + 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077, + 0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147, + 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, + 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, + 0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137, + 0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147, + 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, + 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, + 0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177, + 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, + 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, + 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, + 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, + 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, + 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, + 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, + 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, + 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, + 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, + 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, + 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, + 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, + 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, + 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, + 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377 +}; + +int +strcasecmp(const char *s1, const char *s2) { + const u_char *cm = charmap, + *us1 = (const u_char *)s1, + *us2 = (const u_char *)s2; + + while (cm[*us1] == cm[*us2++]) + if (*us1++ == '\0') + return (0); + return (cm[*us1] - cm[*--us2]); +} + +int +strncasecmp(const char *s1, const char *s2, size_t n) { + if (n != 0) { + const u_char *cm = charmap, + *us1 = (const u_char *)s1, + *us2 = (const u_char *)s2; + + do { + if (cm[*us1] != cm[*us2++]) + return (cm[*us1] - cm[*--us2]); + if (*us1++ == '\0') + break; + } while (--n != 0); + } + return (0); +} + +#endif /*NEED_STRCASECMP*/ diff --git a/lib/bind/bsd/strdup.c b/lib/bind/bsd/strdup.c new file mode 100644 index 0000000000..246bc1f49f --- /dev/null +++ b/lib/bind/bsd/strdup.c @@ -0,0 +1,18 @@ +#include "port_before.h" + +#include + +#include "port_after.h" + +#ifndef NEED_STRDUP +int __bind_strdup_unneeded; +#else +char * +strdup(const char *src) { + char *dst = malloc(strlen(src) + 1); + + if (dst) + strcpy(dst, src); + return (dst); +} +#endif diff --git a/lib/bind/bsd/strerror.c b/lib/bind/bsd/strerror.c new file mode 100644 index 0000000000..5c480291f2 --- /dev/null +++ b/lib/bind/bsd/strerror.c @@ -0,0 +1,80 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: strerror.c,v 1.1 2001/03/29 06:30:36 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "port_before.h" + +#include +#include + +#include + +#include "port_after.h" + +extern int sys_nerr; +extern char *sys_errlist[]; + +#ifndef NEED_STRERROR +int __strerror_unneeded__; +#else + +const char * +strerror(int num) { +#define UPREFIX "Unknown error: " + static char ebuf[40] = UPREFIX; /* 64-bit number + slop */ + u_int errnum; + char *p, *t; + char tmp[40]; + + errnum = num; /* convert to unsigned */ + if (errnum < sys_nerr) + return (sys_errlist[errnum]); + + /* Do this by hand, so we don't include stdio(3). */ + t = tmp; + do { + *t++ = "0123456789"[errnum % 10]; + } while (errnum /= 10); + for (p = ebuf + sizeof(UPREFIX) - 1;;) { + *p++ = *--t; + if (t <= tmp) + break; + } + return (ebuf); +} + +#endif /*NEED_STRERROR*/ diff --git a/lib/bind/bsd/strpbrk.c b/lib/bind/bsd/strpbrk.c new file mode 100644 index 0000000000..ff039e1594 --- /dev/null +++ b/lib/bind/bsd/strpbrk.c @@ -0,0 +1,68 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)strpbrk.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: strpbrk.c,v 1.1 2001/03/29 06:30:36 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "port_before.h" + +#include +#include + +#include + +#include "port_after.h" + +#ifndef NEED_STRPBRK +int __strpbrk_unneeded__; +#else + +/* + * Find the first occurrence in s1 of a character in s2 (excluding NUL). + */ +char * +strpbrk(const char *s1, const char *s2) { + const char *scanp; + int c, sc; + + while ((c = *s1++) != 0) { + for (scanp = s2; (sc = *scanp++) != 0;) + if (sc == c) + return ((char *)(s1 - 1)); + } + return (NULL); +} + +#endif /*NEED_STRPBRK*/ diff --git a/lib/bind/bsd/strsep.c b/lib/bind/bsd/strsep.c new file mode 100644 index 0000000000..3dcee4aab8 --- /dev/null +++ b/lib/bind/bsd/strsep.c @@ -0,0 +1,86 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "strsep.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: strsep.c,v 1.1 2001/03/29 06:30:36 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "port_before.h" +#include +#include +#include +#include "port_after.h" + +#ifndef NEED_STRSEP +int __strsep_unneeded__; +#else + +/* + * Get next token from string *stringp, where tokens are possibly-empty + * strings separated by characters from delim. + * + * Writes NULs into the string at *stringp to end tokens. + * delim need not remain constant from call to call. + * On return, *stringp points past the last NUL written (if there might + * be further tokens), or is NULL (if there are definitely no more tokens). + * + * If *stringp is NULL, strsep returns NULL. + */ +char * +strsep(char **stringp, const char *delim) { + char *s; + const char *spanp; + int c, sc; + char *tok; + + if ((s = *stringp) == NULL) + return (NULL); + for (tok = s;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *stringp = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} + +#endif /*NEED_STRSEP*/ diff --git a/lib/bind/bsd/strtoul.c b/lib/bind/bsd/strtoul.c new file mode 100644 index 0000000000..ab3d5a479e --- /dev/null +++ b/lib/bind/bsd/strtoul.c @@ -0,0 +1,117 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: strtoul.c,v 1.1 2001/03/29 06:30:36 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#ifndef NEED_STRTOUL +int __strtoul_unneeded__; +#else + +/* + * Convert a string to an unsigned long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +u_long +strtoul(const char *nptr, char **endptr, int base) { + const char *s = nptr; + u_long acc, cutoff; + int neg, c, any, cutlim; + + neg = 0; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + cutoff = (u_long)ULONG_MAX / (u_long)base; + cutlim = (u_long)ULONG_MAX % (u_long)base; + for (acc = 0, any = 0;; c = *s++) { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULONG_MAX; + errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} + +#endif /*NEED_STRTOUL*/ diff --git a/lib/bind/bsd/utimes.c b/lib/bind/bsd/utimes.c new file mode 100644 index 0000000000..73e4b02f45 --- /dev/null +++ b/lib/bind/bsd/utimes.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1997,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include + +#include "port_after.h" + +#ifndef NEED_UTIMES +int __bind_utimes_unneeded; +#else + +int +__utimes(char *filename, struct timeval *tvp) { + struct utimbuf utb; + + utb.actime = (time_t)tvp[0].tv_sec; + utb.modtime = (time_t)tvp[1].tv_sec; + return (utime(filename, &utb)); +} + +#endif /* NEED_UTIMES */ diff --git a/lib/bind/bsd/writev.c b/lib/bind/bsd/writev.c new file mode 100644 index 0000000000..37392880fa --- /dev/null +++ b/lib/bind/bsd/writev.c @@ -0,0 +1,86 @@ +#ifndef LINT +static const char rcsid[] = "$Id: writev.c,v 1.1 2001/03/29 06:30:37 marka Exp $"; +#endif + +#include "port_before.h" + +#include +#include +#include +#include + +#include "port_after.h" + +#ifndef NEED_WRITEV +int __bindcompat_writev; +#else + +#ifdef _CRAY +#define OWN_WRITEV +int +__writev(int fd, struct iovec *iov, int iovlen) +{ + struct stat statbuf; + + if (fstat(fd, &statbuf) < 0) + return (-1); + + /* + * Allow for atomic writes to network. + */ + if (statbuf.st_mode & S_IFSOCK) { + struct msghdr mesg; + + mesg.msg_name = 0; + mesg.msg_namelen = 0; + mesg.msg_iov = iov; + mesg.msg_iovlen = iovlen; + mesg.msg_accrights = 0; + mesg.msg_accrightslen = 0; + return (sendmsg(fd, &mesg, 0)); + } else { + struct iovec *tv; + int i, rcode = 0, count = 0; + + for (i = 0, tv = iov; i <= iovlen; tv++) { + rcode = write(fd, tv->iov_base, tv->iov_len); + + if (rcode < 0) + break; + + count += rcode; + } + + if (count == 0) + return (rcode); + else + return (count); + } +} + +#else /*_CRAY*/ + +int +__writev(fd, vp, vpcount) + int fd; + const struct iovec *vp; + int vpcount; +{ + int count = 0; + + while (vpcount-- > 0) { + int written = write(fd, vp->iov_base, vp->iov_len); + + if (written < 0) + return (-1); + count += written; + if (written != vp->iov_len) + break; + vp++; + } + return (count); +} + +#endif /*_CRAY*/ + +#endif /*NEED_WRITEV*/ diff --git a/lib/bind/config.h.in b/lib/bind/config.h.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/bind/configure b/lib/bind/configure new file mode 100644 index 0000000000..5116af49a4 --- /dev/null +++ b/lib/bind/configure @@ -0,0 +1,6825 @@ +#! /bin/sh + + +# From configure.in Revision: 1.238 + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --with-irs-gr Build ...." +ac_help="$ac_help + --with-irs-pw Build ...." +ac_help="$ac_help + --with-irs-nis Build ...." +ac_help="$ac_help + --with-openssl=PATH Specify path for system-supplied openssl + (rather than using bind-9 internal openssl)" +ac_help="$ac_help + --with-randomdev=PATH Specify path for random device" +ac_help="$ac_help + --disable-threads disable multithreading" +ac_help="$ac_help + --with-ptl2 on NetBSD, use the ptl2 thread library (experimental)" +ac_help="$ac_help + --with-purify[=PATH] use Rational purify" +ac_help="$ac_help + --with-libtool use GNU libtool (following indented options supported)" +ac_help="$ac_help + --enable-ipv6 use IPv6 [default=autodetect]" +ac_help="$ac_help + --with-kame[=PATH] use Kame IPv6 [default path /usr/local/v6]" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=resolv/herror.c + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + + + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:581: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:603: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:632: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:671: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + + + + + + +# Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:732: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_AR'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$AR" in + /*) + ac_cv_path_AR="$AR" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_AR="$AR" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_AR="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +AR="$ac_cv_path_AR" +if test -n "$AR"; then + echo "$ac_t""$AR" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +ARFLAGS="cruv" + + + +# The POSIX ln(1) program. Non-POSIX systems may substitute +# "copy" or something. +LN=ln + + +case "$AR" in + "") + { echo "configure: error: +ar program not found. Please fix your PATH to include the directory in +which ar resides, or set AR in the environment with the full path to ar. +" 1>&2; exit 1; } + + ;; +esac + +# +# Etags. +# +for ac_prog in etags emacs-etags +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:791: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_ETAGS'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$ETAGS" in + /*) + ac_cv_path_ETAGS="$ETAGS" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_ETAGS="$ETAGS" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_ETAGS="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +ETAGS="$ac_cv_path_ETAGS" +if test -n "$ETAGS"; then + echo "$ac_t""$ETAGS" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$ETAGS" && break +done + + +# +# Some systems, e.g. RH7, have the Exuberant Ctags etags instead of +# GNU emacs etags, and it requires the -L flag. +# +if test "X$ETAGS" != "X"; then + echo $ac_n "checking for Exuberant Ctags etags""... $ac_c" 1>&6 +echo "configure:833: checking for Exuberant Ctags etags" >&5 + if $ETAGS --version 2>&1 | grep 'Exuberant Ctags' >/dev/null 2>&1; then + echo "$ac_t""yes" 1>&6 + ETAGS="$ETAGS -L" + else + echo "$ac_t""no" 1>&6 + fi +fi + + +# +# Perl is optional; it is used only by some of the system test scripts. +# +for ac_prog in perl5 perl +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:851: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$PERL" in + /*) + ac_cv_path_PERL="$PERL" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_PERL="$PERL" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_PERL="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +PERL="$ac_cv_path_PERL" +if test -n "$PERL"; then + echo "$ac_t""$PERL" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$PERL" && break +done + + + +# +# Special processing of paths depending on whether --prefix, +# --sysconfdir or --localstatedir arguments were given. What's +# desired is some compatability with the way previous versions +# of BIND built; they defaulted to /usr/local for most parts of +# the installation, but named.boot/named.conf was in /etc +# and named.pid was in /var/run. +# +# So ... if none of --prefix, --sysconfdir or --localstatedir are +# specified, set things up that way. If --prefix is given, use +# it for sysconfdir and localstatedir the way configure normally +# would. To change the prefix for everything but leave named.conf +# in /etc or named.pid in /var/run, then do this the usual configure way: +# ./configure --prefix=/somewhere --sysconfdir=/etc +# ./configure --prefix=/somewhere --localstatedir=/var +# +# To put named.conf and named.pid in /usr/local with everything else, +# set the prefix explicitly to /usr/local even though that's the default: +# ./configure --prefix=/usr/local +# +case "$prefix" in + NONE) + case "$sysconfdir" in + '${prefix}/etc') + sysconfdir=/etc + ;; + esac + case "$localstatedir" in + '${prefix}/var') + localstatedir=/var + ;; + esac + ;; +esac + +# +# Make sure INSTALL uses an absolute path, else it will be wrong in all +# Makefiles, since they use make/rules.in and INSTALL will be adjusted by +# configure based on the location of the file where it is substituted. +# Since in BIND9 INSTALL is only substituted into make/rules.in, an immediate +# subdirectory of install-sh, This relative path will be wrong for all +# directories more than one level down from install-sh. +# +case "$INSTALL" in + /*) + ;; + *) + # + # Not all systems have dirname. + # + + ac_dir="`echo $INSTALL | sed 's%/[^/]*$%%'`" + + + ac_prog="`echo $INSTALL | sed 's%.*/%%'`" + test "$ac_dir" = "$ac_prog" && ac_dir=. + test -d "$ac_dir" && ac_dir="`(cd \"$ac_dir\" && pwd)`" + INSTALL="$ac_dir/$ac_prog" + ;; +esac + +# +# On these hosts, we really want to use cc, not gcc, even if it is +# found. The gcc that these systems have will not correctly handle +# pthreads. +# +# However, if the user sets $CC to be something, let that override +# our change. +# +if test "X$CC" = "X" ; then + case "$host" in + *-dec-osf*) + CC="cc" + ;; + *-solaris*) + # Use Sun's cc if it is available, but watch + # out for /usr/ucb/cc; it will never be the right + # compiler to use. + # + # If setting CC here fails, the AC_PROG_CC done + # below might still find gcc. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + case "$ac_dir" in + /usr/ucb) + # exclude + ;; + *) + if test -f "$ac_dir/cc"; then + CC="$ac_dir/cc" + break + fi + ;; + esac + done + IFS="$ac_save_ifs" + ;; + *-hp-hpux*) + CC="cc" + ;; + mips-sgi-irix*) + CC="cc" + ;; + esac +fi + + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:999: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1029: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1080: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:1112: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 1123 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:1128: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:1154: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:1159: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:1187: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:1220: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1241: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1258: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1275: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:1300: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +#include +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1313: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext < +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:1380: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + + + +for ac_hdr in fcntl.h sys/time.h unistd.h sys/sockio.h sys/select.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1409: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1419: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + +echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:1447: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:1501: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + +echo $ac_n "checking for inline""... $ac_c" 1>&6 +echo "configure:1522: checking for inline" >&5 +if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_inline=$ac_kw; break +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +done + +fi + +echo "$ac_t""$ac_cv_c_inline" 1>&6 +case "$ac_cv_c_inline" in + inline | yes) ;; + no) cat >> confdefs.h <<\EOF +#define inline +EOF + ;; + *) cat >> confdefs.h <&6 +echo "configure:1562: checking for size_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#include +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_size_t=yes +else + rm -rf conftest* + ac_cv_type_size_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_size_t" 1>&6 +if test $ac_cv_type_size_t = no; then + cat >> confdefs.h <<\EOF +#define size_t unsigned +EOF + +fi + +echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 +echo "configure:1595: checking whether time.h and sys/time.h may both be included" >&5 +if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +int main() { +struct tm *tp; +; return 0; } +EOF +if { (eval echo configure:1609: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_header_time=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_time=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_time" 1>&6 +if test $ac_cv_header_time = yes; then + cat >> confdefs.h <<\EOF +#define TIME_WITH_SYS_TIME 1 +EOF + +fi + +echo $ac_n "checking for long long""... $ac_c" 1>&6 +echo "configure:1630: checking for long long" >&5 +cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + ISC_PLATFORM_HAVELONGLONG="#define ISC_PLATFORM_HAVELONGLONG 1" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + ISC_PLATFORM_HAVELONGLONG="#undef ISC_PLATFORM_HAVELONGLONG" +fi +rm -f conftest* + + +# +# check if we need to #include sys/select.h explicitly +# +case $ac_cv_header_unistd_h in +yes) +echo $ac_n "checking if unistd.h defines fd_set""... $ac_c" 1>&6 +echo "configure:1659: checking if unistd.h defines fd_set" >&5 +cat > conftest.$ac_ext < +int main() { +fd_set read_set; return (0); +; return 0; } +EOF +if { (eval echo configure:1669: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + ISC_PLATFORM_NEEDSYSSELECTH="#undef ISC_PLATFORM_NEEDSYSSELECTH" + LWRES_PLATFORM_NEEDSYSSELECTH="#undef LWRES_PLATFORM_NEEDSYSSELECTH" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + case ac_cv_header_sys_select_h in + yes) + ISC_PLATFORM_NEEDSYSSELECTH="#define ISC_PLATFORM_NEEDSYSSELECTH 1" + LWRES_PLATFORM_NEEDSYSSELECTH="#define LWRES_PLATFORM_NEEDSYSSELECTH 1" + ;; + no) + { echo "configure: error: need either working unistd.h or sys/select.h" 1>&2; exit 1; } + ;; + esac + +fi +rm -f conftest* + ;; +no) + case ac_cv_header_sys_select_h in + yes) + ISC_PLATFORM_NEEDSYSSELECTH="#define ISC_PLATFORM_NEEDSYSSELECTH 1" + LWRES_PLATFORM_NEEDSYSSELECTH="#define LWRES_PLATFORM_NEEDSYSSELECTH 1" + ;; + no) + { echo "configure: error: need either unistd.h or sys/select.h" 1>&2; exit 1; } + ;; + esac + ;; +esac + + + +# +# Find the machine's endian flavor. +# +echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 +echo "configure:1711: checking whether byte ordering is bigendian" >&5 +if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_bigendian=unknown +# See if sys/param.h defines the BYTE_ORDER macro. +cat > conftest.$ac_ext < +#include +int main() { + +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif +; return 0; } +EOF +if { (eval echo configure:1729: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + # It does; now see whether it defined to BIG_ENDIAN or not. +cat > conftest.$ac_ext < +#include +int main() { + +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif +; return 0; } +EOF +if { (eval echo configure:1744: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_bigendian=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_bigendian=no +fi +rm -f conftest* +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +if test $ac_cv_c_bigendian = unknown; then +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_c_bigendian=no +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_c_bigendian=yes +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_c_bigendian" 1>&6 +if test $ac_cv_c_bigendian = yes; then + cat >> confdefs.h <<\EOF +#define WORDS_BIGENDIAN 1 +EOF + +fi + + +# Check whether --with-irs-gr or --without-irs-gr was given. +if test "${with_irs_gr+set}" = set; then + withval="$with_irs_gr" + want_irs_gr="$withval" +else + want_irs_gr="no" +fi + +case "$want_irs_gr" in +yes) WANT_IRS_GR="#define WANT_IRS_GR 1" + WANT_IRS_GR_OBJS="\${WANT_IRS_GR_OBJS}" + ;; +*) WANT_IRS_GR="#undef WANT_IRS_GR" WANT_IRS_GR_OBJS="";; +esac + + + +# Check whether --with-irs-pw or --without-irs-pw was given. +if test "${with_irs_pw+set}" = set; then + withval="$with_irs_pw" + want_irs_pw="$withval" +else + want_irs_pw="no" +fi + +case "$want_irs_pw" in +yes) WANT_IRS_PW="#define WANT_IRS_PW 1" + WANT_IRS_PW_OBJS="\${WANT_IRS_PW_OBJS}";; +*) WANT_IRS_PW="#undef WANT_IRS_PW" WANT_IRS_PW_OBJS="";; +esac + + + +# Check whether --with-irs-nis or --without-irs-nis was given. +if test "${with_irs_nis+set}" = set; then + withval="$with_irs_nis" + want_irs_nis="$withval" +else + want_irs_nis="no" +fi + +case "$want_irs_nis" in +yes) + WANT_IRS_NIS="#define WANT_IRS_NIS 1" + WANT_IRS_NIS_OBJS="WANT_IRS_NIS_OBJS" + case "$want_irs_gr" in + yes) + WANT_IRS_NISGR_OBJS="\${WANT_IRS_NISGR_OBJS}";; + *) + WANT_IRS_NISGR_OBJS="";; + esac + case "$want_irs_pw" in + yes) + WANT_IRS_NISPW_OBJS="\${WANT_IRS_NISPW_OBJS}";; + *) + WANT_IRS_NISPW_OBJS="";; + esac + ;; +*) + WANT_IRS_NIS="#undef WANT_IRS_NIS" + WANT_IRS_NIS_OBJS="" + WANT_IRS_NISGR_OBJS="" + WANT_IRS_NISPW_OBJS="";; +esac + + + + + +# +# was --with-openssl specified? +# +echo $ac_n "checking for compatible OpenSSL library""... $ac_c" 1>&6 +echo "configure:1874: checking for compatible OpenSSL library" >&5 +# Check whether --with-openssl or --without-openssl was given. +if test "${with_openssl+set}" = set; then + withval="$with_openssl" + use_openssl="$withval" +else + use_openssl="no" +fi + + +# +# If the user didn't specify where openssl is, and we didn't find or it +# is incompatible with our code, use our internal one. +# +# XXX This appears to assume that the user specified path is correct, +# and does no checking. +# + +case "$use_openssl" in + no) + DST_PRIVATEOPENSSL='-DDST_USE_PRIVATE_OPENSSL' + dst_privateopenssl='openssl' + DST_OPENSSL_INC='-I${srcdir}/../openssl/include' + DST_OPENSSL_LIB='' + DST_OPENSSL_OBJS='${OPENSSLOBJS}' + echo "$ac_t""using private library" 1>&6 + openssl_makefiles="lib/dns/sec/openssl/Makefile \ + lib/dns/sec/openssl/include/Makefile \ + lib/dns/sec/openssl/include/openssl/Makefile" + + ;; + yes) + { echo "configure: error: --with-openssl must specify a path" 1>&2; exit 1; } + ;; + *) + DST_PRIVATEOPENSSL='' + dst_privateopenssl='' + DST_OPENSSL_INC="-I$use_openssl/include" + DNS_OPENSSL_LIBS="-L$use_openssl/lib -lcrypto" + DST_OPENSSL_LIB='' + echo "$ac_t""using openssl from $use_openssl/lib and $use_openssl/include" 1>&6 + openssl_makefiles="" + ;; +esac + + + + + + + +# +# This would include the system openssl path (and linker options to use +# it as needed) if it is found. +# + + + +# +# was --with-gssapi specified? +# +#AC_MSG_CHECKING(for GSSAPI library) +#AC_ARG_WITH(gssapi, +#[ --with-gssapi=PATH Specify path for system-supplied GSSAPI], +# use_gssapi="$withval", use_gssapi="no") +# +#case "$use_gssapi" in +# no) +# USE_GSSAPI='' +# DST_GSSAPI_INC='' +# DNS_GSSAPI_LIBS='' +# AC_MSG_RESULT(not specified) +# ;; +# yes) +# AC_MSG_ERROR([--with-gssapi must specify a path]) +# ;; +# *) +# USE_GSSAPI='-DGSSAPI' +# DST_GSSAPI_INC="-I$use_gssapi/include" +# DNS_GSSAPI_LIBS="-L$use_gssapi/lib -lgssapi_krb5" +# AC_MSG_RESULT(using gssapi from $use_gssapi/lib and $use_gssapi/include) +# ;; +#esac + +USE_GSSAPI='' +DST_GSSAPI_INC='' +DNS_GSSAPI_LIBS='' + + + + + +# +# was --with-randomdev specified? +# +echo $ac_n "checking for random device""... $ac_c" 1>&6 +echo "configure:1970: checking for random device" >&5 +# Check whether --with-randomdev or --without-randomdev was given. +if test "${with_randomdev+set}" = set; then + withval="$with_randomdev" + use_randomdev="$withval" +else + use_randomdev="unspec" +fi + + +case "$use_randomdev" in + unspec) + case "$host" in + *-openbsd*) + devrandom=/dev/srandom + ;; + *) + devrandom=/dev/random + ;; + esac + +ac_safe=`echo "$devrandom" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $devrandom""... $ac_c" 1>&6 +echo "configure:1993: checking for $devrandom" >&5 +if eval "test \"`echo '$''{'ac_cv_file_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + { echo "configure: error: Cannot check for file existence when cross compiling" 1>&2; exit 1; } +else + if test -r $devrandom; then + eval "ac_cv_file_$ac_safe=yes" + else + eval "ac_cv_file_$ac_safe=no" + fi +fi +fi +if eval "test \"`echo '$ac_cv_file_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <&6 + +fi + + ;; + yes) + { echo "configure: error: --with-randomdev must specify a path" 1>&2; exit 1; } + ;; + *) + cat >> confdefs.h <&6 + ;; +esac + +# +# Begin pthreads checking. +# +# First, decide whether to use multithreading or not. +# +echo $ac_n "checking whether to look for thread support""... $ac_c" 1>&6 +echo "configure:2037: checking whether to look for thread support" >&5 +# Check whether --enable-threads or --disable-threads was given. +if test "${enable_threads+set}" = set; then + enableval="$enable_threads" + : +fi + +case "$enable_threads" in + yes|'') + echo "$ac_t""yes" 1>&6 + use_threads=true + ;; + no) + echo "$ac_t""no" 1>&6 + use_threads=false + ;; + *) + { echo "configure: error: --enable-threads takes yes or no" 1>&2; exit 1; } + ;; +esac + +if $use_threads +then + # + # Search for / configure pthreads in a system-dependent fashion. + # + case "$host" in + *-netbsd*) + # NetBSD has multiple pthreads implementations. The + # recommended one to use is "unproven-pthreads". The + # older "mit-pthreads" may also work on some NetBSD + # versions. The PTL2 thread library does not + # currently work with bind9, but can be chosen with + # the --with-ptl2 option for those who wish to + # experiment with it. + CC="gcc" + echo $ac_n "checking which NetBSD thread library to use""... $ac_c" 1>&6 +echo "configure:2074: checking which NetBSD thread library to use" >&5 + + # Check whether --with-ptl2 or --without-ptl2 was given. +if test "${with_ptl2+set}" = set; then + withval="$with_ptl2" + use_ptl2="$withval" +else + use_ptl2="no" +fi + + + : ${LOCALBASE:=/usr/pkg} + + if test "X$use_ptl2" = "Xyes" + then + echo "$ac_t""PTL2" 1>&6 + echo "configure: warning: linking with PTL2 is highly experimental and not expected to work" 1>&2 + CC=ptlgcc + else + if test ! -d $LOCALBASE/pthreads + then + echo "$ac_t""none" 1>&6 + use_threads=false + fi + + if $use_threads + then + echo "$ac_t""mit-pthreads/unproven-pthreads" 1>&6 + pkg="$LOCALBASE/pthreads" + lib1="-L$pkg/lib -Wl,-R$pkg/lib" + lib2="-lpthread -lm -lgcc -lpthread" + LIBS="$lib1 $lib2 $LIBS" + CPPFLAGS="$CPPFLAGS -I$pkg/include" + STD_CINCLUDES="$STD_CINCLUDES -I$pkg/include" + fi + fi + ;; + *) + echo $ac_n "checking for pthread_create in -lpthread""... $ac_c" 1>&6 +echo "configure:2113: checking for pthread_create in -lpthread" >&5 +ac_lib_var=`echo pthread'_'pthread_create | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lpthread $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo pthread | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +echo $ac_n "checking for __pthread_create in -lpthread""... $ac_c" 1>&6 +echo "configure:2158: checking for __pthread_create in -lpthread" >&5 +ac_lib_var=`echo pthread'_'__pthread_create | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lpthread $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo pthread | sed -e 's/^a-zA-Z0-9_/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +echo $ac_n "checking for __pthread_create_system in -lpthread""... $ac_c" 1>&6 +echo "configure:2203: checking for __pthread_create_system in -lpthread" >&5 +ac_lib_var=`echo pthread'_'__pthread_create_system | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lpthread $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo pthread | sed -e 's/^a-zA-Z0-9_/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +echo $ac_n "checking for pthread_create in -lc_r""... $ac_c" 1>&6 +echo "configure:2248: checking for pthread_create in -lc_r" >&5 +ac_lib_var=`echo c_r'_'pthread_create | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lc_r $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo c_r | sed -e 's/^a-zA-Z0-9_/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +echo $ac_n "checking for pthread_create in -lc""... $ac_c" 1>&6 +echo "configure:2293: checking for pthread_create in -lc" >&5 +ac_lib_var=`echo c'_'pthread_create | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lc $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo c | sed -e 's/^a-zA-Z0-9_/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +use_threads=false +fi + +fi + +fi + +fi + +fi + + ;; + esac +fi + +if $use_threads +then + # + # We'd like to use sigwait() too + # + echo $ac_n "checking for sigwait in -lc""... $ac_c" 1>&6 +echo "configure:2358: checking for sigwait in -lc" >&5 +ac_lib_var=`echo c'_'sigwait | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lc $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_SIGWAIT 1 +EOF + +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for sigwait in -lpthread""... $ac_c" 1>&6 +echo "configure:2399: checking for sigwait in -lpthread" >&5 +ac_lib_var=`echo pthread'_'sigwait | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lpthread $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_SIGWAIT 1 +EOF + +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for _Psigwait in -lpthread""... $ac_c" 1>&6 +echo "configure:2440: checking for _Psigwait in -lpthread" >&5 +ac_lib_var=`echo pthread'_'_Psigwait | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lpthread $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_SIGWAIT 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + +fi + + +fi + + + echo $ac_n "checking for pthread_attr_getstacksize""... $ac_c" 1>&6 +echo "configure:2489: checking for pthread_attr_getstacksize" >&5 +if eval "test \"`echo '$''{'ac_cv_func_pthread_attr_getstacksize'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char pthread_attr_getstacksize(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_pthread_attr_getstacksize) || defined (__stub___pthread_attr_getstacksize) +choke me +#else +pthread_attr_getstacksize(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2517: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_pthread_attr_getstacksize=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_pthread_attr_getstacksize=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'pthread_attr_getstacksize`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_PTHREAD_ATTR_GETSTACKSIZE 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + + + # + # Additional OS-specific issues related to pthreads and sigwait. + # + case "$host" in + # + # One more place to look for sigwait. + # + *-freebsd*) + echo $ac_n "checking for sigwait in -lc_r""... $ac_c" 1>&6 +echo "configure:2549: checking for sigwait in -lc_r" >&5 +ac_lib_var=`echo c_r'_'sigwait | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lc_r $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_SIGWAIT 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + + ;; + # + # BSDI 3.0 through 4.0.1 needs pthread_init() to be + # called before certain pthreads calls. This is deprecated + # in BSD/OS 4.1. + # + *-bsdi3.*|*-bsdi4.0*) + cat >> confdefs.h <<\EOF +#define NEED_PTHREAD_INIT 1 +EOF + + ;; + # + # LinuxThreads requires some changes to the way we + # deal with signals. + # + *-linux*) + cat >> confdefs.h <<\EOF +#define HAVE_LINUXTHREADS 1 +EOF + + ;; + # + # Ensure the right sigwait() semantics on Solaris and make + # sure we call pthread_setconcurrency. + # + *-solaris*) + cat >> confdefs.h <<\EOF +#define _POSIX_PTHREAD_SEMANTICS 1 +EOF + + echo $ac_n "checking for pthread_setconcurrency""... $ac_c" 1>&6 +echo "configure:2623: checking for pthread_setconcurrency" >&5 +if eval "test \"`echo '$''{'ac_cv_func_pthread_setconcurrency'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char pthread_setconcurrency(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_pthread_setconcurrency) || defined (__stub___pthread_setconcurrency) +choke me +#else +pthread_setconcurrency(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2651: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_pthread_setconcurrency=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_pthread_setconcurrency=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'pthread_setconcurrency`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define CALL_PTHREAD_SETCONCURRENCY 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + + ;; + # + # UnixWare does things its own way. + # + *-UnixWare*) + cat >> confdefs.h <<\EOF +#define HAVE_UNIXWARE_SIGWAIT 1 +EOF + + ;; + esac + + # + # Look for sysconf to allow detection of the number of processors. + # + echo $ac_n "checking for sysconf""... $ac_c" 1>&6 +echo "configure:2689: checking for sysconf" >&5 +if eval "test \"`echo '$''{'ac_cv_func_sysconf'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char sysconf(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_sysconf) || defined (__stub___sysconf) +choke me +#else +sysconf(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2717: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_sysconf=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_sysconf=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'sysconf`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_SYSCONF 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + + + if test "X$GCC" = "Xyes"; then + case "$host" in + *-freebsd*) + CC="$CC -pthread" + CCOPT="$CCOPT -pthread" + STD_CDEFINES="$STD_CDEFINES -D_THREAD_SAFE" + ;; + *-openbsd*) + CC="$CC -pthread" + CCOPT="$CCOPT -pthread" + ;; + *-solaris*) + LIBS="$LIBS -lthread" + ;; + *-ibm-aix*) + STD_CDEFINES="$STD_CDEFINES -D_THREAD_SAFE" + ;; + esac + else + case $host in + *-dec-osf*) + CC="$CC -pthread" + CCOPT="$CCOPT -pthread" + ;; + *-solaris*) + CC="$CC -mt" + CCOPT="$CCOPT -mt" + ;; + *-ibm-aix*) + STD_CDEFINES="$STD_CDEFINES -D_THREAD_SAFE" + ;; + *-UnixWare*) + CC="$CC -Kthread" + CCOPT="$CCOPT -Kthread" + ;; + esac + fi + ALWAYS_DEFINES="-D_REENTRANT" + DO_PTHREADS="#define DO_PTHREADS 1" + WANT_IRS_THREADSGR_OBJS="\${WANT_IRS_THREADSGR_OBJS}" + WANT_IRS_THREADSPW_OBJS="\${WANT_IRS_THREADSPW_OBJS}" + WANT_IRS_THREADS_OBJS="\${WANT_IRS_THREADS_OBJS}" + thread_dir=pthreads +else + ALWAYS_DEFINES="" + DO_PTHREADS="#undef DO_PTHREADS" + WANT_IRS_THREADSGR_OBJS="" + WANT_IRS_THREADSPW_OBJS="" + WANT_IRS_THREADS_OBJS="" + thread_dir=nothreads +fi + + + + + + + +ISC_THREAD_DIR=$thread_dir + + +# +# flockfile is usually provided by pthreads, but we may want to use it +# even if compiled with --disable-threads. +# +echo $ac_n "checking for flockfile""... $ac_c" 1>&6 +echo "configure:2806: checking for flockfile" >&5 +if eval "test \"`echo '$''{'ac_cv_func_flockfile'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char flockfile(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_flockfile) || defined (__stub___flockfile) +choke me +#else +flockfile(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2834: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_flockfile=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_flockfile=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'flockfile`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_FLOCKFILE 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + + +# +# Indicate what the final decision was regarding threads. +# +echo $ac_n "checking whether to build with threads""... $ac_c" 1>&6 +echo "configure:2861: checking whether to build with threads" >&5 +if $use_threads; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# +# End of pthreads stuff. +# + +# +# Additional compiler settings. +# +MKDEPCC="$CC" +MKDEPCFLAGS="-M" +IRIX_DNSSEC_WARNINGS_HACK="" + +if test "X$GCC" = "Xyes"; then + STD_CWARNINGS="$STD_CWARNINGS -W -Wall -Wmissing-prototypes -Wcast-qual -Wwrite-strings" +else + case $host in + *-dec-osf*) + CC="$CC -std" + CCOPT="$CCOPT -std" + MKDEPCC="$CC" + ;; + *-hp-hpux*) + CC="$CC -Ae -z" + # The version of the C compiler that constantly warns about + # 'const' as well as alignment issues is unfortunately not + # able to be discerned via the version of the operating + # system, nor does cc have a version flag. + case "`$CC +W 123 2>&1`" in + *Unknown?option*) + STD_CWARNINGS="+w1" + ;; + *) + # Turn off the pointlessly noisy warnings. + STD_CWARNINGS="+w1 +W 474,530" + ;; + esac + CCOPT="$CCOPT -Ae -z" + LIBS="-Wl,+vnocompatwarnings $LIBS" + MKDEPPROG='cc -Ae -E -Wp,-M >/dev/null 2>>$TMP' + ;; + *-sgi-irix*) + STD_CWARNINGS="-fullwarn -woff 1209" + # + # Silence more than 250 instances of + # "prototyped function redeclared without prototype" + # and 11 instances of + # "variable ... was set but never used" + # from lib/dns/sec/openssl. + # + IRIX_DNSSEC_WARNINGS_HACK="-woff 1692,1552" + ;; + *-solaris*) + MKDEPCFLAGS="-xM" + ;; + *-UnixWare*) + CC="$CC -w" + ;; + esac +fi + + + + + + +# +# NLS +# +echo $ac_n "checking for catgets""... $ac_c" 1>&6 +echo "configure:2936: checking for catgets" >&5 +if eval "test \"`echo '$''{'ac_cv_func_catgets'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char catgets(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_catgets) || defined (__stub___catgets) +choke me +#else +catgets(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2964: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_catgets=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_catgets=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'catgets`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_CATGETS 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + + +# +# -lxnet buys us one big porting headache... standards, gotta love 'em. +# +# AC_CHECK_LIB(xnet, socket, , +# AC_CHECK_LIB(socket, socket) +# AC_CHECK_LIB(nsl, inet_ntoa) +# ) +# +# Use this for now, instead: +# +case "$host" in + mips-sgi-irix*) + ;; + *) + echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6 +echo "configure:3002: checking for socket in -lsocket" >&5 +ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lsocket $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +fi + + echo $ac_n "checking for inet_ntoa in -lnsl""... $ac_c" 1>&6 +echo "configure:3049: checking for inet_ntoa in -lnsl" >&5 +ac_lib_var=`echo nsl'_'inet_ntoa | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lnsl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +fi + + ;; +esac + +# +# Purify support +# +echo $ac_n "checking whether to use purify""... $ac_c" 1>&6 +echo "configure:3102: checking whether to use purify" >&5 +# Check whether --with-purify or --without-purify was given. +if test "${with_purify+set}" = set; then + withval="$with_purify" + use_purify="$withval" +else + use_purify="no" +fi + + +case "$use_purify" in + no) + ;; + yes) + # Extract the first word of "purify", so it can be a program name with args. +set dummy purify; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:3119: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_purify_path'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$purify_path" in + /*) + ac_cv_path_purify_path="$purify_path" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_purify_path="$purify_path" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_purify_path="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_purify_path" && ac_cv_path_purify_path="purify" + ;; +esac +fi +purify_path="$ac_cv_path_purify_path" +if test -n "$purify_path"; then + echo "$ac_t""$purify_path" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + ;; + *) + purify_path="$use_purify" + ;; +esac + +case "$use_purify" in + no) + echo "$ac_t""no" 1>&6 + PURIFY="" + ;; + *) + if test -f $purify_path || test $purify_path = purify; then + echo "$ac_t""$purify_path" 1>&6 + PURIFYFLAGS="`echo $PURIFYOPTIONS`" + PURIFY="$purify_path $PURIFYFLAGS" + else + { echo "configure: error: $purify_path not found. + +Please choose the proper path with the following command: + + configure --with-purify=PATH +" 1>&2; exit 1; } + fi + ;; +esac + + + +# +# GNU libtool support +# +# Check whether --with-libtool or --without-libtool was given. +if test "${with_libtool+set}" = set; then + withval="$with_libtool" + use_libtool="$withval" +else + use_libtool="no" +fi + + +case $use_libtool in + yes) + AM_PROG_LIBTOOL + O=lo + A=la + ;; + *) + O=o + A=a + LIBTOOL= + + ;; +esac + +# +# File name extension for static archive files, for those few places +# where they are treated differently from dynamic ones. +# +SA=a + + + + + +# +# Here begins a very long section to determine the system's networking +# capabilities. The order of the tests is signficant. +# + +# +# IPv6 +# +# Check whether --enable-ipv6 or --disable-ipv6 was given. +if test "${enable_ipv6+set}" = set; then + enableval="$enable_ipv6" + : +fi + + +case "$enable_ipv6" in + yes|''|autodetect) + cat >> confdefs.h <<\EOF +#define WANT_IPV6 1 +EOF + + ;; + no) + ;; +esac + +# +# We do the IPv6 compilation checking after libtool so that we can put +# the right suffix on the files. +# +echo $ac_n "checking for IPv6 structures""... $ac_c" 1>&6 +echo "configure:3248: checking for IPv6 structures" >&5 +cat > conftest.$ac_ext < +#include +#include +int main() { +struct sockaddr_in6 sin6; return (0); +; return 0; } +EOF +if { (eval echo configure:3260: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + found_ipv6=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + found_ipv6=no +fi +rm -f conftest* + +# +# See whether IPv6 support is provided via a Kame add-on. +# This is done before other IPv6 linking tests to LIBS is properly set. +# +echo $ac_n "checking for Kame IPv6 support""... $ac_c" 1>&6 +echo "configure:3278: checking for Kame IPv6 support" >&5 +# Check whether --with-kame or --without-kame was given. +if test "${with_kame+set}" = set; then + withval="$with_kame" + use_kame="$withval" +else + use_kame="no" +fi + + +case "$use_kame" in + no) + ;; + yes) + kame_path=/usr/local/v6 + ;; + *) + kame_path="$use_kame" + ;; +esac + +case "$use_kame" in + no) + echo "$ac_t""no" 1>&6 + ;; + *) + if test -f $kame_path/lib/libinet6.a; then + echo "$ac_t""$kame_path/lib/libinet6.a" 1>&6 + LIBS="-L$kame_path/lib -linet6 $LIBS" + else + { echo "configure: error: $kame_path/lib/libinet6.a not found. + +Please choose the proper path with the following command: + + configure --with-kame=PATH +" 1>&2; exit 1; } + fi + ;; +esac + +# +# Whether netinet6/in6.h is needed has to be defined in isc/platform.h. +# Including it on Kame-using platforms is very bad, though, because +# Kame uses #error against direct inclusion. So include it on only +# the platform that is otherwise broken without it -- BSD/OS 4.0 through 4.1. +# This is done before the in6_pktinfo check because that's what +# netinet6/in6.h is needed for. +# + +case "$host" in +*-bsdi4.[01]*) + ISC_PLATFORM_NEEDNETINET6IN6H="#define ISC_PLATFORM_NEEDNETINET6IN6H 1" + LWRES_PLATFORM_NEEDNETINET6IN6H="#define LWRES_PLATFORM_NEEDNETINET6IN6H 1" + isc_netinet6in6_hack="#include " + ;; +*) + ISC_PLATFORM_NEEDNETINET6IN6H="#undef ISC_PLATFORM_NEEDNETINET6IN6H" + LWRES_PLATFORM_NEEDNETINET6IN6H="#undef LWRES_PLATFORM_NEEDNETINET6IN6H" + isc_netinet6in6_hack="" + ;; +esac + + +# +# This is similar to the netinet6/in6.h issue. +# +case "$host" in +*-UnixWare*) + ISC_PLATFORM_NEEDNETINETIN6H="#define ISC_PLATFORM_NEEDNETINETIN6H 1" + LWRES_PLATFORM_NEEDNETINETIN6H="#define LWRES_PLATFORM_NEEDNETINETIN6H 1" + ISC_PLATFORM_FIXIN6ISADDR="#define ISC_PLATFORM_FIXIN6ISADDR 1" + isc_netinetin6_hack="#include " + ;; +*) + ISC_PLATFORM_NEEDNETINETIN6H="#undef ISC_PLATFORM_NEEDNETINETIN6H" + LWRES_PLATFORM_NEEDNETINETIN6H="#undef LWRES_PLATFORM_NEEDNETINETIN6H" + ISC_PLATFORM_FIXIN6ISADDR="#undef ISC_PLATFORM_FIXIN6ISADDR" + isc_netinetin6_hack="" + ;; +esac + +# +# Now delve deeper into the suitability of the IPv6 support. +# +case "$found_ipv6" in + yes) + ISC_PLATFORM_HAVEIPV6="#define ISC_PLATFORM_HAVEIPV6 1" + LWRES_PLATFORM_HAVEIPV6="#define LWRES_PLATFORM_HAVEIPV6 1" + + echo $ac_n "checking for in6_addr""... $ac_c" 1>&6 +echo "configure:3368: checking for in6_addr" >&5 + cat > conftest.$ac_ext < +#include +#include +$isc_netinetin6_hack +$isc_netinet6in6_hack + +int main() { +struct in6_addr in6; return (0); +; return 0; } +EOF +if { (eval echo configure:3383: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + ISC_PLATFORM_HAVEINADDR6="#undef ISC_PLATFORM_HAVEINADDR6" + LWRES_PLATFORM_HAVEINADDR6="#undef LWRES_PLATFORM_HAVEINADDR6" + isc_in_addr6_hack="" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + ISC_PLATFORM_HAVEINADDR6="#define ISC_PLATFORM_HAVEINADDR6 1" + LWRES_PLATFORM_HAVEINADDR6="#define LWRES_PLATFORM_HAVEINADDR6 1" + isc_in_addr6_hack="#define in6_addr in_addr6" +fi +rm -f conftest* + + echo $ac_n "checking for in6addr_any""... $ac_c" 1>&6 +echo "configure:3401: checking for in6addr_any" >&5 + cat > conftest.$ac_ext < +#include +#include +$isc_netinetin6_hack +$isc_netinet6in6_hack +$isc_in_addr6_hack + +int main() { +struct in6_addr in6; in6 = in6addr_any; return (0); +; return 0; } +EOF +if { (eval echo configure:3417: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + ISC_PLATFORM_NEEDIN6ADDRANY="#undef ISC_PLATFORM_NEEDIN6ADDRANY" + LWRES_PLATFORM_NEEDIN6ADDRANY="#undef LWRES_PLATFORM_NEEDIN6ADDRANY" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + ISC_PLATFORM_NEEDIN6ADDRANY="#define ISC_PLATFORM_NEEDIN6ADDRANY 1" + LWRES_PLATFORM_NEEDIN6ADDRANY="#define LWRES_PLATFORM_NEEDIN6ADDRANY 1" +fi +rm -f conftest* + + echo $ac_n "checking for sin6_scope_id in struct sockaddr_in6""... $ac_c" 1>&6 +echo "configure:3433: checking for sin6_scope_id in struct sockaddr_in6" >&5 + cat > conftest.$ac_ext < +#include +#include +$isc_netinetin6_hack +$isc_netinet6in6_hack + +int main() { +struct sockaddr_in6 xyzzy; xyzzy.sin6_scope_id = 0; return (0); +; return 0; } +EOF +if { (eval echo configure:3448: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + result="#define LWRES_HAVE_SIN6_SCOPE_ID 1" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + result="#undef LWRES_HAVE_SIN6_SCOPE_ID" +fi +rm -f conftest* + LWRES_HAVE_SIN6_SCOPE_ID="$result" + + echo $ac_n "checking for in6_pktinfo""... $ac_c" 1>&6 +echo "configure:3463: checking for in6_pktinfo" >&5 + cat > conftest.$ac_ext < +#include +#include +$isc_netinetin6_hack +$isc_netinet6in6_hack + +int main() { +struct in6_pktinfo xyzzy; return (0); +; return 0; } +EOF +if { (eval echo configure:3478: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + ISC_PLATFORM_HAVEIN6PKTINFO="#define ISC_PLATFORM_HAVEIN6PKTINFO 1" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no -- disabling runtime ipv6 support" 1>&6 + ISC_PLATFORM_HAVEIN6PKTINFO="#undef ISC_PLATFORM_HAVEIN6PKTINFO" +fi +rm -f conftest* + ;; + no) + ISC_PLATFORM_HAVEIPV6="#undef ISC_PLATFORM_HAVEIPV6" + LWRES_PLATFORM_HAVEIPV6="#undef LWRES_PLATFORM_HAVEIPV6" + ISC_PLATFORM_NEEDIN6ADDRANY="#undef ISC_PLATFORM_NEEDIN6ADDRANY" + LWRES_PLATFORM_NEEDIN6ADDRANY="#undef LWRES_PLATFORM_NEEDIN6ADDRANY" + ISC_PLATFORM_HAVEIN6PKTINFO="#undef ISC_PLATFORM_HAVEIN6PKTINFO" + LWRES_HAVE_SIN6_SCOPE_ID="#define LWRES_HAVE_SIN6_SCOPE_ID 1" + ISC_IPV6_H="ipv6.h" + ISC_IPV6_O="ipv6.$O" + ISC_ISCIPV6_O="unix/ipv6.$O" + ISC_IPV6_C="ipv6.c" + ;; +esac + + + + + + + + + + + + + + + + + + + +# +# Check for network functions that are often missing. We do this +# after the libtool checking, so we can put the right suffix on +# the files. It also needs to come after checking for a Kame add-on, +# which provides some (all?) of the desired functions. +# +echo $ac_n "checking for inet_ntop""... $ac_c" 1>&6 +echo "configure:3530: checking for inet_ntop" >&5 +cat > conftest.$ac_ext < +#include +#include +int main() { +inet_ntop(0, 0, 0, 0); return (0); +; return 0; } +EOF +if { (eval echo configure:3542: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + ISC_PLATFORM_NEEDNTOP="#undef ISC_PLATFORM_NEEDNTOP" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_ntop.$O" + ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_ntop.c" + ISC_PLATFORM_NEEDNTOP="#define ISC_PLATFORM_NEEDNTOP 1" +fi +rm -f conftest* +echo $ac_n "checking for inet_pton""... $ac_c" 1>&6 +echo "configure:3557: checking for inet_pton" >&5 +cat > conftest.$ac_ext < +#include +#include +int main() { +inet_pton(0, 0, 0); return (0); +; return 0; } +EOF +if { (eval echo configure:3569: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_pton.$O" + ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_pton.c" + ISC_PLATFORM_NEEDPTON="#define ISC_PLATFORM_NEEDPTON 1" +fi +rm -f conftest* +echo $ac_n "checking for inet_aton""... $ac_c" 1>&6 +echo "configure:3584: checking for inet_aton" >&5 +cat > conftest.$ac_ext < +#include +#include +int main() { +struct in_addr in; inet_aton(0, &in); return (0); +; return 0; } +EOF +if { (eval echo configure:3596: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + ISC_PLATFORM_NEEDATON="#undef ISC_PLATFORM_NEEDATON" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_aton.$O" + ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_aton.c" + ISC_PLATFORM_NEEDATON="#define ISC_PLATFORM_NEEDATON 1" +fi +rm -f conftest* + + + + + +# +# Look for a 4.4BSD-style sa_len member in struct sockaddr. +# +case "$host" in + *-dec-osf*) + # Turn on 4.4BSD style sa_len support. + cat >> confdefs.h <<\EOF +#define _SOCKADDR_LEN 1 +EOF + + ;; +esac + +echo $ac_n "checking for sa_len in struct sockaddr""... $ac_c" 1>&6 +echo "configure:3629: checking for sa_len in struct sockaddr" >&5 +cat > conftest.$ac_ext < +#include +int main() { +struct sockaddr sa; sa.sa_len = 0; return (0); +; return 0; } +EOF +if { (eval echo configure:3640: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + HAVE_SA_LEN="#define HAVE_SA_LEN 1" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + HAVE_SA_LEN="#undef HAVE_SA_LEN" +fi +rm -f conftest* + + +# HAVE_MINIMUM_IFREQ + +case "$host" in + *-bsdi4*) have_minimum_ifreq=yes;; + *-bsdi3*) have_minimum_ifreq=yes;; + *-bsdi2*) have_minimum_ifreq=yes;; + *-darwin*) have_minimum_ifreq=yes;; + *-freebsd*) have_minimum_ifreq=yes;; + *-lynxos*) have_minimum_ifreq=yes;; + *-netbsd*) have_minimum_ifreq=yes;; + *-next*) have_minimum_ifreq=yes;; + *-openbsd*) have_minimum_ifreq=yes;; + *-rhapsody*) have_minimum_ifreq=yes;; +esac +case "$have_minimum_ifreq" in + yes) + HAVE_MINIMUM_IFREQ="#define HAVE_MINIMUM_IFREQ 1";; + no) + HAVE_MINIMUM_IFREQ="#undef HAVE_MINIMUM_IFREQ";; + *) + HAVE_MINIMUM_IFREQ="#undef HAVE_MINIMUM_IFREQ";; +esac + +# +# Look for a 4.4BSD or 4.3BSD struct msghdr +# +echo $ac_n "checking for struct msghdr flavor""... $ac_c" 1>&6 +echo "configure:3681: checking for struct msghdr flavor" >&5 +cat > conftest.$ac_ext < +#include +int main() { +struct msghdr msg; msg.msg_flags = 0; return (0); +; return 0; } +EOF +if { (eval echo configure:3692: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""4.4BSD" 1>&6 + ISC_PLATFORM_MSGHDRFLAVOR="#define ISC_NET_BSD44MSGHDR 1" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""4.3BSD" 1>&6 + ISC_PLATFORM_MSGHDRFLAVOR="#define ISC_NET_BSD43MSGHDR 1" +fi +rm -f conftest* + + +# +# Look for in_port_t. +# +echo $ac_n "checking for type in_port_t""... $ac_c" 1>&6 +echo "configure:3710: checking for type in_port_t" >&5 +cat > conftest.$ac_ext < +#include +int main() { +in_port_t port = 25; return (0); +; return 0; } +EOF +if { (eval echo configure:3721: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + ISC_PLATFORM_NEEDPORTT="#undef ISC_PLATFORM_NEEDPORTT" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + ISC_PLATFORM_NEEDPORTT="#define ISC_PLATFORM_NEEDPORTT 1" +fi +rm -f conftest* + + +# +# Check for addrinfo +# +echo $ac_n "checking for struct addrinfo""... $ac_c" 1>&6 +echo "configure:3739: checking for struct addrinfo" >&5 +cat > conftest.$ac_ext < +int main() { +struct addrinfo a; return (0); +; return 0; } +EOF +if { (eval echo configure:3749: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + ISC_LWRES_NEEDADDRINFO="#undef ISC_LWRES_NEEDADDRINFO" + cat >> confdefs.h <<\EOF +#define HAVE_ADDRINFO 1 +EOF + +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + ISC_LWRES_NEEDADDRINFO="#define ISC_LWRES_NEEDADDRINFO 1" +fi +rm -f conftest* + + +echo $ac_n "checking for int sethostent""... $ac_c" 1>&6 +echo "configure:3768: checking for int sethostent" >&5 +cat > conftest.$ac_ext < +int main() { +int i = sethostent(0); return(0); +; return 0; } +EOF +if { (eval echo configure:3778: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + ISC_LWRES_SETHOSTENTINT="#define ISC_LWRES_SETHOSTENTINT 1" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + ISC_LWRES_SETHOSTENTINT="#undef ISC_LWRES_SETHOSTENTINT" +fi +rm -f conftest* + + +echo $ac_n "checking for int endhostent""... $ac_c" 1>&6 +echo "configure:3793: checking for int endhostent" >&5 +cat > conftest.$ac_ext < +int main() { +int i = endhostent(); return(0); +; return 0; } +EOF +if { (eval echo configure:3803: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + ISC_LWRES_ENDHOSTENTINT="#define ISC_LWRES_ENDHOSTENTINT 1" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + ISC_LWRES_ENDHOSTENTINT="#undef ISC_LWRES_ENDHOSTENTINT" +fi +rm -f conftest* + + +echo $ac_n "checking for getnetbyaddr(in_addr_t, ...)""... $ac_c" 1>&6 +echo "configure:3818: checking for getnetbyaddr(in_addr_t, ...)" >&5 +cat > conftest.$ac_ext < +struct netent *getnetbyaddr(in_addr_t, int); +int main() { + +; return 0; } +EOF +if { (eval echo configure:3829: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + GETNETBYADDR_ADDR_T="#define GETNETBYADDR_ADDR_T in_addr_t" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + GETNETBYADDR_ADDR_T="#define GETNETBYADDR_ADDR_T long" +fi +rm -f conftest* + + +echo $ac_n "checking for int setnetent""... $ac_c" 1>&6 +echo "configure:3844: checking for int setnetent" >&5 +cat > conftest.$ac_ext < +int main() { +int i = setnetent(0); return(0); +; return 0; } +EOF +if { (eval echo configure:3854: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + ISC_LWRES_SETNETENTINT="#define ISC_LWRES_SETNETENTINT 1" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + ISC_LWRES_SETNETENTINT="#undef ISC_LWRES_SETNETENTINT" +fi +rm -f conftest* + + +echo $ac_n "checking for int endnetent""... $ac_c" 1>&6 +echo "configure:3869: checking for int endnetent" >&5 +cat > conftest.$ac_ext < +int main() { +int i = endnetent(); return(0); +; return 0; } +EOF +if { (eval echo configure:3879: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + ISC_LWRES_ENDNETENTINT="#define ISC_LWRES_ENDNETENTINT 1" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + ISC_LWRES_ENDNETENTINT="#undef ISC_LWRES_ENDNETENTINT" +fi +rm -f conftest* + + +echo $ac_n "checking for gethostbyaddr(const void *, size_t, ...)""... $ac_c" 1>&6 +echo "configure:3894: checking for gethostbyaddr(const void *, size_t, ...)" >&5 +cat > conftest.$ac_ext < +struct hostent *gethostbyaddr(const void *, size_t, int); +int main() { +return(0); +; return 0; } +EOF +if { (eval echo configure:3905: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + ISC_LWRES_GETHOSTBYADDRVOID="#define ISC_LWRES_GETHOSTBYADDRVOID 1" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + ISC_LWRES_GETHOSTBYADDRVOID="#undef ISC_LWRES_GETHOSTBYADDRVOID" +fi +rm -f conftest* + + +echo $ac_n "checking for h_errno in netdb.h""... $ac_c" 1>&6 +echo "configure:3920: checking for h_errno in netdb.h" >&5 +cat > conftest.$ac_ext < +int main() { +h_errno = 1; return(0); +; return 0; } +EOF +if { (eval echo configure:3930: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + ISC_LWRES_NEEDHERRNO="#undef ISC_LWRES_NEEDHERRNO" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 + ISC_LWRES_NEEDHERRNO="#define ISC_LWRES_NEEDHERRNO 1" +fi +rm -f conftest* + + +echo $ac_n "checking for getipnodebyname""... $ac_c" 1>&6 +echo "configure:3945: checking for getipnodebyname" >&5 +if eval "test \"`echo '$''{'ac_cv_func_getipnodebyname'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getipnodebyname(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_getipnodebyname) || defined (__stub___getipnodebyname) +choke me +#else +getipnodebyname(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3973: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_getipnodebyname=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_getipnodebyname=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'getipnodebyname`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ISC_LWRES_GETIPNODEPROTO="#undef ISC_LWRES_GETIPNODEPROTO" +else + echo "$ac_t""no" 1>&6 +ISC_LWRES_GETIPNODEPROTO="#define ISC_LWRES_GETIPNODEPROTO 1" +fi + +echo $ac_n "checking for getnameinfo""... $ac_c" 1>&6 +echo "configure:3994: checking for getnameinfo" >&5 +if eval "test \"`echo '$''{'ac_cv_func_getnameinfo'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getnameinfo(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_getnameinfo) || defined (__stub___getnameinfo) +choke me +#else +getnameinfo(); +#endif + +; return 0; } +EOF +if { (eval echo configure:4022: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_getnameinfo=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_getnameinfo=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'getnameinfo`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ISC_LWRES_GETNAMEINFOPROTO="#undef ISC_LWRES_GETNAMEINFOPROTO" +else + echo "$ac_t""no" 1>&6 +ISC_LWRES_GETNAMEINFOPROTO="#define ISC_LWRES_GETNAMEINFOPROTO 1" +fi + +echo $ac_n "checking for getaddrinfo""... $ac_c" 1>&6 +echo "configure:4043: checking for getaddrinfo" >&5 +if eval "test \"`echo '$''{'ac_cv_func_getaddrinfo'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getaddrinfo(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_getaddrinfo) || defined (__stub___getaddrinfo) +choke me +#else +getaddrinfo(); +#endif + +; return 0; } +EOF +if { (eval echo configure:4071: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_getaddrinfo=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_getaddrinfo=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'getaddrinfo`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ISC_LWRES_GETADDRINFOPROTO="#undef ISC_LWRES_GETADDRINFOPROTO" + cat >> confdefs.h <<\EOF +#define HAVE_GETADDRINFO 1 +EOF + +else + echo "$ac_t""no" 1>&6 +ISC_LWRES_GETADDRINFOPROTO="#define ISC_LWRES_GETADDRINFOPROTO 1" +fi + +echo $ac_n "checking for gai_strerror""... $ac_c" 1>&6 +echo "configure:4096: checking for gai_strerror" >&5 +if eval "test \"`echo '$''{'ac_cv_func_gai_strerror'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gai_strerror(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_gai_strerror) || defined (__stub___gai_strerror) +choke me +#else +gai_strerror(); +#endif + +; return 0; } +EOF +if { (eval echo configure:4124: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_gai_strerror=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_gai_strerror=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'gai_strerror`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_GAISTRERROR 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + + + + +echo $ac_n "checking for pselect""... $ac_c" 1>&6 +echo "configure:4150: checking for pselect" >&5 +if eval "test \"`echo '$''{'ac_cv_func_pselect'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char pselect(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_pselect) || defined (__stub___pselect) +choke me +#else +pselect(); +#endif + +; return 0; } +EOF +if { (eval echo configure:4178: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_pselect=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_pselect=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'pselect`\" = yes"; then + echo "$ac_t""yes" 1>&6 + NEED_PSELECT="#undef NEED_PSELECT" +else + echo "$ac_t""no" 1>&6 +NEED_PSELECT="#define NEED_PSELECT" +fi + + + +# +# Look for a sysctl call to get the list of network interfaces. +# +echo $ac_n "checking for interface list sysctl""... $ac_c" 1>&6 +echo "configure:4204: checking for interface list sysctl" >&5 +cat > conftest.$ac_ext < +#include +#include +#ifdef NET_RT_IFLIST +found_rt_iflist +#endif + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "found_rt_iflist" >/dev/null 2>&1; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_IFLIST_SYSCTL 1 +EOF + +else + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* + + +# +# Check for some other useful functions that are not ever-present. +# +echo $ac_n "checking for strsep""... $ac_c" 1>&6 +echo "configure:4236: checking for strsep" >&5 +if eval "test \"`echo '$''{'ac_cv_func_strsep'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char strsep(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_strsep) || defined (__stub___strsep) +choke me +#else +strsep(); +#endif + +; return 0; } +EOF +if { (eval echo configure:4264: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_strsep=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_strsep=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'strsep`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ISC_PLATFORM_NEEDSTRSEP="#undef ISC_PLATFORM_NEEDSTRSEP" +else + echo "$ac_t""no" 1>&6 +ISC_PLATFORM_NEEDSTRSEP="#define ISC_PLATFORM_NEEDSTRSEP 1" +fi + +echo $ac_n "checking for vsnprintf""... $ac_c" 1>&6 +echo "configure:4285: checking for vsnprintf" >&5 +if eval "test \"`echo '$''{'ac_cv_func_vsnprintf'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char vsnprintf(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_vsnprintf) || defined (__stub___vsnprintf) +choke me +#else +vsnprintf(); +#endif + +; return 0; } +EOF +if { (eval echo configure:4313: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_vsnprintf=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_vsnprintf=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'vsnprintf`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ISC_PLATFORM_NEEDVSNPRINTF="#undef ISC_PLATFORM_NEEDVSNPRINTF" +else + echo "$ac_t""no" 1>&6 +ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS print.$O" + ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS print.c" + ISC_PLATFORM_NEEDVSNPRINTF="#define ISC_PLATFORM_NEEDVSNPRINTF 1" +fi + + + + + + + +# +# Determine the printf format characters to use when printing +# values of type isc_int64_t. We make the assumption that platforms +# where a "long long" is the same size as a "long" (e.g., Alpha/OSF1) +# want "%ld" and everyone else can use "%lld". Win32 uses "%I64d", +# but that's defined elsewhere since we don't use configure on Win32. +# +echo $ac_n "checking printf format modifier for 64-bit integers""... $ac_c" 1>&6 +echo "configure:4349: checking printf format modifier for 64-bit integers" >&5 +if test "$cross_compiling" = yes; then + echo "$ac_t""default ll" 1>&6 + ISC_PLATFORM_QUADFORMAT='#define ISC_PLATFORM_QUADFORMAT "ll"' +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + echo "$ac_t""l" 1>&6 + ISC_PLATFORM_QUADFORMAT='#define ISC_PLATFORM_QUADFORMAT "l"' +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + echo "$ac_t""ll" 1>&6 + ISC_PLATFORM_QUADFORMAT='#define ISC_PLATFORM_QUADFORMAT "ll"' +fi +rm -fr conftest* +fi + + + +# +# Security Stuff +# +echo $ac_n "checking for chroot""... $ac_c" 1>&6 +echo "configure:4379: checking for chroot" >&5 +if eval "test \"`echo '$''{'ac_cv_func_chroot'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char chroot(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_chroot) || defined (__stub___chroot) +choke me +#else +chroot(); +#endif + +; return 0; } +EOF +if { (eval echo configure:4407: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_chroot=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_chroot=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'chroot`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_CHROOT 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + +for ac_hdr in linux/capability.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:4433: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:4443: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_hdr in sys/prctl.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:4473: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:4483: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + +# +# BSD/OS, and perhaps some others, don't define rlim_t. +# +echo $ac_n "checking for type rlim_t""... $ac_c" 1>&6 +echo "configure:4514: checking for type rlim_t" >&5 +cat > conftest.$ac_ext < +#include +#include +int main() { +rlim_t rl = 19671212; return (0); +; return 0; } +EOF +if { (eval echo configure:4526: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_RLIM_T 1 +EOF + +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* +echo $ac_n "checking sizeof rlim_cur""... $ac_c" 1>&6 +echo "configure:4541: checking sizeof rlim_cur" >&5 +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext < +#include +#include +main() { struct rlimit r; exit(!(sizeof(r.rlim_cur) == sizeof(int)));} +EOF +if { (eval echo configure:4554: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + echo "$ac_t""int" 1>&6 +ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE int" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext < +#include +#include +main() { struct rlimit r; exit(!(sizeof(r.rlim_cur) == sizeof(long int)));} +EOF +if { (eval echo configure:4575: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + echo "$ac_t""long int" 1>&6 +ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE long int" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext < +#include +#include +main() { struct rlimit r; exit((!sizeof(r.rlim_cur) == sizeof(long long int)));} +EOF +if { (eval echo configure:4596: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + echo "$ac_t""long long int" 1>&6 +ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE long long int" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + { echo "configure: error: unable to determine sizeof rlim_cur" 1>&2; exit 1; } + +fi +rm -fr conftest* +fi + + +fi +rm -fr conftest* +fi + + +fi +rm -fr conftest* +fi + + + +echo $ac_n "checking for getgrouplist""... $ac_c" 1>&6 +echo "configure:4623: checking for getgrouplist" >&5 +if eval "test \"`echo '$''{'ac_cv_func_getgrouplist'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getgrouplist(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_getgrouplist) || defined (__stub___getgrouplist) +choke me +#else +getgrouplist(); +#endif + +; return 0; } +EOF +if { (eval echo configure:4651: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_getgrouplist=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_getgrouplist=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'getgrouplist`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat > conftest.$ac_ext < +int +getgrouplist(const char *name, int basegid, int *groups, int *ngroups) { +} + +int main() { +return (0); +; return 0; } +EOF +if { (eval echo configure:4677: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + GETGROUPLIST_ARGS="#define GETGROUPLIST_ARGS const char *name, int basegid, int *groups, int *ngroups" + +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + GETGROUPLIST_ARGS="#define GETGROUPLIST_ARGS const char *name, gid_t basegid, gid_t *groups, int *ngroups" + +fi +rm -f conftest* +else + echo "$ac_t""no" 1>&6 +GETGROUPLIST_ARGS="#define GETGROUPLIST_ARGS const char *name, gid_t basegid, gid_t *groups, int *ngroups" + +fi + + + +echo $ac_n "checking for getnetbyaddr_r""... $ac_c" 1>&6 +echo "configure:4698: checking for getnetbyaddr_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_getnetbyaddr_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getnetbyaddr_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_getnetbyaddr_r) || defined (__stub___getnetbyaddr_r) +choke me +#else +getnetbyaddr_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:4726: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_getnetbyaddr_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_getnetbyaddr_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'getnetbyaddr_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +NET_R_ARGS="#define NET_R_ARGS char *buf, int buflen" +NET_R_BAD="#define NET_R_BAD NULL" +NET_R_COPY="#define NET_R_COPY buf, buflen" +NET_R_COPY_ARGS="#define NET_R_COPY_ARGS NET_R_ARGS" +NET_R_OK="#define NET_R_OK nptr" +NET_R_RETURN="#define NET_R_RETURN struct netent *" + +fi + + + + + + + + +echo $ac_n "checking for setnetent_r""... $ac_c" 1>&6 +echo "configure:4760: checking for setnetent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_setnetent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char setnetent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_setnetent_r) || defined (__stub___setnetent_r) +choke me +#else +setnetent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:4788: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_setnetent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_setnetent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'setnetent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +NET_R_ENT_ARGS="#undef NET_R_ENT_ARGS /*empty*/" +NET_R_SET_RESULT="#undef NET_R_SET_RESULT /*empty*/" +NET_R_SET_RETURN="#define NET_R_SET_RETURN void" + +fi + + + + + +echo $ac_n "checking for endnetent_r""... $ac_c" 1>&6 +echo "configure:4816: checking for endnetent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_endnetent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char endnetent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_endnetent_r) || defined (__stub___endnetent_r) +choke me +#else +endnetent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:4844: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_endnetent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_endnetent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'endnetent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +NET_R_END_RESULT="#define NET_R_END_RESULT(x) /*empty*/" +NET_R_END_RETURN="#define NET_R_END_RETURN void" + +fi + + + + +echo $ac_n "checking for getgrent_r""... $ac_c" 1>&6 +echo "configure:4870: checking for getgrent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_getgrent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getgrent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_getgrent_r) || defined (__stub___getgrent_r) +choke me +#else +getgrent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:4898: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_getgrent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_getgrent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'getgrent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +GROUP_R_ARGS="#define GROUP_R_ARGS char *buf, int buflen" +GROUP_R_BAD="#define GROUP_R_BAD NULL" +GROUP_R_OK="#define GROUP_R_OK gptr" +GROUP_R_RETURN="#define GROUP_R_RETURN struct group *" + +fi + + + + + + +echo $ac_n "checking for endgrent_r""... $ac_c" 1>&6 +echo "configure:4928: checking for endgrent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_endgrent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char endgrent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_endgrent_r) || defined (__stub___endgrent_r) +choke me +#else +endgrent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:4956: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_endgrent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_endgrent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'endgrent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +GROUP_R_END_RESULT="#define GROUP_R_END_RESULT(x) /*empty*/" +GROUP_R_END_RETURN="#define GROUP_R_END_RETURN void" +GROUP_R_ENT_ARGS="#define GROUP_R_ENT_ARGS void" + +fi + + + + + +echo $ac_n "checking for setgrent_r""... $ac_c" 1>&6 +echo "configure:4984: checking for setgrent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_setgrent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char setgrent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_setgrent_r) || defined (__stub___setgrent_r) +choke me +#else +setgrent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5012: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_setgrent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_setgrent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'setgrent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +GROUP_R_SET_RESULT="#undef GROUP_R_SET_RESULT /*empty*/" +GROUP_R_SET_RETURN="#define GROUP_R_SET_RETURN void" + +fi + + + + +echo $ac_n "checking for gethostbyname_r""... $ac_c" 1>&6 +echo "configure:5038: checking for gethostbyname_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_gethostbyname_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_gethostbyname_r) || defined (__stub___gethostbyname_r) +choke me +#else +gethostbyname_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5066: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_gethostbyname_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_gethostbyname_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'gethostbyname_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +HOST_R_ARGS="#define HOST_R_ARGS char *buf, int buflen, int *h_errnop" +HOST_R_BAD="#define HOST_R_BAD NULL" +HOST_R_COPY="#define HOST_R_COPY buf, buflen" +HOST_R_COPY_ARGS="#define HOST_R_COPY_ARGS char *buf, int buflen" +HOST_R_ERRNO="#define HOST_R_ERRNO *h_errnop = h_errno" +HOST_R_OK="#define HOST_R_OK hptr" +HOST_R_RETURN="#define HOST_R_RETURN struct hostent *" + +fi + + + + + + + + + +echo $ac_n "checking for endhostent_r""... $ac_c" 1>&6 +echo "configure:5102: checking for endhostent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_endhostent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char endhostent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_endhostent_r) || defined (__stub___endhostent_r) +choke me +#else +endhostent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5130: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_endhostent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_endhostent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'endhostent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +HOST_R_END_RESULT="#define HOST_R_END_RESULT(x) /*empty*/" +HOST_R_END_RETURN="#define HOST_R_END_RETURN void" +HOST_R_ENT_ARGS="#undef HOST_R_ENT_ARGS /*empty*/" + +fi + + + + + +echo $ac_n "checking for sethostent_r""... $ac_c" 1>&6 +echo "configure:5158: checking for sethostent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_sethostent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char sethostent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_sethostent_r) || defined (__stub___sethostent_r) +choke me +#else +sethostent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5186: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_sethostent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_sethostent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'sethostent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +HOST_R_SET_RESULT="#undef HOST_R_SET_RESULT /*empty*/" +HOST_R_SET_RETURN="#define HOST_R_SET_RETURN void" + +fi + + + + + +cat > conftest.$ac_ext < +#include +void +setpwent(void) {} + +int main() { +return (0); +; return 0; } +EOF +if { (eval echo configure:5225: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + SETPWENT_VOID="#define SETPWENT_VOID 1" + +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + SETPWENT_VOID="#undef SETPWENT_VOID" + +fi +rm -f conftest* + + +echo $ac_n "checking for getnetgrent_r""... $ac_c" 1>&6 +echo "configure:5240: checking for getnetgrent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_getnetgrent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getnetgrent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_getnetgrent_r) || defined (__stub___getnetgrent_r) +choke me +#else +getnetgrent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5268: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_getnetgrent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_getnetgrent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'getnetgrent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +NGR_R_ARGS="#define NGR_R_ARGS char *buf, int buflen" +NGR_R_BAD="#define NGR_R_BAD (0)" +NGR_R_COPY="#define NGR_R_COPY buf, buflen" +NGR_R_COPY_ARGS="#define NGR_R_COPY_ARGS NGR_R_ARGS" +NGR_R_OK="#define NGR_R_OK 1" +NGR_R_RETURN="#define NGR_R_RETURN int" + +fi + + + + + + + + +echo $ac_n "checking for endnetgrent_r""... $ac_c" 1>&6 +echo "configure:5302: checking for endnetgrent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_endnetgrent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char endnetgrent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_endnetgrent_r) || defined (__stub___endnetgrent_r) +choke me +#else +endnetgrent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5330: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_endnetgrent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_endnetgrent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'endnetgrent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +NGR_R_END_RESULT="#define NGR_R_END_RESULT(x) /*empty*/" +NGR_R_END_RETURN="#define NGR_R_END_RETURN void" +NGR_R_ENT_ARGS="#undef NGR_R_ENT_ARGS /*empty*/" + +fi + + + + + +echo $ac_n "checking for setnetgrent_r""... $ac_c" 1>&6 +echo "configure:5358: checking for setnetgrent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_setnetgrent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char setnetgrent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_setnetgrent_r) || defined (__stub___setnetgrent_r) +choke me +#else +setnetgrent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5386: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_setnetgrent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_setnetgrent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'setnetgrent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +NGR_R_SET_RESULT="#undef NGR_R_SET_RESULT /*empty*/" +NGR_R_SET_RETURN="#define NGR_R_SET_RETURN void" + +fi + + + + + +echo $ac_n "checking for getprotoent_r""... $ac_c" 1>&6 +echo "configure:5413: checking for getprotoent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_getprotoent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getprotoent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_getprotoent_r) || defined (__stub___getprotoent_r) +choke me +#else +getprotoent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5441: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_getprotoent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_getprotoent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'getprotoent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +PROTO_R_ARGS="#define PROTO_R_ARGS char *buf, int buflen" +PROTO_R_BAD="#define PROTO_R_BAD NULL" +PROTO_R_COPY="#define PROTO_R_COPY buf, buflen" +PROTO_R_COPY_ARGS="#define PROTO_R_COPY_ARGS PROTO_R_ARGS" +PROTO_R_OK="#define PROTO_R_OK pptr" +PROTO_R_RETURN="#define PROTO_R_RETURN struct protoent *" + +fi + + + + + + + + +echo $ac_n "checking for endprotoent_r""... $ac_c" 1>&6 +echo "configure:5475: checking for endprotoent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_endprotoent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char endprotoent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_endprotoent_r) || defined (__stub___endprotoent_r) +choke me +#else +endprotoent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5503: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_endprotoent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_endprotoent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'endprotoent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +PROTO_R_END_RESULT="#define PROTO_R_END_RESULT(x) /*empty*/" +PROTO_R_END_RETURN="#define PROTO_R_END_RETURN void" +PROTO_R_ENT_ARGS="#undef PROTO_R_ENT_ARGS /*empty*/" + +fi + + + + + +echo $ac_n "checking for setprotoent_r""... $ac_c" 1>&6 +echo "configure:5531: checking for setprotoent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_setprotoent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char setprotoent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_setprotoent_r) || defined (__stub___setprotoent_r) +choke me +#else +setprotoent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5559: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_setprotoent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_setprotoent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'setprotoent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +PROTO_R_SET_RESULT="#undef PROTO_R_SET_RESULT /*empty*/" +PROTO_R_SET_RETURN="#define PROTO_R_SET_RETURN void" + +fi + + + + +echo $ac_n "checking for getpwent_r""... $ac_c" 1>&6 +echo "configure:5585: checking for getpwent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_getpwent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getpwent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_getpwent_r) || defined (__stub___getpwent_r) +choke me +#else +getpwent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5613: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_getpwent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_getpwent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'getpwent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +PASS_R_ARGS="#define PASS_R_ARGS char *buf, int buflen" +PASS_R_BAD="#define PASS_R_BAD NULL" +PASS_R_COPY="#define PASS_R_COPY buf, buflen" +PASS_R_COPY_ARGS="#define PASS_R_COPY_ARGS PASS_R_ARGS" +PASS_R_OK="#define PASS_R_OK pwptr" +PASS_R_RETURN="#define PASS_R_RETURN struct passwd *" + +fi + + + + + + + + +echo $ac_n "checking for endpwent_r""... $ac_c" 1>&6 +echo "configure:5647: checking for endpwent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_endpwent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char endpwent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_endpwent_r) || defined (__stub___endpwent_r) +choke me +#else +endpwent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5675: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_endpwent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_endpwent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'endpwent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +PASS_R_END_RESULT="#define PASS_R_END_RESULT(x) /*empty*/" +PASS_R_END_RETURN="#define PASS_R_END_RETURN void" +PASS_R_ENT_ARGS="#undef PASS_R_ENT_ARGS /*empty*/" + +fi + + + + + +echo $ac_n "checking for setpwent_r""... $ac_c" 1>&6 +echo "configure:5703: checking for setpwent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_setpwent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char setpwent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_setpwent_r) || defined (__stub___setpwent_r) +choke me +#else +setpwent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5731: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_setpwent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_setpwent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'setpwent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +PASS_R_SET_RESULT="#undef PASS_R_SET_RESULT /*empty*/" +PASS_R_SET_RETURN="#define PASS_R_SET_RETURN void" + +fi + + + + +echo $ac_n "checking for getservent_r""... $ac_c" 1>&6 +echo "configure:5757: checking for getservent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_getservent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getservent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_getservent_r) || defined (__stub___getservent_r) +choke me +#else +getservent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5785: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_getservent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_getservent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'getservent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +SERV_R_ARGS="#define SERV_R_ARGS char *buf, int buflen" +SERV_R_BAD="#define SERV_R_BAD NULL" +SERV_R_COPY="#define SERV_R_COPY buf, buflen" +SERV_R_COPY_ARGS="#define SERV_R_COPY_ARGS SERV_R_ARGS" +SERV_R_OK="#define SERV_R_OK sptr" +SERV_R_RETURN="#define SERV_R_RETURN struct servent *" + +fi + + + + + + + + +echo $ac_n "checking for endservent_r""... $ac_c" 1>&6 +echo "configure:5819: checking for endservent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_endservent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char endservent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_endservent_r) || defined (__stub___endservent_r) +choke me +#else +endservent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5847: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_endservent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_endservent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'endservent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +SERV_R_END_RESULT="#define SERV_R_END_RESULT(x) /*empty*/" +SERV_R_END_RETURN="#define SERV_R_END_RETURN void " +SERV_R_ENT_ARGS="#undef SERV_R_ENT_ARGS /*empty*/" + +fi + + + + + +echo $ac_n "checking for setservent_r""... $ac_c" 1>&6 +echo "configure:5875: checking for setservent_r" >&5 +if eval "test \"`echo '$''{'ac_cv_func_setservent_r'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char setservent_r(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_setservent_r) || defined (__stub___setservent_r) +choke me +#else +setservent_r(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5903: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_setservent_r=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_setservent_r=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'setservent_r`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +SERV_R_SET_RESULT="#undef SERV_R_SET_RESULT /*empty*/" +SERV_R_SET_RETURN="#define SERV_R_SET_RETURN void" + +fi + + + + +# +# Random remaining OS-specific issues involving compiler warnings. +# XXXDCL print messages to indicate some compensation is being done? +# + +ISC_PLATFORM_BRACEPTHREADONCEINIT="#undef ISC_PLATFORM_BRACEPTHREADONCEINIT" + +case "$host" in + *-bsdi3.1*) + hack_shutup_sputaux=yes + ;; + *-bsdi4.0*) + hack_shutup_sigwait=yes + hack_shutup_sputaux=yes + ;; + *-bsdi4.1*) + hack_shutup_stdargcast=yes + ;; + *-solaris2.8) + hack_shutup_pthreadonceinit=yes + ;; +esac + +case "$hack_shutup_pthreadonceinit" in + yes) + # + # Shut up PTHREAD_ONCE_INIT unbraced initializer warnings. + # + ISC_PLATFORM_BRACEPTHREADONCEINIT="#define ISC_PLATFORM_BRACEPTHREADONCEINIT 1" + ;; +esac + +case "$hack_shutup_sigwait" in + yes) + # + # Shut up a -Wmissing-prototypes warning for sigwait(). + # + cat >> confdefs.h <<\EOF +#define SHUTUP_SIGWAIT 1 +EOF + + ;; +esac + +case "$hack_shutup_sputaux" in + yes) + # + # Shut up a -Wmissing-prototypes warning from . + # + cat >> confdefs.h <<\EOF +#define SHUTUP_SPUTAUX 1 +EOF + + ;; +esac + +case "$hack_shutup_stdargcast" in + yes) + # + # Shut up a -Wcast-qual warning from va_start(). + # + cat >> confdefs.h <<\EOF +#define SHUTUP_STDARG_CAST 1 +EOF + + ;; +esac + + +# +# Look for jade, preferring openjade if installed. +# + +for ac_prog in openjade jade +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:6006: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_JADE'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$JADE" in + /*) + ac_cv_path_JADE="$JADE" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_JADE="$JADE" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_JADE="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +JADE="$ac_cv_path_JADE" +if test -n "$JADE"; then + echo "$ac_t""$JADE" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$JADE" && break +done +test -n "$JADE" || JADE="jade" + + + +# +# Look for tex & pdftex. +# + +for ac_prog in tex +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:6053: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_TEX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$TEX" in + /*) + ac_cv_path_TEX="$TEX" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_TEX="$TEX" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_TEX="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +TEX="$ac_cv_path_TEX" +if test -n "$TEX"; then + echo "$ac_t""$TEX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$TEX" && break +done + + + +for ac_prog in pdftex +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:6095: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_PDFTEX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$PDFTEX" in + /*) + ac_cv_path_PDFTEX="$PDFTEX" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_PDFTEX="$PDFTEX" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_PDFTEX="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +PDFTEX="$ac_cv_path_PDFTEX" +if test -n "$PDFTEX"; then + echo "$ac_t""$PDFTEX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$PDFTEX" && break +done + + + +# +# Look for SGML files. NetBSD has them under /usr/pkg/share +# (if installed), FreeBSD has them under /usr/local/share. +# + +SGMLDIR="" + +echo $ac_n "checking for SGML files""... $ac_c" 1>&6 +echo "configure:6140: checking for SGML files" >&5 +for d in /usr/pkg/share/sgml /usr/local/share/sgml +do + if test -f $d/docbook/dsssl/modular/html/docbook.dsl + then + SGMLDIR=$d + echo "$ac_t""in $SGMLDIR" 1>&6 + break + fi +done + +if test "X$SGMLDIR" = "X" +then + echo "$ac_t"""not found"" 1>&6; + SGMLDIR=/usr/local/share/sgml +fi + + + +# +# Look for XML files. +# +XGMLDIR="" + +echo $ac_n "checking for XML files""... $ac_c" 1>&6 +echo "configure:6165: checking for XML files" >&5 +for d in /usr/pkg/share/xml /usr/local/share/xml +do + if test -f $d/dtd/docbook/docbookx.dtd + then + XMLDIR=$d + echo "$ac_t""in $XMLDIR" 1>&6 + break + fi +done + +if test "X$XMLDIR" = "X" +then + echo "$ac_t"""not found"" 1>&6; + XMLDIR=/usr/local/share/xml +fi + + + +# +# Substitutions +# + +BIND9_TOP_BUILDDIR=`pwd` + + + + + + +if test "X$srcdir" != "X"; then + BIND9_ISC_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/isc/include" + BIND9_ISCCFG_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/isccfg/include" + BIND9_DNS_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/dns/include" + BIND9_OMAPI_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/omapi/include" + BIND9_LWRES_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/lwres/include" +else + BIND9_ISC_BUILDINCLUDE="" + BIND9_ISCCFG_BUILDINCLUDE="" + BIND9_DNS_BUILDINCLUDE="" + BIND9_OMAPI_BUILDINCLUDE="" + BIND9_LWRES_BUILDINCLUDE="" +fi + + +BIND9_INCLUDES=$BIND9_TOP_BUILDDIR/make/includes + + +BIND9_MAKE_RULES=$BIND9_TOP_BUILDDIR/make/rules + +. $srcdir/../../version +BIND9_VERSION="VERSION=${MAJORVER}.${MINORVER}.${PATCHVER}${RELEASETYPE}${RELEASEVER}" + + + +LIBISC_API=$srcdir/lib/isc/api + + +LIBISCCFG_API=$srcdir/lib/isccfg/api + + +LIBDNS_API=$srcdir/lib/dns/api + + +LIBLWRES_API=$srcdir/lib/lwres/api + + +LIBOMAPI_API=$srcdir/lib/omapi/api + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile + bsd/Makefile + cylink/Makefile + dnssafe/Makefile + dst/Makefile + include/Makefile + inet/Makefile + irs/Makefile + isc/Makefile + nameser/Makefile + port_after.h + port_before.h + resolv/Makefile + make/rules + make/mkdep + make/includes + config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@host@%$host%g +s%@host_alias@%$host_alias%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@SET_MAKE@%$SET_MAKE%g +s%@RANLIB@%$RANLIB%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@STD_CINCLUDES@%$STD_CINCLUDES%g +s%@STD_CDEFINES@%$STD_CDEFINES%g +s%@STD_CWARNINGS@%$STD_CWARNINGS%g +s%@CCOPT@%$CCOPT%g +s%@AR@%$AR%g +s%@ARFLAGS@%$ARFLAGS%g +s%@LN@%$LN%g +s%@ETAGS@%$ETAGS%g +s%@PERL@%$PERL%g +s%@CC@%$CC%g +s%@CPP@%$CPP%g +s%@ISC_PLATFORM_HAVELONGLONG@%$ISC_PLATFORM_HAVELONGLONG%g +s%@ISC_PLATFORM_NEEDSYSSELECTH@%$ISC_PLATFORM_NEEDSYSSELECTH%g +s%@LWRES_PLATFORM_NEEDSYSSELECTH@%$LWRES_PLATFORM_NEEDSYSSELECTH%g +s%@WANT_IRS_GR@%$WANT_IRS_GR%g +s%@WANT_IRS_GR_OBJS@%$WANT_IRS_GR_OBJS%g +s%@WANT_IRS_PW@%$WANT_IRS_PW%g +s%@WANT_IRS_PW_OBJS@%$WANT_IRS_PW_OBJS%g +s%@WANT_IRS_NIS@%$WANT_IRS_NIS%g +s%@WANT_IRS_NIS_OBJS@%$WANT_IRS_NIS_OBJS%g +s%@WANT_IRS_NISGR_OBJS@%$WANT_IRS_NISGR_OBJS%g +s%@WANT_IRS_NISPW_OBJS@%$WANT_IRS_NISPW_OBJS%g +s%@DST_PRIVATEOPENSSL@%$DST_PRIVATEOPENSSL%g +s%@dst_privateopenssl@%$dst_privateopenssl%g +s%@DST_OPENSSL_INC@%$DST_OPENSSL_INC%g +s%@DST_OPENSSL_LIB@%$DST_OPENSSL_LIB%g +s%@DST_OPENSSL_OBJS@%$DST_OPENSSL_OBJS%g +s%@DNS_OPENSSL_LIBS@%$DNS_OPENSSL_LIBS%g +s%@USE_GSSAPI@%$USE_GSSAPI%g +s%@DST_GSSAPI_INC@%$DST_GSSAPI_INC%g +s%@DNS_GSSAPI_LIBS@%$DNS_GSSAPI_LIBS%g +s%@ALWAYS_DEFINES@%$ALWAYS_DEFINES%g +s%@DO_PTHREADS@%$DO_PTHREADS%g +s%@WANT_IRS_THREADSGR_OBJS@%$WANT_IRS_THREADSGR_OBJS%g +s%@WANT_IRS_THREADSPW_OBJS@%$WANT_IRS_THREADSPW_OBJS%g +s%@WANT_IRS_THREADS_OBJS@%$WANT_IRS_THREADS_OBJS%g +s%@ISC_THREAD_DIR@%$ISC_THREAD_DIR%g +s%@MKDEPCC@%$MKDEPCC%g +s%@MKDEPCFLAGS@%$MKDEPCFLAGS%g +s%@MKDEPPROG@%$MKDEPPROG%g +s%@IRIX_DNSSEC_WARNINGS_HACK@%$IRIX_DNSSEC_WARNINGS_HACK%g +s%@purify_path@%$purify_path%g +s%@PURIFY@%$PURIFY%g +s%@LIBTOOL@%$LIBTOOL%g +s%@O@%$O%g +s%@A@%$A%g +s%@SA@%$SA%g +s%@ISC_PLATFORM_HAVEIPV6@%$ISC_PLATFORM_HAVEIPV6%g +s%@LWRES_PLATFORM_HAVEIPV6@%$LWRES_PLATFORM_HAVEIPV6%g +s%@ISC_PLATFORM_NEEDNETINETIN6H@%$ISC_PLATFORM_NEEDNETINETIN6H%g +s%@LWRES_PLATFORM_NEEDNETINETIN6H@%$LWRES_PLATFORM_NEEDNETINETIN6H%g +s%@ISC_PLATFORM_NEEDNETINET6IN6H@%$ISC_PLATFORM_NEEDNETINET6IN6H%g +s%@LWRES_PLATFORM_NEEDNETINET6IN6H@%$LWRES_PLATFORM_NEEDNETINET6IN6H%g +s%@ISC_PLATFORM_HAVEINADDR6@%$ISC_PLATFORM_HAVEINADDR6%g +s%@LWRES_PLATFORM_HAVEINADDR6@%$LWRES_PLATFORM_HAVEINADDR6%g +s%@ISC_PLATFORM_NEEDIN6ADDRANY@%$ISC_PLATFORM_NEEDIN6ADDRANY%g +s%@LWRES_PLATFORM_NEEDIN6ADDRANY@%$LWRES_PLATFORM_NEEDIN6ADDRANY%g +s%@ISC_PLATFORM_HAVEIN6PKTINFO@%$ISC_PLATFORM_HAVEIN6PKTINFO%g +s%@ISC_PLATFORM_FIXIN6ISADDR@%$ISC_PLATFORM_FIXIN6ISADDR%g +s%@ISC_IPV6_H@%$ISC_IPV6_H%g +s%@ISC_IPV6_O@%$ISC_IPV6_O%g +s%@ISC_ISCIPV6_O@%$ISC_ISCIPV6_O%g +s%@ISC_IPV6_C@%$ISC_IPV6_C%g +s%@LWRES_HAVE_SIN6_SCOPE_ID@%$LWRES_HAVE_SIN6_SCOPE_ID%g +s%@ISC_PLATFORM_NEEDNTOP@%$ISC_PLATFORM_NEEDNTOP%g +s%@ISC_PLATFORM_NEEDPTON@%$ISC_PLATFORM_NEEDPTON%g +s%@ISC_PLATFORM_NEEDATON@%$ISC_PLATFORM_NEEDATON%g +s%@HAVE_SA_LEN@%$HAVE_SA_LEN%g +s%@HAVE_MINIMUM_IFREQ@%$HAVE_MINIMUM_IFREQ%g +s%@ISC_PLATFORM_MSGHDRFLAVOR@%$ISC_PLATFORM_MSGHDRFLAVOR%g +s%@ISC_PLATFORM_NEEDPORTT@%$ISC_PLATFORM_NEEDPORTT%g +s%@ISC_LWRES_NEEDADDRINFO@%$ISC_LWRES_NEEDADDRINFO%g +s%@ISC_LWRES_SETHOSTENTINT@%$ISC_LWRES_SETHOSTENTINT%g +s%@ISC_LWRES_ENDHOSTENTINT@%$ISC_LWRES_ENDHOSTENTINT%g +s%@GETNETBYADDR_ADDR_T@%$GETNETBYADDR_ADDR_T%g +s%@ISC_LWRES_SETNETENTINT@%$ISC_LWRES_SETNETENTINT%g +s%@ISC_LWRES_ENDNETENTINT@%$ISC_LWRES_ENDNETENTINT%g +s%@ISC_LWRES_GETHOSTBYADDRVOID@%$ISC_LWRES_GETHOSTBYADDRVOID%g +s%@ISC_LWRES_NEEDHERRNO@%$ISC_LWRES_NEEDHERRNO%g +s%@ISC_LWRES_GETIPNODEPROTO@%$ISC_LWRES_GETIPNODEPROTO%g +s%@ISC_LWRES_GETADDRINFOPROTO@%$ISC_LWRES_GETADDRINFOPROTO%g +s%@ISC_LWRES_GETNAMEINFOPROTO@%$ISC_LWRES_GETNAMEINFOPROTO%g +s%@NEED_PSELECT@%$NEED_PSELECT%g +s%@ISC_PLATFORM_NEEDSTRSEP@%$ISC_PLATFORM_NEEDSTRSEP%g +s%@ISC_PLATFORM_NEEDVSNPRINTF@%$ISC_PLATFORM_NEEDVSNPRINTF%g +s%@ISC_EXTRA_OBJS@%$ISC_EXTRA_OBJS%g +s%@ISC_EXTRA_SRCS@%$ISC_EXTRA_SRCS%g +s%@ISC_PLATFORM_QUADFORMAT@%$ISC_PLATFORM_QUADFORMAT%g +s%@ISC_PLATFORM_RLIMITTYPE@%$ISC_PLATFORM_RLIMITTYPE%g +s%@GETGROUPLIST_ARGS@%$GETGROUPLIST_ARGS%g +s%@NET_R_ARGS@%$NET_R_ARGS%g +s%@NET_R_BAD@%$NET_R_BAD%g +s%@NET_R_COPY@%$NET_R_COPY%g +s%@NET_R_COPY_ARGS@%$NET_R_COPY_ARGS%g +s%@NET_R_OK@%$NET_R_OK%g +s%@NET_R_RETURN@%$NET_R_RETURN%g +s%@NET_R_ENT_ARGS@%$NET_R_ENT_ARGS%g +s%@NET_R_SET_RESULT@%$NET_R_SET_RESULT%g +s%@NET_R_SET_RETURN@%$NET_R_SET_RETURN%g +s%@NET_R_END_RESULT@%$NET_R_END_RESULT%g +s%@NET_R_END_RETURN@%$NET_R_END_RETURN%g +s%@GROUP_R_ARGS@%$GROUP_R_ARGS%g +s%@GROUP_R_BAD@%$GROUP_R_BAD%g +s%@GROUP_R_OK@%$GROUP_R_OK%g +s%@GROUP_R_RETURN@%$GROUP_R_RETURN%g +s%@GROUP_R_END_RESULT@%$GROUP_R_END_RESULT%g +s%@GROUP_R_END_RETURN@%$GROUP_R_END_RETURN%g +s%@GROUP_R_ENT_ARGS@%$GROUP_R_ENT_ARGS%g +s%@GROUP_R_SET_RESULT@%$GROUP_R_SET_RESULT%g +s%@GROUP_R_SET_RETURN@%$GROUP_R_SET_RETURN%g +s%@HOST_R_ARGS@%$HOST_R_ARGS%g +s%@HOST_R_BAD@%$HOST_R_BAD%g +s%@HOST_R_COPY@%$HOST_R_COPY%g +s%@HOST_R_COPY_ARGS@%$HOST_R_COPY_ARGS%g +s%@HOST_R_ERRNO@%$HOST_R_ERRNO%g +s%@HOST_R_OK@%$HOST_R_OK%g +s%@HOST_R_RETURN@%$HOST_R_RETURN%g +s%@HOST_R_END_RESULT@%$HOST_R_END_RESULT%g +s%@HOST_R_END_RETURN@%$HOST_R_END_RETURN%g +s%@HOST_R_ENT_ARGS@%$HOST_R_ENT_ARGS%g +s%@HOST_R_SET_RESULT@%$HOST_R_SET_RESULT%g +s%@HOST_R_SET_RETURN@%$HOST_R_SET_RETURN%g +s%@SETPWENT_VOID@%$SETPWENT_VOID%g +s%@NGR_R_ARGS@%$NGR_R_ARGS%g +s%@NGR_R_BAD@%$NGR_R_BAD%g +s%@NGR_R_COPY@%$NGR_R_COPY%g +s%@NGR_R_COPY_ARGS@%$NGR_R_COPY_ARGS%g +s%@NGR_R_OK@%$NGR_R_OK%g +s%@NGR_R_RETURN@%$NGR_R_RETURN%g +s%@NGR_R_END_RESULT@%$NGR_R_END_RESULT%g +s%@NGR_R_END_RETURN@%$NGR_R_END_RETURN%g +s%@NGR_R_ENT_ARGS@%$NGR_R_ENT_ARGS%g +s%@NGR_R_SET_RESULT@%$NGR_R_SET_RESULT%g +s%@NGR_R_SET_RETURN@%$NGR_R_SET_RETURN%g +s%@PROTO_R_ARGS@%$PROTO_R_ARGS%g +s%@PROTO_R_BAD@%$PROTO_R_BAD%g +s%@PROTO_R_COPY@%$PROTO_R_COPY%g +s%@PROTO_R_COPY_ARGS@%$PROTO_R_COPY_ARGS%g +s%@PROTO_R_OK@%$PROTO_R_OK%g +s%@PROTO_R_RETURN@%$PROTO_R_RETURN%g +s%@PROTO_R_END_RESULT@%$PROTO_R_END_RESULT%g +s%@PROTO_R_END_RETURN@%$PROTO_R_END_RETURN%g +s%@PROTO_R_ENT_ARGS@%$PROTO_R_ENT_ARGS%g +s%@PROTO_R_SET_RESULT@%$PROTO_R_SET_RESULT%g +s%@PROTO_R_SET_RETURN@%$PROTO_R_SET_RETURN%g +s%@PASS_R_ARGS@%$PASS_R_ARGS%g +s%@PASS_R_BAD@%$PASS_R_BAD%g +s%@PASS_R_COPY@%$PASS_R_COPY%g +s%@PASS_R_COPY_ARGS@%$PASS_R_COPY_ARGS%g +s%@PASS_R_OK@%$PASS_R_OK%g +s%@PASS_R_RETURN@%$PASS_R_RETURN%g +s%@PASS_R_END_RESULT@%$PASS_R_END_RESULT%g +s%@PASS_R_END_RETURN@%$PASS_R_END_RETURN%g +s%@PASS_R_ENT_ARGS@%$PASS_R_ENT_ARGS%g +s%@PASS_R_SET_RESULT@%$PASS_R_SET_RESULT%g +s%@PASS_R_SET_RETURN@%$PASS_R_SET_RETURN%g +s%@SERV_R_ARGS@%$SERV_R_ARGS%g +s%@SERV_R_BAD@%$SERV_R_BAD%g +s%@SERV_R_COPY@%$SERV_R_COPY%g +s%@SERV_R_COPY_ARGS@%$SERV_R_COPY_ARGS%g +s%@SERV_R_OK@%$SERV_R_OK%g +s%@SERV_R_RETURN@%$SERV_R_RETURN%g +s%@SERV_R_END_RESULT@%$SERV_R_END_RESULT%g +s%@SERV_R_END_RETURN@%$SERV_R_END_RETURN%g +s%@SERV_R_ENT_ARGS@%$SERV_R_ENT_ARGS%g +s%@SERV_R_SET_RESULT@%$SERV_R_SET_RESULT%g +s%@SERV_R_SET_RETURN@%$SERV_R_SET_RETURN%g +s%@ISC_PLATFORM_BRACEPTHREADONCEINIT@%$ISC_PLATFORM_BRACEPTHREADONCEINIT%g +s%@JADE@%$JADE%g +s%@TEX@%$TEX%g +s%@PDFTEX@%$PDFTEX%g +s%@SGMLDIR@%$SGMLDIR%g +s%@XMLDIR@%$XMLDIR%g +s%@BIND9_TOP_BUILDDIR@%$BIND9_TOP_BUILDDIR%g +s%@BIND9_ISC_BUILDINCLUDE@%$BIND9_ISC_BUILDINCLUDE%g +s%@BIND9_ISCCFG_BUILDINCLUDE@%$BIND9_ISCCFG_BUILDINCLUDE%g +s%@BIND9_DNS_BUILDINCLUDE@%$BIND9_DNS_BUILDINCLUDE%g +s%@BIND9_OMAPI_BUILDINCLUDE@%$BIND9_OMAPI_BUILDINCLUDE%g +s%@BIND9_LWRES_BUILDINCLUDE@%$BIND9_LWRES_BUILDINCLUDE%g +/@BIND9_INCLUDES@/r $BIND9_INCLUDES +s%@BIND9_INCLUDES@%%g +/@BIND9_MAKE_RULES@/r $BIND9_MAKE_RULES +s%@BIND9_MAKE_RULES@%%g +s%@BIND9_VERSION@%$BIND9_VERSION%g +/@LIBISC_API@/r $LIBISC_API +s%@LIBISC_API@%%g +/@LIBISCCFG_API@/r $LIBISCCFG_API +s%@LIBISCCFG_API@%%g +/@LIBDNS_API@/r $LIBDNS_API +s%@LIBDNS_API@%%g +/@LIBLWRES_API@/r $LIBLWRES_API +s%@LIBLWRES_API@%%g +/@LIBOMAPI_API@/r $LIBOMAPI_API +s%@LIBOMAPI_API@%%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + + +# Tell Emacs to edit this file in shell mode. +# Local Variables: +# mode: sh +# End: diff --git a/lib/bind/configure.in b/lib/bind/configure.in new file mode 100644 index 0000000000..450d8a4bba --- /dev/null +++ b/lib/bind/configure.in @@ -0,0 +1,1821 @@ +# Copyright (C) 1998-2001 Internet Software Consortium. +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM +# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +# INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +dnl +AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)dnl +esyscmd([sed "s/^/# /" COPYRIGHT])dnl +AC_DIVERT_POP()dnl + +AC_REVISION($Revision: 1.1 $) + +AC_INIT(resolv/herror.c) +AC_PREREQ(2.13) + +AC_CONFIG_HEADER(config.h) + +AC_CANONICAL_HOST + +AC_PROG_MAKE_SET +AC_PROG_RANLIB +AC_PROG_INSTALL + +AC_SUBST(STD_CINCLUDES) +AC_SUBST(STD_CDEFINES) +AC_SUBST(STD_CWARNINGS) +AC_SUBST(CCOPT) + +AC_PATH_PROG(AR, ar) +ARFLAGS="cruv" +AC_SUBST(AR) +AC_SUBST(ARFLAGS) + +# The POSIX ln(1) program. Non-POSIX systems may substitute +# "copy" or something. +LN=ln +AC_SUBST(LN) + +case "$AR" in + "") + AC_MSG_ERROR([ +ar program not found. Please fix your PATH to include the directory in +which ar resides, or set AR in the environment with the full path to ar. +]) + + ;; +esac + +# +# Etags. +# +AC_PATH_PROGS(ETAGS, etags emacs-etags) + +# +# Some systems, e.g. RH7, have the Exuberant Ctags etags instead of +# GNU emacs etags, and it requires the -L flag. +# +if test "X$ETAGS" != "X"; then + AC_MSG_CHECKING(for Exuberant Ctags etags) + if $ETAGS --version 2>&1 | grep 'Exuberant Ctags' >/dev/null 2>&1; then + AC_MSG_RESULT(yes) + ETAGS="$ETAGS -L" + else + AC_MSG_RESULT(no) + fi +fi +AC_SUBST(ETAGS) + +# +# Perl is optional; it is used only by some of the system test scripts. +# +AC_PATH_PROGS(PERL, perl5 perl) +AC_SUBST(PERL) + +# +# Special processing of paths depending on whether --prefix, +# --sysconfdir or --localstatedir arguments were given. What's +# desired is some compatability with the way previous versions +# of BIND built; they defaulted to /usr/local for most parts of +# the installation, but named.boot/named.conf was in /etc +# and named.pid was in /var/run. +# +# So ... if none of --prefix, --sysconfdir or --localstatedir are +# specified, set things up that way. If --prefix is given, use +# it for sysconfdir and localstatedir the way configure normally +# would. To change the prefix for everything but leave named.conf +# in /etc or named.pid in /var/run, then do this the usual configure way: +# ./configure --prefix=/somewhere --sysconfdir=/etc +# ./configure --prefix=/somewhere --localstatedir=/var +# +# To put named.conf and named.pid in /usr/local with everything else, +# set the prefix explicitly to /usr/local even though that's the default: +# ./configure --prefix=/usr/local +# +case "$prefix" in + NONE) + case "$sysconfdir" in + '${prefix}/etc') + sysconfdir=/etc + ;; + esac + case "$localstatedir" in + '${prefix}/var') + localstatedir=/var + ;; + esac + ;; +esac + +# +# Make sure INSTALL uses an absolute path, else it will be wrong in all +# Makefiles, since they use make/rules.in and INSTALL will be adjusted by +# configure based on the location of the file where it is substituted. +# Since in BIND9 INSTALL is only substituted into make/rules.in, an immediate +# subdirectory of install-sh, This relative path will be wrong for all +# directories more than one level down from install-sh. +# +case "$INSTALL" in + /*) + ;; + *) + # + # Not all systems have dirname. + # + changequote({, }) + ac_dir="`echo $INSTALL | sed 's%/[^/]*$%%'`" + changequote([, ]) + + ac_prog="`echo $INSTALL | sed 's%.*/%%'`" + test "$ac_dir" = "$ac_prog" && ac_dir=. + test -d "$ac_dir" && ac_dir="`(cd \"$ac_dir\" && pwd)`" + INSTALL="$ac_dir/$ac_prog" + ;; +esac + +# +# On these hosts, we really want to use cc, not gcc, even if it is +# found. The gcc that these systems have will not correctly handle +# pthreads. +# +# However, if the user sets $CC to be something, let that override +# our change. +# +if test "X$CC" = "X" ; then + case "$host" in + *-dec-osf*) + CC="cc" + ;; + *-solaris*) + # Use Sun's cc if it is available, but watch + # out for /usr/ucb/cc; it will never be the right + # compiler to use. + # + # If setting CC here fails, the AC_PROG_CC done + # below might still find gcc. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + case "$ac_dir" in + /usr/ucb) + # exclude + ;; + *) + if test -f "$ac_dir/cc"; then + CC="$ac_dir/cc" + break + fi + ;; + esac + done + IFS="$ac_save_ifs" + ;; + *-hp-hpux*) + CC="cc" + ;; + mips-sgi-irix*) + CC="cc" + ;; + esac +fi + + +AC_PROG_CC + +AC_HEADER_STDC + + +AC_CHECK_HEADERS(fcntl.h sys/time.h unistd.h sys/sockio.h sys/select.h) + +AC_C_CONST +AC_C_INLINE +AC_TYPE_SIZE_T +AC_HEADER_TIME +AC_MSG_CHECKING(for long long) +AC_TRY_COMPILE([],[long long i = 0; return (0);], + [AC_MSG_RESULT(yes) + ISC_PLATFORM_HAVELONGLONG="#define ISC_PLATFORM_HAVELONGLONG 1"], + [AC_MSG_RESULT(no) + ISC_PLATFORM_HAVELONGLONG="#undef ISC_PLATFORM_HAVELONGLONG"]) +AC_SUBST(ISC_PLATFORM_HAVELONGLONG) + +# +# check if we need to #include sys/select.h explicitly +# +case $ac_cv_header_unistd_h in +yes) +AC_MSG_CHECKING(if unistd.h defines fd_set) +AC_TRY_COMPILE([ +#include ], +[fd_set read_set; return (0);], + [AC_MSG_RESULT(yes) + ISC_PLATFORM_NEEDSYSSELECTH="#undef ISC_PLATFORM_NEEDSYSSELECTH" + LWRES_PLATFORM_NEEDSYSSELECTH="#undef LWRES_PLATFORM_NEEDSYSSELECTH"], + [AC_MSG_RESULT(no) + case ac_cv_header_sys_select_h in + yes) + ISC_PLATFORM_NEEDSYSSELECTH="#define ISC_PLATFORM_NEEDSYSSELECTH 1" + LWRES_PLATFORM_NEEDSYSSELECTH="#define LWRES_PLATFORM_NEEDSYSSELECTH 1" + ;; + no) + AC_MSG_ERROR([need either working unistd.h or sys/select.h]) + ;; + esac + ]) + ;; +no) + case ac_cv_header_sys_select_h in + yes) + ISC_PLATFORM_NEEDSYSSELECTH="#define ISC_PLATFORM_NEEDSYSSELECTH 1" + LWRES_PLATFORM_NEEDSYSSELECTH="#define LWRES_PLATFORM_NEEDSYSSELECTH 1" + ;; + no) + AC_MSG_ERROR([need either unistd.h or sys/select.h]) + ;; + esac + ;; +esac +AC_SUBST(ISC_PLATFORM_NEEDSYSSELECTH) +AC_SUBST(LWRES_PLATFORM_NEEDSYSSELECTH) + +# +# Find the machine's endian flavor. +# +AC_C_BIGENDIAN + +AC_ARG_WITH(irs-gr,[ --with-irs-gr Build ....], +want_irs_gr="$withval", want_irs_gr="no") +case "$want_irs_gr" in +yes) WANT_IRS_GR="#define WANT_IRS_GR 1" + WANT_IRS_GR_OBJS="\${WANT_IRS_GR_OBJS}" + ;; +*) WANT_IRS_GR="#undef WANT_IRS_GR" WANT_IRS_GR_OBJS="";; +esac +AC_SUBST(WANT_IRS_GR) +AC_SUBST(WANT_IRS_GR_OBJS) + +AC_ARG_WITH(irs-pw,[ --with-irs-pw Build ....], +want_irs_pw="$withval", want_irs_pw="no") +case "$want_irs_pw" in +yes) WANT_IRS_PW="#define WANT_IRS_PW 1" + WANT_IRS_PW_OBJS="\${WANT_IRS_PW_OBJS}";; +*) WANT_IRS_PW="#undef WANT_IRS_PW" WANT_IRS_PW_OBJS="";; +esac +AC_SUBST(WANT_IRS_PW) +AC_SUBST(WANT_IRS_PW_OBJS) + +AC_ARG_WITH(irs-nis,[ --with-irs-nis Build ....], +want_irs_nis="$withval", want_irs_nis="no") +case "$want_irs_nis" in +yes) + WANT_IRS_NIS="#define WANT_IRS_NIS 1" + WANT_IRS_NIS_OBJS="WANT_IRS_NIS_OBJS" + case "$want_irs_gr" in + yes) + WANT_IRS_NISGR_OBJS="\${WANT_IRS_NISGR_OBJS}";; + *) + WANT_IRS_NISGR_OBJS="";; + esac + case "$want_irs_pw" in + yes) + WANT_IRS_NISPW_OBJS="\${WANT_IRS_NISPW_OBJS}";; + *) + WANT_IRS_NISPW_OBJS="";; + esac + ;; +*) + WANT_IRS_NIS="#undef WANT_IRS_NIS" + WANT_IRS_NIS_OBJS="" + WANT_IRS_NISGR_OBJS="" + WANT_IRS_NISPW_OBJS="";; +esac +AC_SUBST(WANT_IRS_NIS) +AC_SUBST(WANT_IRS_NIS_OBJS) +AC_SUBST(WANT_IRS_NISGR_OBJS) +AC_SUBST(WANT_IRS_NISPW_OBJS) + +# +# was --with-openssl specified? +# +AC_MSG_CHECKING(for compatible OpenSSL library) +AC_ARG_WITH(openssl, +[ --with-openssl=PATH Specify path for system-supplied openssl + (rather than using bind-9 internal openssl)], + use_openssl="$withval", use_openssl="no") + +# +# If the user didn't specify where openssl is, and we didn't find or it +# is incompatible with our code, use our internal one. +# +# XXX This appears to assume that the user specified path is correct, +# and does no checking. +# + +case "$use_openssl" in + no) + DST_PRIVATEOPENSSL='-DDST_USE_PRIVATE_OPENSSL' + dst_privateopenssl='openssl' + DST_OPENSSL_INC='-I${srcdir}/../openssl/include' + DST_OPENSSL_LIB='' + DST_OPENSSL_OBJS='${OPENSSLOBJS}' + AC_MSG_RESULT(using private library) + openssl_makefiles="lib/dns/sec/openssl/Makefile \ + lib/dns/sec/openssl/include/Makefile \ + lib/dns/sec/openssl/include/openssl/Makefile" + + ;; + yes) + AC_MSG_ERROR([--with-openssl must specify a path]) + ;; + *) + DST_PRIVATEOPENSSL='' + dst_privateopenssl='' + DST_OPENSSL_INC="-I$use_openssl/include" + DNS_OPENSSL_LIBS="-L$use_openssl/lib -lcrypto" + DST_OPENSSL_LIB='' + AC_MSG_RESULT(using openssl from $use_openssl/lib and $use_openssl/include) + openssl_makefiles="" + ;; +esac + +AC_SUBST(DST_PRIVATEOPENSSL) +AC_SUBST(dst_privateopenssl) +AC_SUBST(DST_OPENSSL_INC) +AC_SUBST(DST_OPENSSL_LIB) +AC_SUBST(DST_OPENSSL_OBJS) + +# +# This would include the system openssl path (and linker options to use +# it as needed) if it is found. +# + +AC_SUBST(DNS_OPENSSL_LIBS) + +# +# was --with-gssapi specified? +# +#AC_MSG_CHECKING(for GSSAPI library) +#AC_ARG_WITH(gssapi, +#[ --with-gssapi=PATH Specify path for system-supplied GSSAPI], +# use_gssapi="$withval", use_gssapi="no") +# +#case "$use_gssapi" in +# no) +# USE_GSSAPI='' +# DST_GSSAPI_INC='' +# DNS_GSSAPI_LIBS='' +# AC_MSG_RESULT(not specified) +# ;; +# yes) +# AC_MSG_ERROR([--with-gssapi must specify a path]) +# ;; +# *) +# USE_GSSAPI='-DGSSAPI' +# DST_GSSAPI_INC="-I$use_gssapi/include" +# DNS_GSSAPI_LIBS="-L$use_gssapi/lib -lgssapi_krb5" +# AC_MSG_RESULT(using gssapi from $use_gssapi/lib and $use_gssapi/include) +# ;; +#esac + +USE_GSSAPI='' +DST_GSSAPI_INC='' +DNS_GSSAPI_LIBS='' + +AC_SUBST(USE_GSSAPI) +AC_SUBST(DST_GSSAPI_INC) +AC_SUBST(DNS_GSSAPI_LIBS) + +# +# was --with-randomdev specified? +# +AC_MSG_CHECKING(for random device) +AC_ARG_WITH(randomdev, +[ --with-randomdev=PATH Specify path for random device], + use_randomdev="$withval", use_randomdev="unspec") + +case "$use_randomdev" in + unspec) + case "$host" in + *-openbsd*) + devrandom=/dev/srandom + ;; + *) + devrandom=/dev/random + ;; + esac + AC_CHECK_FILE($devrandom, + AC_DEFINE_UNQUOTED(PATH_RANDOMDEV, + "$devrandom"),) + ;; + yes) + AC_MSG_ERROR([--with-randomdev must specify a path]) + ;; + *) + AC_DEFINE_UNQUOTED(PATH_RANDOMDEV, "$use_randomdev") + AC_MSG_RESULT(using "$use_randomdev") + ;; +esac + +# +# Begin pthreads checking. +# +# First, decide whether to use multithreading or not. +# +AC_MSG_CHECKING(whether to look for thread support) +AC_ARG_ENABLE(threads, + [ --disable-threads disable multithreading]) +case "$enable_threads" in + yes|'') + AC_MSG_RESULT(yes) + use_threads=true + ;; + no) + AC_MSG_RESULT(no) + use_threads=false + ;; + *) + AC_MSG_ERROR([--enable-threads takes yes or no]) + ;; +esac + +if $use_threads +then + # + # Search for / configure pthreads in a system-dependent fashion. + # + case "$host" in + *-netbsd*) + # NetBSD has multiple pthreads implementations. The + # recommended one to use is "unproven-pthreads". The + # older "mit-pthreads" may also work on some NetBSD + # versions. The PTL2 thread library does not + # currently work with bind9, but can be chosen with + # the --with-ptl2 option for those who wish to + # experiment with it. + CC="gcc" + AC_MSG_CHECKING(which NetBSD thread library to use) + + AC_ARG_WITH(ptl2, +[ --with-ptl2 on NetBSD, use the ptl2 thread library (experimental)], + use_ptl2="$withval", use_ptl2="no") + + : ${LOCALBASE:=/usr/pkg} + + if test "X$use_ptl2" = "Xyes" + then + AC_MSG_RESULT(PTL2) + AC_MSG_WARN( +[linking with PTL2 is highly experimental and not expected to work]) + CC=ptlgcc + else + if test ! -d $LOCALBASE/pthreads + then + AC_MSG_RESULT(none) + use_threads=false + fi + + if $use_threads + then + AC_MSG_RESULT(mit-pthreads/unproven-pthreads) + pkg="$LOCALBASE/pthreads" + lib1="-L$pkg/lib -Wl,-R$pkg/lib" + lib2="-lpthread -lm -lgcc -lpthread" + LIBS="$lib1 $lib2 $LIBS" + CPPFLAGS="$CPPFLAGS -I$pkg/include" + STD_CINCLUDES="$STD_CINCLUDES -I$pkg/include" + fi + fi + ;; + *) + AC_CHECK_LIB(pthread, pthread_create,, + AC_CHECK_LIB(pthread, __pthread_create,, + AC_CHECK_LIB(pthread, __pthread_create_system,, + AC_CHECK_LIB(c_r, pthread_create,, + AC_CHECK_LIB(c, pthread_create,, + use_threads=false))))) + ;; + esac +fi + +if $use_threads +then + # + # We'd like to use sigwait() too + # + AC_CHECK_LIB(c, sigwait, + AC_DEFINE(HAVE_SIGWAIT), + AC_CHECK_LIB(pthread, sigwait, + AC_DEFINE(HAVE_SIGWAIT), + AC_CHECK_LIB(pthread, _Psigwait, + AC_DEFINE(HAVE_SIGWAIT),)) + ) + + AC_CHECK_FUNC(pthread_attr_getstacksize, + AC_DEFINE(HAVE_PTHREAD_ATTR_GETSTACKSIZE),) + + # + # Additional OS-specific issues related to pthreads and sigwait. + # + case "$host" in + # + # One more place to look for sigwait. + # + *-freebsd*) + AC_CHECK_LIB(c_r, sigwait, AC_DEFINE(HAVE_SIGWAIT),) + ;; + # + # BSDI 3.0 through 4.0.1 needs pthread_init() to be + # called before certain pthreads calls. This is deprecated + # in BSD/OS 4.1. + # + *-bsdi3.*|*-bsdi4.0*) + AC_DEFINE(NEED_PTHREAD_INIT) + ;; + # + # LinuxThreads requires some changes to the way we + # deal with signals. + # + *-linux*) + AC_DEFINE(HAVE_LINUXTHREADS) + ;; + # + # Ensure the right sigwait() semantics on Solaris and make + # sure we call pthread_setconcurrency. + # + *-solaris*) + AC_DEFINE(_POSIX_PTHREAD_SEMANTICS) + AC_CHECK_FUNC(pthread_setconcurrency, + AC_DEFINE(CALL_PTHREAD_SETCONCURRENCY)) + ;; + # + # UnixWare does things its own way. + # + *-UnixWare*) + AC_DEFINE(HAVE_UNIXWARE_SIGWAIT) + ;; + esac + + # + # Look for sysconf to allow detection of the number of processors. + # + AC_CHECK_FUNC(sysconf, AC_DEFINE(HAVE_SYSCONF),) + + if test "X$GCC" = "Xyes"; then + case "$host" in + *-freebsd*) + CC="$CC -pthread" + CCOPT="$CCOPT -pthread" + STD_CDEFINES="$STD_CDEFINES -D_THREAD_SAFE" + ;; + *-openbsd*) + CC="$CC -pthread" + CCOPT="$CCOPT -pthread" + ;; + *-solaris*) + LIBS="$LIBS -lthread" + ;; + *-ibm-aix*) + STD_CDEFINES="$STD_CDEFINES -D_THREAD_SAFE" + ;; + esac + else + case $host in + *-dec-osf*) + CC="$CC -pthread" + CCOPT="$CCOPT -pthread" + ;; + *-solaris*) + CC="$CC -mt" + CCOPT="$CCOPT -mt" + ;; + *-ibm-aix*) + STD_CDEFINES="$STD_CDEFINES -D_THREAD_SAFE" + ;; + *-UnixWare*) + CC="$CC -Kthread" + CCOPT="$CCOPT -Kthread" + ;; + esac + fi + ALWAYS_DEFINES="-D_REENTRANT" + DO_PTHREADS="#define DO_PTHREADS 1" + WANT_IRS_THREADSGR_OBJS="\${WANT_IRS_THREADSGR_OBJS}" + WANT_IRS_THREADSPW_OBJS="\${WANT_IRS_THREADSPW_OBJS}" + WANT_IRS_THREADS_OBJS="\${WANT_IRS_THREADS_OBJS}" + thread_dir=pthreads +else + ALWAYS_DEFINES="" + DO_PTHREADS="#undef DO_PTHREADS" + WANT_IRS_THREADSGR_OBJS="" + WANT_IRS_THREADSPW_OBJS="" + WANT_IRS_THREADS_OBJS="" + thread_dir=nothreads +fi + +AC_SUBST(ALWAYS_DEFINES) +AC_SUBST(DO_PTHREADS) +AC_SUBST(WANT_IRS_THREADSGR_OBJS) +AC_SUBST(WANT_IRS_THREADSPW_OBJS) +AC_SUBST(WANT_IRS_THREADS_OBJS) + +ISC_THREAD_DIR=$thread_dir +AC_SUBST(ISC_THREAD_DIR) + +# +# flockfile is usually provided by pthreads, but we may want to use it +# even if compiled with --disable-threads. +# +AC_CHECK_FUNC(flockfile, AC_DEFINE(HAVE_FLOCKFILE),) + +# +# Indicate what the final decision was regarding threads. +# +AC_MSG_CHECKING(whether to build with threads) +if $use_threads; then + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + +# +# End of pthreads stuff. +# + +# +# Additional compiler settings. +# +MKDEPCC="$CC" +MKDEPCFLAGS="-M" +IRIX_DNSSEC_WARNINGS_HACK="" + +if test "X$GCC" = "Xyes"; then + STD_CWARNINGS="$STD_CWARNINGS -W -Wall -Wmissing-prototypes -Wcast-qual -Wwrite-strings" +else + case $host in + *-dec-osf*) + CC="$CC -std" + CCOPT="$CCOPT -std" + MKDEPCC="$CC" + ;; + *-hp-hpux*) + CC="$CC -Ae -z" + # The version of the C compiler that constantly warns about + # 'const' as well as alignment issues is unfortunately not + # able to be discerned via the version of the operating + # system, nor does cc have a version flag. + case "`$CC +W 123 2>&1`" in + *Unknown?option*) + STD_CWARNINGS="+w1" + ;; + *) + # Turn off the pointlessly noisy warnings. + STD_CWARNINGS="+w1 +W 474,530" + ;; + esac + CCOPT="$CCOPT -Ae -z" + LIBS="-Wl,+vnocompatwarnings $LIBS" + MKDEPPROG='cc -Ae -E -Wp,-M >/dev/null 2>>$TMP' + ;; + *-sgi-irix*) + STD_CWARNINGS="-fullwarn -woff 1209" + # + # Silence more than 250 instances of + # "prototyped function redeclared without prototype" + # and 11 instances of + # "variable ... was set but never used" + # from lib/dns/sec/openssl. + # + IRIX_DNSSEC_WARNINGS_HACK="-woff 1692,1552" + ;; + *-solaris*) + MKDEPCFLAGS="-xM" + ;; + *-UnixWare*) + CC="$CC -w" + ;; + esac +fi + +AC_SUBST(MKDEPCC) +AC_SUBST(MKDEPCFLAGS) +AC_SUBST(MKDEPPROG) +AC_SUBST(IRIX_DNSSEC_WARNINGS_HACK) + +# +# NLS +# +AC_CHECK_FUNC(catgets, AC_DEFINE(HAVE_CATGETS),) + +# +# -lxnet buys us one big porting headache... standards, gotta love 'em. +# +# AC_CHECK_LIB(xnet, socket, , +# AC_CHECK_LIB(socket, socket) +# AC_CHECK_LIB(nsl, inet_ntoa) +# ) +# +# Use this for now, instead: +# +case "$host" in + mips-sgi-irix*) + ;; + *) + AC_CHECK_LIB(socket, socket) + AC_CHECK_LIB(nsl, inet_ntoa) + ;; +esac + +# +# Purify support +# +AC_MSG_CHECKING(whether to use purify) +AC_ARG_WITH(purify, + [ --with-purify[=PATH] use Rational purify], + use_purify="$withval", use_purify="no") + +case "$use_purify" in + no) + ;; + yes) + AC_PATH_PROG(purify_path, purify, purify) + ;; + *) + purify_path="$use_purify" + ;; +esac + +case "$use_purify" in + no) + AC_MSG_RESULT(no) + PURIFY="" + ;; + *) + if test -f $purify_path || test $purify_path = purify; then + AC_MSG_RESULT($purify_path) + PURIFYFLAGS="`echo $PURIFYOPTIONS`" + PURIFY="$purify_path $PURIFYFLAGS" + else + AC_MSG_ERROR([$purify_path not found. + +Please choose the proper path with the following command: + + configure --with-purify=PATH +]) + fi + ;; +esac + +AC_SUBST(PURIFY) + +# +# GNU libtool support +# +AC_ARG_WITH(libtool, + [ --with-libtool use GNU libtool (following indented options supported)], + use_libtool="$withval", use_libtool="no") + +case $use_libtool in + yes) + AM_PROG_LIBTOOL + O=lo + A=la + ;; + *) + O=o + A=a + LIBTOOL= + AC_SUBST(LIBTOOL) + ;; +esac + +# +# File name extension for static archive files, for those few places +# where they are treated differently from dynamic ones. +# +SA=a + +AC_SUBST(O) +AC_SUBST(A) +AC_SUBST(SA) + +# +# Here begins a very long section to determine the system's networking +# capabilities. The order of the tests is signficant. +# + +# +# IPv6 +# +AC_ARG_ENABLE(ipv6, + [ --enable-ipv6 use IPv6 [default=autodetect]]) + +case "$enable_ipv6" in + yes|''|autodetect) + AC_DEFINE(WANT_IPV6) + ;; + no) + ;; +esac + +# +# We do the IPv6 compilation checking after libtool so that we can put +# the right suffix on the files. +# +AC_MSG_CHECKING(for IPv6 structures) +AC_TRY_COMPILE([ +#include +#include +#include ], +[struct sockaddr_in6 sin6; return (0);], + [AC_MSG_RESULT(yes) + found_ipv6=yes], + [AC_MSG_RESULT(no) + found_ipv6=no]) + +# +# See whether IPv6 support is provided via a Kame add-on. +# This is done before other IPv6 linking tests to LIBS is properly set. +# +AC_MSG_CHECKING(for Kame IPv6 support) +AC_ARG_WITH(kame, + [ --with-kame[=PATH] use Kame IPv6 [default path /usr/local/v6]], + use_kame="$withval", use_kame="no") + +case "$use_kame" in + no) + ;; + yes) + kame_path=/usr/local/v6 + ;; + *) + kame_path="$use_kame" + ;; +esac + +case "$use_kame" in + no) + AC_MSG_RESULT(no) + ;; + *) + if test -f $kame_path/lib/libinet6.a; then + AC_MSG_RESULT($kame_path/lib/libinet6.a) + LIBS="-L$kame_path/lib -linet6 $LIBS" + else + AC_MSG_ERROR([$kame_path/lib/libinet6.a not found. + +Please choose the proper path with the following command: + + configure --with-kame=PATH +]) + fi + ;; +esac + +# +# Whether netinet6/in6.h is needed has to be defined in isc/platform.h. +# Including it on Kame-using platforms is very bad, though, because +# Kame uses #error against direct inclusion. So include it on only +# the platform that is otherwise broken without it -- BSD/OS 4.0 through 4.1. +# This is done before the in6_pktinfo check because that's what +# netinet6/in6.h is needed for. +# +changequote({, }) +case "$host" in +*-bsdi4.[01]*) + ISC_PLATFORM_NEEDNETINET6IN6H="#define ISC_PLATFORM_NEEDNETINET6IN6H 1" + LWRES_PLATFORM_NEEDNETINET6IN6H="#define LWRES_PLATFORM_NEEDNETINET6IN6H 1" + isc_netinet6in6_hack="#include " + ;; +*) + ISC_PLATFORM_NEEDNETINET6IN6H="#undef ISC_PLATFORM_NEEDNETINET6IN6H" + LWRES_PLATFORM_NEEDNETINET6IN6H="#undef LWRES_PLATFORM_NEEDNETINET6IN6H" + isc_netinet6in6_hack="" + ;; +esac +changequote([, ]) + +# +# This is similar to the netinet6/in6.h issue. +# +case "$host" in +*-UnixWare*) + ISC_PLATFORM_NEEDNETINETIN6H="#define ISC_PLATFORM_NEEDNETINETIN6H 1" + LWRES_PLATFORM_NEEDNETINETIN6H="#define LWRES_PLATFORM_NEEDNETINETIN6H 1" + ISC_PLATFORM_FIXIN6ISADDR="#define ISC_PLATFORM_FIXIN6ISADDR 1" + isc_netinetin6_hack="#include " + ;; +*) + ISC_PLATFORM_NEEDNETINETIN6H="#undef ISC_PLATFORM_NEEDNETINETIN6H" + LWRES_PLATFORM_NEEDNETINETIN6H="#undef LWRES_PLATFORM_NEEDNETINETIN6H" + ISC_PLATFORM_FIXIN6ISADDR="#undef ISC_PLATFORM_FIXIN6ISADDR" + isc_netinetin6_hack="" + ;; +esac + +# +# Now delve deeper into the suitability of the IPv6 support. +# +case "$found_ipv6" in + yes) + ISC_PLATFORM_HAVEIPV6="#define ISC_PLATFORM_HAVEIPV6 1" + LWRES_PLATFORM_HAVEIPV6="#define LWRES_PLATFORM_HAVEIPV6 1" + + AC_MSG_CHECKING(for in6_addr) + AC_TRY_COMPILE([ +#include +#include +#include +$isc_netinetin6_hack +$isc_netinet6in6_hack +], +[struct in6_addr in6; return (0);], + [AC_MSG_RESULT(yes) + ISC_PLATFORM_HAVEINADDR6="#undef ISC_PLATFORM_HAVEINADDR6" + LWRES_PLATFORM_HAVEINADDR6="#undef LWRES_PLATFORM_HAVEINADDR6" + isc_in_addr6_hack=""], + [AC_MSG_RESULT(no) + ISC_PLATFORM_HAVEINADDR6="#define ISC_PLATFORM_HAVEINADDR6 1" + LWRES_PLATFORM_HAVEINADDR6="#define LWRES_PLATFORM_HAVEINADDR6 1" + isc_in_addr6_hack="#define in6_addr in_addr6"]) + + AC_MSG_CHECKING(for in6addr_any) + AC_TRY_LINK([ +#include +#include +#include +$isc_netinetin6_hack +$isc_netinet6in6_hack +$isc_in_addr6_hack +], + [struct in6_addr in6; in6 = in6addr_any; return (0);], + [AC_MSG_RESULT(yes) + ISC_PLATFORM_NEEDIN6ADDRANY="#undef ISC_PLATFORM_NEEDIN6ADDRANY" + LWRES_PLATFORM_NEEDIN6ADDRANY="#undef LWRES_PLATFORM_NEEDIN6ADDRANY"], + [AC_MSG_RESULT(no) + ISC_PLATFORM_NEEDIN6ADDRANY="#define ISC_PLATFORM_NEEDIN6ADDRANY 1" + LWRES_PLATFORM_NEEDIN6ADDRANY="#define LWRES_PLATFORM_NEEDIN6ADDRANY 1"]) + + AC_MSG_CHECKING(for sin6_scope_id in struct sockaddr_in6) + AC_TRY_COMPILE([ +#include +#include +#include +$isc_netinetin6_hack +$isc_netinet6in6_hack +], + [struct sockaddr_in6 xyzzy; xyzzy.sin6_scope_id = 0; return (0);], + [AC_MSG_RESULT(yes) + result="#define LWRES_HAVE_SIN6_SCOPE_ID 1"], + [AC_MSG_RESULT(no) + result="#undef LWRES_HAVE_SIN6_SCOPE_ID"]) + LWRES_HAVE_SIN6_SCOPE_ID="$result" + + AC_MSG_CHECKING(for in6_pktinfo) + AC_TRY_COMPILE([ +#include +#include +#include +$isc_netinetin6_hack +$isc_netinet6in6_hack +], + [struct in6_pktinfo xyzzy; return (0);], + [AC_MSG_RESULT(yes) + ISC_PLATFORM_HAVEIN6PKTINFO="#define ISC_PLATFORM_HAVEIN6PKTINFO 1"], + [AC_MSG_RESULT(no -- disabling runtime ipv6 support) + ISC_PLATFORM_HAVEIN6PKTINFO="#undef ISC_PLATFORM_HAVEIN6PKTINFO"]) + ;; + no) + ISC_PLATFORM_HAVEIPV6="#undef ISC_PLATFORM_HAVEIPV6" + LWRES_PLATFORM_HAVEIPV6="#undef LWRES_PLATFORM_HAVEIPV6" + ISC_PLATFORM_NEEDIN6ADDRANY="#undef ISC_PLATFORM_NEEDIN6ADDRANY" + LWRES_PLATFORM_NEEDIN6ADDRANY="#undef LWRES_PLATFORM_NEEDIN6ADDRANY" + ISC_PLATFORM_HAVEIN6PKTINFO="#undef ISC_PLATFORM_HAVEIN6PKTINFO" + LWRES_HAVE_SIN6_SCOPE_ID="#define LWRES_HAVE_SIN6_SCOPE_ID 1" + ISC_IPV6_H="ipv6.h" + ISC_IPV6_O="ipv6.$O" + ISC_ISCIPV6_O="unix/ipv6.$O" + ISC_IPV6_C="ipv6.c" + ;; +esac + +AC_SUBST(ISC_PLATFORM_HAVEIPV6) +AC_SUBST(LWRES_PLATFORM_HAVEIPV6) +AC_SUBST(ISC_PLATFORM_NEEDNETINETIN6H) +AC_SUBST(LWRES_PLATFORM_NEEDNETINETIN6H) +AC_SUBST(ISC_PLATFORM_NEEDNETINET6IN6H) +AC_SUBST(LWRES_PLATFORM_NEEDNETINET6IN6H) +AC_SUBST(ISC_PLATFORM_HAVEINADDR6) +AC_SUBST(LWRES_PLATFORM_HAVEINADDR6) +AC_SUBST(ISC_PLATFORM_NEEDIN6ADDRANY) +AC_SUBST(LWRES_PLATFORM_NEEDIN6ADDRANY) +AC_SUBST(ISC_PLATFORM_HAVEIN6PKTINFO) +AC_SUBST(ISC_PLATFORM_FIXIN6ISADDR) +AC_SUBST(ISC_IPV6_H) +AC_SUBST(ISC_IPV6_O) +AC_SUBST(ISC_ISCIPV6_O) +AC_SUBST(ISC_IPV6_C) +AC_SUBST(LWRES_HAVE_SIN6_SCOPE_ID) + +# +# Check for network functions that are often missing. We do this +# after the libtool checking, so we can put the right suffix on +# the files. It also needs to come after checking for a Kame add-on, +# which provides some (all?) of the desired functions. +# +AC_MSG_CHECKING([for inet_ntop]) +AC_TRY_LINK([ +#include +#include +#include ], + [inet_ntop(0, 0, 0, 0); return (0);], + [AC_MSG_RESULT(yes) + ISC_PLATFORM_NEEDNTOP="#undef ISC_PLATFORM_NEEDNTOP"], + + [AC_MSG_RESULT(no) + ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_ntop.$O" + ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_ntop.c" + ISC_PLATFORM_NEEDNTOP="#define ISC_PLATFORM_NEEDNTOP 1"]) +AC_MSG_CHECKING([for inet_pton]) +AC_TRY_LINK([ +#include +#include +#include ], + [inet_pton(0, 0, 0); return (0);], + [AC_MSG_RESULT(yes) + ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON"], + + [AC_MSG_RESULT(no) + ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_pton.$O" + ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_pton.c" + ISC_PLATFORM_NEEDPTON="#define ISC_PLATFORM_NEEDPTON 1"]) +AC_MSG_CHECKING([for inet_aton]) +AC_TRY_LINK([ +#include +#include +#include ], + [struct in_addr in; inet_aton(0, &in); return (0);], + [AC_MSG_RESULT(yes) + ISC_PLATFORM_NEEDATON="#undef ISC_PLATFORM_NEEDATON"], + + [AC_MSG_RESULT(no) + ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_aton.$O" + ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_aton.c" + ISC_PLATFORM_NEEDATON="#define ISC_PLATFORM_NEEDATON 1"]) + +AC_SUBST(ISC_PLATFORM_NEEDNTOP) +AC_SUBST(ISC_PLATFORM_NEEDPTON) +AC_SUBST(ISC_PLATFORM_NEEDATON) + +# +# Look for a 4.4BSD-style sa_len member in struct sockaddr. +# +case "$host" in + *-dec-osf*) + # Turn on 4.4BSD style sa_len support. + AC_DEFINE(_SOCKADDR_LEN) + ;; +esac + +AC_MSG_CHECKING(for sa_len in struct sockaddr) +AC_TRY_COMPILE([ +#include +#include ], +[struct sockaddr sa; sa.sa_len = 0; return (0);], + [AC_MSG_RESULT(yes) + HAVE_SA_LEN="#define HAVE_SA_LEN 1"], + [AC_MSG_RESULT(no) + HAVE_SA_LEN="#undef HAVE_SA_LEN"]) +AC_SUBST(HAVE_SA_LEN) + +# HAVE_MINIMUM_IFREQ + +case "$host" in + *-bsdi4*) have_minimum_ifreq=yes;; + *-bsdi3*) have_minimum_ifreq=yes;; + *-bsdi2*) have_minimum_ifreq=yes;; + *-darwin*) have_minimum_ifreq=yes;; + *-freebsd*) have_minimum_ifreq=yes;; + *-lynxos*) have_minimum_ifreq=yes;; + *-netbsd*) have_minimum_ifreq=yes;; + *-next*) have_minimum_ifreq=yes;; + *-openbsd*) have_minimum_ifreq=yes;; + *-rhapsody*) have_minimum_ifreq=yes;; +esac +case "$have_minimum_ifreq" in + yes) + HAVE_MINIMUM_IFREQ="#define HAVE_MINIMUM_IFREQ 1";; + no) + HAVE_MINIMUM_IFREQ="#undef HAVE_MINIMUM_IFREQ";; + *) + HAVE_MINIMUM_IFREQ="#undef HAVE_MINIMUM_IFREQ";; +esac +AC_SUBST(HAVE_MINIMUM_IFREQ) +# +# Look for a 4.4BSD or 4.3BSD struct msghdr +# +AC_MSG_CHECKING(for struct msghdr flavor) +AC_TRY_COMPILE([ +#include +#include ], +[struct msghdr msg; msg.msg_flags = 0; return (0);], + [AC_MSG_RESULT(4.4BSD) + ISC_PLATFORM_MSGHDRFLAVOR="#define ISC_NET_BSD44MSGHDR 1"], + [AC_MSG_RESULT(4.3BSD) + ISC_PLATFORM_MSGHDRFLAVOR="#define ISC_NET_BSD43MSGHDR 1"]) +AC_SUBST(ISC_PLATFORM_MSGHDRFLAVOR) + +# +# Look for in_port_t. +# +AC_MSG_CHECKING(for type in_port_t) +AC_TRY_COMPILE([ +#include +#include ], +[in_port_t port = 25; return (0);], + [AC_MSG_RESULT(yes) + ISC_PLATFORM_NEEDPORTT="#undef ISC_PLATFORM_NEEDPORTT"], + [AC_MSG_RESULT(no) + ISC_PLATFORM_NEEDPORTT="#define ISC_PLATFORM_NEEDPORTT 1"]) +AC_SUBST(ISC_PLATFORM_NEEDPORTT) + +# +# Check for addrinfo +# +AC_MSG_CHECKING(for struct addrinfo) +AC_TRY_COMPILE([ +#include ], +[struct addrinfo a; return (0);], + [AC_MSG_RESULT(yes) + ISC_LWRES_NEEDADDRINFO="#undef ISC_LWRES_NEEDADDRINFO" + AC_DEFINE(HAVE_ADDRINFO)], + [AC_MSG_RESULT(no) + ISC_LWRES_NEEDADDRINFO="#define ISC_LWRES_NEEDADDRINFO 1"]) +AC_SUBST(ISC_LWRES_NEEDADDRINFO) + +AC_MSG_CHECKING(for int sethostent) +AC_TRY_COMPILE([ +#include ], +[int i = sethostent(0); return(0);], + [AC_MSG_RESULT(yes) + ISC_LWRES_SETHOSTENTINT="#define ISC_LWRES_SETHOSTENTINT 1"], + [AC_MSG_RESULT(no) + ISC_LWRES_SETHOSTENTINT="#undef ISC_LWRES_SETHOSTENTINT"]) +AC_SUBST(ISC_LWRES_SETHOSTENTINT) + +AC_MSG_CHECKING(for int endhostent) +AC_TRY_COMPILE([ +#include ], +[int i = endhostent(); return(0);], + [AC_MSG_RESULT(yes) + ISC_LWRES_ENDHOSTENTINT="#define ISC_LWRES_ENDHOSTENTINT 1"], + [AC_MSG_RESULT(no) + ISC_LWRES_ENDHOSTENTINT="#undef ISC_LWRES_ENDHOSTENTINT"]) +AC_SUBST(ISC_LWRES_ENDHOSTENTINT) + +AC_MSG_CHECKING(for getnetbyaddr(in_addr_t, ...)) +AC_TRY_COMPILE([ +#include +struct netent *getnetbyaddr(in_addr_t, int);], +[], + [AC_MSG_RESULT(yes) + GETNETBYADDR_ADDR_T="#define GETNETBYADDR_ADDR_T in_addr_t"], + [AC_MSG_RESULT(no) + GETNETBYADDR_ADDR_T="#define GETNETBYADDR_ADDR_T long"]) +AC_SUBST(GETNETBYADDR_ADDR_T) + +AC_MSG_CHECKING(for int setnetent) +AC_TRY_COMPILE([ +#include ], +[int i = setnetent(0); return(0);], + [AC_MSG_RESULT(yes) + ISC_LWRES_SETNETENTINT="#define ISC_LWRES_SETNETENTINT 1"], + [AC_MSG_RESULT(no) + ISC_LWRES_SETNETENTINT="#undef ISC_LWRES_SETNETENTINT"]) +AC_SUBST(ISC_LWRES_SETNETENTINT) + +AC_MSG_CHECKING(for int endnetent) +AC_TRY_COMPILE([ +#include ], +[int i = endnetent(); return(0);], + [AC_MSG_RESULT(yes) + ISC_LWRES_ENDNETENTINT="#define ISC_LWRES_ENDNETENTINT 1"], + [AC_MSG_RESULT(no) + ISC_LWRES_ENDNETENTINT="#undef ISC_LWRES_ENDNETENTINT"]) +AC_SUBST(ISC_LWRES_ENDNETENTINT) + +AC_MSG_CHECKING(for gethostbyaddr(const void *, size_t, ...)) +AC_TRY_COMPILE([ +#include +struct hostent *gethostbyaddr(const void *, size_t, int);], +[return(0);], + [AC_MSG_RESULT(yes) + ISC_LWRES_GETHOSTBYADDRVOID="#define ISC_LWRES_GETHOSTBYADDRVOID 1"], + [AC_MSG_RESULT(no) + ISC_LWRES_GETHOSTBYADDRVOID="#undef ISC_LWRES_GETHOSTBYADDRVOID"]) +AC_SUBST(ISC_LWRES_GETHOSTBYADDRVOID) + +AC_MSG_CHECKING(for h_errno in netdb.h) +AC_TRY_COMPILE([ +#include ], +[h_errno = 1; return(0);], + [AC_MSG_RESULT(yes) + ISC_LWRES_NEEDHERRNO="#undef ISC_LWRES_NEEDHERRNO"], + [AC_MSG_RESULT(no) + ISC_LWRES_NEEDHERRNO="#define ISC_LWRES_NEEDHERRNO 1"]) +AC_SUBST(ISC_LWRES_NEEDHERRNO) + +AC_CHECK_FUNC(getipnodebyname, + [ISC_LWRES_GETIPNODEPROTO="#undef ISC_LWRES_GETIPNODEPROTO"], + [ISC_LWRES_GETIPNODEPROTO="#define ISC_LWRES_GETIPNODEPROTO 1"]) +AC_CHECK_FUNC(getnameinfo, + [ISC_LWRES_GETNAMEINFOPROTO="#undef ISC_LWRES_GETNAMEINFOPROTO"], + [ISC_LWRES_GETNAMEINFOPROTO="#define ISC_LWRES_GETNAMEINFOPROTO 1"]) +AC_CHECK_FUNC(getaddrinfo, + [ISC_LWRES_GETADDRINFOPROTO="#undef ISC_LWRES_GETADDRINFOPROTO" + AC_DEFINE(HAVE_GETADDRINFO)], + [ISC_LWRES_GETADDRINFOPROTO="#define ISC_LWRES_GETADDRINFOPROTO 1"]) +AC_CHECK_FUNC(gai_strerror, AC_DEFINE(HAVE_GAISTRERROR)) +AC_SUBST(ISC_LWRES_GETIPNODEPROTO) +AC_SUBST(ISC_LWRES_GETADDRINFOPROTO) +AC_SUBST(ISC_LWRES_GETNAMEINFOPROTO) +AC_CHECK_FUNC(pselect, + [NEED_PSELECT="#undef NEED_PSELECT"], + [NEED_PSELECT="#define NEED_PSELECT"]) +AC_SUBST(NEED_PSELECT) + +# +# Look for a sysctl call to get the list of network interfaces. +# +AC_MSG_CHECKING(for interface list sysctl) +AC_EGREP_CPP(found_rt_iflist, [ +#include +#include +#include +#ifdef NET_RT_IFLIST +found_rt_iflist +#endif +], + [AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_IFLIST_SYSCTL)], + [AC_MSG_RESULT(no)]) + +# +# Check for some other useful functions that are not ever-present. +# +AC_CHECK_FUNC(strsep, + [ISC_PLATFORM_NEEDSTRSEP="#undef ISC_PLATFORM_NEEDSTRSEP"], + [ISC_PLATFORM_NEEDSTRSEP="#define ISC_PLATFORM_NEEDSTRSEP 1"]) +AC_CHECK_FUNC(vsnprintf, + [ISC_PLATFORM_NEEDVSNPRINTF="#undef ISC_PLATFORM_NEEDVSNPRINTF"], + [ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS print.$O" + ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS print.c" + ISC_PLATFORM_NEEDVSNPRINTF="#define ISC_PLATFORM_NEEDVSNPRINTF 1"]) +AC_SUBST(ISC_PLATFORM_NEEDSTRSEP) +AC_SUBST(ISC_PLATFORM_NEEDVSNPRINTF) + +AC_SUBST(ISC_EXTRA_OBJS) +AC_SUBST(ISC_EXTRA_SRCS) + +# +# Determine the printf format characters to use when printing +# values of type isc_int64_t. We make the assumption that platforms +# where a "long long" is the same size as a "long" (e.g., Alpha/OSF1) +# want "%ld" and everyone else can use "%lld". Win32 uses "%I64d", +# but that's defined elsewhere since we don't use configure on Win32. +# +AC_MSG_CHECKING(printf format modifier for 64-bit integers) +AC_TRY_RUN([main() { exit(!(sizeof(long long int) == sizeof(long int))); }], + [AC_MSG_RESULT(l) + ISC_PLATFORM_QUADFORMAT='#define ISC_PLATFORM_QUADFORMAT "l"'], + [AC_MSG_RESULT(ll) + ISC_PLATFORM_QUADFORMAT='#define ISC_PLATFORM_QUADFORMAT "ll"'], + [AC_MSG_RESULT(default ll) + ISC_PLATFORM_QUADFORMAT='#define ISC_PLATFORM_QUADFORMAT "ll"']) +AC_SUBST(ISC_PLATFORM_QUADFORMAT) + +# +# Security Stuff +# +AC_CHECK_FUNC(chroot, AC_DEFINE(HAVE_CHROOT)) +AC_CHECK_HEADERS(linux/capability.h) +AC_CHECK_HEADERS(sys/prctl.h) + +# +# BSD/OS, and perhaps some others, don't define rlim_t. +# +AC_MSG_CHECKING(for type rlim_t) +AC_TRY_COMPILE([ +#include +#include +#include ], +[rlim_t rl = 19671212; return (0);], + [AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_RLIM_T)], + [AC_MSG_RESULT(no)]) +AC_MSG_CHECKING(sizeof rlim_cur) +AC_TRY_RUN([ +#include +#include +#include +main() { struct rlimit r; exit(!(sizeof(r.rlim_cur) == sizeof(int)));}], +[AC_MSG_RESULT(int) +ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE int"], +[ +AC_TRY_RUN([ +#include +#include +#include +main() { struct rlimit r; exit(!(sizeof(r.rlim_cur) == sizeof(long int)));}], +[AC_MSG_RESULT(long int) +ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE long int"], +[ +AC_TRY_RUN([ +#include +#include +#include +main() { struct rlimit r; exit((!sizeof(r.rlim_cur) == sizeof(long long int)));}], +[AC_MSG_RESULT(long long int) +ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE long long int"], +[AC_MSG_ERROR([unable to determine sizeof rlim_cur]) +],[]) +],[]) +],[]) +AC_SUBST(ISC_PLATFORM_RLIMITTYPE) + +AC_CHECK_FUNC(getgrouplist, +AC_TRY_COMPILE( +[#include +int +getgrouplist(const char *name, int basegid, int *groups, int *ngroups) { +} +], +[return (0);], +GETGROUPLIST_ARGS="#define GETGROUPLIST_ARGS const char *name, int basegid, int *groups, int *ngroups" +, +GETGROUPLIST_ARGS="#define GETGROUPLIST_ARGS const char *name, gid_t basegid, gid_t *groups, int *ngroups" +), +GETGROUPLIST_ARGS="#define GETGROUPLIST_ARGS const char *name, gid_t basegid, gid_t *groups, int *ngroups" +) +AC_SUBST(GETGROUPLIST_ARGS) + +AC_CHECK_FUNC(getnetbyaddr_r, +, +NET_R_ARGS="#define NET_R_ARGS char *buf, int buflen" +NET_R_BAD="#define NET_R_BAD NULL" +NET_R_COPY="#define NET_R_COPY buf, buflen" +NET_R_COPY_ARGS="#define NET_R_COPY_ARGS NET_R_ARGS" +NET_R_OK="#define NET_R_OK nptr" +NET_R_RETURN="#define NET_R_RETURN struct netent *" +) +AC_SUBST(NET_R_ARGS) +AC_SUBST(NET_R_BAD) +AC_SUBST(NET_R_COPY) +AC_SUBST(NET_R_COPY_ARGS) +AC_SUBST(NET_R_OK) +AC_SUBST(NET_R_RETURN) + +AC_CHECK_FUNC(setnetent_r, +, +NET_R_ENT_ARGS="#undef NET_R_ENT_ARGS /*empty*/" +NET_R_SET_RESULT="#undef NET_R_SET_RESULT /*empty*/" +NET_R_SET_RETURN="#define NET_R_SET_RETURN void" +) +AC_SUBST(NET_R_ENT_ARGS) +AC_SUBST(NET_R_SET_RESULT) +AC_SUBST(NET_R_SET_RETURN) + +AC_CHECK_FUNC(endnetent_r, +, +NET_R_END_RESULT="#define NET_R_END_RESULT(x) /*empty*/" +NET_R_END_RETURN="#define NET_R_END_RETURN void" +) +AC_SUBST(NET_R_END_RESULT) +AC_SUBST(NET_R_END_RETURN) + +AC_CHECK_FUNC(getgrent_r, +, +GROUP_R_ARGS="#define GROUP_R_ARGS char *buf, int buflen" +GROUP_R_BAD="#define GROUP_R_BAD NULL" +GROUP_R_OK="#define GROUP_R_OK gptr" +GROUP_R_RETURN="#define GROUP_R_RETURN struct group *" +) +AC_SUBST(GROUP_R_ARGS) +AC_SUBST(GROUP_R_BAD) +AC_SUBST(GROUP_R_OK) +AC_SUBST(GROUP_R_RETURN) + +AC_CHECK_FUNC(endgrent_r, +, +GROUP_R_END_RESULT="#define GROUP_R_END_RESULT(x) /*empty*/" +GROUP_R_END_RETURN="#define GROUP_R_END_RETURN void" +GROUP_R_ENT_ARGS="#define GROUP_R_ENT_ARGS void" +) +AC_SUBST(GROUP_R_END_RESULT) +AC_SUBST(GROUP_R_END_RETURN) +AC_SUBST(GROUP_R_ENT_ARGS) + +AC_CHECK_FUNC(setgrent_r, +, +GROUP_R_SET_RESULT="#undef GROUP_R_SET_RESULT /*empty*/" +GROUP_R_SET_RETURN="#define GROUP_R_SET_RETURN void" +) +AC_SUBST(GROUP_R_SET_RESULT) +AC_SUBST(GROUP_R_SET_RETURN) + +AC_CHECK_FUNC(gethostbyname_r, +, +HOST_R_ARGS="#define HOST_R_ARGS char *buf, int buflen, int *h_errnop" +HOST_R_BAD="#define HOST_R_BAD NULL" +HOST_R_COPY="#define HOST_R_COPY buf, buflen" +HOST_R_COPY_ARGS="#define HOST_R_COPY_ARGS char *buf, int buflen" +HOST_R_ERRNO="#define HOST_R_ERRNO *h_errnop = h_errno" +HOST_R_OK="#define HOST_R_OK hptr" +HOST_R_RETURN="#define HOST_R_RETURN struct hostent *" +) +AC_SUBST(HOST_R_ARGS) +AC_SUBST(HOST_R_BAD) +AC_SUBST(HOST_R_COPY) +AC_SUBST(HOST_R_COPY_ARGS) +AC_SUBST(HOST_R_ERRNO) +AC_SUBST(HOST_R_OK) +AC_SUBST(HOST_R_RETURN) + +AC_CHECK_FUNC(endhostent_r, +, +HOST_R_END_RESULT="#define HOST_R_END_RESULT(x) /*empty*/" +HOST_R_END_RETURN="#define HOST_R_END_RETURN void" +HOST_R_ENT_ARGS="#undef HOST_R_ENT_ARGS /*empty*/" +) +AC_SUBST(HOST_R_END_RESULT) +AC_SUBST(HOST_R_END_RETURN) +AC_SUBST(HOST_R_ENT_ARGS) + +AC_CHECK_FUNC(sethostent_r, +, +HOST_R_SET_RESULT="#undef HOST_R_SET_RESULT /*empty*/" +HOST_R_SET_RETURN="#define HOST_R_SET_RETURN void" +) +AC_SUBST(HOST_R_SET_RESULT) +AC_SUBST(HOST_R_SET_RETURN) + + +AC_TRY_COMPILE([ +#include +#include +void +setpwent(void) {} +], +[return (0);], +SETPWENT_VOID="#define SETPWENT_VOID 1" +, +SETPWENT_VOID="#undef SETPWENT_VOID" +) +AC_SUBST(SETPWENT_VOID) + +AC_CHECK_FUNC(getnetgrent_r, +, +NGR_R_ARGS="#define NGR_R_ARGS char *buf, int buflen" +NGR_R_BAD="#define NGR_R_BAD (0)" +NGR_R_COPY="#define NGR_R_COPY buf, buflen" +NGR_R_COPY_ARGS="#define NGR_R_COPY_ARGS NGR_R_ARGS" +NGR_R_OK="#define NGR_R_OK 1" +NGR_R_RETURN="#define NGR_R_RETURN int" +) +AC_SUBST(NGR_R_ARGS) +AC_SUBST(NGR_R_BAD) +AC_SUBST(NGR_R_COPY) +AC_SUBST(NGR_R_COPY_ARGS) +AC_SUBST(NGR_R_OK) +AC_SUBST(NGR_R_RETURN) + +AC_CHECK_FUNC(endnetgrent_r, +, +NGR_R_END_RESULT="#define NGR_R_END_RESULT(x) /*empty*/" +NGR_R_END_RETURN="#define NGR_R_END_RETURN void" +NGR_R_ENT_ARGS="#undef NGR_R_ENT_ARGS /*empty*/" +) +AC_SUBST(NGR_R_END_RESULT) +AC_SUBST(NGR_R_END_RETURN) +AC_SUBST(NGR_R_ENT_ARGS) + +AC_CHECK_FUNC(setnetgrent_r, +, +NGR_R_SET_RESULT="#undef NGR_R_SET_RESULT /*empty*/" +NGR_R_SET_RETURN="#define NGR_R_SET_RETURN void" +) +AC_SUBST(NGR_R_SET_RESULT) +AC_SUBST(NGR_R_SET_RETURN) + + +AC_CHECK_FUNC(getprotoent_r, +, +PROTO_R_ARGS="#define PROTO_R_ARGS char *buf, int buflen" +PROTO_R_BAD="#define PROTO_R_BAD NULL" +PROTO_R_COPY="#define PROTO_R_COPY buf, buflen" +PROTO_R_COPY_ARGS="#define PROTO_R_COPY_ARGS PROTO_R_ARGS" +PROTO_R_OK="#define PROTO_R_OK pptr" +PROTO_R_RETURN="#define PROTO_R_RETURN struct protoent *" +) +AC_SUBST(PROTO_R_ARGS) +AC_SUBST(PROTO_R_BAD) +AC_SUBST(PROTO_R_COPY) +AC_SUBST(PROTO_R_COPY_ARGS) +AC_SUBST(PROTO_R_OK) +AC_SUBST(PROTO_R_RETURN) + +AC_CHECK_FUNC(endprotoent_r, +, +PROTO_R_END_RESULT="#define PROTO_R_END_RESULT(x) /*empty*/" +PROTO_R_END_RETURN="#define PROTO_R_END_RETURN void" +PROTO_R_ENT_ARGS="#undef PROTO_R_ENT_ARGS /*empty*/" +) +AC_SUBST(PROTO_R_END_RESULT) +AC_SUBST(PROTO_R_END_RETURN) +AC_SUBST(PROTO_R_ENT_ARGS) + +AC_CHECK_FUNC(setprotoent_r, +, +PROTO_R_SET_RESULT="#undef PROTO_R_SET_RESULT /*empty*/" +PROTO_R_SET_RETURN="#define PROTO_R_SET_RETURN void" +) +AC_SUBST(PROTO_R_SET_RESULT) +AC_SUBST(PROTO_R_SET_RETURN) + +AC_CHECK_FUNC(getpwent_r, +, +PASS_R_ARGS="#define PASS_R_ARGS char *buf, int buflen" +PASS_R_BAD="#define PASS_R_BAD NULL" +PASS_R_COPY="#define PASS_R_COPY buf, buflen" +PASS_R_COPY_ARGS="#define PASS_R_COPY_ARGS PASS_R_ARGS" +PASS_R_OK="#define PASS_R_OK pwptr" +PASS_R_RETURN="#define PASS_R_RETURN struct passwd *" +) +AC_SUBST(PASS_R_ARGS) +AC_SUBST(PASS_R_BAD) +AC_SUBST(PASS_R_COPY) +AC_SUBST(PASS_R_COPY_ARGS) +AC_SUBST(PASS_R_OK) +AC_SUBST(PASS_R_RETURN) + +AC_CHECK_FUNC(endpwent_r, +, +PASS_R_END_RESULT="#define PASS_R_END_RESULT(x) /*empty*/" +PASS_R_END_RETURN="#define PASS_R_END_RETURN void" +PASS_R_ENT_ARGS="#undef PASS_R_ENT_ARGS /*empty*/" +) +AC_SUBST(PASS_R_END_RESULT) +AC_SUBST(PASS_R_END_RETURN) +AC_SUBST(PASS_R_ENT_ARGS) + +AC_CHECK_FUNC(setpwent_r, +, +PASS_R_SET_RESULT="#undef PASS_R_SET_RESULT /*empty*/" +PASS_R_SET_RETURN="#define PASS_R_SET_RETURN void" +) +AC_SUBST(PASS_R_SET_RESULT) +AC_SUBST(PASS_R_SET_RETURN) + +AC_CHECK_FUNC(getservent_r, +, +SERV_R_ARGS="#define SERV_R_ARGS char *buf, int buflen" +SERV_R_BAD="#define SERV_R_BAD NULL" +SERV_R_COPY="#define SERV_R_COPY buf, buflen" +SERV_R_COPY_ARGS="#define SERV_R_COPY_ARGS SERV_R_ARGS" +SERV_R_OK="#define SERV_R_OK sptr" +SERV_R_RETURN="#define SERV_R_RETURN struct servent *" +) +AC_SUBST(SERV_R_ARGS) +AC_SUBST(SERV_R_BAD) +AC_SUBST(SERV_R_COPY) +AC_SUBST(SERV_R_COPY_ARGS) +AC_SUBST(SERV_R_OK) +AC_SUBST(SERV_R_RETURN) + +AC_CHECK_FUNC(endservent_r, +, +SERV_R_END_RESULT="#define SERV_R_END_RESULT(x) /*empty*/" +SERV_R_END_RETURN="#define SERV_R_END_RETURN void " +SERV_R_ENT_ARGS="#undef SERV_R_ENT_ARGS /*empty*/" +) +AC_SUBST(SERV_R_END_RESULT) +AC_SUBST(SERV_R_END_RETURN) +AC_SUBST(SERV_R_ENT_ARGS) + +AC_CHECK_FUNC(setservent_r, +, +SERV_R_SET_RESULT="#undef SERV_R_SET_RESULT /*empty*/" +SERV_R_SET_RETURN="#define SERV_R_SET_RETURN void" +) +AC_SUBST(SERV_R_SET_RESULT) +AC_SUBST(SERV_R_SET_RETURN) + +# +# Random remaining OS-specific issues involving compiler warnings. +# XXXDCL print messages to indicate some compensation is being done? +# +AC_SUBST(ISC_PLATFORM_BRACEPTHREADONCEINIT) +ISC_PLATFORM_BRACEPTHREADONCEINIT="#undef ISC_PLATFORM_BRACEPTHREADONCEINIT" + +case "$host" in + *-bsdi3.1*) + hack_shutup_sputaux=yes + ;; + *-bsdi4.0*) + hack_shutup_sigwait=yes + hack_shutup_sputaux=yes + ;; + *-bsdi4.1*) + hack_shutup_stdargcast=yes + ;; + *-solaris2.8) + hack_shutup_pthreadonceinit=yes + ;; +esac + +case "$hack_shutup_pthreadonceinit" in + yes) + # + # Shut up PTHREAD_ONCE_INIT unbraced initializer warnings. + # + ISC_PLATFORM_BRACEPTHREADONCEINIT="#define ISC_PLATFORM_BRACEPTHREADONCEINIT 1" + ;; +esac + +case "$hack_shutup_sigwait" in + yes) + # + # Shut up a -Wmissing-prototypes warning for sigwait(). + # + AC_DEFINE(SHUTUP_SIGWAIT) + ;; +esac + +case "$hack_shutup_sputaux" in + yes) + # + # Shut up a -Wmissing-prototypes warning from . + # + AC_DEFINE(SHUTUP_SPUTAUX) + ;; +esac + +case "$hack_shutup_stdargcast" in + yes) + # + # Shut up a -Wcast-qual warning from va_start(). + # + AC_DEFINE(SHUTUP_STDARG_CAST) + ;; +esac + + +# +# Look for jade, preferring openjade if installed. +# + +AC_PATH_PROGS(JADE, openjade jade, jade) +AC_SUBST(JADE) + +# +# Look for tex & pdftex. +# + +AC_PATH_PROGS(TEX, tex) +AC_SUBST(TEX) + +AC_PATH_PROGS(PDFTEX, pdftex) +AC_SUBST(PDFTEX) + +# +# Look for SGML files. NetBSD has them under /usr/pkg/share +# (if installed), FreeBSD has them under /usr/local/share. +# + +SGMLDIR="" + +AC_MSG_CHECKING(for SGML files) +for d in /usr/pkg/share/sgml /usr/local/share/sgml +do + if test -f $d/docbook/dsssl/modular/html/docbook.dsl + then + SGMLDIR=$d + AC_MSG_RESULT(in $SGMLDIR) + break + fi +done + +if test "X$SGMLDIR" = "X" +then + AC_MSG_RESULT("not found"); + SGMLDIR=/usr/local/share/sgml +fi + +AC_SUBST(SGMLDIR) + +# +# Look for XML files. +# +XGMLDIR="" + +AC_MSG_CHECKING(for XML files) +for d in /usr/pkg/share/xml /usr/local/share/xml +do + if test -f $d/dtd/docbook/docbookx.dtd + then + XMLDIR=$d + AC_MSG_RESULT(in $XMLDIR) + break + fi +done + +if test "X$XMLDIR" = "X" +then + AC_MSG_RESULT("not found"); + XMLDIR=/usr/local/share/xml +fi + +AC_SUBST(XMLDIR) + +# +# Substitutions +# +AC_SUBST(BIND9_TOP_BUILDDIR) +BIND9_TOP_BUILDDIR=`pwd` + +AC_SUBST(BIND9_ISC_BUILDINCLUDE) +AC_SUBST(BIND9_ISCCFG_BUILDINCLUDE) +AC_SUBST(BIND9_DNS_BUILDINCLUDE) +AC_SUBST(BIND9_OMAPI_BUILDINCLUDE) +AC_SUBST(BIND9_LWRES_BUILDINCLUDE) +if test "X$srcdir" != "X"; then + BIND9_ISC_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/isc/include" + BIND9_ISCCFG_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/isccfg/include" + BIND9_DNS_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/dns/include" + BIND9_OMAPI_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/omapi/include" + BIND9_LWRES_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/lwres/include" +else + BIND9_ISC_BUILDINCLUDE="" + BIND9_ISCCFG_BUILDINCLUDE="" + BIND9_DNS_BUILDINCLUDE="" + BIND9_OMAPI_BUILDINCLUDE="" + BIND9_LWRES_BUILDINCLUDE="" +fi + +AC_SUBST_FILE(BIND9_INCLUDES) +BIND9_INCLUDES=$BIND9_TOP_BUILDDIR/make/includes + +AC_SUBST_FILE(BIND9_MAKE_RULES) +BIND9_MAKE_RULES=$BIND9_TOP_BUILDDIR/make/rules + +. $srcdir/../../version +BIND9_VERSION="VERSION=${MAJORVER}.${MINORVER}.${PATCHVER}${RELEASETYPE}${RELEASEVER}" +AC_SUBST(BIND9_VERSION) + +AC_SUBST_FILE(LIBISC_API) +LIBISC_API=$srcdir/lib/isc/api + +AC_SUBST_FILE(LIBISCCFG_API) +LIBISCCFG_API=$srcdir/lib/isccfg/api + +AC_SUBST_FILE(LIBDNS_API) +LIBDNS_API=$srcdir/lib/dns/api + +AC_SUBST_FILE(LIBLWRES_API) +LIBLWRES_API=$srcdir/lib/lwres/api + +AC_SUBST_FILE(LIBOMAPI_API) +LIBOMAPI_API=$srcdir/lib/omapi/api + +AC_OUTPUT( + Makefile + bsd/Makefile + cylink/Makefile + dnssafe/Makefile + dst/Makefile + include/Makefile + inet/Makefile + irs/Makefile + isc/Makefile + nameser/Makefile + port_after.h + port_before.h + resolv/Makefile + make/rules + make/mkdep + make/includes +) + +# Tell Emacs to edit this file in shell mode. +# Local Variables: +# mode: sh +# End: diff --git a/lib/bind/cylink/Makefile.in b/lib/bind/cylink/Makefile.in new file mode 100644 index 0000000000..c4fd9ac909 --- /dev/null +++ b/lib/bind/cylink/Makefile.in @@ -0,0 +1,12 @@ +OBJS= bn.@O@ bn00.@O@ lbn00.@O@ lbnmem.@O@ legal.@O@ \ + bits.@O@ dss.@O@ math.@O@ ctk_prime.@O@ rand.@O@ sha.@O@ swap.@O@ + +SRCS= bn.c bn00.c lbn00.c lbnmem.c legal.c \ + bits.c dss.c math.c ctk_prime.c rand.c sha.c swap.c + +TARGETS= ${OBJS} + +CINCLUDES= -I.. -I../include +CWARNINGS= -Werror + +@BIND9_MAKE_RULES@ diff --git a/lib/bind/cylink/bits.c b/lib/bind/cylink/bits.c new file mode 100644 index 0000000000..7cfae8c76b --- /dev/null +++ b/lib/bind/cylink/bits.c @@ -0,0 +1,359 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: bit.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Bit Utility Functions +* +* PUBLIC FUNCTIONS: +* +* +* PRIVATE FUNCTIONS: +* +* REVISION HISTORY: +* +* +****************************************************************************/ + +/**************************************************************************** +* INCLUDE FILES +****************************************************************************/ +/* bn files */ +#include "port_before.h" +#include +#include "bn.h" +/* system files */ +#ifdef VXD +#include +#else +#include +#include +#endif +/* program files */ +#include "cylink.h" +#include "ctk_endian.h" +#include "c_asm.h" +#include "port_after.h" + + +/**************************************************************************** +* NAME: void RShiftL( ord *X, +* u_int32_t len_X, +* u_int32_t n_bit ) +* +* DESCRIPTION: Shift array to the right by n_bit. +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to array +* u_int32_t len_X Length of array +* u_int32_t n_bit Number of bits +* OUTPUT: +* PARAMETERS: +* ord *X Pointer to array +* +* RETURN: +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +void RShiftL_big( ord *X, + u_int32_t len_X, + u_int32_t n_bit ) +{ + +struct BigNum dest; +bnInit(); +bnBegin(&dest); + +dest.ptr = X; +dest.size = len_X; +dest.allocated = len_X; + +bnRShift(&dest,n_bit); + +} + +/**************************************************************************** +* NAME: void LShiftL( ord *X, +* u_int32_t len_X, +* u_int32_t n_bit ) +* +* DESCRIPTION: Shifts array to the left by n_bit. +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to array +* u_int32_t len_X Length of array +* u_int32_t n_bit Number of bits +* OUTPUT: +* PARAMETERS: +* ord *X Pointer to array +* +* RETURN: +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +void LShiftL_big( ord *X, + u_int32_t len_X, + u_int32_t n_bit ) +{ +struct BigNum dest; +bnInit(); +bnBegin(&dest); + +dest.ptr = X; +dest.size = len_X; +dest.allocated = len_X; + +bnLShift(&dest,n_bit); +} + +/************9**************************************************************** +* NAME: int RShiftMostBit( ord *a, +* u_int32_t len ) +* +* DESCRIPTION: Find a least significant non zero bit +* and sfift array to the right +* +* INPUTS: +* PARAMETERS: +* ord *a Pointer to array +* u_int32_t len Number of elements in number +* OUTPUT: +* +* RETURN: +* Number of shifted bits +* +* REVISION HISTORY: +* +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +int RShiftMostBit( ord *a, + u_int32_t len ) +{ + +struct BigNum n; +bnInit(); +bnBegin(&n); + +n.size = len; +n.ptr = a; +n.allocated = len; + +return (bnMakeOdd(&n)); + +} + + +/**************************************************************************** +* NAME: void ByteLong (uchar *X, u_int32_t X_bytes, +* u_int32_t *Y ) +* +* +* DESCRIPTION: Transfer bytes to u_int32_t. +* +* INPUTS: +* PARAMETERS: +* uchar *X Pointer to byte array +* u_int32_t X_bytes Number of bytes in array +* OUTPUT: +* PARAMETERS: +* u_int32_t *Y Pointer to long arrray +* +* RETURN: +* +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +void ByteLong( uchar *X, + u_int32_t X_bytes, + u_int32_t *Y ) +{ + u_int32_t i, j; /* counters */ + for ( i = 0, j = 0; j < X_bytes; i++, j += 4) + { + Y[i] = ( (u_int32_t)X[j] ) | ( ((u_int32_t)X[j+1]) << 8 ) | + ( ((u_int32_t)X[j+2]) << 16 ) | ( ((u_int32_t)X[j+3]) << 24 ); + } +} + +/**************************************************************************** +* NAME: void ByteOrd (uchar *X, u_int32_t X_bytes, +* ord *Y ) +* +* +* DESCRIPTION: Transfer bytes to ord. +* +* INPUTS: +* PARAMETERS: +* uchar *X Pointer to byte array +* u_int32_t X_bytes Number of bytes in array +* OUTPUT: +* PARAMETERS: +* ord *Y Pointer to long array +* +* RETURN: +* +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +void ByteOrd( uchar *X, + u_int32_t X_bytes, + ord *Y ) +{ + u_int32_t i, j; /* counters */ + for ( i = 0, j = 0; j < X_bytes; i++, j += sizeof(ord)) + { + Y[i] = ( (ord)X[j] ) | ( ((ord)X[j+1]) << 8 ) +#ifdef ORD_32 + | ( ((ord)X[j+2]) << 16 ) | ( ((ord)X[j+3]) << 24 ) +#endif + ; + } +} + +/**************************************************************************** +* NAME: void OrdByte (ord *X, u_int32_t X_bytes, +* uchar *Y ) +* +* +* DESCRIPTION: Transfer ord to bytes. +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to ord array +* u_int32_t X_bytes Number of bytes in array +* OUTPUT: +* PARAMETERS: +* uchar *Y Pointer to byte array +* +* RETURN: +* +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +void OrdByte( ord *X, + u_int32_t X_bytes, + uchar *Y ) +{ + u_int32_t i, j; /* counters */ + for ( i=0, j=0; j < X_bytes; i++, j += sizeof(ord)) + { + Y[j] = (uchar ) ( X[i] & 0xff ); + Y[j+1] = (uchar)( (X[i] >> 8) & 0xff ); +#ifdef ORD_32 + Y[j+2] = (uchar)( (X[i] >> 16) & 0xff ); + Y[j+3] = (uchar)( (X[i] >> 24) & 0xff ); +#endif + } +} + +/**************************************************************************** +* NAME: void LongByte( u_int32_t *X, +* u_int32_t X_bytes, +* uchar *Y ) +* +* DESCRIPTION: Transfer u_int32_t to bytes. +* +* INPUTS: +* PARAMETERS: +* u_int32_t *X Pointer to long array +* u_int32_t X_bytes Number of longs in array +* OUTPUT: +* PARAMETERS: +* uchar *Y Pointer to bytes array +* +* RETURN: +* +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +void LongByte( u_int32_t *X, + u_int32_t X_bytes, + uchar *Y ) +{ + u_int32_t i, j; /* counters */ + for ( i=0, j=0; j < X_bytes; i++, j += 4) + { + Y[j] = (uchar ) ( X[i] & 0xff ); + Y[j+1] = (uchar)( (X[i] >> 8) & 0xff ); + Y[j+2] = (uchar)( (X[i] >> 16) & 0xff ); + Y[j+3] = (uchar)( (X[i] >> 24) & 0xff ); + } +} + + diff --git a/lib/bind/cylink/bn.c b/lib/bind/cylink/bn.c new file mode 100644 index 0000000000..6685dca8be --- /dev/null +++ b/lib/bind/cylink/bn.c @@ -0,0 +1,131 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bn.c - the high-level bignum interface + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + */ + +#include "port_before.h" +#include "bn.h" +#include "port_after.h" + +/* Functions */ +void +bnBegin(struct BigNum *bn) +{ + static int bninit = 0; + + if (!bninit) { + bnInit(); + bninit = 1; + } + + bn->ptr = 0; + bn->size = 0; + bn->allocated = 0; +} + +void +bnSwap(struct BigNum *a, struct BigNum *b) +{ + void *p; + unsigned t; + + p = a->ptr; + a->ptr = b->ptr; + b->ptr = p; + + t = a->size; + a->size = b->size; + b->size = t; + + t = a->allocated; + a->allocated = b->allocated; + b->allocated = t; +} + +void (*bnEnd)(struct BigNum *bn); +int (*bnPrealloc)(struct BigNum *bn, unsigned bits); +int (*bnCopy)(struct BigNum *dest, struct BigNum const *src); +void (*bnNorm)(struct BigNum *bn); +void (*bnExtractBigBytes)(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned len); +int (*bnInsertBigBytes)(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len); +void (*bnExtractLittleBytes)(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned len); +int (*bnInsertLittleBytes)(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len); +unsigned (*bnLSWord)(struct BigNum const *src); +unsigned (*bnBits)(struct BigNum const *src); +int (*bnAdd)(struct BigNum *dest, struct BigNum const *src); +int (*bnSub)(struct BigNum *dest, struct BigNum const *src); +int (*bnCmpQ)(struct BigNum const *a, unsigned b); +int (*bnSetQ)(struct BigNum *dest, unsigned src); +int (*bnAddQ)(struct BigNum *dest, unsigned src); +int (*bnSubQ)(struct BigNum *dest, unsigned src); +int (*bnCmp)(struct BigNum const *a, struct BigNum const *b); +int (*bnSquare)(struct BigNum *dest, struct BigNum const *src); +int (*bnMul)(struct BigNum *dest, struct BigNum const *a, + struct BigNum const *b); +int (*bnMulQ)(struct BigNum *dest, struct BigNum const *a, unsigned b); +int (*bnDivMod)(struct BigNum *q, struct BigNum *r, struct BigNum const *n, + struct BigNum const *d); +int (*bnMod)(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *d); +unsigned (*bnModQ)(struct BigNum const *src, unsigned d); +int (*bnExpMod)(struct BigNum *result, struct BigNum const *n, + struct BigNum const *exp, struct BigNum const *mod); +int (*bnDoubleExpMod)(struct BigNum *dest, + struct BigNum const *n1, struct BigNum const *e1, + struct BigNum const *n2, struct BigNum const *e2, + struct BigNum const *mod); +int (*bnTwoExpMod)(struct BigNum *n, struct BigNum const *exp, + struct BigNum const *mod); +int (*bnGcd)(struct BigNum *dest, struct BigNum const *a, + struct BigNum const *b); +int (*bnInv)(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *mod); +int (*bnLShift)(struct BigNum *dest, unsigned amt); +void (*bnRShift)(struct BigNum *dest, unsigned amt); +unsigned (*bnMakeOdd)(struct BigNum *n); diff --git a/lib/bind/cylink/bn.h b/lib/bind/cylink/bn.h new file mode 100644 index 0000000000..a0029cde0d --- /dev/null +++ b/lib/bind/cylink/bn.h @@ -0,0 +1,221 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bn.h - the interface to the bignum routines. + * All functions which return ints can potentially allocate memory + * and return -1 if they are unable to. All "const" arguments + * are unmodified. + * + * This is not particularly asymmetric, as some operations are of the + * form a = b @ c, while others do a @= b. In general, outputs may not + * point to the same struct BigNums as inputs, except as specified + * below. This relationship is referred to as "being the same as". + * This is not numerical equivalence. + * + * The "Q" operations take "unsigned" inputs. Higher values of the + * extra input may work on some implementations, but 65535 is the + * highest portable value. Just because UNSIGNED_MAX is larger than + * that, or you know that the word size of the library is larger than that, + * that, does *not* mean it's allowed. + */ +#ifndef BN_H +#define BN_H + +struct BigNum { + void *ptr; + unsigned size; /* Note: in (variable-sized) words */ + unsigned allocated; +}; + +/* Functions */ + +/* + * You usually never have to call this function explicitly, as + * bnBegin() takes care of it. If the program jumps to address 0, + * this function has bot been called. + */ +void bnInit(void); + +/* + * This initializes an empty struct BigNum to a zero value. + * Do not use this on a BigNum which has had a value stored in it! + */ +void bnBegin(struct BigNum *bn); + +/* Swap two BigNums. Cheap. */ +void bnSwap(struct BigNum *a, struct BigNum *b); + +/* Reset an initialized bigNum to empty, pending deallocation. */ +extern void (*bnEnd)(struct BigNum *bn); + +/* + * If you know you'll need space in the number soon, you can use this function + * to ensure that there is room for at least "bits" bits. Optional. + * Returns <0 on out of memory, but the value is unaffected. + */ +extern int (*bnPrealloc)(struct BigNum *bn, unsigned bits); + +/* Hopefully obvious. dest = src. dest may be the same as src. */ +extern int (*bnCopy)(struct BigNum *dest, struct BigNum const *src); + +/* + * Mostly done automatically, but this removes leading zero words from + * the internal representation of the BigNum. Use is unclear. + */ +extern void (*bnNorm)(struct BigNum *bn); + +/* + * Move bytes between the given buffer and the given BigNum encoded in + * base 256. I.e. after either of these, the buffer will be equal to + * (bn / 256^lsbyte) % 256^len. The difference is which is altered to + * match the other! + */ +extern void (*bnExtractBigBytes)(struct BigNum const *bn, + unsigned char *dest, unsigned lsbyte, unsigned len); +extern int (*bnInsertBigBytes)(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len); + +/* The same, but the buffer is little-endian. */ +extern void (*bnExtractLittleBytes)(struct BigNum const *bn, + unsigned char *dest, unsigned lsbyte, unsigned len); +extern int (*bnInsertLittleBytes)(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len); + +/* Return the least-significant bits (at least 16) of the BigNum */ +extern unsigned (*bnLSWord)(struct BigNum const *src); + +/* + * Return the number of significant bits in the BigNum. + * 0 or 1+floor(log2(src)) + */ +extern unsigned (*bnBits)(struct BigNum const *src); + +/* + * dest += src. dest and src may be the same. Guaranteed not to + * allocate memory unnecessarily, so if you're sure bnBits(dest) + * won't change, you don't need to check the return value. + */ +extern int (*bnAdd)(struct BigNum *dest, struct BigNum const *src); + +/* + * dest -= src. dest and src may be the same, but bnSetQ(dest, 0) is faster. + * if dest < src, returns +1 and sets dest = src-dest. + */ +extern int (*bnSub)(struct BigNum *dest, struct BigNum const *src); + +/* Return sign (-1, 0, +1) of a-b. a <=> b --> bnCmpQ(a, b) <=> 0 */ +extern int (*bnCmpQ)(struct BigNum const *a, unsigned b); + +/* dest = src, where 0 <= src < 2^16. */ +extern int (*bnSetQ)(struct BigNum *dest, unsigned src); + +/* dest += src, where 0 <= src < 2^16 */ +extern int (*bnAddQ)(struct BigNum *dest, unsigned src); + +/* dest -= src, where 0 <= src < 2^16 */ +extern int (*bnSubQ)(struct BigNum *dest, unsigned src); + +/* Return sign (-1, 0, +1) of a-b. a <=> b --> bnCmp(a, b) <=> 0 */ +extern int (*bnCmp)(struct BigNum const *a, struct BigNum const *b); + +/* dest = src^2. dest may be the same as src, but it costs time. */ +extern int (*bnSquare)(struct BigNum *dest, struct BigNum const *src); + +/* dest = a * b. dest may be the same as a or b, but it costs time. */ +extern int (*bnMul)(struct BigNum *dest, struct BigNum const *a, + struct BigNum const *b); + +/* dest = a * b, where 0 <= b < 2^16. dest and a may be the same. */ +extern int (*bnMulQ)(struct BigNum *dest, struct BigNum const *a, unsigned b); + +/* + * q = n/d, r = n%d. r may be the same as n, but not d, + * and q may not be the same as n or d. + * re-entrancy issue: this temporarily modifies d, but restores + * it for return. + */ +extern int (*bnDivMod)(struct BigNum *q, struct BigNum *r, + struct BigNum const *n, struct BigNum const *d); +/* + * dest = src % d. dest and src may be the same, but not dest and d. + * re-entrancy issue: this temporarily modifies d, but restores + * it for return. + */ +extern int (*bnMod)(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *d); + +/* return src % d, where 0 <= d < 2^16. */ +extern unsigned int (*bnModQ)(struct BigNum const *src, unsigned d); + +/* n = n^exp, modulo "mod" "mod" *must* be odd */ +extern int (*bnExpMod)(struct BigNum *result, struct BigNum const *n, + struct BigNum const *exp, struct BigNum const *mod); + +/* + * dest = n1^e1 * n2^e2, modulo "mod". "mod" *must* be odd. + * dest may be the same as n1 or n2. + */ +extern int (*bnDoubleExpMod)(struct BigNum *dest, + struct BigNum const *n1, struct BigNum const *e1, + struct BigNum const *n2, struct BigNum const *e2, + struct BigNum const *mod); + +/* n = 2^exp, modulo "mod" "mod" *must* be odd */ +extern int (*bnTwoExpMod)(struct BigNum *n, struct BigNum const *exp, + struct BigNum const *mod); + +/* dest = gcd(a, b). The inputs may overlap arbitrarily. */ +extern int (*bnGcd)(struct BigNum *dest, struct BigNum const *a, + struct BigNum const *b); + +/* dest = src^-1, modulo "mod". dest may be the same as src. */ +extern int (*bnInv)(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *mod); + +/* Shift dest left "amt" places */ +extern int (*bnLShift)(struct BigNum *dest, unsigned amt); +/* Shift dest right "amt" places, discarding low-order bits */ +extern void (*bnRShift)(struct BigNum *dest, unsigned amt); + +/* For the largest 2^k that divides n, divide n by it and return k. */ +extern unsigned (*bnMakeOdd)(struct BigNum *n); + +#endif/* !BN_H */ diff --git a/lib/bind/cylink/bn00.c b/lib/bind/cylink/bn00.c new file mode 100644 index 0000000000..bf02d2c0ec --- /dev/null +++ b/lib/bind/cylink/bn00.c @@ -0,0 +1,68 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bn00.c - auto-size-detecting bn??.c file. + * + * Written in 1995 by Colin Plumb. + */ + +#include "port_before.h" +#include "bnsize00.h" + +#if BNSIZE64 + +/* Include all of the C source file by reference */ +#include "bn64.c" +#include "bninit64.c" + +#elif BNSIZE32 + +/* Include all of the C source file by reference */ +#include "bn32.c" +#include "bninit32.c" + +#else /* BNSIZE16 */ + +/* Include all of the C source file by reference */ +#include "bn16.c" +#include "bninit16.c" + +#endif diff --git a/lib/bind/cylink/bn16.c b/lib/bind/cylink/bn16.c new file mode 100644 index 0000000000..6d9c3a64e2 --- /dev/null +++ b/lib/bind/cylink/bn16.c @@ -0,0 +1,949 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bn16.c - the high-level bignum interface + * + * Like lbn16.c, this reserves the string "16" for textual replacement. + * The string must not appear anywhere unless it is intended to be replaced + * to generate other bignum interface functions. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + */ + +#ifndef HAVE_CONFIG_H +#define HAVE_CONFIG_H 0 +#endif +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Some compilers complain about #if FOO if FOO isn't defined, + * so do the ANSI-mandated thing explicitly... + */ +#ifndef NO_ASSERT_H +#define NO_ASSERT_H 0 +#endif +#ifndef NO_STRING_H +#define NO_STRING_H 0 +#endif +#ifndef HAVE_STRINGS_H +#define HAVE_STRINGS_H 0 +#endif +#ifndef NEED_MEMORY_H +#define NEED_MEMORY_H 0 +#endif + +#if !NO_ASSERT_H +#include +#else +#define assert(x) (void)0 +#endif + +#if !NO_STRING_H +#include /* for memmove() in bnMakeOdd */ +#elif HAVE_STRINGS_H +#include +#endif +#if NEED_MEMORY_H +#include +#endif + +/* + * This was useful during debugging, so it's left in here. + * You can ignore it. DBMALLOC is generally undefined. + */ +#ifndef DBMALLOC +#define DBAMLLOC 0 +#endif +#if DBMALLOC +#include "../dbmalloc/malloc.h" +#define MALLOCDB malloc_chain_check(1) +#else +#define MALLOCDB (void)0 +#endif + +#include "lbn.h" +#include "lbn16.h" +#include "lbnmem.h" +#include "bn16.h" +#include "bn.h" + +/* Work-arounds for some particularly broken systems */ +#include "kludge.h" /* For memmove() */ +#include + +/* Functions */ +void +bnInit_16(void) +{ + bnEnd = bnEnd_16; + bnPrealloc = bnPrealloc_16; + bnCopy = bnCopy_16; + bnNorm = bnNorm_16; + bnExtractBigBytes = bnExtractBigBytes_16; + bnInsertBigBytes = bnInsertBigBytes_16; + bnExtractLittleBytes = bnExtractLittleBytes_16; + bnInsertLittleBytes = bnInsertLittleBytes_16; + bnLSWord = bnLSWord_16; + bnBits = bnBits_16; + bnAdd = bnAdd_16; + bnSub = bnSub_16; + bnCmpQ = bnCmpQ_16; + bnSetQ = bnSetQ_16; + bnAddQ = bnAddQ_16; + bnSubQ = bnSubQ_16; + bnCmp = bnCmp_16; + bnSquare = bnSquare_16; + bnMul = bnMul_16; + bnMulQ = bnMulQ_16; + bnDivMod = bnDivMod_16; + bnMod = bnMod_16; + bnModQ = bnModQ_16; + bnExpMod = bnExpMod_16; + bnDoubleExpMod = bnDoubleExpMod_16; + bnTwoExpMod = bnTwoExpMod_16; + bnGcd = bnGcd_16; + bnInv = bnInv_16; + bnLShift = bnLShift_16; + bnRShift = bnRShift_16; + bnMakeOdd = bnMakeOdd_16; +} + +void +bnEnd_16(struct BigNum *bn) +{ + if (bn->ptr) { + LBNFREE((BNWORD16 *)bn->ptr, bn->allocated); + bn->ptr = 0; + } + bn->size = 0; + bn->allocated = 0; + + MALLOCDB; +} + +/* Internal function. It operates in words. */ +static int +bnResize_16(struct BigNum *bn, unsigned len) +{ + void *p; + + /* Round size up: most mallocs impose 8-byte granularity anyway */ + len = (len + (8/sizeof(BNWORD16) - 1)) & ~(8/sizeof(BNWORD16) - 1); + p = LBNREALLOC((BNWORD16 *)bn->ptr, bn->allocated, len); + if (!p) + return -1; + bn->ptr = p; + bn->allocated = len; + + MALLOCDB; + + return 0; +} + +#define bnSizeCheck(bn, size) \ + if (bn->allocated < size && bnResize_16(bn, size) < 0) \ + return -1 + +int +bnPrealloc_16(struct BigNum *bn, unsigned bits) +{ + bits = (bits + 16-1)/16; + bnSizeCheck(bn, bits); + MALLOCDB; + return 0; +} + +int +bnCopy_16(struct BigNum *dest, struct BigNum const *src) +{ + bnSizeCheck(dest, src->size); + dest->size = src->size; + lbnCopy_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, src->size); + MALLOCDB; + return 0; +} + +void +bnNorm_16(struct BigNum *bn) +{ + bn->size = lbnNorm_16((BNWORD16 *)bn->ptr, bn->size); +} + +/* + * Convert a bignum to big-endian bytes. Returns, in big-endian form, a + * substring of the bignum starting from lsbyte and "len" bytes long. + * Unused high-order (leading) bytes are filled with 0. + */ +void +bnExtractBigBytes_16(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned len) +{ + unsigned s = bn->size * (16 / 8); + + /* Fill unused leading bytes with 0 */ + while (s < lsbyte+len) { + *dest++ = 0; + len--; + } + + if (len) + lbnExtractBigBytes_16((BNWORD16 *)bn->ptr, dest, lsbyte, len); + MALLOCDB; +} + +int +bnInsertBigBytes_16(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len) +{ + unsigned s = bn->size; + unsigned words = (len+lsbyte+sizeof(BNWORD16)-1) / sizeof(BNWORD16); + + /* Pad with zeros as required */ + bnSizeCheck(bn, words); + + if (s < words) { + lbnZero_16((BNWORD16 *)bn->ptr BIGLITTLE(-s,+s), words-s); + s = words; + } + + lbnInsertBigBytes_16((BNWORD16 *)bn->ptr, src, lsbyte, len); + + bn->size = lbnNorm_16((BNWORD16 *)bn->ptr, s); + + MALLOCDB; + return 0; +} + + +/* + * Convert a bignum to little-endian bytes. Returns, in little-endian form, a + * substring of the bignum starting from lsbyte and "len" bytes long. + * Unused high-order (trailing) bytes are filled with 0. + */ +void +bnExtractLittleBytes_16(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned len) +{ + unsigned s = bn->size * (16 / 8); + + /* Fill unused leading bytes with 0 */ + while (s < lsbyte+len) + dest[--len] = 0; + + if (len) + lbnExtractLittleBytes_16((BNWORD16 *)bn->ptr, dest, + lsbyte, len); + MALLOCDB; +} + +int +bnInsertLittleBytes_16(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len) +{ + unsigned s = bn->size; + unsigned words = (len+lsbyte+sizeof(BNWORD16)-1) / sizeof(BNWORD16); + + /* Pad with zeros as required */ + bnSizeCheck(bn, words); + + if (s < words) { + lbnZero_16((BNWORD16 *)bn->ptr BIGLITTLE(-s,+s), words-s); + s = words; + } + + lbnInsertLittleBytes_16((BNWORD16 *)bn->ptr, src, lsbyte, len); + + bn->size = lbnNorm_16((BNWORD16 *)bn->ptr, s); + + MALLOCDB; + return 0; +} + +/* Return the least-significant word of the input. */ +unsigned +bnLSWord_16(struct BigNum const *src) +{ + return src->size ? (unsigned)((BNWORD16 *)src->ptr)[BIGLITTLE(-1,0)]: 0; +} + +unsigned +bnBits_16(struct BigNum const *src) +{ + return lbnBits_16((BNWORD16 *)src->ptr, src->size); +} + +int +bnAdd_16(struct BigNum *dest, struct BigNum const *src) +{ + unsigned s = src->size, d = dest->size; + BNWORD16 t; + + if (!s) + return 0; + + bnSizeCheck(dest, s); + + if (d < s) { + lbnZero_16((BNWORD16 *)dest->ptr BIGLITTLE(-d,+d), s-d); + dest->size = d = s; + MALLOCDB; + } + t = lbnAddN_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, s); + MALLOCDB; + if (t) { + if (d > s) { + t = lbnAdd1_16((BNWORD16 *)dest->ptr BIGLITTLE(-s,+s), + d-s, t); + MALLOCDB; + } + if (t) { + bnSizeCheck(dest, d+1); + ((BNWORD16 *)dest->ptr)[BIGLITTLE(-1-d,d)] = t; + dest->size = d+1; + } + } + return 0; +} + +/* + * dest -= src. + * If dest goes negative, this produces the absolute value of + * the difference (the negative of the true value) and returns 1. + * Otherwise, it returls 0. + */ +int +bnSub_16(struct BigNum *dest, struct BigNum const *src) +{ + unsigned s = src->size, d = dest->size; + BNWORD16 t; + + if (d < s && d < (s = lbnNorm_16((BNWORD16 *)src->ptr, s))) { + bnSizeCheck(dest, s); + lbnZero_16((BNWORD16 *)dest->ptr BIGLITTLE(-d,+d), s-d); + dest->size = d = s; + MALLOCDB; + } + if (!s) + return 0; + t = lbnSubN_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, s); + MALLOCDB; + if (t) { + if (d > s) { + t = lbnSub1_16((BNWORD16 *)dest->ptr BIGLITTLE(-s,+s), + d-s, t); + MALLOCDB; + } + if (t) { + lbnNeg_16((BNWORD16 *)dest->ptr, d); + dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, + dest->size); + MALLOCDB; + return 1; + } + } + dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, dest->size); + return 0; +} + +/* + * Compare the BigNum to the given value, which must be < 65536. + * Returns -1. 0 or 1 if ab. + * a <=> b --> bnCmpQ(a,b) <=> 0 + */ +int +bnCmpQ_16(struct BigNum const *a, unsigned b) +{ + unsigned t; + BNWORD16 v; + + t = lbnNorm_16((BNWORD16 *)a->ptr, a->size); + /* If a is more than one word long or zero, it's easy... */ + if (t != 1) + return (t > 1) ? 1 : (b ? -1 : 0); + v = (unsigned)((BNWORD16 *)a->ptr)[BIGLITTLE(-1,0)]; + return (v > b) ? 1 : ((v < b) ? -1 : 0); +} + +int +bnSetQ_16(struct BigNum *dest, unsigned src) +{ + if (src) { + bnSizeCheck(dest, 1); + + ((BNWORD16 *)dest->ptr)[BIGLITTLE(-1,0)] = (BNWORD16)src; + dest->size = 1; + } else { + dest->size = 0; + } + return 0; +} + +int +bnAddQ_16(struct BigNum *dest, unsigned src) +{ + BNWORD16 t; + + if (!dest->size) + return bnSetQ(dest, src); + + t = lbnAdd1_16((BNWORD16 *)dest->ptr, dest->size, (BNWORD16)src); + MALLOCDB; + if (t) { + src = dest->size; + bnSizeCheck(dest, src+1); + ((BNWORD16 *)dest->ptr)[BIGLITTLE(-1-src,src)] = t; + dest->size = src+1; + } + return 0; +} + +/* + * Return value as for bnSub: 1 if subtract underflowed, in which + * case the return is the negative of the computed value. + */ +int +bnSubQ_16(struct BigNum *dest, unsigned src) +{ + BNWORD16 t; + + if (!dest->size) + return bnSetQ(dest, src) < 0 ? -1 : (src != 0); + + t = lbnSub1_16((BNWORD16 *)dest->ptr, dest->size, (BNWORD16)src); + MALLOCDB; + if (t) { + /* Underflow. <= 1 word, so do it simply. */ + lbnNeg_16((BNWORD16 *)dest->ptr, 1); + dest->size = 1; + return 1; + } +/* Try to normalize? Needing this is going to be very rare. */ +/* dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, dest->size); */ + return 0; +} + +/* + * Compare two BigNums. Returns -1. 0 or 1 if ab. + * a <=> b --> bnCmp(a,b) <=> 0 + */ +int +bnCmp_16(struct BigNum const *a, struct BigNum const *b) +{ + unsigned s, t; + + s = lbnNorm_16((BNWORD16 *)a->ptr, a->size); + t = lbnNorm_16((BNWORD16 *)b->ptr, b->size); + + if (s != t) + return s > t ? 1 : -1; + return lbnCmp_16((BNWORD16 *)a->ptr, (BNWORD16 *)b->ptr, s); +} + +int +bnSquare_16(struct BigNum *dest, struct BigNum const *src) +{ + unsigned s; + BNWORD16 *srcbuf; + + s = lbnNorm_16((BNWORD16 *)src->ptr, src->size); + if (!s) { + dest->size = 0; + return 0; + } + bnSizeCheck(dest, 2*s); + + if (src == dest) { + LBNALLOC(srcbuf, s); + if (!srcbuf) + return -1; + lbnCopy_16(srcbuf, (BNWORD16 *)src->ptr, s); + lbnSquare_16((BNWORD16 *)dest->ptr, (BNWORD16 *)srcbuf, s); + LBNFREE(srcbuf, s); + } else { + lbnSquare_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, s); + } + + dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, 2*s); + MALLOCDB; + return 0; +} + +int +bnMul_16(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b) +{ + unsigned s, t; + BNWORD16 *srcbuf; + + s = lbnNorm_16((BNWORD16 *)a->ptr, a->size); + t = lbnNorm_16((BNWORD16 *)b->ptr, b->size); + + if (!s || !t) { + dest->size = 0; + return 0; + } + + if (a == b) + return bnSquare_16(dest, a); + + bnSizeCheck(dest, s+t); + + if (dest == a) { + LBNALLOC(srcbuf, s); + if (!srcbuf) + return -1; + lbnCopy_16(srcbuf, (BNWORD16 *)a->ptr, s); + lbnMul_16((BNWORD16 *)dest->ptr, srcbuf, s, + (BNWORD16 *)b->ptr, t); + LBNFREE(srcbuf, s); + } else if (dest == b) { + LBNALLOC(srcbuf, t); + if (!srcbuf) + return -1; + lbnCopy_16(srcbuf, (BNWORD16 *)b->ptr, t); + lbnMul_16((BNWORD16 *)dest->ptr, (BNWORD16 *)a->ptr, s, + srcbuf, t); + LBNFREE(srcbuf, t); + } else { + lbnMul_16((BNWORD16 *)dest->ptr, (BNWORD16 *)a->ptr, s, + (BNWORD16 *)b->ptr, t); + } + dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, s+t); + MALLOCDB; + return 0; +} + +int +bnMulQ_16(struct BigNum *dest, struct BigNum const *a, unsigned b) +{ + unsigned s; + + s = lbnNorm_16((BNWORD16 *)a->ptr, a->size); + if (!s || !b) { + dest->size = 0; + return 0; + } + if (b == 1) + return bnCopy_16(dest, a); + bnSizeCheck(dest, s+1); + lbnMulN1_16((BNWORD16 *)dest->ptr, (BNWORD16 *)a->ptr, s, (BNWORD16)b); + dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, s+1); + MALLOCDB; + return 0; +} + +int +bnDivMod_16(struct BigNum *q, struct BigNum *r, struct BigNum const *n, + struct BigNum const *d) +{ + unsigned dsize, nsize; + BNWORD16 qhigh; + + dsize = lbnNorm_16((BNWORD16 *)d->ptr, d->size); + nsize = lbnNorm_16((BNWORD16 *)n->ptr, n->size); + + if (nsize < dsize) { + q->size = 0; /* No quotient */ + r->size = nsize; + return 0; /* Success */ + } + + bnSizeCheck(q, nsize-dsize); + + if (r != n) { /* You are allowed to reduce in place */ + bnSizeCheck(r, nsize); + lbnCopy_16((BNWORD16 *)r->ptr, (BNWORD16 *)n->ptr, nsize); + } + + qhigh = lbnDiv_16((BNWORD16 *)q->ptr, (BNWORD16 *)r->ptr, nsize, + (BNWORD16 *)d->ptr, dsize); + nsize -= dsize; + if (qhigh) { + bnSizeCheck(q, nsize+1); + *((BNWORD16 *)q->ptr BIGLITTLE(-nsize-1,+nsize)) = qhigh; + q->size = nsize+1; + } else { + q->size = lbnNorm_16((BNWORD16 *)q->ptr, nsize); + } + r->size = lbnNorm_16((BNWORD16 *)r->ptr, dsize); + MALLOCDB; + return 0; +} + +int +bnMod_16(struct BigNum *dest, struct BigNum const *src, struct BigNum const *d) +{ + unsigned dsize, nsize; + + nsize = lbnNorm_16((BNWORD16 *)src->ptr, src->size); + dsize = lbnNorm_16((BNWORD16 *)d->ptr, d->size); + + + if (dest != src) { + bnSizeCheck(dest, nsize); + lbnCopy_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, nsize); + } + + if (nsize < dsize) { + dest->size = nsize; /* No quotient */ + return 0; + } + + (void)lbnDiv_16((BNWORD16 *)dest->ptr BIGLITTLE(-dsize,+dsize), + (BNWORD16 *)dest->ptr, nsize, + (BNWORD16 *)d->ptr, dsize); + dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, dsize); + MALLOCDB; + return 0; +} + +unsigned +bnModQ_16(struct BigNum const *src, unsigned d) +{ + unsigned s; + + s = lbnNorm_16((BNWORD16 *)src->ptr, src->size); + if (!s) + return 0; + + return lbnModQ_16((BNWORD16 *)src->ptr, s, d); +} + +int +bnExpMod_16(struct BigNum *dest, struct BigNum const *n, + struct BigNum const *exp, struct BigNum const *mod) +{ + unsigned nsize, esize, msize; + + nsize = lbnNorm_16((BNWORD16 *)n->ptr, n->size); + esize = lbnNorm_16((BNWORD16 *)exp->ptr, exp->size); + msize = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size); + + if (!msize || (((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) + return -1; /* Illegal modulus! */ + + bnSizeCheck(dest, msize); + + /* Special-case base of 2 */ + if (nsize == 1 && ((BNWORD16 *)n->ptr)[BIGLITTLE(-1,0)] == 2) { + if (lbnTwoExpMod_16((BNWORD16 *)dest->ptr, + (BNWORD16 *)exp->ptr, esize, + (BNWORD16 *)mod->ptr, msize) < 0) + return -1; + } else { + if (lbnExpMod_16((BNWORD16 *)dest->ptr, + (BNWORD16 *)n->ptr, nsize, + (BNWORD16 *)exp->ptr, esize, + (BNWORD16 *)mod->ptr, msize) < 0) + return -1; + } + + dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, msize); + MALLOCDB; + return 0; +} + +int +bnDoubleExpMod_16(struct BigNum *dest, + struct BigNum const *n1, struct BigNum const *e1, + struct BigNum const *n2, struct BigNum const *e2, + struct BigNum const *mod) +{ + unsigned n1size, e1size, n2size, e2size, msize; + + n1size = lbnNorm_16((BNWORD16 *)n1->ptr, n1->size); + e1size = lbnNorm_16((BNWORD16 *)e1->ptr, e1->size); + n2size = lbnNorm_16((BNWORD16 *)n2->ptr, n2->size); + e2size = lbnNorm_16((BNWORD16 *)e2->ptr, e2->size); + msize = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size); + + if (!msize || (((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) + return -1; /* Illegal modulus! */ + + bnSizeCheck(dest, msize); + + if (lbnDoubleExpMod_16((BNWORD16 *)dest->ptr, + (BNWORD16 *)n1->ptr, n1size, (BNWORD16 *)e1->ptr, e1size, + (BNWORD16 *)n2->ptr, n2size, (BNWORD16 *)e2->ptr, e2size, + (BNWORD16 *)mod->ptr, msize) < 0) + return -1; + + dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, msize); + MALLOCDB; + return 0; +} + +int +bnTwoExpMod_16(struct BigNum *n, struct BigNum const *exp, + struct BigNum const *mod) +{ + unsigned esize, msize; + + esize = lbnNorm_16((BNWORD16 *)exp->ptr, exp->size); + msize = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size); + + if (!msize || (((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) + return -1; /* Illegal modulus! */ + + bnSizeCheck(n, msize); + + if (lbnTwoExpMod_16((BNWORD16 *)n->ptr, (BNWORD16 *)exp->ptr, esize, + (BNWORD16 *)mod->ptr, msize) < 0) + return -1; + + n->size = lbnNorm_16((BNWORD16 *)n->ptr, msize); + MALLOCDB; + return 0; +} + +int +bnGcd_16(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b) +{ + BNWORD16 *tmp; + unsigned asize, bsize; + int i; + + /* Kind of silly, but we might as well permit it... */ + if (a == b) + return dest == a ? 0 : bnCopy(dest, a); + + /* Ensure a is not the same as "dest" */ + if (a == dest) { + a = b; + b = dest; + } + + asize = lbnNorm_16((BNWORD16 *)a->ptr, a->size); + bsize = lbnNorm_16((BNWORD16 *)b->ptr, b->size); + + bnSizeCheck(dest, bsize+1); + + /* Copy a to tmp */ + LBNALLOC(tmp, asize+1); + if (!tmp) + return -1; + lbnCopy_16(tmp, (BNWORD16 *)a->ptr, asize); + + /* Copy b to dest,if necessary */ + if (dest != b) + lbnCopy_16((BNWORD16 *)dest->ptr, + (BNWORD16 *)b->ptr, bsize); + if (bsize > asize || (bsize == asize && + lbnCmp_16((BNWORD16 *)b->ptr, (BNWORD16 *)a->ptr, asize) > 0)) + { + i = lbnGcd_16((BNWORD16 *)dest->ptr, bsize, tmp, asize); + if (i >= 0) { + dest->size = (unsigned)i; + } else { + lbnCopy_16((BNWORD16 *)dest->ptr, tmp, + (unsigned)-i); + dest->size = (unsigned)-i; + } + } else { + i = lbnGcd_16(tmp, asize, (BNWORD16 *)dest->ptr, bsize); + if (i <= 0) { + dest->size = (unsigned)-i; + } else { + lbnCopy_16((BNWORD16 *)dest->ptr, tmp, + (unsigned)i); + dest->size = (unsigned)i; + } + } + LBNFREE(tmp, asize+1); + MALLOCDB; + return 0; +} + +int +bnInv_16(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *mod) +{ + unsigned s, m; + int i; + + s = lbnNorm_16((BNWORD16 *)src->ptr, src->size); + m = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size); + + /* lbnInv_16 requires that the input be less than the modulus */ + if (m < s || + (m==s && lbnCmp_16((BNWORD16 *)src->ptr, (BNWORD16 *)mod->ptr, s))) + { + bnSizeCheck(dest, s + (m==s)); + if (dest != src) + lbnCopy_16((BNWORD16 *)dest->ptr, + (BNWORD16 *)src->ptr, s); + /* Pre-reduce modulo the modulus */ + (void)lbnDiv_16((BNWORD16 *)dest->ptr BIGLITTLE(-m,+m), + (BNWORD16 *)dest->ptr, s, + (BNWORD16 *)mod->ptr, m); + s = lbnNorm_16((BNWORD16 *)dest->ptr, m); + MALLOCDB; + } else { + bnSizeCheck(dest, m+1); + if (dest != src) + lbnCopy_16((BNWORD16 *)dest->ptr, + (BNWORD16 *)src->ptr, s); + } + + i = lbnInv_16((BNWORD16 *)dest->ptr, s, (BNWORD16 *)mod->ptr, m); + if (i == 0) + dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, m); + + MALLOCDB; + return i; +} + +/* + * Shift a bignum left the appropriate number of bits, + * multiplying by 2^amt. + */ +int +bnLShift_16(struct BigNum *dest, unsigned amt) +{ + unsigned s = dest->size; + BNWORD16 carry; + + if (amt % 16) { + carry = lbnLshift_16(dest->ptr, s, amt % 16); + if (carry) { + s++; + bnSizeCheck(dest, s); + ((BNWORD16 *)dest->ptr)[BIGLITTLE(-s,s-1)] = carry; + } + } + + amt /= 16; + if (amt) { + bnSizeCheck(dest, s+amt); + memmove((BNWORD16 *)dest->ptr BIGLITTLE(-s-amt, +amt), + (BNWORD16 *)dest->ptr BIG(-s), + s * sizeof(BNWORD16)); + lbnZero_16((BNWORD16 *)dest->ptr, amt); + s += amt; + } + dest->size = s; + MALLOCDB; + return 0; +} + +/* + * Shift a bignum right the appropriate number of bits, + * dividing by 2^amt. + */ +void bnRShift_16(struct BigNum *dest, unsigned amt) +{ + unsigned s = dest->size; + + if (amt >= 16) { + memmove( + (BNWORD16 *)dest->ptr BIG(-s+amt/16), + (BNWORD16 *)dest->ptr BIGLITTLE(-s, +amt/16), + s-amt/16 * sizeof(BNWORD16)); + s -= amt/16; + amt %= 16; + } + + if (amt) + (void)lbnRshift_16(dest->ptr, s, amt); + + dest->size = lbnNorm_16(dest->ptr, s); + MALLOCDB; +} + +/* + * Shift a bignum right until it is odd, and return the number of + * bits shifted. n = d * 2^s. Replaces n with d and returns s. + * Returns 0 when given 0. (Another valid answer is infinity.) + */ +unsigned +bnMakeOdd_16(struct BigNum *n) +{ + unsigned size; + unsigned s; /* shift amount */ + BNWORD16 *p; + BNWORD16 t; + + p = (BNWORD16 *)n->ptr; + size = lbnNorm_16(p, n->size); + if (!size) + return 0; + + t = BIGLITTLE(p[-1],p[0]); + s = 0; + + /* See how many words we have to shift */ + if (!t) { + /* Shift by words */ + do { + + s++; + BIGLITTLE(--p,p++); + } while ((t = BIGLITTLE(p[-1],p[0])) == 0); + size -= s; + s *= 16; + memmove((BNWORD16 *)n->ptr BIG(-size), p BIG(-size), + size * sizeof(BNWORD16)); + p = (BNWORD16 *)n->ptr; + MALLOCDB; + } + + assert(t); + + /* Now count the bits */ + while ((t & 1) == 0) { + t >>= 1; + s++; + } + + /* Shift the bits */ + if (s & (16-1)) { + lbnRshift_16(p, size, s & (16-1)); + /* Renormalize */ + if (BIGLITTLE(*(p-size),*(p+(size-1))) == 0) + --size; + } + n->size = size; + + MALLOCDB; + return s; +} diff --git a/lib/bind/cylink/bn16.h b/lib/bind/cylink/bn16.h new file mode 100644 index 0000000000..fcf65bb50d --- /dev/null +++ b/lib/bind/cylink/bn16.h @@ -0,0 +1,92 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bn16.h - interface to 16-bit bignum routines. + */ +struct BigNum; + +void bnInit_16(void); +void bnEnd_16(struct BigNum *bn); +int bnPrealloc_16(struct BigNum *bn, unsigned bits); +int bnCopy_16(struct BigNum *dest, struct BigNum const *src); +int bnSwap_16(struct BigNum *a, struct BigNum *b); +void bnNorm_16(struct BigNum *bn); +void bnExtractBigBytes_16(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned dlen); +int bnInsertBigBytes_16(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len); +void bnExtractLittleBytes_16(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned dlen); +int bnInsertLittleBytes_16(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len); +unsigned bnLSWord_16(struct BigNum const *src); +unsigned bnBits_16(struct BigNum const *src); +int bnAdd_16(struct BigNum *dest, struct BigNum const *src); +int bnSub_16(struct BigNum *dest, struct BigNum const *src); +int bnCmpQ_16(struct BigNum const *a, unsigned b); +int bnSetQ_16(struct BigNum *dest, unsigned src); +int bnAddQ_16(struct BigNum *dest, unsigned src); +int bnSubQ_16(struct BigNum *dest, unsigned src); +int bnCmp_16(struct BigNum const *a, struct BigNum const *b); +int bnSquare_16(struct BigNum *dest, struct BigNum const *src); +int bnMul_16(struct BigNum *dest, struct BigNum const *a, + struct BigNum const *b); +int bnMulQ_16(struct BigNum *dest, struct BigNum const *a, unsigned b); +int bnDivMod_16(struct BigNum *q, struct BigNum *r, struct BigNum const *n, + struct BigNum const *d); +int bnMod_16(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *d); +unsigned bnModQ_16(struct BigNum const *src, unsigned d); +int bnExpMod_16(struct BigNum *dest, struct BigNum const *n, + struct BigNum const *exp, struct BigNum const *mod); +int bnDoubleExpMod_16(struct BigNum *dest, + struct BigNum const *n1, struct BigNum const *e1, + struct BigNum const *n2, struct BigNum const *e2, + struct BigNum const *mod); +int bnTwoExpMod_16(struct BigNum *n, struct BigNum const *exp, + struct BigNum const *mod); +int bnGcd_16(struct BigNum *dest, struct BigNum const *a, + struct BigNum const *b); +int bnInv_16(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *mod); +int bnLShift_16(struct BigNum *dest, unsigned amt); +void bnRShift_16(struct BigNum *dest, unsigned amt); +unsigned bnMakeOdd_16(struct BigNum *n); diff --git a/lib/bind/cylink/bn32.c b/lib/bind/cylink/bn32.c new file mode 100644 index 0000000000..a477778cf6 --- /dev/null +++ b/lib/bind/cylink/bn32.c @@ -0,0 +1,949 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bn32.c - the high-level bignum interface + * + * Like lbn32.c, this reserves the string "32" for textual replacement. + * The string must not appear anywhere unless it is intended to be replaced + * to generate other bignum interface functions. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + */ + +#ifndef HAVE_CONFIG_H +#define HAVE_CONFIG_H 0 +#endif +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Some compilers complain about #if FOO if FOO isn't defined, + * so do the ANSI-mandated thing explicitly... + */ +#ifndef NO_ASSERT_H +#define NO_ASSERT_H 0 +#endif +#ifndef NO_STRING_H +#define NO_STRING_H 0 +#endif +#ifndef HAVE_STRINGS_H +#define HAVE_STRINGS_H 0 +#endif +#ifndef NEED_MEMORY_H +#define NEED_MEMORY_H 0 +#endif + +#if !NO_ASSERT_H +#include +#else +#define assert(x) (void)0 +#endif + +#if !NO_STRING_H +#include /* for memmove() in bnMakeOdd */ +#elif HAVE_STRINGS_H +#include +#endif +#if NEED_MEMORY_H +#include +#endif + +/* + * This was useful during debugging, so it's left in here. + * You can ignore it. DBMALLOC is generally undefined. + */ +#ifndef DBMALLOC +#define DBAMLLOC 0 +#endif +#if DBMALLOC +#include "../dbmalloc/malloc.h" +#define MALLOCDB malloc_chain_check(1) +#else +#define MALLOCDB (void)0 +#endif + +#include "lbn.h" +#include "lbn32.h" +#include "lbnmem.h" +#include "bn32.h" +#include "bn.h" + +/* Work-arounds for some particularly broken systems */ +#include "kludge.h" /* For memmove() */ +#include + +/* Functions */ +void +bnInit_32(void) +{ + bnEnd = bnEnd_32; + bnPrealloc = bnPrealloc_32; + bnCopy = bnCopy_32; + bnNorm = bnNorm_32; + bnExtractBigBytes = bnExtractBigBytes_32; + bnInsertBigBytes = bnInsertBigBytes_32; + bnExtractLittleBytes = bnExtractLittleBytes_32; + bnInsertLittleBytes = bnInsertLittleBytes_32; + bnLSWord = bnLSWord_32; + bnBits = bnBits_32; + bnAdd = bnAdd_32; + bnSub = bnSub_32; + bnCmpQ = bnCmpQ_32; + bnSetQ = bnSetQ_32; + bnAddQ = bnAddQ_32; + bnSubQ = bnSubQ_32; + bnCmp = bnCmp_32; + bnSquare = bnSquare_32; + bnMul = bnMul_32; + bnMulQ = bnMulQ_32; + bnDivMod = bnDivMod_32; + bnMod = bnMod_32; + bnModQ = bnModQ_32; + bnExpMod = bnExpMod_32; + bnDoubleExpMod = bnDoubleExpMod_32; + bnTwoExpMod = bnTwoExpMod_32; + bnGcd = bnGcd_32; + bnInv = bnInv_32; + bnLShift = bnLShift_32; + bnRShift = bnRShift_32; + bnMakeOdd = bnMakeOdd_32; +} + +void +bnEnd_32(struct BigNum *bn) +{ + if (bn->ptr) { + LBNFREE((BNWORD32 *)bn->ptr, bn->allocated); + bn->ptr = 0; + } + bn->size = 0; + bn->allocated = 0; + + MALLOCDB; +} + +/* Internal function. It operates in words. */ +static int +bnResize_32(struct BigNum *bn, unsigned len) +{ + void *p; + + /* Round size up: most mallocs impose 8-byte granularity anyway */ + len = (len + (8/sizeof(BNWORD32) - 1)) & ~(8/sizeof(BNWORD32) - 1); + p = LBNREALLOC((BNWORD32 *)bn->ptr, bn->allocated, len); + if (!p) + return -1; + bn->ptr = p; + bn->allocated = len; + + MALLOCDB; + + return 0; +} + +#define bnSizeCheck(bn, size) \ + if (bn->allocated < size && bnResize_32(bn, size) < 0) \ + return -1 + +int +bnPrealloc_32(struct BigNum *bn, unsigned bits) +{ + bits = (bits + 32-1)/32; + bnSizeCheck(bn, bits); + MALLOCDB; + return 0; +} + +int +bnCopy_32(struct BigNum *dest, struct BigNum const *src) +{ + bnSizeCheck(dest, src->size); + dest->size = src->size; + lbnCopy_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, src->size); + MALLOCDB; + return 0; +} + +void +bnNorm_32(struct BigNum *bn) +{ + bn->size = lbnNorm_32((BNWORD32 *)bn->ptr, bn->size); +} + +/* + * Convert a bignum to big-endian bytes. Returns, in big-endian form, a + * substring of the bignum starting from lsbyte and "len" bytes long. + * Unused high-order (leading) bytes are filled with 0. + */ +void +bnExtractBigBytes_32(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned len) +{ + unsigned s = bn->size * (32 / 8); + + /* Fill unused leading bytes with 0 */ + while (s < lsbyte+len) { + *dest++ = 0; + len--; + } + + if (len) + lbnExtractBigBytes_32((BNWORD32 *)bn->ptr, dest, lsbyte, len); + MALLOCDB; +} + +int +bnInsertBigBytes_32(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len) +{ + unsigned s = bn->size; + unsigned words = (len+lsbyte+sizeof(BNWORD32)-1) / sizeof(BNWORD32); + + /* Pad with zeros as required */ + bnSizeCheck(bn, words); + + if (s < words) { + lbnZero_32((BNWORD32 *)bn->ptr BIGLITTLE(-s,+s), words-s); + s = words; + } + + lbnInsertBigBytes_32((BNWORD32 *)bn->ptr, src, lsbyte, len); + + bn->size = lbnNorm_32((BNWORD32 *)bn->ptr, s); + + MALLOCDB; + return 0; +} + + +/* + * Convert a bignum to little-endian bytes. Returns, in little-endian form, a + * substring of the bignum starting from lsbyte and "len" bytes long. + * Unused high-order (trailing) bytes are filled with 0. + */ +void +bnExtractLittleBytes_32(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned len) +{ + unsigned s = bn->size * (32 / 8); + + /* Fill unused leading bytes with 0 */ + while (s < lsbyte+len) + dest[--len] = 0; + + if (len) + lbnExtractLittleBytes_32((BNWORD32 *)bn->ptr, dest, + lsbyte, len); + MALLOCDB; +} + +int +bnInsertLittleBytes_32(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len) +{ + unsigned s = bn->size; + unsigned words = (len+lsbyte+sizeof(BNWORD32)-1) / sizeof(BNWORD32); + + /* Pad with zeros as required */ + bnSizeCheck(bn, words); + + if (s < words) { + lbnZero_32((BNWORD32 *)bn->ptr BIGLITTLE(-s,+s), words-s); + s = words; + } + + lbnInsertLittleBytes_32((BNWORD32 *)bn->ptr, src, lsbyte, len); + + bn->size = lbnNorm_32((BNWORD32 *)bn->ptr, s); + + MALLOCDB; + return 0; +} + +/* Return the least-significant word of the input. */ +unsigned +bnLSWord_32(struct BigNum const *src) +{ + return src->size ? (unsigned)((BNWORD32 *)src->ptr)[BIGLITTLE(-1,0)]: 0; +} + +unsigned +bnBits_32(struct BigNum const *src) +{ + return lbnBits_32((BNWORD32 *)src->ptr, src->size); +} + +int +bnAdd_32(struct BigNum *dest, struct BigNum const *src) +{ + unsigned s = src->size, d = dest->size; + BNWORD32 t; + + if (!s) + return 0; + + bnSizeCheck(dest, s); + + if (d < s) { + lbnZero_32((BNWORD32 *)dest->ptr BIGLITTLE(-d,+d), s-d); + dest->size = d = s; + MALLOCDB; + } + t = lbnAddN_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, s); + MALLOCDB; + if (t) { + if (d > s) { + t = lbnAdd1_32((BNWORD32 *)dest->ptr BIGLITTLE(-s,+s), + d-s, t); + MALLOCDB; + } + if (t) { + bnSizeCheck(dest, d+1); + ((BNWORD32 *)dest->ptr)[BIGLITTLE(-1-d,d)] = t; + dest->size = d+1; + } + } + return 0; +} + +/* + * dest -= src. + * If dest goes negative, this produces the absolute value of + * the difference (the negative of the true value) and returns 1. + * Otherwise, it returls 0. + */ +int +bnSub_32(struct BigNum *dest, struct BigNum const *src) +{ + unsigned s = src->size, d = dest->size; + BNWORD32 t; + + if (d < s && d < (s = lbnNorm_32((BNWORD32 *)src->ptr, s))) { + bnSizeCheck(dest, s); + lbnZero_32((BNWORD32 *)dest->ptr BIGLITTLE(-d,+d), s-d); + dest->size = d = s; + MALLOCDB; + } + if (!s) + return 0; + t = lbnSubN_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, s); + MALLOCDB; + if (t) { + if (d > s) { + t = lbnSub1_32((BNWORD32 *)dest->ptr BIGLITTLE(-s,+s), + d-s, t); + MALLOCDB; + } + if (t) { + lbnNeg_32((BNWORD32 *)dest->ptr, d); + dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, + dest->size); + MALLOCDB; + return 1; + } + } + dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, dest->size); + return 0; +} + +/* + * Compare the BigNum to the given value, which must be < 65536. + * Returns -1. 0 or 1 if ab. + * a <=> b --> bnCmpQ(a,b) <=> 0 + */ +int +bnCmpQ_32(struct BigNum const *a, unsigned b) +{ + unsigned t; + BNWORD32 v; + + t = lbnNorm_32((BNWORD32 *)a->ptr, a->size); + /* If a is more than one word long or zero, it's easy... */ + if (t != 1) + return (t > 1) ? 1 : (b ? -1 : 0); + v = (unsigned)((BNWORD32 *)a->ptr)[BIGLITTLE(-1,0)]; + return (v > b) ? 1 : ((v < b) ? -1 : 0); +} + +int +bnSetQ_32(struct BigNum *dest, unsigned src) +{ + if (src) { + bnSizeCheck(dest, 1); + + ((BNWORD32 *)dest->ptr)[BIGLITTLE(-1,0)] = (BNWORD32)src; + dest->size = 1; + } else { + dest->size = 0; + } + return 0; +} + +int +bnAddQ_32(struct BigNum *dest, unsigned src) +{ + BNWORD32 t; + + if (!dest->size) + return bnSetQ(dest, src); + + t = lbnAdd1_32((BNWORD32 *)dest->ptr, dest->size, (BNWORD32)src); + MALLOCDB; + if (t) { + src = dest->size; + bnSizeCheck(dest, src+1); + ((BNWORD32 *)dest->ptr)[BIGLITTLE(-1-src,src)] = t; + dest->size = src+1; + } + return 0; +} + +/* + * Return value as for bnSub: 1 if subtract underflowed, in which + * case the return is the negative of the computed value. + */ +int +bnSubQ_32(struct BigNum *dest, unsigned src) +{ + BNWORD32 t; + + if (!dest->size) + return bnSetQ(dest, src) < 0 ? -1 : (src != 0); + + t = lbnSub1_32((BNWORD32 *)dest->ptr, dest->size, src); + MALLOCDB; + if (t) { + /* Underflow. <= 1 word, so do it simply. */ + lbnNeg_32((BNWORD32 *)dest->ptr, 1); + dest->size = 1; + return 1; + } +/* Try to normalize? Needing this is going to be very rare. */ +/* dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, dest->size); */ + return 0; +} + +/* + * Compare two BigNums. Returns -1. 0 or 1 if ab. + * a <=> b --> bnCmp(a,b) <=> 0 + */ +int +bnCmp_32(struct BigNum const *a, struct BigNum const *b) +{ + unsigned s, t; + + s = lbnNorm_32((BNWORD32 *)a->ptr, a->size); + t = lbnNorm_32((BNWORD32 *)b->ptr, b->size); + + if (s != t) + return s > t ? 1 : -1; + return lbnCmp_32((BNWORD32 *)a->ptr, (BNWORD32 *)b->ptr, s); +} + +int +bnSquare_32(struct BigNum *dest, struct BigNum const *src) +{ + unsigned s; + BNWORD32 *srcbuf; + + s = lbnNorm_32((BNWORD32 *)src->ptr, src->size); + if (!s) { + dest->size = 0; + return 0; + } + bnSizeCheck(dest, 2*s); + + if (src == dest) { + LBNALLOC(srcbuf, s); + if (!srcbuf) + return -1; + lbnCopy_32(srcbuf, (BNWORD32 *)src->ptr, s); + lbnSquare_32((BNWORD32 *)dest->ptr, (BNWORD32 *)srcbuf, s); + LBNFREE(srcbuf, s); + } else { + lbnSquare_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, s); + } + + dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, 2*s); + MALLOCDB; + return 0; +} + +int +bnMul_32(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b) +{ + unsigned s, t; + BNWORD32 *srcbuf; + + s = lbnNorm_32((BNWORD32 *)a->ptr, a->size); + t = lbnNorm_32((BNWORD32 *)b->ptr, b->size); + + if (!s || !t) { + dest->size = 0; + return 0; + } + + if (a == b) + return bnSquare_32(dest, a); + + bnSizeCheck(dest, s+t); + + if (dest == a) { + LBNALLOC(srcbuf, s); + if (!srcbuf) + return -1; + lbnCopy_32(srcbuf, (BNWORD32 *)a->ptr, s); + lbnMul_32((BNWORD32 *)dest->ptr, srcbuf, s, + (BNWORD32 *)b->ptr, t); + LBNFREE(srcbuf, s); + } else if (dest == b) { + LBNALLOC(srcbuf, t); + if (!srcbuf) + return -1; + lbnCopy_32(srcbuf, (BNWORD32 *)b->ptr, t); + lbnMul_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s, + srcbuf, t); + LBNFREE(srcbuf, t); + } else { + lbnMul_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s, + (BNWORD32 *)b->ptr, t); + } + dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, s+t); + MALLOCDB; + return 0; +} + +int +bnMulQ_32(struct BigNum *dest, struct BigNum const *a, unsigned b) +{ + unsigned s; + + s = lbnNorm_32((BNWORD32 *)a->ptr, a->size); + if (!s || !b) { + dest->size = 0; + return 0; + } + if (b == 1) + return bnCopy_32(dest, a); + bnSizeCheck(dest, s+1); + lbnMulN1_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s, b); + dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, s+1); + MALLOCDB; + return 0; +} + +int +bnDivMod_32(struct BigNum *q, struct BigNum *r, struct BigNum const *n, + struct BigNum const *d) +{ + unsigned dsize, nsize; + BNWORD32 qhigh; + + dsize = lbnNorm_32((BNWORD32 *)d->ptr, d->size); + nsize = lbnNorm_32((BNWORD32 *)n->ptr, n->size); + + if (nsize < dsize) { + q->size = 0; /* No quotient */ + r->size = nsize; + return 0; /* Success */ + } + + bnSizeCheck(q, nsize-dsize); + + if (r != n) { /* You are allowed to reduce in place */ + bnSizeCheck(r, nsize); + lbnCopy_32((BNWORD32 *)r->ptr, (BNWORD32 *)n->ptr, nsize); + } + + qhigh = lbnDiv_32((BNWORD32 *)q->ptr, (BNWORD32 *)r->ptr, nsize, + (BNWORD32 *)d->ptr, dsize); + nsize -= dsize; + if (qhigh) { + bnSizeCheck(q, nsize+1); + *((BNWORD32 *)q->ptr BIGLITTLE(-nsize-1,+nsize)) = qhigh; + q->size = nsize+1; + } else { + q->size = lbnNorm_32((BNWORD32 *)q->ptr, nsize); + } + r->size = lbnNorm_32((BNWORD32 *)r->ptr, dsize); + MALLOCDB; + return 0; +} + +int +bnMod_32(struct BigNum *dest, struct BigNum const *src, struct BigNum const *d) +{ + unsigned dsize, nsize; + + nsize = lbnNorm_32((BNWORD32 *)src->ptr, src->size); + dsize = lbnNorm_32((BNWORD32 *)d->ptr, d->size); + + + if (dest != src) { + bnSizeCheck(dest, nsize); + lbnCopy_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, nsize); + } + + if (nsize < dsize) { + dest->size = nsize; /* No quotient */ + return 0; + } + + (void)lbnDiv_32((BNWORD32 *)dest->ptr BIGLITTLE(-dsize,+dsize), + (BNWORD32 *)dest->ptr, nsize, + (BNWORD32 *)d->ptr, dsize); + dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, dsize); + MALLOCDB; + return 0; +} + +unsigned +bnModQ_32(struct BigNum const *src, unsigned d) +{ + unsigned s; + + s = lbnNorm_32((BNWORD32 *)src->ptr, src->size); + if (!s) + return 0; + + return lbnModQ_32((BNWORD32 *)src->ptr, s, d); +} + +int +bnExpMod_32(struct BigNum *dest, struct BigNum const *n, + struct BigNum const *exp, struct BigNum const *mod) +{ + unsigned nsize, esize, msize; + + nsize = lbnNorm_32((BNWORD32 *)n->ptr, n->size); + esize = lbnNorm_32((BNWORD32 *)exp->ptr, exp->size); + msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size); + + if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) + return -1; /* Illegal modulus! */ + + bnSizeCheck(dest, msize); + + /* Special-case base of 2 */ + if (nsize == 1 && ((BNWORD32 *)n->ptr)[BIGLITTLE(-1,0)] == 2) { + if (lbnTwoExpMod_32((BNWORD32 *)dest->ptr, + (BNWORD32 *)exp->ptr, esize, + (BNWORD32 *)mod->ptr, msize) < 0) + return -1; + } else { + if (lbnExpMod_32((BNWORD32 *)dest->ptr, + (BNWORD32 *)n->ptr, nsize, + (BNWORD32 *)exp->ptr, esize, + (BNWORD32 *)mod->ptr, msize) < 0) + return -1; + } + + dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, msize); + MALLOCDB; + return 0; +} + +int +bnDoubleExpMod_32(struct BigNum *dest, + struct BigNum const *n1, struct BigNum const *e1, + struct BigNum const *n2, struct BigNum const *e2, + struct BigNum const *mod) +{ + unsigned n1size, e1size, n2size, e2size, msize; + + n1size = lbnNorm_32((BNWORD32 *)n1->ptr, n1->size); + e1size = lbnNorm_32((BNWORD32 *)e1->ptr, e1->size); + n2size = lbnNorm_32((BNWORD32 *)n2->ptr, n2->size); + e2size = lbnNorm_32((BNWORD32 *)e2->ptr, e2->size); + msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size); + + if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) + return -1; /* Illegal modulus! */ + + bnSizeCheck(dest, msize); + + if (lbnDoubleExpMod_32((BNWORD32 *)dest->ptr, + (BNWORD32 *)n1->ptr, n1size, (BNWORD32 *)e1->ptr, e1size, + (BNWORD32 *)n2->ptr, n2size, (BNWORD32 *)e2->ptr, e2size, + (BNWORD32 *)mod->ptr, msize) < 0) + return -1; + + dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, msize); + MALLOCDB; + return 0; +} + +int +bnTwoExpMod_32(struct BigNum *n, struct BigNum const *exp, + struct BigNum const *mod) +{ + unsigned esize, msize; + + esize = lbnNorm_32((BNWORD32 *)exp->ptr, exp->size); + msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size); + + if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) + return -1; /* Illegal modulus! */ + + bnSizeCheck(n, msize); + + if (lbnTwoExpMod_32((BNWORD32 *)n->ptr, (BNWORD32 *)exp->ptr, esize, + (BNWORD32 *)mod->ptr, msize) < 0) + return -1; + + n->size = lbnNorm_32((BNWORD32 *)n->ptr, msize); + MALLOCDB; + return 0; +} + +int +bnGcd_32(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b) +{ + BNWORD32 *tmp; + unsigned asize, bsize; + int i; + + /* Kind of silly, but we might as well permit it... */ + if (a == b) + return dest == a ? 0 : bnCopy(dest, a); + + /* Ensure a is not the same as "dest" */ + if (a == dest) { + a = b; + b = dest; + } + + asize = lbnNorm_32((BNWORD32 *)a->ptr, a->size); + bsize = lbnNorm_32((BNWORD32 *)b->ptr, b->size); + + bnSizeCheck(dest, bsize+1); + + /* Copy a to tmp */ + LBNALLOC(tmp, asize+1); + if (!tmp) + return -1; + lbnCopy_32(tmp, (BNWORD32 *)a->ptr, asize); + + /* Copy b to dest,if necessary */ + if (dest != b) + lbnCopy_32((BNWORD32 *)dest->ptr, + (BNWORD32 *)b->ptr, bsize); + if (bsize > asize || (bsize == asize && + lbnCmp_32((BNWORD32 *)b->ptr, (BNWORD32 *)a->ptr, asize) > 0)) + { + i = lbnGcd_32((BNWORD32 *)dest->ptr, bsize, tmp, asize); + if (i >= 0) { + dest->size = (unsigned)i; + } else { + lbnCopy_32((BNWORD32 *)dest->ptr, tmp, + (unsigned)-i); + dest->size = (unsigned)-i; + } + } else { + i = lbnGcd_32(tmp, asize, (BNWORD32 *)dest->ptr, bsize); + if (i <= 0) { + dest->size = (unsigned)-i; + } else { + lbnCopy_32((BNWORD32 *)dest->ptr, tmp, + (unsigned)i); + dest->size = (unsigned)i; + } + } + LBNFREE(tmp, asize+1); + MALLOCDB; + return 0; +} + +int +bnInv_32(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *mod) +{ + unsigned s, m; + int i; + + s = lbnNorm_32((BNWORD32 *)src->ptr, src->size); + m = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size); + + /* lbnInv_32 requires that the input be less than the modulus */ + if (m < s || + (m==s && lbnCmp_32((BNWORD32 *)src->ptr, (BNWORD32 *)mod->ptr, s))) + { + bnSizeCheck(dest, s + (m==s)); + if (dest != src) + lbnCopy_32((BNWORD32 *)dest->ptr, + (BNWORD32 *)src->ptr, s); + /* Pre-reduce modulo the modulus */ + (void)lbnDiv_32((BNWORD32 *)dest->ptr BIGLITTLE(-m,+m), + (BNWORD32 *)dest->ptr, s, + (BNWORD32 *)mod->ptr, m); + s = lbnNorm_32((BNWORD32 *)dest->ptr, m); + MALLOCDB; + } else { + bnSizeCheck(dest, m+1); + if (dest != src) + lbnCopy_32((BNWORD32 *)dest->ptr, + (BNWORD32 *)src->ptr, s); + } + + i = lbnInv_32((BNWORD32 *)dest->ptr, s, (BNWORD32 *)mod->ptr, m); + if (i == 0) + dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, m); + + MALLOCDB; + return i; +} + +/* + * Shift a bignum left the appropriate number of bits, + * multiplying by 2^amt. + */ +int +bnLShift_32(struct BigNum *dest, unsigned amt) +{ + unsigned s = dest->size; + BNWORD32 carry; + + if (amt % 32) { + carry = lbnLshift_32(dest->ptr, s, amt % 32); + if (carry) { + s++; + bnSizeCheck(dest, s); + ((BNWORD32 *)dest->ptr)[BIGLITTLE(-s,s-1)] = carry; + } + } + + amt /= 32; + if (amt) { + bnSizeCheck(dest, s+amt); + memmove((BNWORD32 *)dest->ptr BIGLITTLE(-s-amt, +amt), + (BNWORD32 *)dest->ptr BIG(-s), + s * sizeof(BNWORD32)); + lbnZero_32((BNWORD32 *)dest->ptr, amt); + s += amt; + } + dest->size = s; + MALLOCDB; + return 0; +} + +/* + * Shift a bignum right the appropriate number of bits, + * dividing by 2^amt. + */ +void bnRShift_32(struct BigNum *dest, unsigned amt) +{ + unsigned s = dest->size; + + if (amt >= 32) { + memmove( + (BNWORD32 *)dest->ptr BIG(-s+amt/32), + (BNWORD32 *)dest->ptr BIGLITTLE(-s, +amt/32), + s-amt/32 * sizeof(BNWORD32)); + s -= amt/32; + amt %= 32; + } + + if (amt) + (void)lbnRshift_32(dest->ptr, s, amt); + + dest->size = lbnNorm_32(dest->ptr, s); + MALLOCDB; +} + +/* + * Shift a bignum right until it is odd, and return the number of + * bits shifted. n = d * 2^s. Replaces n with d and returns s. + * Returns 0 when given 0. (Another valid answer is infinity.) + */ +unsigned +bnMakeOdd_32(struct BigNum *n) +{ + unsigned size; + unsigned s; /* shift amount */ + BNWORD32 *p; + BNWORD32 t; + + p = (BNWORD32 *)n->ptr; + size = lbnNorm_32(p, n->size); + if (!size) + return 0; + + t = BIGLITTLE(p[-1],p[0]); + s = 0; + + /* See how many words we have to shift */ + if (!t) { + /* Shift by words */ + do { + + s++; + BIGLITTLE(--p,p++); + } while ((t = BIGLITTLE(p[-1],p[0])) == 0); + size -= s; + s *= 32; + memmove((BNWORD32 *)n->ptr BIG(-size), p BIG(-size), + size * sizeof(BNWORD32)); + p = (BNWORD32 *)n->ptr; + MALLOCDB; + } + + assert(t); + + /* Now count the bits */ + while ((t & 1) == 0) { + t >>= 1; + s++; + } + + /* Shift the bits */ + if (s & (32-1)) { + lbnRshift_32(p, size, s & (32-1)); + /* Renormalize */ + if (BIGLITTLE(*(p-size),*(p+(size-1))) == 0) + --size; + } + n->size = size; + + MALLOCDB; + return s; +} diff --git a/lib/bind/cylink/bn32.h b/lib/bind/cylink/bn32.h new file mode 100644 index 0000000000..3c042eeaa7 --- /dev/null +++ b/lib/bind/cylink/bn32.h @@ -0,0 +1,92 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bn32.h - interface to 32-bit bignum routines. + */ +struct BigNum; + +void bnInit_32(void); +void bnEnd_32(struct BigNum *bn); +int bnPrealloc_32(struct BigNum *bn, unsigned bits); +int bnCopy_32(struct BigNum *dest, struct BigNum const *src); +int bnSwap_32(struct BigNum *a, struct BigNum *b); +void bnNorm_32(struct BigNum *bn); +void bnExtractBigBytes_32(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned dlen); +int bnInsertBigBytes_32(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len); +void bnExtractLittleBytes_32(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned dlen); +int bnInsertLittleBytes_32(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len); +unsigned bnLSWord_32(struct BigNum const *src); +unsigned bnBits_32(struct BigNum const *src); +int bnAdd_32(struct BigNum *dest, struct BigNum const *src); +int bnSub_32(struct BigNum *dest, struct BigNum const *src); +int bnCmpQ_32(struct BigNum const *a, unsigned b); +int bnSetQ_32(struct BigNum *dest, unsigned src); +int bnAddQ_32(struct BigNum *dest, unsigned src); +int bnSubQ_32(struct BigNum *dest, unsigned src); +int bnCmp_32(struct BigNum const *a, struct BigNum const *b); +int bnSquare_32(struct BigNum *dest, struct BigNum const *src); +int bnMul_32(struct BigNum *dest, struct BigNum const *a, + struct BigNum const *b); +int bnMulQ_32(struct BigNum *dest, struct BigNum const *a, unsigned b); +int bnDivMod_32(struct BigNum *q, struct BigNum *r, struct BigNum const *n, + struct BigNum const *d); +int bnMod_32(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *d); +unsigned bnModQ_32(struct BigNum const *src, unsigned d); +int bnExpMod_32(struct BigNum *dest, struct BigNum const *n, + struct BigNum const *exp, struct BigNum const *mod); +int bnDoubleExpMod_32(struct BigNum *dest, + struct BigNum const *n1, struct BigNum const *e1, + struct BigNum const *n2, struct BigNum const *e2, + struct BigNum const *mod); +int bnTwoExpMod_32(struct BigNum *n, struct BigNum const *exp, + struct BigNum const *mod); +int bnGcd_32(struct BigNum *dest, struct BigNum const *a, + struct BigNum const *b); +int bnInv_32(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *mod); +int bnLShift_32(struct BigNum *dest, unsigned amt); +void bnRShift_32(struct BigNum *dest, unsigned amt); +unsigned bnMakeOdd_32(struct BigNum *n); diff --git a/lib/bind/cylink/bn68000.c b/lib/bind/cylink/bn68000.c new file mode 100644 index 0000000000..66132e7c6e --- /dev/null +++ b/lib/bind/cylink/bn68000.c @@ -0,0 +1,62 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bn68000.c - bnInit() for Motorola 680x0 family, 16 or 32-bit. + * + * Written in 1995 by Colin Plumb. + */ + +#include "lbn.h" +#include "bn16.h" +#include "bn32.h" + +#ifndef BNINCLUDE +#error You must define BNINCLUDE to lbn68000.h to use assembly primitives. +#endif + +void +bnInit(void) +{ + if (is68020()) + bnInit_32(); + else + bnInit_16(); +} diff --git a/lib/bind/cylink/bn8086.c b/lib/bind/cylink/bn8086.c new file mode 100644 index 0000000000..fecf929901 --- /dev/null +++ b/lib/bind/cylink/bn8086.c @@ -0,0 +1,62 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bn8086.c - bnInit() for Intel x86 family in 16-bit mode. + * + * Written in 1995 by Colin Plumb. + */ + +#include "lbn.h" +#include "bn16.h" +#include "bn32.h" + +#ifndef BNINCLUDE +#error You must define BNINCLUDE to lbn8086.h to use assembly primitives. +#endif + +void +bnInit(void) +{ +/* if (not386()) + bnInit_16(); + else */ + bnInit_32(); +} diff --git a/lib/bind/cylink/bninit16.c b/lib/bind/cylink/bninit16.c new file mode 100644 index 0000000000..7e7c99fd11 --- /dev/null +++ b/lib/bind/cylink/bninit16.c @@ -0,0 +1,56 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bninit16.c - Provide an init function that sets things up for 16-bit + * operation. This is a seaparate tiny file so you can compile two bn + * packages into the library and write a custom init routine. + * + * Written in 1995 by Colin Plumb. + */ + +#include "bn.h" +#include "bn16.h" + +void +bnInit(void) +{ + bnInit_16(); +} diff --git a/lib/bind/cylink/bninit32.c b/lib/bind/cylink/bninit32.c new file mode 100644 index 0000000000..396bd12d95 --- /dev/null +++ b/lib/bind/cylink/bninit32.c @@ -0,0 +1,56 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bninit32.c - Provide an init function that sets things up for 32-bit + * operation. This is a seaparate tiny file so you can compile two bn + * packages into the library and write a custom init routine. + * + * Written in 1995 by Colin Plumb. + */ + +#include "bn.h" +#include "bn32.h" + +void +bnInit(void) +{ + bnInit_32(); +} diff --git a/lib/bind/cylink/bnsize00.h b/lib/bind/cylink/bnsize00.h new file mode 100644 index 0000000000..7986235130 --- /dev/null +++ b/lib/bind/cylink/bnsize00.h @@ -0,0 +1,75 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bnsize00.h - pick the correct machine word size to use. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + */ +#include "lbn.h" /* Get basic information */ + +#if !BNSIZE64 && !BNSIZE32 && !BNSIZE16 && defined(BNWORD64) +# if defined(BNWORD128) || (defined(lbnMulAdd1_64) && defined(lbnMulSub1_64)) +# define BNSIZE64 1 +# elif defined(mul64_ppmm) || defined(mul64_ppmma) || defined(mul64_ppmmaa) +# define BNSIZE64 1 +# endif +#endif + +#if !BNSIZE64 && !BNSIZE32 && !BNSIZE16 && defined(BNWORD32) +# if defined(BNWORD64) || (defined(lbnMulAdd1_32) && defined(lbnMulSub1_32)) +# define BNSIZE32 1 +# elif defined(mul32_ppmm) || defined(mul32_ppmma) || defined(mul32_ppmmaa) +# define BNSIZE32 1 +# endif +#endif + +#if !BNSIZE64 && !BNSIZE32 && !BNSIZE16 && defined(BNWORD16) +# if defined(BNWORD32) || (defined(lbnMulAdd1_16) && defined(lbnMulSub1_16)) +# define BNSIZE16 1 +# elif defined(mul16_ppmm) || defined(mul16_ppmma) || defined(mul16_ppmmaa) +# define BNSIZE16 1 +# endif +#endif + +#if !BNSIZE64 && !BNSIZE32 && !BNSIZE16 +#error Unable to find a viable word size to compile bignum library. +#endif diff --git a/lib/bind/cylink/c_asm.h b/lib/bind/cylink/c_asm.h new file mode 100644 index 0000000000..f291ca9528 --- /dev/null +++ b/lib/bind/cylink/c_asm.h @@ -0,0 +1,133 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: c_asm.h PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: C / ASM Header File +* +* USAGE: File should be included to use Toolkit Functions +* +* +* Copyright (c) Cylink Corporation 1994. All rights reserved. +* +* REVISION HISTORY: +* +* 14 Oct 94 GKL For Second version (big endian support) +* 26 Oct 94 GKL (alignment for big endian support ) +* +****************************************************************************/ +#if !defined( C_ASM_H ) +#define C_ASM_H + +#include +#include "cylink.h" +#include "ctk_endian.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + int Sum_big (ord *X, + ord *Y, + ord *Z, + int len_X ); + int Sum (ord *X, ord *Y, ushort len_X ); + int Sub_big (ord *X, + ord *Y, + ord *Z, + int len_X ); +/* + void Mul_big( ord *X, ord *Y,ord *XY, + ushort lx, ushort ly, + ushort elements_in_X, + ushort elements_in_Y);*/ + void Mul_big( ord *X, ord *Y,ord *XY, + ushort lx, ushort ly); + + void PReLo_big( ord *X, ord *P, + ushort len_X, ushort el); + + void Div_big( ord *X, ord *P, + ushort len_X, ushort el, + ord *div); + +int LeftMostBit_big ( ord X ); +int LeftMostEl_big( ord *X, ushort len_X ); +void RShiftL_big( ord *X, u_int32_t len_X, u_int32_t n_bit ); +void LShiftL_big( ord *X, u_int32_t len_X, u_int32_t n_bit ); +int RShiftMostBit(ord *a, u_int32_t len); +void ByteLong(uchar *X, u_int32_t X_bytes, u_int32_t *Y); +void ByteOrd(uchar *X, u_int32_t X_bytes, ord *Y); +void OrdByte(ord *X, u_int32_t X_bytes, uchar *Y); +void LongByte(u_int32_t *X, u_int32_t X_bytes, uchar *Y); +int BitValue_big( ord *X, ushort n_bits ); +int BitsValue_big( ord *X, ushort n_bits, ushort bit_count ); +void ByteSwap32_big( uchar *X, ushort X_len ); +void Complement_big( ord *X, ushort X_longs); +void Diagonal_big (ord *X, ushort X_len, ord *X2); +void Square_big( ord *X, ushort X_len, ord *X2); +void Mul_big_1( ord X, ord *Y, ord *XY, ushort ly ); +int Sum_Q(ord *X, ushort src, ushort len_X ); + + + +/* In-place DES encryption */ + void DES_encrypt(uchar *keybuf, uchar *block); + +/* In-place DES decryption */ + void DES_decrypt(uchar *keybuf, uchar *block); + +/* In-place KAPPA encryption */ + void KAPPA_encrypt(uchar *a, uchar *k, ushort r); + +/* In-place KAPPA decryption */ + void KAPPA_decrypt(uchar *a, uchar *k, ushort r); + +#ifdef __cplusplus +} +#endif + + +#endif /*C_ASM_H*/ + diff --git a/lib/bind/cylink/cencrint.h b/lib/bind/cylink/cencrint.h new file mode 100644 index 0000000000..1d6ecb6cc9 --- /dev/null +++ b/lib/bind/cylink/cencrint.h @@ -0,0 +1,255 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: cencrint.h PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Cryptographic Toolkit Internal Functions Header File +* +* USAGE: File should be included to use Toolkit Functions +* +* +* Copyright (c) Cylink Corporation 1994. All rights reserved. +* +* REVISION HISTORY: +* +* 23 Aug 94 KPZ Initial release +* 24 Sep 94 KPZ Added prototypes of internal functions +* 14 Oct 94 GKL Second version (big endian support) +* 08 Dec 94 GKL Added YIELD_context to Expo, VerPrime and GenPrime +* +****************************************************************************/ + +#ifndef CENCRINT_H /* Prevent multiple inclusions of same header file */ +#define CENCRINT_H + +/**************************************************************************** +* INCLUDE FILES +****************************************************************************/ + +/* system files */ +#include +#include "cylink.h" +#include "ctk_endian.h" +#include "toolkit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Compute a modulo */ + int PartReduct( u_int16_t X_bytes, ord *X, + u_int16_t P_bytes, ord *P, + ord *Z ); + +/* Compute a modulo product */ + int Mul( u_int16_t X_bytes, ord *X, + u_int16_t Y_bytes, ord *Y, + u_int16_t P_bytes, ord *P, + ord *Z ); +/*Compute a modulo squaring*/ +int Mul_Squr( u_int16_t X_bytes, ord *X, + u_int16_t P_bytes, ord *P, + ord *Z ); +int Square( u_int16_t X_bytes, + ord *X, + u_int16_t P_bytes, + ord *P, + ord *Z ); + +/*Compare two array*/ +int Comp_Mont ( ord *X, ord *P, u_int16_t P_longs ); +/*Compute invers element*/ +ord Inv_Mont ( ord x ); +/*Modulo by the Mongomery*/ +void PartReduct_Mont( ord *X, u_int16_t P_bytes, ord *P, ord inv ); +/*Computes squaring by the Mongomery modulo*/ +int Mul_Squr_Mont(ord *X, u_int16_t P_bytes, + ord *P, ord *Z, + ord inv ); +/*Computes multiply by the montgomery modulo*/ +int Mul_Mont( ord *X, ord *Y, + u_int16_t P_bytes, ord *P, + ord *Z, ord inv ); + +/* Compute a modulo exponent */ + int Expo( u_int16_t X_bytes, ord *X, + u_int16_t Y_bytes, ord *Y, + u_int16_t P_bytes, ord *P, + ord *Z ); + /*Compute double exponent */ + int DoubleExpo( u_int16_t X1_bytes,ord *X1, + u_int16_t Y1_bytes,ord *Y1, + u_int16_t X2_bytes,ord *X2, + u_int16_t Y2_bytes,ord *Y2, + u_int16_t P_bytes,ord *P, + ord *Z); +/* Compute a modulo inverse element */ + int Inverse( u_int16_t X_bytes, ord *X, + u_int16_t P_bytes, ord *P, + ord *Z ); + +/* Verify Pseudo Prime number */ + int VerPrime( u_int16_t P_bytes, ord *P, + u_int16_t k, ord *RVAL, + YIELD_context *yield_cont ); /*TKL00601*/ + +/* Generate Random Pseudo Prime number */ + int GenPrime( u_int16_t P_bytes, ord *P, + u_int16_t k, ord *RVAL, + YIELD_context *yield_cont ); /*TKL00601*/ + +/* Transfer bytes to u_int32_t */ + void ByteLong( uchar *X, + u_int16_t X_bytes, + u_int32_t *Y ); + +/* Transfer u_int32_t to bytes */ + void LongByte( u_int32_t *X, + u_int16_t X_bytes, + uchar *Y ); + +/* Transfer bytes to ord */ + void ByteOrd( uchar *X, + u_int16_t X_bytes, + ord *Y ); + +/* Transfer ord to bytes */ + void OrdByte( ord *X, + u_int16_t X_bytes, + uchar *Y ); + +/* Find the left most non zero bit */ + int LeftMostBit ( ord X ); + +/* Find the left most element */ + int LeftMostEl( ord *X, + u_int16_t len_X ); + +/* Shift array to rigth by n_bit */ + void RShiftL( ord *X, + u_int16_t len_X, + u_int16_t n_bit ); + +/* Shifts array to left by n_bit */ + void LShiftL( ord *X, + u_int16_t len_X, + u_int16_t n_bit ); + +/* Find the value of bit */ + int BitValue( ord *X, + u_int16_t n_bits ); + +/* Perform byte reversal on an array of ordinar type (longword or shortword) */ + void ByteSwap( uchar *X, + u_int16_t X_len ); + +/* Perform byte reversal on an array from LSB to MSB */ + void BigSwap( uchar *X, + u_int16_t X_len ); + +/* Perform byte reversal on an array of longword */ + void ByteSwap32( uchar *X, + u_int16_t X_len ); + +/* Perform short reversal on an array of longword */ + void WordSwap( uchar *X, + u_int16_t X_len ); + +/* Perform SHS transformation */ + void shaTransform( u_int32_t *state, + const uchar *block ); + +/* Compute modulo addition + int Add( ord *X, + ord *Y, + u_int16_t P_len, + ord *P, + ord *Z ); + */ + int Add( ord *X, + ord *Y, + u_int16_t P_len, + ord *P ); +/* Initialize Secure Hash Function for generate + random number for DSS */ + void SHAInitK( SHA_context *hash_context ); + +/* Set parity bits */ + void SetKeyParity( uchar *key ); + +/* Find a least significant non zero bit + and sfift array to right */ + int RShiftMostBit( ord *a, u_int16_t len ); + +/*Compute great common divisor */ + int SteinGCD( ord *m, ord *b, u_int16_t len ); + +/* Compute a modulo and divisor */ + int DivRem( u_int16_t X_bytes, ord *X, + u_int16_t P_bytes, ord *P, + ord *Z, ord *D ); + +/* Generate random number */ +int MyGenRand( u_int16_t A_bytes, ord *A, + ord *RVAL); + +/* Compute a Secure Hash Function */ +int MySHA( uchar *message, + u_int16_t message_bytes, + uchar *hash_result ); + +/* Finalize Secure Hash Function */ + int MySHAFinal( SHA_context *hash_context, + uchar *hash_result ); + + void shaTransform_new( u_int32_t *state, + uchar *block ); + + +#ifdef __cplusplus +} +#endif + + +#endif /* CENCRINT_H */ + diff --git a/lib/bind/cylink/ctk_endian.h b/lib/bind/cylink/ctk_endian.h new file mode 100644 index 0000000000..fd1a89e16a --- /dev/null +++ b/lib/bind/cylink/ctk_endian.h @@ -0,0 +1,212 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**********************************************************************\ +* FILENAME: ctk_endian.h PRODUCT NAME: +* +* DESCRIPTION: header file of defines +* +* USAGE: Platform-dependend compilation modes header +* +* +* Copyright (c) Cylink Corporation 1994. All rights reserved. +* +* REVISION HISTORY: +* +\**********************************************************************/ + +#ifndef CTK_ENDIAN_H /* Prevent multiple inclusions of same header file */ +#define CTK_ENDIAN_H + +#include +#include +#include +#include "lbn.h" + +#if (defined(BIG_ENDIAN) || defined(_BIG_ENDIAN)) && !(defined(LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN)) +# undef BIG_ENDIAN +# undef _BIG_ENDIAN +# define BIG_ENDIAN 4321 +# define LITTLE_ENDIAN 1234 +# define BYTE_ORDER BIG_ENDIAN + +#elif !(defined(BIG_ENDIAN) || defined(_BIG_ENDIAN)) && (defined(LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN)) +# undef LITTLE_ENDIAN +# undef _LITTLE_ENDIAN +# define BIG_ENDIAN 4321 +# define LITTLE_ENDIAN 1234 +# define BYTE_ORDER LITTLE_ENDIAN +#endif + +#if !defined(BYTE_ORDER) || \ + (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN) + /* you must determine what the correct bit order is for + * your compiler - the next line is an intentional error + * which will force your compiles to bomb until you fix + * the above macros. + */ +# if !defined(CTK_LITTLE_ENDIAN) && !defined(CTK_BIG_ENDIAN) +# error "Undefined or invalid BYTE_ORDER"; +# endif +#endif + +#if !defined(CTK_BIG_ENDIAN) && !defined(CTK_LITTLE_ENDIAN) +# ifdef BYTE_ORDER +# if (BYTE_ORDER == LITTLE_ENDIAN) +# define CTK_LITTLE_ENDIAN +# elif (BYTE_ORDER == BIG_ENDIAN) +# define CTK_BIG_ENDIAN +# else +# error CAN NOT determine ENDIAN with BYTE_ORDER +# endif +# elif defined(_LITTLE_ENDIAN) +# define CTK_LITTLE_ENDIAN +# elif defined(_BIG_ENDIAN) +# define CTK_BIG_ENDIAN +# else +# error CAN NOT determine ENDIAN +# endif +#endif + +#if !defined(CTK_BIG_ENDIAN) && !defined(CTK_LITTLE_ENDIAN) +# error NO CTK_???_ENDIAN defined +#endif + +#if defined( CTK_LITTLE_ENDIAN ) && defined( CTK_BIG_ENDIAN ) +# error Use only one define CPU type CTK_LITTLE or BIG ENDIAN. +#endif + +#if !defined( ORD_32 ) && !defined( ORD_16 ) +# ifdef BNSIZE64 +# error BNSIZE64 do not know how to do this +# elif defined(BNSIZE32) +# define ORD_32 +# elif defined(BNSIZE16) +# define ORD_16 +# elif !defined( UINT_MAX) /* No */ +# define ORD_16 /* default */ +# else +# if ULONG_MAX == 0xffffffff +# define ORD_16 +# else +# define ORD_32 +# endif +# endif +#endif + +#if !defined( ORD_32 ) && !defined( ORD_16 ) +#error Not defined basic word type ORD_32 or ORD_16. +#endif + +#if defined( ORD_32 ) && defined( ORD_16 ) +#error Use only one define basic word type ORD_32 or ORD_16. +#endif + + +#ifdef ORD_16 +/* typedef unsigned short ord; deleted by ogud@tis.com 1998/9/14 */ +typedef u_int16_t ord; +#define BITS_COUNT 16 +#define MAXDIGIT (ord)(0xFFFF) +#endif + +#ifdef ORD_32 +/* typedef unsigned long ord; deleted by ogud@tis.com 1998/9/14 */ +typedef u_int32_t ord; +#define BITS_COUNT 32 +#define MAXDIGIT (ord)(0xFFFFFFFF) +#endif /* ORD_32 */ + + + +#define CALLOC(var,type,len) \ + var=(type *)calloc(len,1); \ + if (var==NULL) \ + status=ERR_ALLOC +#ifdef CTK_BIG_ENDIAN +#define ALIGN_CALLOC(i,o,l) \ + CALLOC(o,ord,l) +#define ALIGN_CALLOC_COPY(i,o,l) \ + CALLOC(o,ord,l); \ + if (o) ByteOrd(i,l,o) +#define ALIGN_CALLOC_MOVE(i,o,l) \ + CALLOC(o,ord,l); \ + if (o) memcpy(o,i,l) +#define ALIGN_FREE(o) \ + free ( o ) +#define ALIGN_COPY_FREE(o,i,l) \ + if ((o) && (status==SUCCESS)) \ + OrdByte(o,l,i); \ + free (o) +#define ALIGN_MOVE_FREE(o,i,l) \ + if ((o) && (status==SUCCESS)) \ + memcpy(i,o,l); \ + memset(o,0,l); \ + free (o) +#else +#define ALIGN_CALLOC(i,o,l) o=(ord *)i +#define ALIGN_CALLOC_COPY(i,o,l) o=(ord *)i +#define ALIGN_CALLOC_MOVE(i,o,l) o=(ord *)i +#define ALIGN_FREE(o) ; +#define ALIGN_COPY_FREE(o,i,l) ; +#define ALIGN_MOVE_FREE(o,i,l) ; +#endif +#define DSS_P_ALIGN_CALLOC_COPY(i,o,l) \ + if (i) \ + { ALIGN_CALLOC_COPY(i,o,l);} \ + else \ + o = &DSS_P_NUMBERS[DSS_NUM_INDEX[(l-DSS_LENGTH_MIN)/LENGTH_STEP]] + +#define DSS_G_ALIGN_CALLOC_COPY(i,o,l) \ + if (i) \ + { ALIGN_CALLOC_COPY(i,o,l);} \ + else \ + o = &DSS_G_NUMBERS[DSS_NUM_INDEX[(l-DSS_LENGTH_MIN)/LENGTH_STEP]] + +#define DSS_Q_ALIGN_CALLOC_COPY(i,o,l) \ + if (i) \ + { ALIGN_CALLOC_COPY(i,o,l);} \ + else \ + o = DSS_Q_NUMBER + +#define DSS_ALIGN_FREE(o,i) \ + if (i) \ + { ALIGN_FREE(o);} +#endif /* CTK_ENDIAN_H */ diff --git a/lib/bind/cylink/ctk_prime.c b/lib/bind/cylink/ctk_prime.c new file mode 100644 index 0000000000..0d1c9f27e0 --- /dev/null +++ b/lib/bind/cylink/ctk_prime.c @@ -0,0 +1,435 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: prime.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Cryptographic Toolkit Internal Functions File +* Prime Number functions +* PRIVATE FUNCTIONS: +* +* int VerPrime( u_int16_t P_bytes, ord *P, +* u_int16_t k, ord *RVAL, +* YIELD_context *yield_cont ) +* int GenPrime( u_int16_t P_bytes, ord *P, +* u_int16_t k, ord *RVAL, +* YIELD_context *yield_cont ) +* Copyright (c) Cylink Corporation 1996. All rights reserved. +* +* REVISION HISTORY: +* +* +****************************************************************************/ + +/**************************************************************************** +* INCLUDE FILES +****************************************************************************/ + +#include "port_before.h" +#include +#include "cylink.h" +#include "ctk_endian.h" + +/* system files */ +#ifdef VXD +#include +#else +#include +#include +#include +#endif + +/* program files */ +#include "cylink.h" +#include "ctk_endian.h" +#include "toolkit.h" +#include "cencrint.h" +#include "port_after.h" + +/**************************************************************************** +* PRIVATE FUNCTIONS DEFINITIONS +****************************************************************************/ +/**************************************************************************** +* NAME: int VerPrime( u_int16_t P_bytes, +* ord *P, +* u_int16_t k, +* ord *RVAL, +* YIELD_context *yield_cont ) +* +* DESCRIPTION: Verify Pseudo Prime number +* +* INPUTS: +* PARAMETERS: +* u_int16_t P_bytes Number of bytes in array +* u_int16_t k Number of testing +* ord *RVAL Pointer to random number generator value +* YIELD_context *yield_cont Pointer to yield_cont structure (NULL if not used) +* OUTPUT: +* PARAMETERS: +* ord *P Pointer to prime number +* ord *RVAL Pointer to updated value +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data(zero bytes) +* ERR_PRIME Number is not prime +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 08 Dec 94 GKL Added YIELD_context +* +****************************************************************************/ + + int VerPrime( u_int16_t P_bytes, + ord *P, + u_int16_t k, + ord *RVAL, + YIELD_context *yield_cont ) /*TKL00601*/ + +{ + int status = SUCCESS; /*function return status*/ + ord *b, *n, *c, *pp; /*pointers to working buffers */ + ord *m, *buf, *P_buf; + u_int16_t max_bytes; /*number of maximum bytes*/ + u_int16_t P_longs; /*number of longs in Y*/ + u_int16_t i, j, s, k_b; /*counters*/ + u_int16_t exit ; /*flag for exit*/ +/* product of prime numbers from 3 to 379 (512-bit number) */ +#ifdef ORD_32 + ord b1[DSS_LENGTH_MIN/sizeof(ord)]={ + 0x2e30c48fL, 0x0decece9L, 0xbada8f98L, 0x9f7ecb29L, + 0xa4a11de4L, 0x6ef04659L, 0xcbc38405L, 0x233db117L, + 0x03e81187L, 0xc1b631a2L, 0x238bfb99L, 0x077ec3baL, + 0xc5d5f09fL, 0xb0813c28L, 0x7646fa6eL, 0x106aa9fbL }; +#else + ord b1[DSS_LENGTH_MIN/sizeof(ord)]={ + 0xc48f, 0x2e30, 0xece9, 0x0dec, 0x8f98, 0xbada, 0xcb29, 0x9f7e, + 0x1de4, 0xa4a1, 0x4659, 0x6ef0, 0x8405, 0xcbc3, 0xb117, 0x233d, + 0x1187, 0x03e8, 0x31a2, 0xc1b6, 0xfb99, 0x238b, 0xc3ba, 0x077e, + 0xf09f, 0xc5d5, 0x3c28, 0xb081, 0xfa6e, 0x7646, 0xa9fb, 0x106a }; +#endif + if ( P_bytes % sizeof(ord) != 0 ) /* not multiple 4 (32 bit) */ + { + status = ERR_INPUT_LEN; /* invalid length for input data */ + return status; + } + if ( P_bytes <= DSS_LENGTH_MIN ) + { + max_bytes = DSS_LENGTH_MIN; + } + else + { + max_bytes = P_bytes; + } + buf = (ord *)calloc( max_bytes / sizeof(ord), sizeof(ord) ); + P_buf = (ord *)calloc( max_bytes / sizeof(ord), sizeof(ord)); + if( !buf || !P_buf ) + { + if ( buf ) + free( buf ); + if( P_buf ) + free( P_buf ); + return ERR_ALLOC; + } + memcpy( buf, b1, DSS_LENGTH_MIN ); + memcpy( P_buf, P, P_bytes ); + + if ( (P_buf[0] & 0x1) == 0 ) + { +#ifdef DEBUG1 + printf ("\n P is not pseudoprime"); +#endif + status = ERR_PRIME; + free ( buf ); + free( P_buf ); + return status; + } + P_longs = (u_int16_t) (P_bytes / sizeof(ord)); + b = (ord *)calloc( P_longs, sizeof(ord) ); + m = (ord *)malloc( P_longs * sizeof(ord) ); + n = (ord *)calloc( P_longs, sizeof(ord) ); + c = (ord *)calloc( P_longs, sizeof(ord) ); + pp = (ord *)malloc( P_longs * sizeof(ord) ); + if( !b || !m || !n || !c || !pp ) + { + if( b ) + free( b ); + if( m ) + free( m ); + if( n ) + free( n ); + if( c ) + free( c ); + if( pp ) + free ( pp ); + } + memcpy( m, P, P_bytes ); + memcpy( pp, P, P_bytes ); + /* Compute great common divisor(gcd) */ + if ( SteinGCD( P_buf, buf, (u_int16_t)(max_bytes / sizeof(ord)) ) == 0 ) + { + pp[0] = pp[0] - 1; /* Initialized work buffer */ + m[0] = m[0] - 1; + s = (u_int16_t) RShiftMostBit( m, (u_int16_t)(P_bytes / sizeof(ord)) ); /* Right shift by number of*/ + exit = 0; /* zero bits at rigth */ + k_b = 0; + while( k_b != k ) + { + MyGenRand( 4, b, RVAL ); /* generate random number */ + if ( SteinGCD( P_buf, b , (u_int16_t)(P_bytes / sizeof(ord)) ) ) /* check gcd */ + { +#ifdef DEBUG1 + printf ("\n P is not pseudoprime"); +#endif + status = ERR_PRIME; + break; + } + k_b++; /* increment counter */ + if ( ( status = Expo ( 4, b, P_bytes, m, + P_bytes, P, c ) ) != SUCCESS ) /* c=b^m mod(P) */ /*TKL00601*/ + { + free( b ); + free( m ); + free( n ); + free( c ); + free( pp ); + free (buf ); + free( P_buf ); + return status; + } + if ( c[0] == 1 ) /* if c==1 number is pseudo prime */ + { + for ( i = 1; i < P_bytes / sizeof(ord); i++ ) + { + if ( c[i] != 0 ) + { + break; + } + } + if ( i == P_bytes / sizeof(ord) ) + { + if (yield_cont) /*TKL00601*/ +#ifdef VXD + if ( VXD_Yield (yield_cont->yield_proc) ) +#else + if ( yield_cont->yield_proc(0xFFFF) ) +#endif + + { + status = ERR_CANCEL; + free( b ); + free( m ); + free( n ); + free( c ); + free( pp ); + free( P_buf ); + free (buf ); + return status; + } +#ifdef DEBUG1 + printf ("\n P is a pseudoprime %d",k_b); +#endif + if ( k_b == k ) + { + break; + } + } + } + else + { + for ( j = 1; j <= s; j++ ) + { + for ( i = 0; i < P_bytes / sizeof(ord); i++ ) /* if c==pp number is pseudo prime */ + { + if ( c[i] != pp[i] ) + { + break; + } + } + if ( i == P_bytes / sizeof(ord) ) + { + if (yield_cont) /*TKL00601*/ +#ifdef VXD + if ( VXD_Yield (yield_cont->yield_proc) ) +#else + if ( yield_cont->yield_proc(0xFFFF) ) +#endif + + { + status = ERR_CANCEL; + free( b ); + free( m ); + free( n ); + free( c ); + free( pp ); + free( P_buf ); + free (buf ); + return status; + } +#ifdef DEBUG1 + printf ("\n P is a pseudoprime %d",k_b); +#endif + break; + } + if ( j == s ) + { +#ifdef DEBUG1 + printf ("\n P is not pseudoprime"); +#endif + status = ERR_PRIME; + exit = 1; + break; + } + else + { + if ( (status = Square(P_bytes, c, /*P_bytes, + c,*/ P_bytes, P, c) ) + != SUCCESS ) /* c=c^2mod(p) */ + { + free( b ); + free( m ); + free( n ); + free( c ); + free( pp ); + free( P_buf ); + free (buf ); + return status; + } + } + } + } + if ( exit == 1 ) /* Exit */ + { + break; + } + } + } + else + { + if (yield_cont) /*TKL00601*/ +#ifdef VXD + if ( VXD_Yield (yield_cont->yield_proc) ) +#else + if ( yield_cont->yield_proc(0xFFFF) ) +#endif + + { + status = ERR_CANCEL; + free( b ); + free( m ); + free( n ); + free( c ); + free( pp ); + free( P_buf ); + free (buf ); + return status; + } +#ifdef DEBUG1 + printf ("\n P is not pseudoprime"); +#endif + status = ERR_PRIME; + } + free( b ); + free( m ); + free( n ); + free( c ); + free( pp ); + free( P_buf ); + free (buf ); + return status; +} + +/**************************************************************************** +* NAME: int GenPrime( u_int16_t P_bytes, +* ord *P, +* u_int16_t k, +* ord *RVAL, +* YIELD_context *yield_cont ) +* +* DESCRIPTION: Generate Random Pseudo Prime number +* +* INPUTS: +* PARAMETERS: +* u_int16_t P_bytes Number of bytes in array +* u_int16_t k Number of testing +* ord *RVAL Pointer to random number generator value +* YIELD_context *yield_cont Pointer to yield_cont structure (NULL if not used) +* OUTPUT: +* PARAMETERS: +* ord *P Pointer to prime number +* ord *RVAL Pointer to updated value +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data(zero bytes) +* ERR_PRIME Number is not prime +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 08 Dec 94 GKL Added YIELD_context +* +****************************************************************************/ + + int GenPrime( u_int16_t P_bytes, + ord *P, + u_int16_t k, + ord *RVAL, + YIELD_context *yield_cont ) /*TKL00601*/ +{ + int status = SUCCESS; /* function return status */ + if ( P_bytes % sizeof(ord) != 0 ) /* not multiple 4 (32 bit) */ + { + status = ERR_INPUT_LEN; /* invalid length for input data */ + return status; + } + do + { + MyGenRand( P_bytes, P, RVAL ); /* generate random number */ + P[0] |= 1; + P[(P_bytes/sizeof(ord))-1] |= ((ord)1 << (BITS_COUNT-1)); + status = VerPrime( P_bytes, P, k, RVAL, yield_cont); /*TKL00601*/ + } while ((status != SUCCESS) && (status != ERR_CANCEL)); /*TKL00601*/ + return status; +} + diff --git a/lib/bind/cylink/cylink.h b/lib/bind/cylink/cylink.h new file mode 100644 index 0000000000..36aeb9c49f --- /dev/null +++ b/lib/bind/cylink/cylink.h @@ -0,0 +1,82 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**********************************************************************\ +* FILENAME: cylink.h PRODUCT NAME: +* +* DESCRIPTION: Company standard include file +* +* USAGE: File should be #included +* +* +* Copyright (c) Cylink Corporation 1994. All rights reserved. +* +* REVISION HISTORY: +* +\**********************************************************************/ + +#ifndef CYLINK_H /* Prevent multiple inclusions of same header file */ +#define CYLINK_H + +#include +#if (!defined(BSD)) || (BSD < 199306) +# include +#else +# include +#endif + +#if ! ( defined(__alpha) && defined(__osf__) ) /* in sys/types.h */ +#if !defined(_H_INTTYPES) && !defined (_H_TYPES) /* AIX puts this in inttypes.h */ +typedef unsigned char uchar; +#endif /* _H_INTTYPES */ +#endif + +typedef u_int16_t USHORT; +typedef u_int32_t ULONG; + +#define FALSE 0 +#define TRUE 1 + +/*-- ANSI-recommended NULL Pointer definition --*/ +#ifndef NULL +edefine NULL (void *) 0 +#endif + +#endif /* CYLINK_H */ diff --git a/lib/bind/cylink/dss.c b/lib/bind/cylink/dss.c new file mode 100644 index 0000000000..38cf28906c --- /dev/null +++ b/lib/bind/cylink/dss.c @@ -0,0 +1,1202 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: dss.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Cryptographic Toolkit Functions File +* Digital Signature Algorithms +* PUBLIC FUNCTIONS: +* uchar *RVAL ) +* int GenDSSKey( u_int16_t dss_p_bytes, uchar *dss_p, +* uchar *dss_q, uchar *dss_g, +* uchar *dss_x, uchar *dss_y, +* uchar *XKEY ) +* +* int GenDSSNumber( uchar *dss_k, uchar dss_q, +* uchar *KKEY ) +* int GenDSSParameters( u_int16_t dss_p_bytes, uchar *dss_p, +* uchar *dss_q, uchar *dss_g, +* uchar *RVAL ); +* +* Copyright (c) Cylink Corporation 1996. All rights reserved. +* +* REVISION HISTORY: +* +* +****************************************************************************/ + +/**************************************************************************** +* INCLUDE FILES +****************************************************************************/ + +#include "port_before.h" +#include +#include "cylink.h" +#include "ctk_endian.h" + +/* system files */ +#ifdef VXD +#include +#else +#include +#include +#endif + +/* program files */ +#ifdef VXD +#include "tkvxd.h" +#endif +#include "toolkit.h" +#include "cencrint.h" +#define INITIALIZ_PQG /*TKL01101*/ +#include "dssnum.h" /*TKL01101*/ +#include "sha.h" +#include "port_after.h" + +#define BEGIN_PROCESSING do { +#define END_PROCESSING } while (0); +#define ERROR_BREAK break +#define CONTINUE continue + +#define BEGIN_LOOP do { +#define END_LOOP } while (1); +#define BREAK break + + +extern u_int16_t DataOrder; + +/**************************************************************************** +* NAME: int GenDSSSignature( u_int16_t dss_p_bytes, +* uchar *dss_p, +* uchar *dss_q, +* uchar *dss_g, +* uchar *dss_x, +* uchar *dss_k, +* uchar *r, +* uchar *s, +* uchar *hash_result) +* +* DESCRIPTION: Compute a DSS Signature +* +* INPUTS: +* PARAMETERS: +* u_int16_t dss_p_bytes Length of dss_p +* uchar *dss_p Pointer to p prime +* uchar *dss_q Pointer to q prime +* uchar *dss_g Pointer to g +* uchar *dss_x Pointer to secret number +* uchar *dss_k Pointer to random secret number +* uchar *hash_result Pointer to message hashing result +* +* +* OUTPUT: +* PARAMETERS: +* uchar *r Pointer to r part of signature +* uchar *s Pointer to s part of signature +* +* RETURN: +* E_SUCCESS No errors +* E_DSS_LEN Invalid length for dss_p +* ERR_ALLOC Insufficient memory +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC) +* 08 Dec 94 GKL Changed Expo call +* +****************************************************************************/ + +int GenDSSSignature( u_int16_t dss_p_bytes, + uchar *dss_p, + uchar *dss_q, + uchar *dss_g, + uchar *dss_x, + uchar *dss_k, + uchar *r, + uchar *s, + uchar *hash_result) + +{ + int status = SUCCESS; /* function return status */ + ord r_temp[DSS_LENGTH_MAX]; /* r intermidiate value */ + ord k_inverse[SHA_LENGTH+1]; + ord temp[SHA_LENGTH+1]; /* intermidiate values */ + ord *dss_p_a; + ord *dss_g_a; + ord *dss_q_a; + ord *dss_x_a; + ord *dss_k_a; + ord *hash_result_a; + ord *r_a; + ord *s_a; + + if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */ + (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + if ( dss_p_bytes & 0x07 ) /* not multiple 8 (64 bit)*/ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_x, SHA_LENGTH); + BigSwap(dss_k, SHA_LENGTH); + BigSwap(hash_result, SHA_LENGTH); + } + + DSS_G_ALIGN_CALLOC_COPY(dss_g, dss_g_a, dss_p_bytes); /*TKL01101*/ + DSS_P_ALIGN_CALLOC_COPY(dss_p, dss_p_a, dss_p_bytes); /*TKL01101*/ + DSS_Q_ALIGN_CALLOC_COPY(dss_q, dss_q_a, SHA_LENGTH); /*TKL01101*/ + + ALIGN_CALLOC_COPY(dss_x, dss_x_a, SHA_LENGTH); + ALIGN_CALLOC_COPY(dss_k, dss_k_a, SHA_LENGTH); + ALIGN_CALLOC_COPY(hash_result, hash_result_a, SHA_LENGTH); + ALIGN_CALLOC(r, r_a, SHA_LENGTH); + ALIGN_CALLOC(s, s_a, SHA_LENGTH); + if ( status != SUCCESS ) + { + if( dss_p_a ) + DSS_ALIGN_FREE(dss_p_a,dss_p); + if( dss_g_a ) + DSS_ALIGN_FREE(dss_g_a,dss_g); + if( dss_q_a ) + DSS_ALIGN_FREE(dss_q_a,dss_q); + if( dss_x_a ) + { + memset ( dss_x_a , 0 , SHA_LENGTH ); + ALIGN_FREE(dss_x_a); + } + if( dss_k_a ) + { + ALIGN_FREE(dss_k_a); + } + if( hash_result_a ) + { + ALIGN_FREE(hash_result_a); + } + if( r_a ) + { + ALIGN_COPY_FREE(r_a,r,SHA_LENGTH); + } + if( s_a ) + { + ALIGN_COPY_FREE(s_a,s,SHA_LENGTH); + } + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_x, SHA_LENGTH); + BigSwap(dss_k, SHA_LENGTH); + BigSwap(hash_result, SHA_LENGTH); + } + return status; /* ERR_ALLOC insufficient memory */ + } + +/* Compute DSS r value */ + BEGIN_PROCESSING + if (( status = Expo ( dss_p_bytes, + dss_g_a, + SHA_LENGTH, /* r_temp=(dss_g^dss_k)mod(dss_p)*/ + dss_k_a, + dss_p_bytes, + dss_p_a, + r_temp )) != SUCCESS ) + { + ERROR_BREAK; + } + if (( status = PartReduct ( dss_p_bytes, + r_temp, + SHA_LENGTH, /* r=(r_temp)mod(dss_q) */ + dss_q_a, + r_a )) != SUCCESS ) + { + ERROR_BREAK; + } +/* Compute k modulo inverse value */ + if (( status = Inverse( SHA_LENGTH, /* k_inverse=dss_k^(-1)mod(dss_q)*/ + dss_k_a, + SHA_LENGTH, + dss_q_a, + k_inverse )) != SUCCESS ) + { + ERROR_BREAK; + } +/* Compute DSS s value */ + if (( status = Mul ( SHA_LENGTH, /* temp=(dss_x*r)mod(dss_q) */ + dss_x_a, + SHA_LENGTH, + r_a, + SHA_LENGTH, + dss_q_a, + temp )) != SUCCESS ) + { + ERROR_BREAK; + } + + /* Add( temp, hash_result_a, + SHA_LENGTH, dss_q_a, temp ); temp=(temp+hash_result)mod(dss_q)*/ + + Add( temp, hash_result_a, + SHA_LENGTH, dss_q_a ); + if (( status = Mul ( SHA_LENGTH, /* s=(temp*k_inverse)mod(dss_q) */ + temp, + SHA_LENGTH, + k_inverse, + SHA_LENGTH, + dss_q_a, + s_a )) != SUCCESS ) + { + ERROR_BREAK; + } + END_PROCESSING + + DSS_ALIGN_FREE(dss_p_a,dss_p); /*TKL01101*/ + DSS_ALIGN_FREE(dss_g_a,dss_g); /*TKL01101*/ + DSS_ALIGN_FREE(dss_q_a,dss_q); /*TKL01101*/ + ALIGN_FREE(dss_x_a); + ALIGN_FREE(dss_k_a); + ALIGN_FREE(hash_result_a); + ALIGN_COPY_FREE(r_a,r,SHA_LENGTH); + ALIGN_COPY_FREE(s_a,s,SHA_LENGTH); + + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_x, SHA_LENGTH); + BigSwap(dss_k, SHA_LENGTH); + BigSwap(hash_result, SHA_LENGTH); + BigSwap(r, SHA_LENGTH); + BigSwap(s, SHA_LENGTH); + } + + return status; +} + +/**************************************************************************** +* NAME: int VerDSSSignature( u_int16_t dss_p_bytes, +* uchar *dss_p, +* uchar *dss_q, +* uchar *dss_g, +* uchar *dss_y, +* uchar *r, +* uchar *s, +* uchar *hash_result) +* +* DESCRIPTION: Verify a DSS Signature +* +* INPUTS: +* PARAMETERS: +* u_int16_t dss_p_bytes Length of dss_p +* uchar *dss_p Pointer to p prime +* uchar *dss_q Pointer to q prime +* uchar *dss_g Pointer to g +* uchar *dss_y Pointer to public number +* uchar *hash_result Pointer to message hashing result +* OUTPUT: +* PARAMETERS: +* +* RETURN: +* SUCCESS No errors +* ERR_SIGNATURE Signature is not valid +* ERR_DSS_LEN Invalid length for dss_p +* ERR_ALLOC Insufficient memory +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC) +* 08 Dec 94 GKL Changed Expo call +* 21 Aug 96 AAB DoubleExpo call +****************************************************************************/ + +int VerDSSSignature( u_int16_t dss_p_bytes, + uchar *dss_p, + uchar *dss_q, + uchar *dss_g, + uchar *dss_y, + uchar *r, + uchar *s, + uchar *hash_result) +{ + int status = SUCCESS; /* function return status */ + ord w[(SHA_LENGTH / sizeof(ord)) + 1]; + ord u1[SHA_LENGTH / sizeof(ord)]; + ord u2[SHA_LENGTH / sizeof(ord)]; + ord *v; + ord *dss_p_a; + ord *dss_g_a; + ord *dss_q_a; + ord *dss_y_a; + ord *hash_result_a; + ord *r_a; + ord *s_a; + if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */ + (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + if ( dss_p_bytes & 0x07 ) /* not multiple 8 (64 bit)*/ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_y, dss_p_bytes); + BigSwap(hash_result, SHA_LENGTH); + BigSwap(r, SHA_LENGTH); + BigSwap(s, SHA_LENGTH); + } + + DSS_P_ALIGN_CALLOC_COPY(dss_p, dss_p_a, dss_p_bytes); /*TKL01101*/ + DSS_Q_ALIGN_CALLOC_COPY(dss_q, dss_q_a, SHA_LENGTH); /*TKL01101*/ + DSS_G_ALIGN_CALLOC_COPY(dss_g, dss_g_a, dss_p_bytes); /*TKL01101*/ + + ALIGN_CALLOC_COPY(dss_y, dss_y_a, dss_p_bytes); + ALIGN_CALLOC_COPY(hash_result, hash_result_a, SHA_LENGTH); + ALIGN_CALLOC_COPY(r, r_a, SHA_LENGTH); + ALIGN_CALLOC_COPY(s, s_a, SHA_LENGTH); + CALLOC(v,ord,dss_p_bytes); + + if ( status != SUCCESS ) + { + if( dss_p_a ) + { + DSS_ALIGN_FREE(dss_p_a,dss_p); + } + if( dss_g_a ) + { + DSS_ALIGN_FREE(dss_g_a,dss_g); + } + if ( dss_q_a ) + { + DSS_ALIGN_FREE(dss_q_a,dss_q); + } + if( dss_y_a ) + { + ALIGN_FREE(dss_y_a); + } + if( hash_result_a ) + { + ALIGN_FREE(hash_result_a); + } + if( r_a ) + { + ALIGN_FREE(r_a); + } + if( s_a ) + { + ALIGN_FREE(s_a); + } + if( v ) + { + free ( v ); + } + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_y, dss_p_bytes); + BigSwap(hash_result, SHA_LENGTH); + BigSwap(r, SHA_LENGTH); + BigSwap(s, SHA_LENGTH); + } + + return status; /* ERR_ALLOC insufficient memory */ + } + + BEGIN_PROCESSING + if (( status = Inverse( SHA_LENGTH, /* w=dss_k^(-1)mod(dss_q)*/ + s_a, + SHA_LENGTH, + dss_q_a, + w )) !=SUCCESS ) + { + ERROR_BREAK; + } + if (( status = Mul ( SHA_LENGTH, /* u1=(hash_result_*w)mod(dss_q) */ + hash_result_a, + SHA_LENGTH, + w, + SHA_LENGTH, + dss_q_a, + u1 )) != SUCCESS ) + { + ERROR_BREAK; + } + if (( status = Mul ( SHA_LENGTH, /* u2=(r*w)mod(dss_q) */ + r_a, + SHA_LENGTH, + w, + SHA_LENGTH, + dss_q_a, + u2 )) != SUCCESS ) + { + ERROR_BREAK; + } + /* v = dss_g_a^u1*dss_y_a^u2 moddss_p_a */ + if((status = DoubleExpo( dss_p_bytes, dss_g_a, + SHA_LENGTH, u1, + dss_p_bytes, dss_y_a, + SHA_LENGTH, u2, + dss_p_bytes, dss_p_a, v)) != SUCCESS ) + { + + ERROR_BREAK; + } + if (( status = PartReduct ( dss_p_bytes, /*v = v mod(dss_q)*/ + v, + SHA_LENGTH, + dss_q_a, + v )) != SUCCESS ) + { + ERROR_BREAK; + } + + if (( status = memcmp( r_a, v, SHA_LENGTH)) != 0) /*if v=r sign valid */ + { + status = ERR_SIGNATURE; /* signature is not valid */ + ERROR_BREAK; + } + END_PROCESSING + free ( v ); + DSS_ALIGN_FREE(dss_p_a,dss_p); /*TKL01101*/ + DSS_ALIGN_FREE(dss_g_a,dss_g); /*TKL01101*/ + DSS_ALIGN_FREE(dss_q_a,dss_q); /*TKL01101*/ + ALIGN_FREE(dss_y_a); + ALIGN_FREE(hash_result_a); + ALIGN_FREE(r_a); + ALIGN_FREE(s_a); + + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_y, dss_p_bytes); + BigSwap(hash_result, SHA_LENGTH); + BigSwap(r, SHA_LENGTH); + BigSwap(s, SHA_LENGTH); + } + + return status; +} + + +/**************************************************************************** +* NAME: int GenDSSKey( u_int16_t dss_p_bytes, +* uchar *dss_p, +* uchar *dss_q, +* uchar *dss_g, +* uchar *dss_x, +* uchar *dss_y, +* uchar *XKEY ) +* +* +* DESCRIPTION: Compute DSS public/secret number pair. +* +* INPUTS: +* PARAMETERS: +* u_int16_t dss_p_bytes Length of modulo +* uchar *dss_p Pointer to modulo +* uchar *dss_q Pointer to modulo +* uchar *dss_g Pointer to public key +* uchar *XKEY Pointer to user supplied random number +* +* +* OUTPUT: +* PARAMETERS: +* uchar *dss_x Pointer to secret key +* uchar *dss_y Pointer to public key +* uchar *XKEY Pointer to updated number +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data +* ERR_DATA Generic data error +* ERR_ALLOC Insufficient memory +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC) +* 08 Dec 94 GKL Changed Expo call +* +****************************************************************************/ + +int GenDSSKey( u_int16_t dss_p_bytes, + uchar *dss_p, + uchar *dss_q, + uchar *dss_g, + uchar *dss_x, + uchar *dss_y, + uchar *XKEY ) +{ + + int status = SUCCESS; /* function return status */ + SHA_context hash_context; /* SHA context structure */ + uchar M[DSS_LENGTH_MIN]; /* message block */ + ord *dss_p_a; + ord *dss_q_a; + ord *dss_g_a; + ord *dss_x_a; + ord *dss_y_a; + ord *XKEY_a; + if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */ + (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + if ( dss_p_bytes & 0x07 ) /* not multiple 8 (64 bit)*/ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + } + + DSS_P_ALIGN_CALLOC_COPY(dss_p, dss_p_a, dss_p_bytes); /*TKL01101*/ + DSS_G_ALIGN_CALLOC_COPY(dss_g, dss_g_a, dss_p_bytes); /*TKL01101*/ + DSS_Q_ALIGN_CALLOC_COPY(dss_q, dss_q_a, SHA_LENGTH); /*TKL01101*/ + ALIGN_CALLOC(dss_x, dss_x_a, SHA_LENGTH); + ALIGN_CALLOC(dss_y, dss_y_a, dss_p_bytes); + if ( status != SUCCESS ) + { + if( dss_p_a ) + DSS_ALIGN_FREE(dss_p_a,dss_p); + if( dss_g_a ) + DSS_ALIGN_FREE(dss_g_a,dss_g); + if( dss_q_a ) + DSS_ALIGN_FREE(dss_q_a,dss_q); + if( dss_x_a ) + { + memset(dss_x_a, 0, SHA_LENGTH ); + ALIGN_COPY_FREE(dss_x_a,dss_x,SHA_LENGTH); + } + if( dss_y_a ) + { + ALIGN_COPY_FREE(dss_y_a,dss_y,dss_p_bytes); + } + + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + } + return status; /* ERR_ALLOC insufficient memory */ + } + + BEGIN_PROCESSING + SHAInit ( &hash_context ); + memcpy( M, XKEY, SHA_LENGTH); + memset( M + SHA_LENGTH, 0, DSS_LENGTH_MIN - SHA_LENGTH ); + if ( (status = SHAUpdate( &hash_context, M, DSS_LENGTH_MIN )) + != SUCCESS ) + { + ERROR_BREAK; + } + if ( (status = MySHAFinal (&hash_context, (uchar *)dss_x_a)) != SUCCESS ) + { + ERROR_BREAK; + } + if (( status = PartReduct ( SHA_LENGTH, /* dss_x = dss_x mod(dss_q)*/ + dss_x_a, + SHA_LENGTH, + dss_q_a, + dss_x_a )) != SUCCESS ) + { + ERROR_BREAK; + } + + BigSwap(XKEY, SHA_LENGTH); + ALIGN_CALLOC_COPY(XKEY, XKEY_a, SHA_LENGTH); + if ( status != SUCCESS ) + { + if( XKEY_a ) + { + ALIGN_COPY_FREE(XKEY_a,XKEY,SHA_LENGTH); + BigSwap(XKEY, SHA_LENGTH); + return status; /* ERR_ALLOC insufficient memory */ + } + } + + Sum_Q((ord*)XKEY_a, 1, SHA_LENGTH / sizeof (ord) ); + + Sum_big( XKEY_a, dss_x_a, /* XKEY=XKEY+dss_x */ + XKEY_a, SHA_LENGTH / sizeof(ord) ); + + ALIGN_COPY_FREE(XKEY_a,XKEY,SHA_LENGTH); + BigSwap(XKEY, SHA_LENGTH); + + if (( status = Expo ( dss_p_bytes, /*dss_y = g^dss_x mod(dss_p)*/ + dss_g_a, + SHA_LENGTH, + dss_x_a, + dss_p_bytes, + dss_p_a, + dss_y_a)) != SUCCESS ) /*TKL00601*/ + { + ERROR_BREAK; + } + END_PROCESSING + + DSS_ALIGN_FREE(dss_p_a,dss_p); /*TKL01101*/ + DSS_ALIGN_FREE(dss_g_a,dss_g); /*TKL01101*/ + DSS_ALIGN_FREE(dss_q_a,dss_q); /*TKL01101*/ + ALIGN_COPY_FREE(dss_x_a,dss_x,SHA_LENGTH); + ALIGN_COPY_FREE(dss_y_a,dss_y,dss_p_bytes); + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_x, SHA_LENGTH); + BigSwap(dss_y, dss_p_bytes); + } + + return status; +} + + + +/**************************************************************************** +* NAME: int GenDSSNumber( uchar *dss_k, +* uchar *dss_q, +* uchar *KKEY ) +* +* DESCRIPTION: Generate secret number +* +* INPUTS: +* PARAMETERS: +* uchar *KKEY Pointer to input random number +* uchar *dss_q Pointer to modulo +* +* +* OUTPUT: +* PARAMETERS: +* uchar *dss_x Pointer to secret number +* uchar *KKEY Pointer to updated KKEY +* +* RETURN: +* SUCCESS No errors +* ERR_DATA Generic data error +* ERR_ALLOC Insufficient memory +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC) +* +****************************************************************************/ + +int GenDSSNumber( uchar *dss_k, + uchar *dss_q, + uchar *KKEY ) +{ + + int status = SUCCESS; /* function return status */ + ord *dss_k_a; + ord *dss_q_a; + ord *KKEY_a; + SHA_context hash_context; /* SHA context structure*/ + uchar M[DSS_LENGTH_MIN]; /* message block */ + + if (DataOrder) + { + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + } + + DSS_Q_ALIGN_CALLOC_COPY(dss_q, dss_q_a, SHA_LENGTH); /*TKL01101*/ + ALIGN_CALLOC(dss_k, dss_k_a, SHA_LENGTH); + if ( status != SUCCESS ) + { + if( dss_q_a ) + DSS_ALIGN_FREE(dss_q_a,dss_q); + if( dss_k_a ) + { + ALIGN_COPY_FREE(dss_k_a,dss_k,SHA_LENGTH); + } + if (DataOrder) + { + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + } + return status; /* ERR_ALLOC insufficient memory */ + } + + BEGIN_PROCESSING + SHAInitK ( &hash_context ); + memcpy( M, KKEY, SHA_LENGTH); + memset( M + SHA_LENGTH, 0, DSS_LENGTH_MIN - SHA_LENGTH ); + if ( (status = SHAUpdate( &hash_context, M, DSS_LENGTH_MIN )) + != SUCCESS ) + { + ERROR_BREAK; + } + if ( (status = MySHAFinal (&hash_context, (uchar *)dss_k_a)) != SUCCESS ) + { + ERROR_BREAK; + } + if (( status = PartReduct ( SHA_LENGTH, /* dss_k = dss_k mod(dss_q)*/ + dss_k_a, + SHA_LENGTH, + dss_q_a, + dss_k_a )) != SUCCESS ) + { + ERROR_BREAK; + } + BigSwap(KKEY, SHA_LENGTH); + ALIGN_CALLOC_COPY(KKEY, KKEY_a, SHA_LENGTH ); + if ( status != SUCCESS ) + { + if ( KKEY_a ) + { + ALIGN_COPY_FREE(KKEY_a,KKEY,SHA_LENGTH); + BigSwap(KKEY, SHA_LENGTH); + } + return status; /* ERR_ALLOC insufficient memory */ + } + + Sum_Q( KKEY_a, 1, SHA_LENGTH / sizeof(ord)); + + Sum_big( KKEY_a, dss_k_a, /* KKEY=KKEY+dss_k*/ + KKEY_a, SHA_LENGTH / sizeof(ord) ); + + ALIGN_COPY_FREE(KKEY_a,KKEY,SHA_LENGTH); + BigSwap(KKEY, SHA_LENGTH); + + END_PROCESSING + + DSS_ALIGN_FREE(dss_q_a,dss_q); /*TKL01101*/ + + ALIGN_COPY_FREE(dss_k_a,dss_k,SHA_LENGTH); + if (DataOrder) + { + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + BigSwap(dss_k, SHA_LENGTH); + } + + return status; +} + + +/**************************************************************************** +* NAME: int GenDSSParameters( u_int16_t dss_p_bytes, +* uchar *dss_p, +* uchar *dss_q, +* uchar *dss_g, +* uchar *RVAL, +* YIELD_context *yield_cont ) +* +* DESCRIPTION: Generate DSS Common Parameters +* +* INPUTS: +* PARAMETERS: +* u_int16_t dss_p_bytes Number of bytes in dss_p +* uchar *RVAL Pointer to user supplied random number +* YIELD_context *yield_cont Pointer to yield_cont structure (NULL if not used) +* OUTPUT: +* PARAMETERS: +* uchar *dss_p Pointer to N-byte prime number +* uchar *dss_q Pointer to SHA_LENGTH prime number +* uchar *dss_g Pointer to N-byte number +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data(zero bytes) +* ERR_DSS_LEN; Invalid length for dss_p +* ERR_ALLOC Insufficient memory +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC) +* 08 Dec 94 GKL Added YIELD_context +* +****************************************************************************/ + + int GenDSSParameters( u_int16_t dss_p_bytes, + uchar *dss_p, + uchar *dss_q, + uchar *dss_g, + uchar *RVAL, + YIELD_context *yield_cont ) /*TKL00701*/ +{ + int status = SUCCESS; /* function return status */ + ord seed[SHA_LENGTH / sizeof (ord)]; + ord u[SHA_LENGTH / sizeof (ord)]; /* work buffers */ + ord u1[SHA_LENGTH / sizeof (ord)]; + ord *dss_p_a; + ord *dss_q_a; + ord *dss_g_a; + ord *RVAL_a; + ord ofone[SHA_LENGTH / sizeof(ord)]; + ord dss_q2[SHA_LENGTH / sizeof(ord) + 1]; /* dss_q2 = 2 * q */ + ord v[SHA_LENGTH / sizeof(ord)]; + ord *w, *c, *c1, *one, *e; /* Pointers to work buffers */ + u_int16_t i, n, count, offset, k; /* counters */ + u_int16_t dss_p_longs; /* number of longs */ + if ( dss_p_bytes == 0 ) /* invalid length for input data (zero bytes) */ + { + status = ERR_INPUT_LEN; + return status; + } + if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */ + (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + if ( dss_p_bytes & 0x07 ) /* not multiple 4 (64 bit)*/ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + + n = (u_int16_t) (dss_p_bytes / SHA_LENGTH); /* SHA passes count */ + dss_p_longs = (u_int16_t) (dss_p_bytes / sizeof(ord)); /* number of long in dss_p */ + CALLOC(w, ord, (n + 1) * SHA_LENGTH); + CALLOC(c, ord, dss_p_bytes); + CALLOC(c1, ord, dss_p_bytes); + CALLOC(one, ord, dss_p_bytes); + CALLOC(e,ord, dss_p_bytes - SHA_LENGTH + sizeof(ord)); + ALIGN_CALLOC_MOVE(RVAL, RVAL_a, SHA_LENGTH); + ALIGN_CALLOC(dss_p, dss_p_a, dss_p_bytes); + ALIGN_CALLOC(dss_q, dss_q_a, SHA_LENGTH); + ALIGN_CALLOC(dss_g, dss_g_a, dss_p_bytes); + if ( status != SUCCESS ) + { + if( e ) + free ( e ); + if( one ) + free ( one ); + if( c ) + free ( c ); + if( w ) + free ( w ); + if( c1 ) + free ( c1 ); + if( dss_p_a ) + { + ALIGN_COPY_FREE(dss_p_a, dss_p, dss_p_bytes); + } + if( dss_q_a ) + { + ALIGN_COPY_FREE(dss_q_a, dss_q, SHA_LENGTH); + } + if( dss_g_a ) + { + ALIGN_COPY_FREE(dss_g_a, dss_g, dss_p_bytes); + } + if( RVAL_a ) + { + ALIGN_MOVE_FREE(RVAL_a, RVAL, SHA_LENGTH); + } + return status; /* ERR_ALLOC insufficient memory */ + } + one[0] = 1; + BEGIN_PROCESSING /* Generate DSS Common Parameters */ + + BEGIN_LOOP /* Generate prime & dss_p */ /*TKL00501*/ + /* generate prime number of length 160-bit */ + do + { + MyGenRand( SHA_LENGTH, seed, RVAL_a); /* generate random number */ + /* compute message digest from seed */ + if ( (status = MySHA((uchar *)seed, SHA_LENGTH, (uchar *)u)) != SUCCESS ) + { + break; /* error */ + } + memcpy(ofone, seed,SHA_LENGTH); + Sum_Q( ofone, 1, SHA_LENGTH / sizeof(ord) ); + /* compute message digest from seed */ + if ( (status = MySHA( (uchar *)ofone, SHA_LENGTH,(uchar *)dss_q_a)) != SUCCESS ) + { + break; /* error */ + } + + for ( i = 0; i < (SHA_LENGTH / sizeof(ord)); i++ ) /* dss_q = dss_q ^ u */ + { + dss_q_a[i] = dss_q_a[i] ^ u[i]; + } + /* set least and most significant bits */ + dss_q_a[SHA_LENGTH / sizeof(ord) - 1] |= ((ord)1 << (BITS_COUNT-1)); + dss_q_a[0] |= 0x01; + } while ( VerPrime( SHA_LENGTH, dss_q_a, TEST_COUNT, RVAL_a, yield_cont) /*TKL00701*/ + != SUCCESS ); /* perform a robust primality test */ + if (status != SUCCESS ) + { + ERROR_BREAK; + } + /* dss_q2 = 2 * dss_q */ + memcpy( dss_q2, dss_q_a, SHA_LENGTH ); + dss_q2[SHA_LENGTH / sizeof(ord)] = 0; + LShiftL_big( dss_q2, SHA_LENGTH / sizeof(ord) +1, 1 ); + count = 0; + offset = 2; + memset( ofone, 0, SHA_LENGTH ); + do /* find dss_p */ + { + /* generate random number by dss_p bytes */ + for ( k = 0; k <= n; k++ ) + { + ofone[0] = offset + k; + /* v = ofone + seed */ + Sum_big( seed, ofone, v, SHA_LENGTH / sizeof(ord) ); + if ( (status = MySHA ( (uchar *)v, SHA_LENGTH, + (uchar *)( w + (SHA_LENGTH / sizeof(ord)) * k ))) + != SUCCESS ) /* compute message digest */ + { + break; /* error */ + } + } + if (status != SUCCESS ) + { + break; /* error */ + } + /* set most significant bit */ + w[dss_p_longs - 1] |= ((ord)1 << (BITS_COUNT-1)); + memcpy( c, w, dss_p_bytes); + /* c1 = c mod(dss_q2) */ + if( (status = PartReduct( dss_p_bytes, c, + SHA_LENGTH + sizeof(ord), + dss_q2, c1)) != SUCCESS ) + { + break; /* error */ + } + /* c1 = c1 - 1*/ + Sub_big( c1, one, c1, dss_p_longs ); + /* dss_p = w - c1 */ + Sub_big( w, c1, dss_p_a, dss_p_longs ); + if ( dss_p_a[dss_p_bytes / sizeof(ord) - 1] >= (ord)((ord)1 << (BITS_COUNT-1)) ) + { + if ( VerPrime ( dss_p_bytes, dss_p_a, TEST_COUNT, RVAL_a, yield_cont) /*TKL00701*/ + == SUCCESS ) /* perform a robust primality test */ + { + break; + } + } + count++; + offset = (u_int16_t) (offset + n + 1); + } while ( count < 4096); + if (status != SUCCESS ) + { + ERROR_BREAK; + } + if (count != 4096) /*TKL00501*/ + { + BREAK; /*TKL00501*/ + } + END_LOOP /* Generate dss_p */ /*TKL00501*/ + + if (status != SUCCESS ) + { + ERROR_BREAK; + } + dss_p_a[0] -= 1; /* dss_p = dss_p - 1 */ + if ( (status= DivRem (dss_p_bytes, dss_p_a, SHA_LENGTH, dss_q_a, u1, + e )) != SUCCESS ) /* e = dss_p / dss_q */ + { + ERROR_BREAK; + } + dss_p_a[0] += 1; /* dss_p = dss_p + 1 */ + + BEGIN_LOOP /* Generate dss_g */ /*TKL00501*/ + MyGenRand( SHA_LENGTH, u, RVAL_a ); /*generate random number*/ + u[SHA_LENGTH / sizeof(ord) - 1] &= ~((ord)1 << (BITS_COUNT-1)); /* u < dss_q */ + if ( (status = Expo( SHA_LENGTH, u, (u_int16_t)(dss_p_bytes - SHA_LENGTH + + sizeof(ord)), e, dss_p_bytes, dss_p_a, dss_g_a )) + != SUCCESS ) /* dss_g = e ^ u mod(dss_p) */ + { + ERROR_BREAK; + } + if ( dss_g_a[0] == 1 ) /* check dss_g == 1 */ + { + for ( i = 1; i < (dss_p_bytes / sizeof(ord)); i++ ) + { + if ( dss_g_a[i] != 0 ) + { + break; + } + } + if ( i == (dss_p_bytes / sizeof(ord)) ) + { + CONTINUE; + } + } + BREAK; /*TKL00501*/ + END_LOOP /* Generate dss_g */ /*TKL00501*/ + END_PROCESSING /* Generate DSS Common Parameters */ + free ( e ); + free ( one ); + free ( c ); + free ( w ); + free ( c1 ); + ALIGN_COPY_FREE(dss_p_a, dss_p, dss_p_bytes); + ALIGN_COPY_FREE(dss_q_a, dss_q, SHA_LENGTH); + ALIGN_COPY_FREE(dss_g_a, dss_g, dss_p_bytes); + ALIGN_MOVE_FREE(RVAL_a, RVAL, SHA_LENGTH); + if (DataOrder) + { + BigSwap(dss_p, dss_p_bytes); + BigSwap(dss_q, SHA_LENGTH); + BigSwap(dss_g, dss_p_bytes); + } + return status; +} + + +/**************************************************************************** +* NAME: int GetDSSPQG(u_int16_t dss_p_bytes, +* uchar *dss_p, +* uchar *dss_q, +* uchar *dss_g) +* +* DESCRIPTION: Copy Cylink DSS P,Q,G numbers to *dss_p,*dss_q,*dss_g +* +* INPUTS: +* PARAMETERS: +* u_int16_t dss_p_bytes Number of bytes in dss_p +* uchar *dss_p Pointer to N-byte buffer +* uchar *dss_q Pointer to SHA_LENGTH-byte buffer +* uchar *dss_g Pointer to N-byte buffer +* OUTPUT: +* RETURN: +* SUCCESS No errors +* ERR_DSS_LEN; Invalid length for dss_p +* REVISION HISTORY: +* +* 22 Apr 95 GKL Initial release LOG TKL01201 +* +****************************************************************************/ +int GetDSSPQG(u_int16_t dss_p_bytes, + uchar *dss_p, + uchar *dss_q, + uchar *dss_g) +{ + int status = SUCCESS; /* function return status */ + ord *dss_p_a; + ord *dss_g_a; + + if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */ + (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + if ( dss_p_bytes & 0x07 ) /* not multiple 8 (64 bit)*/ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + dss_p_a = &DSS_P_NUMBERS[DSS_NUM_INDEX[(dss_p_bytes-DSS_LENGTH_MIN)/LENGTH_STEP]]; + dss_g_a = &DSS_G_NUMBERS[DSS_NUM_INDEX[(dss_p_bytes-DSS_LENGTH_MIN)/LENGTH_STEP]]; + OrdByte(dss_p_a,dss_p_bytes,dss_p); + OrdByte(dss_g_a,dss_p_bytes,dss_g); + OrdByte(DSS_Q_NUMBER,SHA_LENGTH,dss_q); + if (DataOrder) + { + BigSwap(dss_p, dss_p_bytes); + BigSwap(dss_q, SHA_LENGTH); + BigSwap(dss_g, dss_p_bytes); + } + + return status; +} + + diff --git a/lib/bind/cylink/dssnum.h b/lib/bind/cylink/dssnum.h new file mode 100644 index 0000000000..82a846f6c4 --- /dev/null +++ b/lib/bind/cylink/dssnum.h @@ -0,0 +1,724 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**********************************************************************\ +* FILENAME: DSSNum.h PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* DESCRIPTION: Standard Cylink DSS numbers (P Q G) support. +* +* USAGE: File should be included to get access to +* Cylink DSS numbers +* +* +* Copyright (c) Cylink Corporation 1995. All rights reserved. +* +* REVISION HISTORY: +* 10 APR 95 GKL Initial release +* +\**********************************************************************/ +#ifndef DSSNUMBER_H /* Prevent multiple inclusions */ +#define DSSNUMBER_H + +#include "ctk_endian.h" + +#define LENGTH_MULT_TO_64 + +#define F0 0 +#define F1 (F0 + 1) +#define F2 (F1 + 2) +#define F3 (F2 + 3) +#define F4 (F3 + 4) +#define F5 (F4 + 5) +#define F6 (F5 + 6) +#define F7 (F6 + 7) +#define F8 (F7 + 8) +#define F9 (F8 + 9) +#define F10 (F9 + 10) +#define F11 (F10 + 11) +#define F12 (F11 + 12) +#define F13 (F12 + 13) +#define F14 (F13 + 14) +#define F15 (F14 + 15) + + +#ifdef LENGTH_MULT_TO_64 +#define LENGTH_STEP 8U +#define LAST_F F8 +#endif + +#ifdef LENGTH_MULT_TO_32 +#define LENGTH_STEP 4U +#define LAST_F (F15 + 16) +#endif + + +#define DSS_LENS_NUMBER (int) (1 + ( DSS_LENGTH_MAX - DSS_LENGTH_MIN )/LENGTH_STEP) + +#define DSS_LAST_INDEX (DSS_LENGTH_MIN*DSS_LENS_NUMBER + LENGTH_STEP*LAST_F)/sizeof(ord) + +#ifndef INITIALIZ_PQG + +extern ushort DSS_NUM_INDEX[ DSS_LENS_NUMBER ]; +extern ord DSS_Q_NUMBER[SHA_LENGTH/sizeof(ord)]; +extern ord DSS_P_NUMBERS[DSS_LAST_INDEX]; +extern ord DSS_G_NUMBERS[DSS_LAST_INDEX]; + +#else +ushort DSS_NUM_INDEX[ DSS_LENS_NUMBER ] = +{ + (DSS_LENGTH_MIN*0 + LENGTH_STEP*0 )/sizeof(ord), + (DSS_LENGTH_MIN*1 + LENGTH_STEP*F0 )/sizeof(ord), + (DSS_LENGTH_MIN*2 + LENGTH_STEP*F1 )/sizeof(ord), + (DSS_LENGTH_MIN*3 + LENGTH_STEP*F2 )/sizeof(ord), + (DSS_LENGTH_MIN*4 + LENGTH_STEP*F3 )/sizeof(ord), + (DSS_LENGTH_MIN*5 + LENGTH_STEP*F4 )/sizeof(ord), + (DSS_LENGTH_MIN*6 + LENGTH_STEP*F5 )/sizeof(ord), + (DSS_LENGTH_MIN*7 + LENGTH_STEP*F6 )/sizeof(ord), + (DSS_LENGTH_MIN*8 + LENGTH_STEP*F7 )/sizeof(ord) +#ifdef LENGTH_MULT_TO_32 + , + (DSS_LENGTH_MIN*9 + LENGTH_STEP*F8 )/sizeof(ord), + (DSS_LENGTH_MIN*10 + LENGTH_STEP*F9 )/sizeof(ord), + (DSS_LENGTH_MIN*11 + LENGTH_STEP*F10)/sizeof(ord), + (DSS_LENGTH_MIN*12 + LENGTH_STEP*F11)/sizeof(ord), + (DSS_LENGTH_MIN*13 + LENGTH_STEP*F12)/sizeof(ord), + (DSS_LENGTH_MIN*14 + LENGTH_STEP*F13)/sizeof(ord), + (DSS_LENGTH_MIN*15 + LENGTH_STEP*F14)/sizeof(ord), + (DSS_LENGTH_MIN*16 + LENGTH_STEP*F15)/sizeof(ord) +#endif +}; + +ord DSS_Q_NUMBER[SHA_LENGTH/sizeof(ord)] = +#ifdef ORD_16 + { + 0x8fb7, 0x81f0, 0x6b9e, 0x122a, 0x4dc4, 0x03ca, 0xc896, 0x8d0e, 0xbe3b, 0xed4b + }; +#else + { + 0x81f08fb7L, 0x122a6b9eL, 0x03ca4dc4L, 0x8d0ec896L, 0xed4bbe3bL + }; +#endif + + +ord DSS_P_NUMBERS[DSS_LAST_INDEX] = +#ifdef ORD_16 + { + /* dss_p length = 512*/ + 0x92b7, 0xbd96, 0x9aab, 0x584c, 0xd617, 0xf2f0, 0xda85, 0xd370, + 0xcc82, 0x273e, 0x6b04, 0xc171, 0x5c32, 0xd3ff, 0x352e, 0xf2f8, + 0x4fc2, 0x20bc, 0xbdec, 0xe96e, 0x3503, 0x4d89, 0xe92d, 0xeb7d, + 0x9c1a, 0x7852, 0xfe2a, 0x0a25, 0x4446, 0xce18, 0x7829, 0x95d8, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 544*/ + 0x12db, 0x0d31, 0x9950, 0x16c9, 0x3045, 0x0acb, 0x3c46, 0x3c5c, + 0x6c94, 0x2458, 0x0736, 0x13da, 0xa0af, 0x790f, 0xb177, 0xa6ae, + 0xd111, 0x2bda, 0x697c, 0x49a2, 0xe3e5, 0x6f27, 0x02f5, 0x9bc9, + 0xd4da, 0x7d9b, 0x89c6, 0x63bc, 0x0b6d, 0xfe2d, 0xc7a1, 0x435f, + 0x7fad, 0x9e40, +#endif + /* dss_p length = 576*/ + 0x626b, 0x41b5, 0xd218, 0x25bf, 0x1825, 0x42b3, 0x9eb0, 0xc244, + 0x96ce, 0x22ac, 0x3ac6, 0x713f, 0x321d, 0x398c, 0x3022, 0xbc49, + 0xdd03, 0x52d5, 0x29f8, 0x2a57, 0x8fa1, 0x2173, 0xee7d, 0xb90d, + 0xcc64, 0x5fae, 0xaa81, 0xe3d0, 0x648f, 0xfa6e, 0xdc6c, 0x039f, + 0x2cd6, 0xc552, 0xe2dc, 0xebec, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 608*/ + 0x35f5, 0xb2af, 0x27d0, 0x398b, 0x493d, 0x6f2e, 0xbe27, 0xe5b5, + 0x972c, 0x3470, 0x9638, 0xe90e, 0xf7b7, 0x98ad, 0xd091, 0xb4ca, + 0x3f43, 0x5f58, 0xb6c5, 0xd014, 0x25ee, 0x414d, 0xe2c1, 0x6fd6, + 0xd737, 0x9be6, 0x66ca, 0xe241, 0x1897, 0xf740, 0xe5df, 0xceb0, + 0xdb38, 0xabc8, 0x8af8, 0xc58b, 0xc6a0, 0x9a04, +#endif + /* dss_p length = 640*/ + 0x4095, 0xf6bf, 0x7568, 0x4032, 0x5c0f, 0x64f2, 0x5aae, 0xb099, + 0x346f, 0x0e81, 0x357a, 0x7aeb, 0x0291, 0xfd0a, 0x8d54, 0xce80, + 0x0c05, 0xbea3, 0x889f, 0x8a1b, 0xf1c1, 0x6049, 0x214a, 0x8ec3, + 0xb926, 0xdde1, 0x61b4, 0x384e, 0x404b, 0xb6d7, 0x2e2d, 0x4584, + 0xae6a, 0xcc7a, 0x7bfa, 0x9eb0, 0x3a26, 0x3904, 0x8cac, 0xc036, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 672*/ + 0x0abb, 0xaea3, 0xc749, 0x757c, 0x3035, 0x29d0, 0x46bd, 0xd56c, + 0xf49d, 0xa355, 0x1297, 0x8dcb, 0x9802, 0xc58c, 0xf1ec, 0x8aac, + 0x55dd, 0xb107, 0x0140, 0x26d1, 0x8a5d, 0x8a90, 0xf33e, 0xde0b, + 0xb844, 0xb429, 0x4db2, 0x9806, 0xf629, 0x4c3b, 0xcd76, 0x2f23, + 0x6c68, 0x7bf4, 0x2a7e, 0xd982, 0xc89f, 0x16a2, 0xfe84, 0x953c, + 0x3e4a, 0x8de8, +#endif + /* dss_p length = 704*/ + 0x0113, 0x1535, 0xca0b, 0x8faf, 0xa327, 0x989c, 0x12c8, 0xe512, + 0x796f, 0x1229, 0x12bf, 0x62c8, 0xa50a, 0x2b99, 0xc93b, 0x450c, + 0x71ad, 0x0826, 0xf4c6, 0x3913, 0x9b6e, 0x96da, 0xa08d, 0xbc5e, + 0xd4d3, 0x7b26, 0xf9fd, 0xdd76, 0x4e82, 0x2f06, 0x1f96, 0xbf47, + 0xcadf, 0x3610, 0x917b, 0x4e94, 0xe2e8, 0x0eaf, 0x1cb9, 0x6b90, + 0xb917, 0x6d6f, 0x92b9, 0xb329, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 736*/ + 0x6dad, 0xd878, 0xc913, 0xe61e, 0x87d9, 0xe275, 0xad24, 0xf090, + 0xe12b, 0xfdfe, 0x39a3, 0xc9a1, 0x8330, 0x138a, 0x4bed, 0xc319, + 0x8094, 0x88ba, 0x4b80, 0x1325, 0x7852, 0x67e2, 0x715e, 0x7313, + 0x3b4e, 0x7727, 0x9870, 0x5c6e, 0xe0ce, 0xc67a, 0xd057, 0xf3c5, + 0x55ea, 0x98ba, 0x6ea0, 0xaee7, 0x31e8, 0x3cd6, 0x0e28, 0x42d1, + 0x8946, 0xc395, 0x34fc, 0x1b9d, 0x19d1, 0x86f9, +#endif + /* dss_p length = 768*/ + 0xe293, 0xea08, 0xcdd0, 0xf668, 0x8b2a, 0x06db, 0x7c71, 0xadb2, + 0x943d, 0x6721, 0x54f5, 0xbc44, 0xf7ca, 0x3345, 0x1bf6, 0x0b90, + 0xb475, 0xd3c4, 0xbdb6, 0x7caa, 0xa45f, 0xe9b4, 0x6e0e, 0x0c1a, + 0xb5c3, 0x9760, 0x851a, 0x53af, 0x96b7, 0x4979, 0xf162, 0xe951, + 0x6a54, 0xd020, 0x9ded, 0xdecb, 0xfc81, 0x7d74, 0x5e92, 0x2aee, + 0x0946, 0x0eb5, 0x3700, 0x9bce, 0x845a, 0xa7a3, 0x157a, 0x8618, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 800*/ + 0xb0a1, 0xac27, 0xec4e, 0xf623, 0x55e2, 0x2cb6, 0x288b, 0x4b28, + 0xd74e, 0xbbe6, 0xfdf7, 0xaecd, 0x5758, 0xe251, 0x9074, 0x1aee, + 0xe6ed, 0x4d5e, 0x01d9, 0x529e, 0xf736, 0x0091, 0x0212, 0xc725, + 0x60ce, 0x966f, 0x851d, 0x5c4b, 0x80de, 0x34df, 0x1c88, 0x0636, + 0xbb71, 0x32ce, 0x45cb, 0x86da, 0x4d0e, 0x13e0, 0x7d7d, 0x544b, + 0x1272, 0x747f, 0xd6a7, 0xfa3b, 0xcb86, 0x6b43, 0x66f5, 0xd012, + 0xfe7a, 0xa0cb, +#endif + /* dss_p length = 832*/ + 0xed2d, 0x84dd, 0xf274, 0xdd8f, 0xcd5f, 0x7928, 0xbfc6, 0xa522, + 0xe4e4, 0x50f0, 0xcddf, 0x5842, 0xbb29, 0x7c4d, 0xeef4, 0x6946, + 0x87f6, 0xe486, 0x61b5, 0xc1b6, 0xadef, 0x575a, 0x360f, 0x724f, + 0xcb29, 0x591b, 0x9a4c, 0xf7bc, 0x309e, 0xa348, 0x0ff5, 0x94f3, + 0x932f, 0x9dc6, 0x992c, 0xc6d7, 0x12f6, 0xc2d7, 0x38aa, 0x8c01, + 0x5dca, 0x74f4, 0xfcfd, 0x4cf4, 0x588a, 0x7837, 0x097e, 0xd2e2, + 0x6eac, 0x8869, 0xe92f, 0xec62, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 864*/ + 0x7c21, 0x931e, 0x553d, 0x00f2, 0xa860, 0x940f, 0x411e, 0x7d20, + 0xb168, 0x52a3, 0x69ee, 0x166e, 0xb9e6, 0x1b23, 0xd5e0, 0xef64, + 0x2850, 0x724c, 0xc1fe, 0xea73, 0xda8c, 0xe342, 0x1d7b, 0xd256, + 0x359b, 0x180f, 0xd7f5, 0xca77, 0x06ac, 0x2162, 0xa977, 0x78bb, + 0x5018, 0x5de2, 0x6061, 0xe217, 0x4d42, 0xfed1, 0x3929, 0xd50f, + 0xc946, 0x2433, 0x15f8, 0x361b, 0xbf51, 0x3ff0, 0x3efa, 0x3157, + 0x7350, 0x53a0, 0xd1a4, 0x261b, 0xde5b, 0x9236, +#endif + /* dss_p length = 896*/ + 0x8e21, 0x0364, 0x86d2, 0xe58c, 0x2274, 0x780a, 0x9ffc, 0x4951, + 0x3f99, 0xbc96, 0x9e60, 0x5a7e, 0x010a, 0x23d4, 0x54d1, 0x48e9, + 0xfd6b, 0x979c, 0x5202, 0x8af3, 0x5d87, 0xfe8f, 0x3e3c, 0x1e0c, + 0xe294, 0xcc52, 0xa8d6, 0x480e, 0xa898, 0xd4ce, 0x5949, 0xd341, + 0xe325, 0xf41b, 0x72d6, 0x6a90, 0x7a8b, 0x6f14, 0x3e2b, 0x6636, + 0x3748, 0x4eea, 0xa590, 0x03e4, 0x0524, 0x9c32, 0xeb53, 0x02af, + 0xca71, 0x6792, 0xd673, 0xedf8, 0x6448, 0x59c3, 0x7319, 0x883f, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 928*/ + 0xc17d, 0xa4e8, 0xea08, 0x8ff8, 0x2cb0, 0x73f5, 0xd7ba, 0xc027, + 0xb9c8, 0x989d, 0xe5fe, 0xe3a1, 0xf324, 0x39d3, 0xf142, 0x5ba8, + 0xe6cb, 0x3708, 0xa0b7, 0xed9a, 0xb6b3, 0xe314, 0xf80a, 0x6778, + 0x4d27, 0x7107, 0x6ee8, 0xb9c2, 0xc6af, 0xab70, 0x53be, 0xc445, + 0x7926, 0x34bb, 0x5191, 0xe11d, 0x67f1, 0xcc3a, 0x5354, 0xd34d, + 0xa1ac, 0x08ba, 0x32d4, 0x068a, 0x7c3b, 0x415f, 0xbce0, 0xb549, + 0x0ecf, 0x538f, 0xb5d0, 0x22a3, 0x1d47, 0xe837, 0x14c0, 0x69dd, + 0xa02d, 0xce91, +#endif + /* dss_p length = 960*/ + 0x1ff3, 0xf77e, 0xae7a, 0x5a28, 0x43b1, 0xe187, 0x2e04, 0xb3ea, + 0x7394, 0xa3e8, 0x4985, 0xc9bc, 0x7b7d, 0x1e1c, 0xd99c, 0x55f8, + 0x447b, 0x5704, 0xd758, 0xbed1, 0xe698, 0x2a5e, 0x5c19, 0xc206, + 0x6d38, 0x1f88, 0x2ea4, 0x5f15, 0xebfd, 0xd716, 0x8a2a, 0xf960, + 0x83ac, 0xc493, 0xb966, 0x8f13, 0x4778, 0x9682, 0x4712, 0x84cd, + 0xbb4e, 0xe567, 0x644f, 0x0780, 0x133d, 0x0b0a, 0xe42e, 0x06e8, + 0xa4cc, 0x3131, 0x39d9, 0xfaf8, 0x12a3, 0x5550, 0x43b1, 0xb8a9, + 0xb0eb, 0x0fad, 0x986f, 0xd427, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 992*/ + 0xbcfd, 0x363f, 0x050a, 0x18f0, 0x78d8, 0xcac9, 0x423a, 0xf31e, + 0x198f, 0xd0c3, 0xb319, 0x5d1b, 0x917a, 0xc0b0, 0x8d1b, 0x6b91, + 0xea69, 0xa9d1, 0x02ce, 0x5345, 0x2c80, 0x6992, 0x4dad, 0x7a28, + 0xbb75, 0xd46d, 0x0faa, 0x5612, 0x6878, 0x8a0e, 0x63b4, 0x46ab, + 0xaca0, 0x5381, 0xb90a, 0x3e70, 0x19c4, 0xb639, 0xf778, 0xe751, + 0x5974, 0xb726, 0x589f, 0x8679, 0xeb04, 0xc0b5, 0xdffd, 0x2b32, + 0x4b51, 0xc632, 0xd8c6, 0x9501, 0x4f94, 0x2026, 0x253a, 0x0d27, + 0x07bb, 0x0838, 0x2725, 0xa3eb, 0x3c4e, 0x89b6, +#endif + /* dss_p length = 1024*/ + 0xa141, 0xecf7, 0xc6d6, 0x867d, 0xefa3, 0x1cdd, 0x6c9d, 0x6ca5, + 0x2e2f, 0x68af, 0x90e1, 0x1d3e, 0xd75f, 0x0c2a, 0x844b, 0x36c7, + 0x3420, 0xfd1a, 0xb9ee, 0xf6e5, 0x5fde, 0xc8ed, 0x0c90, 0xd353, + 0x6faa, 0x80a4, 0x5bbd, 0xa59d, 0x9e72, 0x3223, 0x8f59, 0xf33d, + 0x10eb, 0xeccd, 0x184e, 0x3e2a, 0x4c07, 0x564b, 0x4c0a, 0x3263, + 0xc535, 0x8aeb, 0xf982, 0x2be2, 0xe475, 0x9b87, 0xcca0, 0x4d08, + 0x3adf, 0x0484, 0xd528, 0x7acd, 0x304d, 0x55a0, 0x70ae, 0x8298, + 0x6a7a, 0x2298, 0x15c0, 0x7a86, 0x7fc5, 0x654a, 0x14ad, 0xd0aa + }; +#else + { +/* dss_p length = 512*/ + 0xbd9692b7L, 0x584c9aabL, 0xf2f0d617L, 0xd370da85L, + 0x273ecc82L, 0xc1716b04L, 0xd3ff5c32L, 0xf2f8352eL, + 0x20bc4fc2L, 0xe96ebdecL, 0x4d893503L, 0xeb7de92dL, + 0x78529c1aL, 0x0a25fe2aL, 0xce184446L, 0x95d87829L, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 544*/ + 0x0d3112dbL, 0x16c99950L, 0x0acb3045L, 0x3c5c3c46L, + 0x24586c94L, 0x13da0736L, 0x790fa0afL, 0xa6aeb177L, + 0x2bdad111L, 0x49a2697cL, 0x6f27e3e5L, 0x9bc902f5L, + 0x7d9bd4daL, 0x63bc89c6L, 0xfe2d0b6dL, 0x435fc7a1L, + 0x9e407fadL, +#endif + /* dss_p length = 576*/ + 0x41b5626bL, 0x25bfd218L, 0x42b31825L, 0xc2449eb0L, + 0x22ac96ceL, 0x713f3ac6L, 0x398c321dL, 0xbc493022L, + 0x52d5dd03L, 0x2a5729f8L, 0x21738fa1L, 0xb90dee7dL, + 0x5faecc64L, 0xe3d0aa81L, 0xfa6e648fL, 0x039fdc6cL, + 0xc5522cd6L, 0xebece2dcL, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 608*/ + 0xb2af35f5L, 0x398b27d0L, 0x6f2e493dL, 0xe5b5be27L, + 0x3470972cL, 0xe90e9638L, 0x98adf7b7L, 0xb4cad091L, + 0x5f583f43L, 0xd014b6c5L, 0x414d25eeL, 0x6fd6e2c1L, + 0x9be6d737L, 0xe24166caL, 0xf7401897L, 0xceb0e5dfL, + 0xabc8db38L, 0xc58b8af8L, 0x9a04c6a0L, +#endif + /* dss_p length = 640*/ + 0xf6bf4095L, 0x40327568L, 0x64f25c0fL, 0xb0995aaeL, + 0x0e81346fL, 0x7aeb357aL, 0xfd0a0291L, 0xce808d54L, + 0xbea30c05L, 0x8a1b889fL, 0x6049f1c1L, 0x8ec3214aL, + 0xdde1b926L, 0x384e61b4L, 0xb6d7404bL, 0x45842e2dL, + 0xcc7aae6aL, 0x9eb07bfaL, 0x39043a26L, 0xc0368cacL, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 672*/ + 0xaea30abbL, 0x757cc749L, 0x29d03035L, 0xd56c46bdL, + 0xa355f49dL, 0x8dcb1297L, 0xc58c9802L, 0x8aacf1ecL, + 0xb10755ddL, 0x26d10140L, 0x8a908a5dL, 0xde0bf33eL, + 0xb429b844L, 0x98064db2L, 0x4c3bf629L, 0x2f23cd76L, + 0x7bf46c68L, 0xd9822a7eL, 0x16a2c89fL, 0x953cfe84L, + 0x8de83e4aL, +#endif + /* dss_p length = 704*/ + 0x15350113L, 0x8fafca0bL, 0x989ca327L, 0xe51212c8L, + 0x1229796fL, 0x62c812bfL, 0x2b99a50aL, 0x450cc93bL, + 0x082671adL, 0x3913f4c6L, 0x96da9b6eL, 0xbc5ea08dL, + 0x7b26d4d3L, 0xdd76f9fdL, 0x2f064e82L, 0xbf471f96L, + 0x3610cadfL, 0x4e94917bL, 0x0eafe2e8L, 0x6b901cb9L, + 0x6d6fb917L, 0xb32992b9L, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 736*/ + 0xd8786dadL, 0xe61ec913L, 0xe27587d9L, 0xf090ad24L, + 0xfdfee12bL, 0xc9a139a3L, 0x138a8330L, 0xc3194bedL, + 0x88ba8094L, 0x13254b80L, 0x67e27852L, 0x7313715eL, + 0x77273b4eL, 0x5c6e9870L, 0xc67ae0ceL, 0xf3c5d057L, + 0x98ba55eaL, 0xaee76ea0L, 0x3cd631e8L, 0x42d10e28L, + 0xc3958946L, 0x1b9d34fcL, 0x86f919d1L, +#endif + /* dss_p length = 768*/ + 0xea08e293L, 0xf668cdd0L, 0x06db8b2aL, 0xadb27c71L, + 0x6721943dL, 0xbc4454f5L, 0x3345f7caL, 0x0b901bf6L, + 0xd3c4b475L, 0x7caabdb6L, 0xe9b4a45fL, 0x0c1a6e0eL, + 0x9760b5c3L, 0x53af851aL, 0x497996b7L, 0xe951f162L, + 0xd0206a54L, 0xdecb9dedL, 0x7d74fc81L, 0x2aee5e92L, + 0x0eb50946L, 0x9bce3700L, 0xa7a3845aL, 0x8618157aL, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 800*/ + 0xac27b0a1L, 0xf623ec4eL, 0x2cb655e2L, 0x4b28288bL, + 0xbbe6d74eL, 0xaecdfdf7L, 0xe2515758L, 0x1aee9074L, + 0x4d5ee6edL, 0x529e01d9L, 0x0091f736L, 0xc7250212L, + 0x966f60ceL, 0x5c4b851dL, 0x34df80deL, 0x06361c88L, + 0x32cebb71L, 0x86da45cbL, 0x13e04d0eL, 0x544b7d7dL, + 0x747f1272L, 0xfa3bd6a7L, 0x6b43cb86L, 0xd01266f5L, + 0xa0cbfe7aL, +#endif + /* dss_p length = 832*/ + 0x84dded2dL, 0xdd8ff274L, 0x7928cd5fL, 0xa522bfc6L, + 0x50f0e4e4L, 0x5842cddfL, 0x7c4dbb29L, 0x6946eef4L, + 0xe48687f6L, 0xc1b661b5L, 0x575aadefL, 0x724f360fL, + 0x591bcb29L, 0xf7bc9a4cL, 0xa348309eL, 0x94f30ff5L, + 0x9dc6932fL, 0xc6d7992cL, 0xc2d712f6L, 0x8c0138aaL, + 0x74f45dcaL, 0x4cf4fcfdL, 0x7837588aL, 0xd2e2097eL, + 0x88696eacL, 0xec62e92fL, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 864*/ + 0x931e7c21L, 0x00f2553dL, 0x940fa860L, 0x7d20411eL, + 0x52a3b168L, 0x166e69eeL, 0x1b23b9e6L, 0xef64d5e0L, + 0x724c2850L, 0xea73c1feL, 0xe342da8cL, 0xd2561d7bL, + 0x180f359bL, 0xca77d7f5L, 0x216206acL, 0x78bba977L, + 0x5de25018L, 0xe2176061L, 0xfed14d42L, 0xd50f3929L, + 0x2433c946L, 0x361b15f8L, 0x3ff0bf51L, 0x31573efaL, + 0x53a07350L, 0x261bd1a4L, 0x9236de5bL, +#endif + /* dss_p length = 896*/ + 0x03648e21L, 0xe58c86d2L, 0x780a2274L, 0x49519ffcL, + 0xbc963f99L, 0x5a7e9e60L, 0x23d4010aL, 0x48e954d1L, + 0x979cfd6bL, 0x8af35202L, 0xfe8f5d87L, 0x1e0c3e3cL, + 0xcc52e294L, 0x480ea8d6L, 0xd4cea898L, 0xd3415949L, + 0xf41be325L, 0x6a9072d6L, 0x6f147a8bL, 0x66363e2bL, + 0x4eea3748L, 0x03e4a590L, 0x9c320524L, 0x02afeb53L, + 0x6792ca71L, 0xedf8d673L, 0x59c36448L, 0x883f7319L, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 928*/ + 0xa4e8c17dL, 0x8ff8ea08L, 0x73f52cb0L, 0xc027d7baL, + 0x989db9c8L, 0xe3a1e5feL, 0x39d3f324L, 0x5ba8f142L, + 0x3708e6cbL, 0xed9aa0b7L, 0xe314b6b3L, 0x6778f80aL, + 0x71074d27L, 0xb9c26ee8L, 0xab70c6afL, 0xc44553beL, + 0x34bb7926L, 0xe11d5191L, 0xcc3a67f1L, 0xd34d5354L, + 0x08baa1acL, 0x068a32d4L, 0x415f7c3bL, 0xb549bce0L, + 0x538f0ecfL, 0x22a3b5d0L, 0xe8371d47L, 0x69dd14c0L, + 0xce91a02dL, +#endif + /* dss_p length = 960*/ + 0xf77e1ff3L, 0x5a28ae7aL, 0xe18743b1L, 0xb3ea2e04L, + 0xa3e87394L, 0xc9bc4985L, 0x1e1c7b7dL, 0x55f8d99cL, + 0x5704447bL, 0xbed1d758L, 0x2a5ee698L, 0xc2065c19L, + 0x1f886d38L, 0x5f152ea4L, 0xd716ebfdL, 0xf9608a2aL, + 0xc49383acL, 0x8f13b966L, 0x96824778L, 0x84cd4712L, + 0xe567bb4eL, 0x0780644fL, 0x0b0a133dL, 0x06e8e42eL, + 0x3131a4ccL, 0xfaf839d9L, 0x555012a3L, 0xb8a943b1L, + 0x0fadb0ebL, 0xd427986fL, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 992*/ + 0x363fbcfdL, 0x18f0050aL, 0xcac978d8L, 0xf31e423aL, + 0xd0c3198fL, 0x5d1bb319L, 0xc0b0917aL, 0x6b918d1bL, + 0xa9d1ea69L, 0x534502ceL, 0x69922c80L, 0x7a284dadL, + 0xd46dbb75L, 0x56120faaL, 0x8a0e6878L, 0x46ab63b4L, + 0x5381aca0L, 0x3e70b90aL, 0xb63919c4L, 0xe751f778L, + 0xb7265974L, 0x8679589fL, 0xc0b5eb04L, 0x2b32dffdL, + 0xc6324b51L, 0x9501d8c6L, 0x20264f94L, 0x0d27253aL, + 0x083807bbL, 0xa3eb2725L, 0x89b63c4eL, +#endif + /* dss_p length = 1024*/ + 0xecf7a141L, 0x867dc6d6L, 0x1cddefa3L, 0x6ca56c9dL, + 0x68af2e2fL, 0x1d3e90e1L, 0x0c2ad75fL, 0x36c7844bL, + 0xfd1a3420L, 0xf6e5b9eeL, 0xc8ed5fdeL, 0xd3530c90L, + 0x80a46faaL, 0xa59d5bbdL, 0x32239e72L, 0xf33d8f59L, + 0xeccd10ebL, 0x3e2a184eL, 0x564b4c07L, 0x32634c0aL, + 0x8aebc535L, 0x2be2f982L, 0x9b87e475L, 0x4d08cca0L, + 0x04843adfL, 0x7acdd528L, 0x55a0304dL, 0x829870aeL, + 0x22986a7aL, 0x7a8615c0L, 0x654a7fc5L, 0xd0aa14adL + }; +#endif + +ord DSS_G_NUMBERS[DSS_LAST_INDEX] = +#ifdef ORD_16 + { + /* dss_g length = 512*/ + 0x8b1a, 0xedfe, 0xef16, 0xdb26, 0xeae0, 0x1f1d, 0xaf3a, 0x3e30, + 0x2bd6, 0x25ec, 0xa451, 0x6255, 0xbc75, 0x499c, 0x4071, 0x5da2, + 0x1149, 0xc7fc, 0x1402, 0x9b69, 0xc168, 0xb0ea, 0xaf92, 0x6a33, + 0xf45f, 0xd93a, 0x75a6, 0x263c, 0xb820, 0x7eb1, 0x5f5b, 0x4bd7, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 544*/ + 0x2772, 0xe0e6, 0xce97, 0x605b, 0x4aa8, 0x2586, 0x095a, 0xb83f, + 0x8b01, 0xfe53, 0x9250, 0x74ef, 0x74d4, 0xd9fa, 0xb78b, 0xa714, + 0x106f, 0x03a6, 0xb406, 0xc549, 0xc44d, 0xd559, 0x8100, 0xfef4, + 0x34a4, 0x1f4c, 0x3c6b, 0x4ae0, 0xe770, 0x158b, 0x3f8d, 0xf73d, + 0x0cc5, 0x61b7, +#endif + /* dss_g length = 576*/ + 0x3dde, 0x64fd, 0x2b69, 0x03c3, 0xad1d, 0x1751, 0x11dc, 0xfe67, + 0x6379, 0x76de, 0xe333, 0x3b8f, 0x242f, 0x27d8, 0x5f33, 0x3597, + 0xb98c, 0x11dc, 0x718c, 0xe3b5, 0xa3d4, 0x58f2, 0x71fa, 0x2675, + 0x49f9, 0xf2c7, 0x510e, 0xa4e1, 0xeca4, 0x7c64, 0x243b, 0x78fc, + 0x2ce2, 0x7017, 0x0095, 0x23b6, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 608*/ + 0xdad8, 0x1e27, 0x41f5, 0xd536, 0x528f, 0x7047, 0x028a, 0x56f5, + 0xe55f, 0xe20d, 0x612c, 0x520f, 0xebfd, 0x8c86, 0x0924, 0x562a, + 0x2185, 0xe5ac, 0xa113, 0x4b8c, 0x87da, 0xfa4c, 0x8788, 0x9d8d, + 0x41c0, 0x9d25, 0x9c77, 0xff33, 0x6861, 0xd10a, 0xc734, 0x8454, + 0xf803, 0x55ce, 0xfeac, 0x6580, 0x6cd2, 0x482b, +#endif + /* dss_g length = 640*/ + 0x4ff7, 0x2829, 0x8ab0, 0xa0bd, 0x7b1c, 0xf544, 0xe633, 0x6e7b, + 0x9824, 0x494a, 0xfb7f, 0xc8ad, 0x45b6, 0x956e, 0x0574, 0x5b0d, + 0xd40c, 0xf807, 0x7372, 0x56fd, 0xdd12, 0x8960, 0x255c, 0x019e, + 0xfc39, 0x06b3, 0x9f8e, 0x4cd9, 0xe714, 0x77f6, 0x76f7, 0xb573, + 0x010e, 0x9b52, 0x04d2, 0xe269, 0xd4bb, 0xbdec, 0x089d, 0x7f88, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 672*/ + 0x3d36, 0xb22d, 0x2144, 0xfda0, 0x1d4a, 0xc144, 0xef8f, 0x70e8, + 0xfd0f, 0xcbf9, 0x7433, 0xbf29, 0x1657, 0x757b, 0x011d, 0x5c7e, + 0xa0d3, 0xec5a, 0xd45d, 0xacd6, 0x136a, 0x9454, 0x61fd, 0xc3f6, + 0x3758, 0x5c89, 0xe4df, 0xd3c9, 0x6f99, 0xa113, 0x0992, 0x16b2, + 0xf92f, 0xfb67, 0x3f34, 0x57e6, 0xb224, 0xdfd1, 0x43c4, 0x639a, + 0xccf5, 0x86c4, +#endif + /* dss_g length = 704*/ + 0x1621, 0x8313, 0x216e, 0xcb3b, 0xde00, 0xa11b, 0xf27f, 0xd5d4, + 0x6d2e, 0xc870, 0x1c47, 0x2e21, 0x780b, 0x1db6, 0x8adf, 0xe5c6, + 0x837d, 0x7dba, 0x9c8c, 0x28b5, 0xd309, 0xf3fa, 0x6c65, 0xe37f, + 0x6a1e, 0x2601, 0xbb92, 0x56aa, 0x9c0e, 0x9db1, 0xb782, 0x642b, + 0x6cc9, 0xb9fb, 0x6a3c, 0x97b9, 0xf1a8, 0xd8a2, 0xfe6b, 0xcb93, + 0x59ee, 0x32a4, 0x0aa1, 0x58ad, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 736*/ + 0x648c, 0xa15c, 0x27b2, 0x8137, 0xefb3, 0x0e81, 0x258e, 0xabe0, + 0x9f2f, 0x6c67, 0xbed6, 0xd201, 0x3647, 0xbe9a, 0x0091, 0xba9a, + 0x4df1, 0xdc8c, 0x5b15, 0x5a37, 0xb5b1, 0x50f8, 0xdfe6, 0x081b, + 0x48d7, 0xd40b, 0x7c51, 0x0417, 0x97c7, 0x2565, 0xf960, 0x89b2, + 0xa1f0, 0x7aac, 0xed6f, 0x20fe, 0x1d98, 0x0eee, 0x48b8, 0xb062, + 0x70e7, 0xa3f3, 0xbe3f, 0x9183, 0x76ae, 0x6cbc, +#endif + /* dss_g length = 768*/ + 0x6216, 0x4b90, 0xc254, 0x7ab6, 0x7a04, 0xf90f, 0x42dd, 0x58c7, + 0xd015, 0x904d, 0xfbf7, 0x624a, 0x5010, 0x627f, 0x696c, 0x1a32, + 0xe0bc, 0xcdfd, 0xe32f, 0xb081, 0x1377, 0x1913, 0x5f96, 0x86c6, + 0x864a, 0x8429, 0x4bb9, 0xd0c6, 0x3361, 0xbc7d, 0xbd8d, 0xa3b2, + 0x47d5, 0x5086, 0xed0b, 0x3bb6, 0xdba6, 0x6f2c, 0x707a, 0x434b, + 0xd4cc, 0x7b10, 0x8ef0, 0x3466, 0x4737, 0x8f27, 0x3399, 0x3716, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 800*/ + 0x99a7, 0xa90c, 0xdf8e, 0xba50, 0x83b5, 0x7ea0, 0x1d8a, 0xe5bb, + 0x34c9, 0x8c4d, 0xb151, 0x3aba, 0xee2f, 0x76c8, 0xeebf, 0x3db9, + 0xc1e0, 0x2b9a, 0x774f, 0xb476, 0x9b93, 0x53b5, 0xc008, 0xed2c, + 0x0ad4, 0x8af4, 0xc0e6, 0x0e98, 0x2d7b, 0xdb37, 0x7b59, 0x8a31, + 0x0667, 0x1225, 0xb882, 0x0355, 0x58ba, 0xf079, 0x80d7, 0x8033, + 0x54bc, 0xf9cd, 0x461e, 0xc70a, 0x9170, 0x1dba, 0xc447, 0xd3e5, + 0xaf18, 0x04c4, +#endif + /* dss_g length = 832*/ + 0xd1b5, 0x3d20, 0xfbdb, 0xa0b6, 0x0505, 0x4e88, 0xa781, 0x7c65, + 0xd381, 0x5b6e, 0xfd1e, 0xbb71, 0xe085, 0x855d, 0x6d0b, 0x650a, + 0xa248, 0x82d0, 0xd4dd, 0x7ea0, 0x16d1, 0x6937, 0x2cc2, 0x2dec, + 0x5e07, 0x97b4, 0x0c5a, 0xcf21, 0x0299, 0x9b96, 0x4acf, 0xc732, + 0xfbcf, 0xeefb, 0x0032, 0x40bb, 0xc86e, 0xeacb, 0xae2b, 0x8adb, + 0x39aa, 0xbb47, 0xaf3a, 0xfd36, 0xf859, 0x97fc, 0x5535, 0x0d3d, + 0x627a, 0x3f62, 0x1f90, 0x5490, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 864*/ + 0xbf83, 0x8b52, 0xc2b1, 0x0808, 0x4a3e, 0x6ccb, 0x8aa8, 0xcfdd, + 0xb046, 0x4948, 0xcdf4, 0x9881, 0x13d8, 0x85b0, 0xa22a, 0x3786, + 0xe9db, 0xcb8a, 0x89ad, 0x5e27, 0xd925, 0x1fcb, 0x3855, 0x4afd, + 0x7f67, 0x83be, 0xb092, 0xe061, 0x6703, 0xf21f, 0x403e, 0x4c6a, + 0xa8bd, 0x536a, 0x89b6, 0xb25e, 0xe165, 0xd259, 0xb765, 0xd7f3, + 0xc474, 0xd8bc, 0x617d, 0x1a0a, 0xa054, 0x8c28, 0x9fb0, 0x9595, + 0x6f2d, 0x6254, 0xe1c2, 0xb450, 0xef81, 0x277f, +#endif + /* dss_g length = 896*/ + 0x7490, 0x2aea, 0xd005, 0xa3cc, 0x9211, 0x235a, 0x7b6d, 0xacec, + 0xfca5, 0x5407, 0x8515, 0x5bc1, 0x8b2a, 0x9388, 0x8ff9, 0xed56, + 0xf4e9, 0xf31e, 0x7e05, 0x172a, 0x6e2a, 0x8165, 0x7a24, 0x975b, + 0x1f6e, 0xd4d1, 0x8232, 0xd6ff, 0x2363, 0x4072, 0xa1f1, 0xd18b, + 0xe574, 0xb032, 0xc330, 0x81b6, 0x6033, 0x07d5, 0x5107, 0xb7cc, + 0x2c10, 0xbd8e, 0xc6a3, 0xe731, 0xfcd6, 0xe567, 0x3440, 0xbcde, + 0x1976, 0xdbb3, 0xd15a, 0x4e39, 0xc282, 0x4b0b, 0x82b3, 0x286b, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 928*/ + 0x9f66, 0xd0e5, 0xd7d2, 0xe875, 0x0707, 0x2dca, 0xa5a2, 0x266d, + 0x80c2, 0x6d20, 0x69b3, 0x759c, 0x497f, 0x74b4, 0x0f56, 0x4b63, + 0xa294, 0x4995, 0x3eda, 0xf5c4, 0x7951, 0x3a3d, 0x22e9, 0x617f, + 0x1906, 0xd45d, 0x047f, 0x2726, 0x27be, 0x660e, 0xc1d3, 0xa588, + 0xceb2, 0xe300, 0xca06, 0x8620, 0x1110, 0x76ae, 0xf7b8, 0xe368, + 0x89a7, 0x2ded, 0x2756, 0x3ed6, 0x5449, 0x4bd8, 0xb73d, 0xb406, + 0x25ec, 0x32f7, 0x989c, 0x6623, 0x6b1f, 0xf7f0, 0x4807, 0x0954, + 0x51e6, 0x97d0, +#endif + /* dss_g length = 960*/ + 0x4118, 0xe87c, 0x809a, 0x1287, 0x2a0f, 0x51d6, 0x7fc8, 0xdad8, + 0x8dc6, 0xddce, 0xd27c, 0x898a, 0x96a9, 0xaee1, 0xe44c, 0xd322, + 0x9d58, 0x3a34, 0xcebd, 0x322a, 0x5b48, 0x9c21, 0x6d04, 0x2d77, + 0x41f1, 0x5123, 0xaa5f, 0x2192, 0x8175, 0x5cac, 0xf547, 0xdc08, + 0xb0d9, 0x4f11, 0x85c9, 0xb5bf, 0x7147, 0x9fbf, 0x3c20, 0x7f7a, + 0xdd8a, 0xa163, 0x0ae4, 0xfcb2, 0x8251, 0x8162, 0xb96e, 0x84f9, + 0xd652, 0x94ba, 0xbb90, 0x9559, 0xac51, 0x6418, 0xdb54, 0x4739, + 0x3ec0, 0x9b7c, 0xae96, 0x3e14, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 992*/ + 0x4eff, 0x399a, 0x5da9, 0x1e5a, 0x9040, 0x4bad, 0xc85d, 0x5b9a, + 0x825b, 0x5464, 0x7538, 0xe2ea, 0xb957, 0x5def, 0xbfa6, 0x4916, + 0x89be, 0x93fe, 0xe5da, 0x919f, 0x791c, 0xe7a8, 0xef86, 0xc186, + 0xbf63, 0xa881, 0x1e38, 0x9abe, 0x8b58, 0x70b4, 0x9dfd, 0x0719, + 0x85e5, 0xc60a, 0xab36, 0xe07d, 0x0c49, 0xd6fe, 0xfdb4, 0x6619, + 0xe55d, 0x997e, 0x5f38, 0x824f, 0x47ff, 0xf800, 0xb137, 0x839d, + 0x2dae, 0xe0db, 0x2a74, 0x2f58, 0x6fb3, 0x1bab, 0x62ed, 0x0e02, + 0xbef2, 0xd7f1, 0xe566, 0xa9ae, 0xbc35, 0x6357, +#endif + /* dss_g length = 1024*/ + 0x914d, 0x76b2, 0xfee4, 0x9cf7, 0xa136, 0x07a1, 0x3808, 0x1857, + 0x8f96, 0x870c, 0x1f3c, 0x59f2, 0x6f01, 0x4d4d, 0x580e, 0xafc6, + 0x99af, 0xff1b, 0xc019, 0x6c1f, 0xe449, 0x1698, 0x4787, 0x0aa2, + 0x6e68, 0x768d, 0x5ff0, 0x27dc, 0xca9e, 0x630f, 0x01ae, 0x9981, + 0x688d, 0xf278, 0x7f3d, 0x17ad, 0x48aa, 0x65d6, 0x181f, 0x1802, + 0x647c, 0x9ef5, 0x7081, 0x5843, 0x1f0d, 0x9364, 0xebe9, 0x6330, + 0x033a, 0x5d2a, 0xb68a, 0x5639, 0xfa7c, 0xd77e, 0x4bdc, 0x4a62, + 0x5c6d, 0xfed5, 0xa8aa, 0x5eff, 0x1138, 0xae4a, 0xe993, 0x3a73 + }; +#else + { + /* dss_g length = 512*/ + 0xedfe8b1aL, 0xdb26ef16L, 0x1f1deae0L, 0x3e30af3aL, + 0x25ec2bd6L, 0x6255a451L, 0x499cbc75L, 0x5da24071L, + 0xc7fc1149L, 0x9b691402L, 0xb0eac168L, 0x6a33af92L, + 0xd93af45fL, 0x263c75a6L, 0x7eb1b820L, 0x4bd75f5bL, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 544*/ + 0xe0e62772L, 0x605bce97L, 0x25864aa8L, 0xb83f095aL, + 0xfe538b01L, 0x74ef9250L, 0xd9fa74d4L, 0xa714b78bL, + 0x03a6106fL, 0xc549b406L, 0xd559c44dL, 0xfef48100L, + 0x1f4c34a4L, 0x4ae03c6bL, 0x158be770L, 0xf73d3f8dL, + 0x61b70cc5L, +#endif + /* dss_g length = 576*/ + 0x64fd3ddeL, 0x03c32b69L, 0x1751ad1dL, 0xfe6711dcL, + 0x76de6379L, 0x3b8fe333L, 0x27d8242fL, 0x35975f33L, + 0x11dcb98cL, 0xe3b5718cL, 0x58f2a3d4L, 0x267571faL, + 0xf2c749f9L, 0xa4e1510eL, 0x7c64eca4L, 0x78fc243bL, + 0x70172ce2L, 0x23b60095L, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 608*/ + 0x1e27dad8L, 0xd53641f5L, 0x7047528fL, 0x56f5028aL, + 0xe20de55fL, 0x520f612cL, 0x8c86ebfdL, 0x562a0924L, + 0xe5ac2185L, 0x4b8ca113L, 0xfa4c87daL, 0x9d8d8788L, + 0x9d2541c0L, 0xff339c77L, 0xd10a6861L, 0x8454c734L, + 0x55cef803L, 0x6580feacL, 0x482b6cd2L, +#endif + /* dss_g length = 640*/ + 0x28294ff7L, 0xa0bd8ab0L, 0xf5447b1cL, 0x6e7be633L, + 0x494a9824L, 0xc8adfb7fL, 0x956e45b6L, 0x5b0d0574L, + 0xf807d40cL, 0x56fd7372L, 0x8960dd12L, 0x019e255cL, + 0x06b3fc39L, 0x4cd99f8eL, 0x77f6e714L, 0xb57376f7L, + 0x9b52010eL, 0xe26904d2L, 0xbdecd4bbL, 0x7f88089dL, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 672*/ + 0xb22d3d36L, 0xfda02144L, 0xc1441d4aL, 0x70e8ef8fL, + 0xcbf9fd0fL, 0xbf297433L, 0x757b1657L, 0x5c7e011dL, + 0xec5aa0d3L, 0xacd6d45dL, 0x9454136aL, 0xc3f661fdL, + 0x5c893758L, 0xd3c9e4dfL, 0xa1136f99L, 0x16b20992L, + 0xfb67f92fL, 0x57e63f34L, 0xdfd1b224L, 0x639a43c4L, + 0x86c4ccf5L, +#endif + /* dss_g length = 704*/ + 0x83131621L, 0xcb3b216eL, 0xa11bde00L, 0xd5d4f27fL, + 0xc8706d2eL, 0x2e211c47L, 0x1db6780bL, 0xe5c68adfL, + 0x7dba837dL, 0x28b59c8cL, 0xf3fad309L, 0xe37f6c65L, + 0x26016a1eL, 0x56aabb92L, 0x9db19c0eL, 0x642bb782L, + 0xb9fb6cc9L, 0x97b96a3cL, 0xd8a2f1a8L, 0xcb93fe6bL, + 0x32a459eeL, 0x58ad0aa1L, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 736*/ + 0xa15c648cL, 0x813727b2L, 0x0e81efb3L, 0xabe0258eL, + 0x6c679f2fL, 0xd201bed6L, 0xbe9a3647L, 0xba9a0091L, + 0xdc8c4df1L, 0x5a375b15L, 0x50f8b5b1L, 0x081bdfe6L, + 0xd40b48d7L, 0x04177c51L, 0x256597c7L, 0x89b2f960L, + 0x7aaca1f0L, 0x20feed6fL, 0x0eee1d98L, 0xb06248b8L, + 0xa3f370e7L, 0x9183be3fL, 0x6cbc76aeL, +#endif + /* dss_g length = 768*/ + 0x4b906216L, 0x7ab6c254L, 0xf90f7a04L, 0x58c742ddL, + 0x904dd015L, 0x624afbf7L, 0x627f5010L, 0x1a32696cL, + 0xcdfde0bcL, 0xb081e32fL, 0x19131377L, 0x86c65f96L, + 0x8429864aL, 0xd0c64bb9L, 0xbc7d3361L, 0xa3b2bd8dL, + 0x508647d5L, 0x3bb6ed0bL, 0x6f2cdba6L, 0x434b707aL, + 0x7b10d4ccL, 0x34668ef0L, 0x8f274737L, 0x37163399L, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 800*/ + 0xa90c99a7L, 0xba50df8eL, 0x7ea083b5L, 0xe5bb1d8aL, + 0x8c4d34c9L, 0x3abab151L, 0x76c8ee2fL, 0x3db9eebfL, + 0x2b9ac1e0L, 0xb476774fL, 0x53b59b93L, 0xed2cc008L, + 0x8af40ad4L, 0x0e98c0e6L, 0xdb372d7bL, 0x8a317b59L, + 0x12250667L, 0x0355b882L, 0xf07958baL, 0x803380d7L, + 0xf9cd54bcL, 0xc70a461eL, 0x1dba9170L, 0xd3e5c447L, + 0x04c4af18L, +#endif + /* dss_g length = 832*/ + 0x3d20d1b5L, 0xa0b6fbdbL, 0x4e880505L, 0x7c65a781L, + 0x5b6ed381L, 0xbb71fd1eL, 0x855de085L, 0x650a6d0bL, + 0x82d0a248L, 0x7ea0d4ddL, 0x693716d1L, 0x2dec2cc2L, + 0x97b45e07L, 0xcf210c5aL, 0x9b960299L, 0xc7324acfL, + 0xeefbfbcfL, 0x40bb0032L, 0xeacbc86eL, 0x8adbae2bL, + 0xbb4739aaL, 0xfd36af3aL, 0x97fcf859L, 0x0d3d5535L, + 0x3f62627aL, 0x54901f90L, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 864*/ + 0x8b52bf83L, 0x0808c2b1L, 0x6ccb4a3eL, 0xcfdd8aa8L, + 0x4948b046L, 0x9881cdf4L, 0x85b013d8L, 0x3786a22aL, + 0xcb8ae9dbL, 0x5e2789adL, 0x1fcbd925L, 0x4afd3855L, + 0x83be7f67L, 0xe061b092L, 0xf21f6703L, 0x4c6a403eL, + 0x536aa8bdL, 0xb25e89b6L, 0xd259e165L, 0xd7f3b765L, + 0xd8bcc474L, 0x1a0a617dL, 0x8c28a054L, 0x95959fb0L, + 0x62546f2dL, 0xb450e1c2L, 0x277fef81L, +#endif + /* dss_g length = 896*/ + 0x2aea7490L, 0xa3ccd005L, 0x235a9211L, 0xacec7b6dL, + 0x5407fca5L, 0x5bc18515L, 0x93888b2aL, 0xed568ff9L, + 0xf31ef4e9L, 0x172a7e05L, 0x81656e2aL, 0x975b7a24L, + 0xd4d11f6eL, 0xd6ff8232L, 0x40722363L, 0xd18ba1f1L, + 0xb032e574L, 0x81b6c330L, 0x07d56033L, 0xb7cc5107L, + 0xbd8e2c10L, 0xe731c6a3L, 0xe567fcd6L, 0xbcde3440L, + 0xdbb31976L, 0x4e39d15aL, 0x4b0bc282L, 0x286b82b3L, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 928*/ + 0xd0e59f66L, 0xe875d7d2L, 0x2dca0707L, 0x266da5a2L, + 0x6d2080c2L, 0x759c69b3L, 0x74b4497fL, 0x4b630f56L, + 0x4995a294L, 0xf5c43edaL, 0x3a3d7951L, 0x617f22e9L, + 0xd45d1906L, 0x2726047fL, 0x660e27beL, 0xa588c1d3L, + 0xe300ceb2L, 0x8620ca06L, 0x76ae1110L, 0xe368f7b8L, + 0x2ded89a7L, 0x3ed62756L, 0x4bd85449L, 0xb406b73dL, + 0x32f725ecL, 0x6623989cL, 0xf7f06b1fL, 0x09544807L, + 0x97d051e6L, +#endif + /* dss_g length = 960*/ + 0xe87c4118L, 0x1287809aL, 0x51d62a0fL, 0xdad87fc8L, + 0xddce8dc6L, 0x898ad27cL, 0xaee196a9L, 0xd322e44cL, + 0x3a349d58L, 0x322acebdL, 0x9c215b48L, 0x2d776d04L, + 0x512341f1L, 0x2192aa5fL, 0x5cac8175L, 0xdc08f547L, + 0x4f11b0d9L, 0xb5bf85c9L, 0x9fbf7147L, 0x7f7a3c20L, + 0xa163dd8aL, 0xfcb20ae4L, 0x81628251L, 0x84f9b96eL, + 0x94bad652L, 0x9559bb90L, 0x6418ac51L, 0x4739db54L, + 0x9b7c3ec0L, 0x3e14ae96L, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 992*/ + 0x399a4effL, 0x1e5a5da9L, 0x4bad9040L, 0x5b9ac85dL, + 0x5464825bL, 0xe2ea7538L, 0x5defb957L, 0x4916bfa6L, + 0x93fe89beL, 0x919fe5daL, 0xe7a8791cL, 0xc186ef86L, + 0xa881bf63L, 0x9abe1e38L, 0x70b48b58L, 0x07199dfdL, + 0xc60a85e5L, 0xe07dab36L, 0xd6fe0c49L, 0x6619fdb4L, + 0x997ee55dL, 0x824f5f38L, 0xf80047ffL, 0x839db137L, + 0xe0db2daeL, 0x2f582a74L, 0x1bab6fb3L, 0x0e0262edL, + 0xd7f1bef2L, 0xa9aee566L, 0x6357bc35L, +#endif + /* dss_g length = 1024*/ + 0x76b2914dL, 0x9cf7fee4L, 0x07a1a136L, 0x18573808L, + 0x870c8f96L, 0x59f21f3cL, 0x4d4d6f01L, 0xafc6580eL, + 0xff1b99afL, 0x6c1fc019L, 0x1698e449L, 0x0aa24787L, + 0x768d6e68L, 0x27dc5ff0L, 0x630fca9eL, 0x998101aeL, + 0xf278688dL, 0x17ad7f3dL, 0x65d648aaL, 0x1802181fL, + 0x9ef5647cL, 0x58437081L, 0x93641f0dL, 0x6330ebe9L, + 0x5d2a033aL, 0x5639b68aL, 0xd77efa7cL, 0x4a624bdcL, + 0xfed55c6dL, 0x5effa8aaL, 0xae4a1138L, 0x3a73e993L + }; +#endif + +#endif /*INITIALIZ_PQG*/ + +#endif /*DSSNUMBER_H*/ diff --git a/lib/bind/cylink/funcs.h b/lib/bind/cylink/funcs.h new file mode 100644 index 0000000000..69ae69f56f --- /dev/null +++ b/lib/bind/cylink/funcs.h @@ -0,0 +1,7 @@ +void RShiftL_big(ord *X, u_int32_t len_X, u_int32_t n_bit); +void LShiftL_big(ord *X, u_int32_t len_X, u_int32_t n_bit); +int RShiftMostBit(ord *a, u_int32_t len); +void ByteLong(uchar *X, u_int32_t X_bytes, u_int32_t *Y); +void ByteOrd(uchar *X, u_int32_t X_bytes, ord *Y); +void OrdByte(ord *X, u_int32_t X_bytes, uchar *Y); +void LongByte(u_int32_t *X, u_int32_t X_bytes, uchar *Y); diff --git a/lib/bind/cylink/kludge.h b/lib/bind/cylink/kludge.h new file mode 100644 index 0000000000..4b02385fc2 --- /dev/null +++ b/lib/bind/cylink/kludge.h @@ -0,0 +1,158 @@ +#ifndef KLUDGE_H +#define KLUDGE_H + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * Kludges for not-quite-ANSI systems. + * This should always be the last file included, because it may + * mess up some system header files. + */ + +/* + * Some compilers complain about #if FOO if FOO isn't defined, + * so do the ANSI-mandated thing explicitly... + */ +#ifndef ASSERT_NEEDS_STDIO +#define ASSERT_NEEDS_STDIO 0 +#endif +#ifndef ASSERT_NEEDS_STDLIB +#define ASSERT_NEEDS_STDLIB 0 +#endif +#ifndef NO_STDLIB_H +#define NO_STDLIB_H 0 +#endif + +/* SunOS 4.1.x needs "stderr" defined, and "exit" declared... */ +#ifdef assert +#if ASSERT_NEEDS_STDIO +#include +#endif +#if ASSERT_NEEDS_STDLIB +#if !NO_STDLIB_H +#include +#endif +#endif +#endif + +#ifndef NO_MEMMOVE +#define NO_MEMMOVE 0 +#endif +#if NO_MEMMOVE /* memove() not in libraries */ +#define memmove(dest,src,len) bcopy(src,dest,len) +#endif + +#ifndef NO_MEMCPY +#define NO_MEMCPY 0 +#endif +#if NO_MEMCPY /* memcpy() not in libraries */ +#define memcpy(dest,src,len) bcopy(src,dest,len) +#endif + +#ifndef MEM_PROTOS_BROKEN +#define MEM_PROTOS_BROKEN 0 +#endif +#if MEM_PROTOS_BROKEN +#define memcpy(d,s,l) memcpy((void *)(d), (void const *)(s), l) +#define memmove(d,s,l) memmove((void *)(d), (void const *)(s), l) +#define memcmp(d,s,l) memcmp((void const *)(d), (void const *)(s), l) +#define memset(d,v,l) memset((void *)(d), v, l) +#endif + +/* + * If there are no prototypes for the stdio functions, use these to + * reduce compiler warnings. Uses EOF as a giveaway to indicate + * that was #included. + */ +#ifndef NO_STDIO_PROTOS +#define NO_STDIO_PROTOS 0 +#endif +#if NO_STDIO_PROTOS /* Missing prototypes for "simple" functions */ +#ifdef EOF +#ifdef __cplusplus +extern "C" { +#endif +int (puts)(char const *); +int (fputs)(char const *, FILE *); +int (fflush)(FILE *); +int (printf)(char const *, ...); +int (fprintf)(FILE *, char const *, ...); +/* If we have a sufficiently old-fashioned stdio, it probably uses these... */ +int (_flsbuf)(int, FILE *); +int (_filbuf)(FILE *); +#ifdef __cplusplus +} +#endif +#endif /* EOF */ +#endif /* NO_STDIO_PROTOS */ + +/* + * Borland C seems to think that it's a bad idea to decleare a + * structure tag and not declare the contents. I happen to think + * it's a *good* idea to use such "opaque" structures wherever + * possible. So shut up. + */ +#ifdef __BORLANDC__ +#pragma warn -stu +#ifndef MSDOS +#define MSDOS 1 +#endif +#endif + +/* Turn off warning about negation of unsigned values */ +#ifdef _MSC_VER +#pragma warning(disable:4146) +#endif + +/* Cope with people forgetting to define the OS, if possible... */ + +#ifndef MSDOS +#ifdef __MSDOS +#define MSDOS 1 +#endif +#endif +#ifndef MSDOS +#ifdef __MSDOS__ +#define MSDOS 1 +#endif +#endif + +#endif /* KLUDGE_H */ diff --git a/lib/bind/cylink/lbn.h b/lib/bind/cylink/lbn.h new file mode 100644 index 0000000000..328f87fd3a --- /dev/null +++ b/lib/bind/cylink/lbn.h @@ -0,0 +1,186 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn.h - Low-level bignum header. + * Defines various word sizes and useful macros. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + */ +#ifndef LBN_H +#define LBN_H + +#ifndef HAVE_CONFIG_H +#define HAVE_CONFIG_H 0 +#endif +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Some compilers complain about #if FOO if FOO isn't defined, + * so do the ANSI-mandated thing explicitly... + */ +#ifndef NO_LIMITS_H +#define NO_LIMITS_H 0 +#endif + +/* Make sure we have 8-bit bytes */ +#if !NO_LIMITS_H +#include +#if UCHAR_MAX != 0xff || CHAR_BIT != 8 +#error The bignum library requires 8-bit unsigned characters. +#endif +#endif /* !NO_LIMITS_H */ + +#ifdef BNINCLUDE /* If this is defined as, say, foo.h */ +#define STR(x) #x /* STR(BNINCLUDE) -> "BNINCLUDE" */ +#define XSTR(x) STR(x) /* XSTR(BNINCLUDE) -> STR(foo.h) -> "foo.h" */ +#include XSTR(BNINCLUDE) /* #include "foo.h" */ +#undef XSTR +#undef STR +#endif + +/* Figure out the endianness */ +/* Error if more than one is defined */ +#if BN_BIG_ENDIAN && BN_LITTLE_ENDIAN +#error Only one of BN_BIG_ENDIAN or BN_LITTLE_ENDIAN may be defined +#endif + +/* + * If no preference is stated, little-endian C code is slightly more + * efficient, so prefer that. (The endianness here does NOT have to + * match the machine's native byte sex; the library's C code will work + * either way. The flexibility is allowed for assembly routines + * that do care. + */ +#if !defined(BN_BIG_ENDIAN) && !defined(BN_LITTLE_ENDIAN) +#define BN_LITTLE_ENDIAN 1 +#endif /* !BN_BIG_ENDIAN && !BN_LITTLE_ENDIAN */ + +/* Macros to choose between big and little endian */ +#if BN_BIG_ENDIAN +#define BIG(b) b +#define LITTLE(l) /*nothing*/ +#define BIGLITTLE(b,l) b +#elif BN_LITTLE_ENDIAN +#define BIG(b) /*nothing*/ +#define LITTLE(l) l +#define BIGLITTLE(b,l) l +#else +#error One of BN_BIG_ENDIAN or BN_LITTLE_ENDIAN must be defined as 1 +#endif + + +/* + * Find a 16-bit unsigned type. + * Unsigned short is preferred over unsigned int to make the type chosen + * by this file more stable on platforms (such as many 68000 compilers) + * which support both 16- and 32-bit ints. + */ +#ifndef BNWORD16 +#ifndef USHRT_MAX /* No available - guess */ +typedef unsigned short bnword16; +#define BNWORD16 bnword16 +#elif USHRT_MAX == 0xffff +typedef unsigned short bnword16; +#define BNWORD16 bnword16 +#elif UINT_MAX == 0xffff +typedef unsigned bnword16; +#define BNWORD16 bnword16 +#endif +#endif /* BNWORD16 */ + +/* + * Find a 32-bit unsigned type. + * Unsigned long is preferred over unsigned int to make the type chosen + * by this file more stable on platforms (such as many 68000 compilers) + * which support both 16- and 32-bit ints. + */ +#ifndef BNWORD32 +#ifndef ULONG_MAX /* No available - guess */ +typedef unsigned long bnword32; +#define BNWORD32 bnword32 +#elif ULONG_MAX == 0xfffffffful +typedef unsigned long bnword32; +#define BNWORD32 bnword32 +#elif UINT_MAX == 0xffffffff +typedef unsigned bnword32; +#define BNWORD32 bnword32 +#elif USHRT_MAX == 0xffffffff +typedef unsigned short bnword32; +#define BNWORD32 bnword32 +#endif +#endif /* BNWORD16 */ + +/* + * Find a 64-bit unsigned type. + * The conditions here are more complicated to avoid using numbers that + * will choke lesser preprocessors (like 0xffffffffffffffff) unless + * we're reasonably certain that they'll be acceptable. + */ +#if !defined(BNWORD64) && ULONG_MAX > 0xfffffffful +#if ULONG_MAX == 0xffffffffffffffff +typedef unsigned long bnword64; +#define BNWORD64 bnword64 +#endif +#endif + +#if 0 +/* + * I would test the value of unsigned long long, but some *preprocessors* + * don't constants that long even if the compiler can accept them, so it + * doesn't work reliably. So cross our fingers and hope that it's a 64-bit + * type. + * + * GCC uses ULONG_LONG_MAX. Solaris uses ULLONG_MAX. IRIX uses ULONGLONG_MAX. + * Are there any other names for this? + */ +#if !defined(BNWORD64) && \ + (defined(ULONG_LONG_MAX) || defined (ULLONG_MAX) || defined(ULONGLONG_MAX)) +typedef unsigned long long bnword64; +#define BNWORD64 bnword64 +#endif +#endif + +/* We don't even try to find a 128-bit type at the moment */ + +#endif /* !LBN_H */ diff --git a/lib/bind/cylink/lbn00.c b/lib/bind/cylink/lbn00.c new file mode 100644 index 0000000000..46e325a27d --- /dev/null +++ b/lib/bind/cylink/lbn00.c @@ -0,0 +1,65 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn00.c - auto-size-detecting lbn??.c file. + * + * Written in 1995 by Colin Plumb. + */ + +#include "port_before.h" +#include "bnsize00.h" + +#if BNSIZE64 + +/* Include all of the C source file by reference */ +#include "lbn64.c" + +#elif BNSIZE32 + +/* Include all of the C source file by reference */ +#include "lbn32.c" + +#else /* BNSIZE16 */ + +/* Include all of the C source file by reference */ +#include "lbn16.c" + +#endif diff --git a/lib/bind/cylink/lbn16.c b/lib/bind/cylink/lbn16.c new file mode 100644 index 0000000000..b73636bb75 --- /dev/null +++ b/lib/bind/cylink/lbn16.c @@ -0,0 +1,3644 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn16.c - Low-level bignum routines, 16-bit version. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + * + * NOTE: the magic constants "16" and "32" appear in many places in this + * file, including inside identifiers. Because it is not possible to + * ask "#ifdef" of a macro expansion, it is not possible to use the + * preprocessor to conditionalize these properly. Thus, this file is + * intended to be edited with textual search and replace to produce + * alternate word size versions. Any reference to the number of bits + * in a word must be the string "16", and that string must not appear + * otherwise. Any reference to twice this number must appear as "32", + * which likewise must not appear otherwise. Is that clear? + * + * Remember, when doubling the bit size replace the larger number (32) + * first, then the smaller (16). When halving the bit size, do the + * opposite. Otherwise, things will get wierd. Also, be sure to replace + * every instance that appears. (:%s/foo/bar/g in vi) + * + * These routines work with a pointer to the least-significant end of + * an array of WORD16s. The BIG(x), LITTLE(y) and BIGLTTLE(x,y) macros + * defined in lbn.h (which expand to x on a big-edian machine and y on a + * little-endian machine) are used to conditionalize the code to work + * either way. If you have no assembly primitives, it doesn't matter. + * Note that on a big-endian machine, the least-significant-end pointer + * is ONE PAST THE END. The bytes are ptr[-1] through ptr[-len]. + * On little-endian, they are ptr[0] through ptr[len-1]. This makes + * perfect sense if you consider pointers to point *between* bytes rather + * than at them. + * + * Because the array index values are unsigned integers, ptr[-i] + * may not work properly, since the index -i is evaluated as an unsigned, + * and if pointers are wider, zero-extension will produce a positive + * number rahter than the needed negative. The expression used in this + * code, *(ptr-i) will, however, work. (The array syntax is equivalent + * to *(ptr+-i), which is a pretty subtle difference.) + * + * Many of these routines will get very unhappy if fed zero-length inputs. + * They use assert() to enforce this. An higher layer of code must make + * sure that these aren't called with zero-length inputs. + * + * Any of these routines can be replaced with more efficient versions + * elsewhere, by just #defining their names. If one of the names + * is #defined, the C code is not compiled in and no declaration is + * made. Use the BNINCLUDE file to do that. Typically, you compile + * asm subroutines with the same name and just, e.g. + * #define lbnMulAdd1_16 lbnMulAdd1_16 + * + * If you want to write asm routines, start with lbnMulAdd1_16(). + * This is the workhorse of modular exponentiation. lbnMulN1_16() is + * also used a fair bit, although not as much and it's defined in terms + * of lbnMulAdd1_16 if that has a custom version. lbnMulSub1_16 and + * lbnDiv21_16 are used in the usual division and remainder finding. + * (Not the Montgomery reduction used in modular exponentiation, though.) + * Once you have lbnMulAdd1_16 defined, writing the other two should + * be pretty easy. (Just make sure you get the sign of the subtraction + * in lbnMulSub1_16 right - it's dest = dest - source * k.) + * + * The only definitions that absolutely need a double-word (BNWORD32) + * type are lbnMulAdd1_16 and lbnMulSub1_16; if those are provided, + * the rest follows. lbnDiv21_16, however, is a lot slower unless you + * have them, and lbnModQ_16 takes after it. That one is used quite a + * bit for prime sieving. + */ + +#ifndef HAVE_CONFIG_H +#define HAVE_CONFIG_H 0 +#endif +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Some compilers complain about #if FOO if FOO isn't defined, + * so do the ANSI-mandated thing explicitly... + */ +#ifndef NO_ASSERT_H +#define NO_ASSERT_H 0 +#endif +#ifndef NO_STRING_H +#define NO_STRING_H 0 +#endif +#ifndef HAVE_STRINGS_H +#define HAVE_STRINGS_H 0 +#endif +#ifndef NEED_MEMORY_H +#define NEED_MEMORY_H 0 +#endif + +#if !NO_ASSERT_H +#include +#else +#define assert(x) (void)0 +#endif + +#if !NO_STRING_H +#include /* For memcpy */ +#elif HAVE_STRINGS_H +#include +#endif +#if NEED_MEMORY_H +#include +#endif + +#include "lbn.h" +#include "lbn16.h" +#include "lbnmem.h" +#include "legal.h" + +#include "kludge.h" +#include + +#ifndef BNWORD16 +#error 16-bit bignum library requires a 16-bit data type +#endif + +/* Make sure the copyright notice gets included */ +volatile const char * volatile const lbnCopyright_16 = bnCopyright; + +/* + * Most of the multiply (and Montgomery reduce) routines use an outer + * loop that iterates over one of the operands - a so-called operand + * scanning approach. One big advantage of this is that the assembly + * support routines are simpler. The loops can be rearranged to have + * an outer loop that iterates over the product, a so-called product + * scanning approach. This has the advantage of writing less data + * and doing fewer adds to memory, so is supposedly faster. Some + * code has been written using a product-scanning approach, but + * it appears to be slower, so it is turned off by default. Some + * experimentation would be appreciated. + * + * (The code is also annoying to get right and not very well commented, + * one of my pet peeves about math libraries. I'm sorry.) + */ +#ifndef PRODUCT_SCAN +#define PRODUCT_SCAN 0 +#endif + +/* + * Copy an array of words. Thrilling, isn't it? + * This is a good example of how the byte offsets and BIGLITTLE() macros work. + * Another alternative would have been + * memcpy(dest BIG(-len), src BIG(-len), len*sizeof(BNWORD16)), but I find that + * putting operators into conditional macros is confusing. + */ +#ifndef lbnCopy_16 +void +lbnCopy_16(BNWORD16 *dest, BNWORD16 const *src, unsigned len) +{ + memcpy(BIGLITTLE(dest-len,dest), BIGLITTLE(src-len,src), + len * sizeof(*src)); +} +#endif /* !lbnCopy_16 */ + +/* + * Fill n words with zero. This does it manually rather than calling + * memset because it can assume alignment to make things faster while + * memset can't. Note how big-endian numbers are naturally addressed + * using predecrement, while little-endian is postincrement. + */ +#ifndef lbnZero_16 +void +lbnZero_16(BNWORD16 *num, unsigned len) +{ + while (len--) + BIGLITTLE(*--num,*num++) = 0; +} +#endif /* !lbnZero_16 */ + +/* + * Negate an array of words. + * Negation is subtraction from zero. Negating low-order words + * entails doing nothing until a non-zero word is hit. Once that + * is negated, a borrow is generated and never dies until the end + * of the number is hit. Negation with borrow, -x-1, is the same as ~x. + * Repeat that until the end of the number. + * + * Doesn't return borrow out because that's pretty useless - it's + * always set unless the input is 0, which is easy to notice in + * normalized form. + */ +#ifndef lbnNeg_16 +void +lbnNeg_16(BNWORD16 *num, unsigned len) +{ + assert(len); + + /* Skip low-order zero words */ + while (BIGLITTLE(*--num,*num) == 0) { + if (!--len) + return; + LITTLE(num++;) + } + /* Negate the lowest-order non-zero word */ + *num = -*num; + /* Complement all the higher-order words */ + while (--len) { + BIGLITTLE(--num,++num); + *num = ~*num; + } +} +#endif /* !lbnNeg_16 */ + + +/* + * lbnAdd1_16: add the single-word "carry" to the given number. + * Used for minor increments and propagating the carry after + * adding in a shorter bignum. + * + * Technique: If we have a double-width word, presumably the compiler + * can add using its carry in inline code, so we just use a larger + * accumulator to compute the carry from the first addition. + * If not, it's more complex. After adding the first carry, which may + * be > 1, compare the sum and the carry. If the sum wraps (causing a + * carry out from the addition), the result will be less than each of the + * inputs, since the wrap subtracts a number (2^16) which is larger than + * the other input can possibly be. If the sum is >= the carry input, + * return success immediately. + * In either case, if there is a carry, enter a loop incrementing words + * until one does not wrap. Since we are adding 1 each time, the wrap + * will be to 0 and we can test for equality. + */ +#ifndef lbnAdd1_16 /* If defined, it's provided as an asm subroutine */ +#ifdef BNWORD32 +BNWORD16 +lbnAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry) +{ + BNWORD32 t; + assert(len > 0); /* Alternative: if (!len) return carry */ + + t = (BNWORD32)BIGLITTLE(*--num,*num) + carry; + BIGLITTLE(*num,*num++) = (BNWORD16)t; + if ((t >> 16) == 0) + return 0; + while (--len) { + if (++BIGLITTLE(*--num,*num++) != 0) + return 0; + } + return 1; +} +#else /* no BNWORD32 */ +BNWORD16 +lbnAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry) +{ + assert(len > 0); /* Alternative: if (!len) return carry */ + + if ((BIGLITTLE(*--num,*num++) += carry) >= carry) + return 0; + while (--len) { + if (++BIGLITTLE(*--num,*num++) != 0) + return 0; + } + return 1; +} +#endif +#endif/* !lbnAdd1_16 */ + +/* + * lbnSub1_16: subtract the single-word "borrow" from the given number. + * Used for minor decrements and propagating the borrow after + * subtracting a shorter bignum. + * + * Technique: Similar to the add, above. If there is a double-length type, + * use that to generate the first borrow. + * If not, after subtracting the first borrow, which may be > 1, compare + * the difference and the *negative* of the carry. If the subtract wraps + * (causing a borrow out from the subtraction), the result will be at least + * as large as -borrow. If the result < -borrow, then no borrow out has + * appeared and we may return immediately, except when borrow == 0. To + * deal with that case, use the identity that -x = ~x+1, and instead of + * comparing < -borrow, compare for <= ~borrow. + * Either way, if there is a borrow out, enter a loop decrementing words + * until a non-zero word is reached. + * + * Note the cast of ~borrow to (BNWORD16). If the size of an int is larger + * than BNWORD16, C rules say the number is expanded for the arithmetic, so + * the inversion will be done on an int and the value won't be quite what + * is expected. + */ +#ifndef lbnSub1_16 /* If defined, it's provided as an asm subroutine */ +#ifdef BNWORD32 +BNWORD16 +lbnSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow) +{ + BNWORD32 t; + assert(len > 0); /* Alternative: if (!len) return borrow */ + + t = (BNWORD32)BIGLITTLE(*--num,*num) - borrow; + BIGLITTLE(*num,*num++) = (BNWORD16)t; + if ((t >> 16) == 0) + return 0; + while (--len) { + if ((BIGLITTLE(*--num,*num++))-- != 0) + return 0; + } + return 1; +} +#else /* no BNWORD32 */ +BNWORD16 +lbnSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow) +{ + assert(len > 0); /* Alternative: if (!len) return borrow */ + + if ((BIGLITTLE(*--num,*num++) -= borrow) <= (BNWORD16)~borrow) + return 0; + while (--len) { + if ((BIGLITTLE(*--num,*num++))-- != 0) + return 0; + } + return 1; +} +#endif +#endif /* !lbnSub1_16 */ + +/* + * lbnAddN_16: add two bignums of the same length, returning the carry (0 or 1). + * One of the building blocks, along with lbnAdd1, of adding two bignums of + * differing lengths. + * + * Technique: Maintain a word of carry. If there is no double-width type, + * use the same technique as in lbnAdd1, above, to maintain the carry by + * comparing the inputs. Adding the carry sources is used as an OR operator; + * at most one of the two comparisons can possibly be true. The first can + * only be true if carry == 1 and x, the result, is 0. In that case the + * second can't possibly be true. + */ +#ifndef lbnAddN_16 +#ifdef BNWORD32 +BNWORD16 +lbnAddN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len) +{ + BNWORD32 t; + + assert(len > 0); + + t = (BNWORD32)BIGLITTLE(*--num1,*num1) + BIGLITTLE(*--num2,*num2++); + BIGLITTLE(*num1,*num1++) = (BNWORD16)t; + while (--len) { + t = (BNWORD32)BIGLITTLE(*--num1,*num1) + + (BNWORD32)BIGLITTLE(*--num2,*num2++) + (t >> 16); + BIGLITTLE(*num1,*num1++) = (BNWORD16)t; + } + + return (BNWORD16)(t>>16); +} +#else /* no BNWORD32 */ +BNWORD16 +lbnAddN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len) +{ + BNWORD16 x, carry = 0; + + assert(len > 0); /* Alternative: change loop to test at start */ + + do { + x = BIGLITTLE(*--num2,*num2++); + carry = (x += carry) < carry; + carry += (BIGLITTLE(*--num1,*num1++) += x) < x; + } while (--len); + + return carry; +} +#endif +#endif /* !lbnAddN_16 */ + +/* + * lbnSubN_16: add two bignums of the same length, returning the carry (0 or 1). + * One of the building blocks, along with subn1, of subtracting two bignums of + * differing lengths. + * + * Technique: If no double-width type is availble, maintain a word of borrow. + * First, add the borrow to the subtrahend (did you have to learn all those + * awful words in elementary school, too?), and if it overflows, set the + * borrow again. Then subtract the modified subtrahend from the next word + * of input, using the same technique as in subn1, above. + * Adding the borrows is used as an OR operator; at most one of the two + * comparisons can possibly be true. The first can only be true if + * borrow == 1 and x, the result, is 0. In that case the second can't + * possibly be true. + * + * In the double-word case, (BNWORD16)-(t>>16) is subtracted, rather than + * adding t>>16, because the shift would need to sign-extend and that's + * not guaranteed to happen in ANSI C, even with signed types. + */ +#ifndef lbnSubN_16 +#ifdef BNWORD32 +BNWORD16 +lbnSubN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len) +{ + BNWORD32 t; + + assert(len > 0); + + t = (BNWORD32)BIGLITTLE(*--num1,*num1) - BIGLITTLE(*--num2,*num2++); + BIGLITTLE(*num1,*num1++) = (BNWORD16)t; + + while (--len) { + t = (BNWORD32)BIGLITTLE(*--num1,*num1) - + (BNWORD32)BIGLITTLE(*--num2,*num2++) - (BNWORD16)-(t >> 16); + BIGLITTLE(*num1,*num1++) = (BNWORD16)t; + } + + return -(BNWORD16)(t>>16); +} +#else +BNWORD16 +lbnSubN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len) +{ + BNWORD16 x, borrow = 0; + + assert(len > 0); /* Alternative: change loop to test at start */ + + do { + x = BIGLITTLE(*--num2,*num2++); + borrow = (x += borrow) < borrow; + borrow += (BIGLITTLE(*--num1,*num1++) -= x) > (BNWORD16)~x; + } while (--len); + + return borrow; +} +#endif +#endif /* !lbnSubN_16 */ + +#ifndef lbnCmp_16 +/* + * lbnCmp_16: compare two bignums of equal length, returning the sign of + * num1 - num2. (-1, 0 or +1). + * + * Technique: Change the little-endian pointers to big-endian pointers + * and compare from the most-significant end until a difference if found. + * When it is, figure out the sign of the difference and return it. + */ +int +lbnCmp_16(BNWORD16 const *num1, BNWORD16 const *num2, unsigned len) +{ + BIGLITTLE(num1 -= len, num1 += len); + BIGLITTLE(num2 -= len, num2 += len); + + while (len--) { + if (BIGLITTLE(*num1++ != *num2++, *--num1 != *--num2)) { + if (BIGLITTLE(num1[-1] < num2[-1], *num1 < *num2)) + return -1; + else + return 1; + } + } + return 0; +} +#endif /* !lbnCmp_16 */ + +/* + * mul16_ppmmaa(ph,pl,x,y,a,b) is an optional routine that + * computes (ph,pl) = x * y + a + b. mul16_ppmma and mul16_ppmm + * are simpler versions. If you want to be lazy, all of these + * can be defined in terms of the others, so here we create any + * that have not been defined in terms of the ones that have been. + */ + +/* Define ones with fewer a's in terms of ones with more a's */ +#if !defined(mul16_ppmma) && defined(mul16_ppmmaa) +#define mul16_ppmma(ph,pl,x,y,a) mul16_ppmmaa(ph,pl,x,y,a,0) +#endif + +#if !defined(mul16_ppmm) && defined(mul16_ppmma) +#define mul16_ppmm(ph,pl,x,y) mul16_ppmma(ph,pl,x,y,0) +#endif + +/* + * Use this definition to test the mul16_ppmm-based operations on machines + * that do not provide mul16_ppmm. Change the final "0" to a "1" to + * enable it. + */ +#if !defined(mul16_ppmm) && defined(BNWORD32) && 0 /* Debugging */ +#define mul16_ppmm(ph,pl,x,y) \ + ({BNWORD32 _ = (BNWORD32)(x)*(y); (pl) = _; (ph) = _>>16;}) +#endif + +#if defined(mul16_ppmm) && !defined(mul16_ppmma) +#define mul16_ppmma(ph,pl,x,y,a) \ + (mul16_ppmm(ph,pl,x,y), (ph) += ((pl) += (a)) < (a)) +#endif + +#if defined(mul16_ppmma) && !defined(mul16_ppmmaa) +#define mul16_ppmmaa(ph,pl,x,y,a,b) \ + (mul16_ppmma(ph,pl,x,y,a), (ph) += ((pl) += (b)) < (b)) +#endif + +/* + * lbnMulN1_16: Multiply an n-word input by a 1-word input and store the + * n+1-word product. This uses either the mul16_ppmm and mul16_ppmma + * macros, or C multiplication with the BNWORD32 type. This uses mul16_ppmma + * if available, assuming you won't bother defining it unless you can do + * better than the normal multiplication. + */ +#ifndef lbnMulN1_16 +#ifdef lbnMulAdd1_16 /* If we have this asm primitive, use it. */ +void +lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + lbnZero_16(out, len); + BIGLITTLE(*(out-len),*(out+len)) = lbnMulAdd1_16(out, in, len, k); +} +#elif defined(mul16_ppmm) +void +lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + BNWORD16 prod, carry, carryin; + + assert(len > 0); + + BIG(--out;--in;); + mul16_ppmm(carry, *out, *in, k); + LITTLE(out++;in++;) + + while (--len) { + BIG(--out;--in;) + carryin = carry; + mul16_ppmma(carry, *out, *in, k, carryin); + LITTLE(out++;in++;) + } + BIGLITTLE(*--out,*out) = carry; +} +#elif defined(BNWORD32) +void +lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + BNWORD32 p; + + assert(len > 0); + + p = (BNWORD32)BIGLITTLE(*--in,*in++) * k; + BIGLITTLE(*--out,*out++) = (BNWORD16)p; + + while (--len) { + p = (BNWORD32)BIGLITTLE(*--in,*in++) * k + (BNWORD16)(p >> 16); + BIGLITTLE(*--out,*out++) = (BNWORD16)p; + } + BIGLITTLE(*--out,*out) = (BNWORD16)(p >> 16); +} +#else +#error No 16x16 -> 32 multiply available for 16-bit bignum package +#endif +#endif /* lbnMulN1_16 */ + +/* + * lbnMulAdd1_16: Multiply an n-word input by a 1-word input and add the + * low n words of the product to the destination. *Returns the n+1st word + * of the product.* (That turns out to be more convenient than adding + * it into the destination and dealing with a possible unit carry out + * of *that*.) This uses either the mul16_ppmma and mul16_ppmmaa macros, + * or C multiplication with the BNWORD32 type. + * + * If you're going to write assembly primitives, this is the one to + * start with. It is by far the most commonly called function. + */ +#ifndef lbnMulAdd1_16 +#if defined(mul16_ppmm) +BNWORD16 +lbnMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + BNWORD16 prod, carry, carryin; + + assert(len > 0); + + BIG(--out;--in;); + carryin = *out; + mul16_ppmma(carry, *out, *in, k, carryin); + LITTLE(out++;in++;) + + while (--len) { + BIG(--out;--in;); + carryin = carry; + mul16_ppmmaa(carry, prod, *in, k, carryin, *out); + *out = prod; + LITTLE(out++;in++;) + } + + return carry; +} +#elif defined(BNWORD32) +BNWORD16 +lbnMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + BNWORD32 p; + + assert(len > 0); + + p = (BNWORD32)BIGLITTLE(*--in,*in++) * k + BIGLITTLE(*--out,*out); + BIGLITTLE(*out,*out++) = (BNWORD16)p; + + while (--len) { + p = (BNWORD32)BIGLITTLE(*--in,*in++) * k + + (BNWORD16)(p >> 16) + BIGLITTLE(*--out,*out); + BIGLITTLE(*out,*out++) = (BNWORD16)p; + } + + return (BNWORD16)(p >> 16); +} +#else +#error No 16x16 -> 32 multiply available for 16-bit bignum package +#endif +#endif /* lbnMulAdd1_16 */ + +/* + * lbnMulSub1_16: Multiply an n-word input by a 1-word input and subtract the + * n-word product from the destination. Returns the n+1st word of the product. + * This uses either the mul16_ppmm and mul16_ppmma macros, or + * C multiplication with the BNWORD32 type. + * + * This is rather uglier than adding, but fortunately it's only used in + * division which is not used too heavily. + */ +#ifndef lbnMulN1_16 +#if defined(mul16_ppmm) +BNWORD16 +lbnMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + BNWORD16 prod, carry, carryin; + + assert(len > 0); + + BIG(--in;) + mul16_ppmm(carry, prod, *in, k); + LITTLE(in++;) + carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD16)~prod; + + while (--len) { + BIG(--in;); + carryin = carry; + mul16_ppmma(carry, prod, *in, k, carryin); + LITTLE(in++;) + carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD16)~prod; + } + + return carry; +} +#elif defined(BNWORD32) +BNWORD16 +lbnMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + BNWORD32 p; + BNWORD16 carry, t; + + assert(len > 0); + + p = (BNWORD32)BIGLITTLE(*--in,*in++) * k; + t = BIGLITTLE(*--out,*out); + carry = (BNWORD16)(p>>16) + ((BIGLITTLE(*out,*out++)=t-(BNWORD16)p) > t); + + while (--len) { + p = (BNWORD32)BIGLITTLE(*--in,*in++) * k + carry; + t = BIGLITTLE(*--out,*out); + carry = (BNWORD16)(p>>16) + + ( (BIGLITTLE(*out,*out++)=t-(BNWORD16)p) > t ); + } + + return carry; +} +#else +#error No 16x16 -> 32 multiply available for 16-bit bignum package +#endif +#endif /* !lbnMulSub1_16 */ + +/* + * Shift n words left "shift" bits. 0 < shift < 16. Returns the + * carry, any bits shifted off the left-hand side (0 <= carry < 2^shift). + */ +#ifndef lbnLshift_16 +BNWORD16 +lbnLshift_16(BNWORD16 *num, unsigned len, unsigned shift) +{ + BNWORD16 x, carry; + + assert(shift > 0); + assert(shift < 16); + + carry = 0; + while (len--) { + BIG(--num;) + x = *num; + *num = (x<> (16-shift); + } + return carry; +} +#endif /* !lbnLshift_16 */ + +/* + * An optimized version of the above, for shifts of 1. + * Some machines can use add-with-carry tricks for this. + */ +#ifndef lbnDouble_16 +BNWORD16 +lbnDouble_16(BNWORD16 *num, unsigned len) +{ + BNWORD16 x, carry; + + carry = 0; + while (len--) { + BIG(--num;) + x = *num; + *num = (x<<1) | carry; + LITTLE(num++;) + carry = x >> (16-1); + } + return carry; +} +#endif /* !lbnDouble_16 */ + +/* + * Shift n words right "shift" bits. 0 < shift < 16. Returns the + * carry, any bits shifted off the right-hand side (0 <= carry < 2^shift). + */ +#ifndef lbnRshift_16 +BNWORD16 +lbnRshift_16(BNWORD16 *num, unsigned len, unsigned shift) +{ + BNWORD16 x, carry = 0; + + assert(shift > 0); + assert(shift < 16); + + BIGLITTLE(num -= len, num += len); + + while (len--) { + LITTLE(--num;) + x = *num; + *num = (x>>shift) | carry; + BIG(num++;) + carry = x << (16-shift); + } + return carry >> (16-shift); +} +#endif /* !lbnRshift_16 */ + +/* + * Multiply two numbers of the given lengths. prod and num2 may overlap, + * provided that the low len1 bits of prod are free. (This corresponds + * nicely to the place the result is returned from lbnMontReduce_16.) + * + * TODO: Use Karatsuba multiply. The overlap constraints may have + * to get rewhacked. + */ +#ifndef lbnMul_16 +void +lbnMul_16(BNWORD16 *prod, BNWORD16 const *num1, unsigned len1, + BNWORD16 const *num2, unsigned len2) +{ + /* Special case of zero */ + if (!len1 || !len2) { + lbnZero_16(prod, len1+len2); + return; + } + + /* Multiply first word */ + lbnMulN1_16(prod, num1, len1, BIGLITTLE(*--num2,*num2++)); + + /* + * Add in subsequent words, storing the most significant word, + * which is new each time. + */ + while (--len2) { + BIGLITTLE(--prod,prod++); + BIGLITTLE(*(prod-len1-1),*(prod+len1)) = + lbnMulAdd1_16(prod, num1, len1, BIGLITTLE(*--num2,*num2++)); + } +} +#endif /* !lbnMul_16 */ + +/* + * lbnMulX_16 is a square multiply - both inputs are the same length. + * It's normally just a macro wrapper around the general multiply, + * but might be implementable in assembly more efficiently (such as + * when product scanning). + */ +#ifndef lbnMulX_16 +#if defined(BNWORD32) && PRODUCT_SCAN +/* + * Test code to see whether product scanning is any faster. It seems + * to make the C code slower, so PRODUCT_SCAN is not defined. + */ +static void +lbnMulX_16(BNWORD16 *prod, BNWORD16 const *num1, BNWORD16 const *num2, + unsigned len) +{ + BNWORD32 x, y; + BNWORD16 const *p1, *p2; + unsigned carry; + unsigned i, j; + + /* Special case of zero */ + if (!len) + return; + + x = (BNWORD32)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]); + BIGLITTLE(*--prod, *prod++) = (BNWORD16)x; + x >>= 16; + + for (i = 1; i < len; i++) { + carry = 0; + p1 = num1; + p2 = BIGLITTLE(num2-i-1,num2+i+1); + for (j = 0; j <= i; j++) { + BIG(y = (BNWORD32)*--p1 * *p2++;) + LITTLE(y = (BNWORD32)*p1++ * *--p2;) + x += y; + carry += (x < y); + } + BIGLITTLE(*--prod,*prod++) = (BNWORD16)x; + x = (x >> 16) | (BNWORD32)carry << 16; + } + for (i = 1; i < len; i++) { + carry = 0; + p1 = BIGLITTLE(num1-i,num1+i); + p2 = BIGLITTLE(num2-len,num2+len); + for (j = i; j < len; j++) { + BIG(y = (BNWORD32)*--p1 * *p2++;) + LITTLE(y = (BNWORD32)*p1++ * *--p2;) + x += y; + carry += (x < y); + } + BIGLITTLE(*--prod,*prod++) = (BNWORD16)x; + x = (x >> 16) | (BNWORD32)carry << 16; + } + + BIGLITTLE(*--prod,*prod) = (BNWORD16)x; +} +#else /* !defined(BNWORD32) || !PRODUCT_SCAN */ +/* Default trivial macro definition */ +#define lbnMulX_16(prod, num1, num2, len) lbnMul_16(prod, num1, len, num2, len) +#endif /* !defined(BNWORD32) || !PRODUCT_SCAN */ +#endif /* !lbmMulX_16 */ + +#if !defined(lbnMontMul_16) && defined(BNWORD32) && PRODUCT_SCAN +/* + * Test code for product-scanning multiply. This seems to slow the C + * code down rather than speed it up. + * This does a multiply and Montgomery reduction together, using the + * same loops. The outer loop scans across the product, twice. + * The first pass computes the low half of the product and the + * Montgomery multipliers. These are stored in the product array, + * which contains no data as of yet. x and carry add up the columns + * and propagate carries forward. + * + * The second half multiplies the upper half, adding in the modulus + * times the Montgomery multipliers. The results of this multiply + * are stored. + */ +static void +lbnMontMul_16(BNWORD16 *prod, BNWORD16 const *num1, BNWORD16 const *num2, + BNWORD16 const *mod, unsigned len, BNWORD16 inv) +{ + BNWORD32 x, y; + BNWORD16 const *p1, *p2, *pm; + BNWORD16 *pp; + BNWORD16 t; + unsigned carry; + unsigned i, j; + + /* Special case of zero */ + if (!len) + return; + + /* + * This computes directly into the high half of prod, so just + * shift the pointer and consider prod only "len" elements long + * for the rest of the code. + */ + BIGLITTLE(prod -= len, prod += len); + + /* Pass 1 - compute Montgomery multipliers */ + /* First iteration can have certain simplifications. */ + x = (BNWORD32)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]); + BIGLITTLE(prod[-1], prod[0]) = t = inv * (BNWORD16)x; + y = (BNWORD32)t * BIGLITTLE(mod[-1],mod[0]); + x += y; + /* Note: GCC 2.6.3 has a bug if you try to eliminate "carry" */ + carry = (x < y); + assert((BNWORD16)x == 0); + x = x >> 16 | (BNWORD32)carry << 16; + + for (i = 1; i < len; i++) { + carry = 0; + p1 = num1; + p2 = BIGLITTLE(num2-i-1,num2+i+1); + pp = prod; + pm = BIGLITTLE(mod-i-1,mod+i+1); + for (j = 0; j < i; j++) { + y = (BNWORD32)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2); + x += y; + carry += (x < y); + y = (BNWORD32)BIGLITTLE(*--pp * *pm++, *pp++ * *--pm); + x += y; + carry += (x < y); + } + y = (BNWORD32)BIGLITTLE(p1[-1] * p2[0], p1[0] * p2[-1]); + x += y; + carry += (x < y); + assert(BIGLITTLE(pp == prod-i, pp == prod+i)); + BIGLITTLE(pp[-1], pp[0]) = t = inv * (BNWORD16)x; + assert(BIGLITTLE(pm == mod-1, pm == mod+1)); + y = (BNWORD32)t * BIGLITTLE(pm[0],pm[-1]); + x += y; + carry += (x < y); + assert((BNWORD16)x == 0); + x = x >> 16 | (BNWORD32)carry << 16; + } + + /* Pass 2 - compute reduced product and store */ + for (i = 1; i < len; i++) { + carry = 0; + p1 = BIGLITTLE(num1-i,num1+i); + p2 = BIGLITTLE(num2-len,num2+len); + pm = BIGLITTLE(mod-i,mod+i); + pp = BIGLITTLE(prod-len,prod+len); + for (j = i; j < len; j++) { + y = (BNWORD32)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2); + x += y; + carry += (x < y); + y = (BNWORD32)BIGLITTLE(*--pm * *pp++, *pm++ * *--pp); + x += y; + carry += (x < y); + } + assert(BIGLITTLE(pm == mod-len, pm == mod+len)); + assert(BIGLITTLE(pp == prod-i, pp == prod+i)); + BIGLITTLE(pp[0],pp[-1]) = (BNWORD16)x; + x = (x >> 16) | (BNWORD32)carry << 16; + } + + /* Last round of second half, simplified. */ + BIGLITTLE(*(prod-len),*(prod+len-1)) = (BNWORD16)x; + carry = (x >> 16); + + while (carry) + carry -= lbnSubN_16(prod, mod, len); + while (lbnCmp_16(prod, mod, len) >= 0) + (void)lbnSubN_16(prod, mod, len); +} +/* Suppress later definition */ +#define lbnMontMul_16 lbnMontMul_16 +#endif + +#if !defined(lbnSquare_16) && defined(BNWORD32) && PRODUCT_SCAN +/* + * Trial code for product-scanning squaring. This seems to slow the C + * code down rather than speed it up. + */ +void +lbnSquare_16(BNWORD16 *prod, BNWORD16 const *num, unsigned len) +{ + BNWORD32 x, y, z; + BNWORD16 const *p1, *p2; + unsigned carry; + unsigned i, j; + + /* Special case of zero */ + if (!len) + return; + + /* Word 0 of product */ + x = (BNWORD32)BIGLITTLE(num[-1] * num[-1], num[0] * num[0]); + BIGLITTLE(*--prod, *prod++) = (BNWORD16)x; + x >>= 16; + + /* Words 1 through len-1 */ + for (i = 1; i < len; i++) { + carry = 0; + y = 0; + p1 = num; + p2 = BIGLITTLE(num-i-1,num+i+1); + for (j = 0; j < (i+1)/2; j++) { + BIG(z = (BNWORD32)*--p1 * *p2++;) + LITTLE(z = (BNWORD32)*p1++ * *--p2;) + y += z; + carry += (y < z); + } + y += z = y; + carry += carry + (y < z); + if ((i & 1) == 0) { + assert(BIGLITTLE(--p1 == p2, p1 == --p2)); + BIG(z = (BNWORD32)*p2 * *p2;) + LITTLE(z = (BNWORD32)*p1 * *p1;) + y += z; + carry += (y < z); + } + x += y; + carry += (x < y); + BIGLITTLE(*--prod,*prod++) = (BNWORD16)x; + x = (x >> 16) | (BNWORD32)carry << 16; + } + /* Words len through 2*len-2 */ + for (i = 1; i < len; i++) { + carry = 0; + y = 0; + p1 = BIGLITTLE(num-i,num+i); + p2 = BIGLITTLE(num-len,num+len); + for (j = 0; j < (len-i)/2; j++) { + BIG(z = (BNWORD32)*--p1 * *p2++;) + LITTLE(z = (BNWORD32)*p1++ * *--p2;) + y += z; + carry += (y < z); + } + y += z = y; + carry += carry + (y < z); + if ((len-i) & 1) { + assert(BIGLITTLE(--p1 == p2, p1 == --p2)); + BIG(z = (BNWORD32)*p2 * *p2;) + LITTLE(z = (BNWORD32)*p1 * *p1;) + y += z; + carry += (y < z); + } + x += y; + carry += (x < y); + BIGLITTLE(*--prod,*prod++) = (BNWORD16)x; + x = (x >> 16) | (BNWORD32)carry << 16; + } + + /* Word 2*len-1 */ + BIGLITTLE(*--prod,*prod) = (BNWORD16)x; +} +/* Suppress later definition */ +#define lbnSquare_16 lbnSquare_16 +#endif + +/* + * Square a number, using optimized squaring to reduce the number of + * primitive multiples that are executed. There may not be any + * overlap of the input and output. + * + * Technique: Consider the partial products in the multiplication + * of "abcde" by itself: + * + * a b c d e + * * a b c d e + * ================== + * ae be ce de ee + * ad bd cd dd de + * ac bc cc cd ce + * ab bb bc bd be + * aa ab ac ad ae + * + * Note that everything above the main diagonal: + * ae be ce de = (abcd) * e + * ad bd cd = (abc) * d + * ac bc = (ab) * c + * ab = (a) * b + * + * is a copy of everything below the main diagonal: + * de + * cd ce + * bc bd be + * ab ac ad ae + * + * Thus, the sum is 2 * (off the diagonal) + diagonal. + * + * This is accumulated beginning with the diagonal (which + * consist of the squares of the digits of the input), which is then + * divided by two, the off-diagonal added, and multiplied by two + * again. The low bit is simply a copy of the low bit of the + * input, so it doesn't need special care. + * + * TODO: Merge the shift by 1 with the squaring loop. + * TODO: Use Karatsuba. (a*W+b)^2 = a^2 * (W^2+W) + b^2 * (W+1) - (a-b)^2 * W. + */ +#ifndef lbnSquare_16 +void +lbnSquare_16(BNWORD16 *prod, BNWORD16 const *num, unsigned len) +{ + BNWORD16 t; + BNWORD16 *prodx = prod; /* Working copy of the argument */ + BNWORD16 const *numx = num; /* Working copy of the argument */ + unsigned lenx = len; /* Working copy of the argument */ + + if (!len) + return; + + /* First, store all the squares */ + while (lenx--) { +#ifdef mul16_ppmm + BNWORD16 ph, pl; + t = BIGLITTLE(*--numx,*numx++); + mul16_ppmm(ph,pl,t,t); + BIGLITTLE(*--prodx,*prodx++) = pl; + BIGLITTLE(*--prodx,*prodx++) = ph; +#elif defined(BNWORD32) /* use BNWORD32 */ + BNWORD32 p; + t = BIGLITTLE(*--numx,*numx++); + p = (BNWORD32)t * t; + BIGLITTLE(*--prodx,*prodx++) = (BNWORD16)p; + BIGLITTLE(*--prodx,*prodx++) = (BNWORD16)(p>>16); +#else /* Use lbnMulN1_16 */ + t = BIGLITTLE(numx[-1],*numx); + lbnMulN1_16(prodx, numx, 1, t); + BIGLITTLE(--numx,numx++); + BIGLITTLE(prodx -= 2, prodx += 2); +#endif + } + /* Then, shift right 1 bit */ + (void)lbnRshift_16(prod, 2*len, 1); + + /* Then, add in the off-diagonal sums */ + lenx = len; + numx = num; + prodx = prod; + while (--lenx) { + t = BIGLITTLE(*--numx,*numx++); + BIGLITTLE(--prodx,prodx++); + t = lbnMulAdd1_16(prodx, numx, lenx, t); + lbnAdd1_16(BIGLITTLE(prodx-lenx,prodx+lenx), lenx+1, t); + BIGLITTLE(--prodx,prodx++); + } + + /* Shift it back up */ + lbnDouble_16(prod, 2*len); + + /* And set the low bit appropriately */ + BIGLITTLE(prod[-1],prod[0]) |= BIGLITTLE(num[-1],num[0]) & 1; +} +#endif /* !lbnSquare_16 */ + +/* + * lbnNorm_16 - given a number, return a modified length such that the + * most significant digit is non-zero. Zero-length input is okay. + */ +#ifndef lbnNorm_16 +unsigned +lbnNorm_16(BNWORD16 const *num, unsigned len) +{ + BIGLITTLE(num -= len,num += len); + while (len && BIGLITTLE(*num++,*--num) == 0) + --len; + return len; +} +#endif /* lbnNorm_16 */ + +/* + * lbnBits_16 - return the number of significant bits in the array. + * It starts by normalizing the array. Zero-length input is okay. + * Then assuming there's anything to it, it fetches the high word, + * generates a bit length by multiplying the word length by 16, and + * subtracts off 16/2, 16/4, 16/8, ... bits if the high bits are clear. + */ +#ifndef lbnBits_16 +unsigned +lbnBits_16(BNWORD16 const *num, unsigned len) +{ + BNWORD16 t; + unsigned i; + + len = lbnNorm_16(num, len); + if (len) { + t = BIGLITTLE(*(num-len),*(num+(len-1))); + assert(t); + len *= 16; + i = 16/2; + do { + if (t >> i) + t >>= i; + else + len -= i; + } while ((i /= 2) != 0); + } + return len; +} +#endif /* lbnBits_16 */ + +/* + * If defined, use hand-rolled divide rather than compiler's native. + * If the machine doesn't do it in line, the manual code is probably + * faster, since it can assume normalization and the fact that the + * quotient will fit into 16 bits, which a general 32-bit divide + * in a compiler's run-time library can't do. + */ +#ifndef BN_SLOW_DIVIDE_32 +/* Assume that divisors of more than thirty-two bits are slow */ +#define BN_SLOW_DIVIDE_32 (32 > 0x20) +#endif + +/* + * Return (nh<<16|nl) % d, and place the quotient digit into *q. + * It is guaranteed that nh < d, and that d is normalized (with its high + * bit set). If we have a double-width type, it's easy. If not, ooh, + * yuk! + */ +#ifndef lbnDiv21_16 +#if defined(BNWORD32) && !BN_SLOW_DIVIDE_32 +BNWORD16 +lbnDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d) +{ + BNWORD32 n = (BNWORD32)nh << 16 | nl; + + /* Divisor must be normalized */ + assert(d >> (16-1) == 1); + + *q = (BNWORD16)(n / d); + return (BNWORD16)(n % d); +} +#else +/* + * This is where it gets ugly. + * + * Do the division in two halves, using Algorithm D from section 4.3.1 + * of Knuth. Note Theorem B from that section, that the quotient estimate + * is never more than the true quotient, and is never more than two + * too low. + * + * The mapping onto conventional long division is (everything a half word): + * _____________qh___ql_ + * dh dl ) nh.h nh.l nl.h nl.l + * - (qh * d) + * ----------- + * rrrr rrrr nl.l + * - (ql * d) + * ----------- + * rrrr rrrr + * + * The implicit 3/2-digit d*qh and d*ql subtractors are computed this way: + * First, estimate a q digit so that nh/dh works. Subtracting qh*dh from + * the (nh.h nh.l) list leaves a 1/2-word remainder r. Then compute the + * low part of the subtractor, qh * dl. This also needs to be subtracted + * from (nh.h nh.l nl.h) to get the final remainder. So we take the + * remainder, which is (nh.h nh.l) - qh*dl, shift it and add in nl.h, and + * try to subtract qh * dl from that. Since the remainder is 1/2-word + * long, shifting and adding nl.h results in a single word r. + * It is possible that the remainder we're working with, r, is less than + * the product qh * dl, if we estimated qh too high. The estimation + * technique can produce a qh that is too large (never too small), leading + * to r which is too small. In that case, decrement the digit qh, add + * shifted dh to r (to correct for that error), and subtract dl from the + * product we're comparing r with. That's the "correct" way to do it, but + * just adding dl to r instead of subtracting it from the product is + * equivalent and a lot simpler. You just have to watch out for overflow. + * + * The process is repeated with (rrrr rrrr nl.l) for the low digit of the + * quotient ql. + * + * The various uses of 16/2 for shifts are because of the note about + * automatic editing of this file at the very top of the file. + */ +#define highhalf(x) ( (x) >> 16/2 ) +#define lowhalf(x) ( (x) & (((BNWORD16)1 << 16/2)-1) ) +BNWORD16 +lbnDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d) +{ + BNWORD16 dh = highhalf(d), dl = lowhalf(d); + BNWORD16 qh, ql, prod, r; + + /* Divisor must be normalized */ + assert((d >> (16-1)) == 1); + + /* Do first half-word of division */ + qh = nh / dh; + r = nh % dh; + prod = qh * dl; + + /* + * Add next half-word of numerator to remainder and correct. + * qh may be up to two too large. + */ + r = (r << (16/2)) | highhalf(nl); + if (r < prod) { + --qh; r += d; + if (r >= d && r < prod) { + --qh; r += d; + } + } + r -= prod; + + /* Do second half-word of division */ + ql = r / dh; + r = r % dh; + prod = ql * dl; + + r = (r << (16/2)) | lowhalf(nl); + if (r < prod) { + --ql; r += d; + if (r >= d && r < prod) { + --ql; r += d; + } + } + r -= prod; + + *q = (qh << (16/2)) | ql; + + return r; +} +#endif +#endif /* lbnDiv21_16 */ + + +/* + * In the division functions, the dividend and divisor are referred to + * as "n" and "d", which stand for "numerator" and "denominator". + * + * The quotient is (nlen-dlen+1) digits long. It may be overlapped with + * the high (nlen-dlen) words of the dividend, but one extra word is needed + * on top to hold the top word. + */ + +/* + * Divide an n-word number by a 1-word number, storing the remainder + * and n-1 words of the n-word quotient. The high word is returned. + * It IS legal for rem to point to the same address as n, and for + * q to point one word higher. + * + * TODO: If BN_SLOW_DIVIDE_32, add a divnhalf_16 which uses 16-bit + * dividends if the divisor is half that long. + * TODO: Shift the dividend on the fly to avoid the last division and + * instead have a remainder that needs shifting. + * TODO: Use reciprocals rather than dividing. + */ +#ifndef lbnDiv1_16 +BNWORD16 +lbnDiv1_16(BNWORD16 *q, BNWORD16 *rem, BNWORD16 const *n, unsigned len, + BNWORD16 d) +{ + unsigned shift; + unsigned xlen; + BNWORD16 r; + BNWORD16 qhigh; + + assert(len > 0); + assert(d); + + if (len == 1) { + r = *n; + *rem = r%d; + return r/d; + } + + shift = 0; + r = d; + xlen = 16/2; + do { + if (r >> xlen) + r >>= xlen; + else + shift += xlen; + } while ((xlen /= 2) != 0); + assert((d >> (16-1-shift)) == 1); + d <<= shift; + + BIGLITTLE(q -= len-1,q += len-1); + BIGLITTLE(n -= len,n += len); + + r = BIGLITTLE(*n++,*--n); + if (r < d) { + qhigh = 0; + } else { + qhigh = r/d; + r %= d; + } + + xlen = len; + while (--xlen) + r = lbnDiv21_16(BIGLITTLE(q++,--q), r, BIGLITTLE(*n++,*--n), d); + + /* + * Final correction for shift - shift the quotient up "shift" + * bits, and merge in the extra bits of quotient. Then reduce + * the final remainder mod the real d. + */ + if (shift) { + d >>= shift; + qhigh = (qhigh << shift) | lbnLshift_16(q, len-1, shift); + BIGLITTLE(q[-1],*q) |= r/d; + r %= d; + } + *rem = r; + + return qhigh; +} +#endif + +/* + * This function performs a "quick" modulus of a number with a divisor + * d which is guaranteed to be at most sixteen bits, i.e. less than 65536. + * This applies regardless of the word size the library is compiled with. + * + * This function is important to prime generation, for sieving. + */ +#ifndef lbnModQ_16 +/* If there's a custom lbnMod21_16, no normalization needed */ +#ifdef lbnMod21_16 +unsigned +lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d) +{ + unsigned i, shift; + BNWORD16 r; + + assert(len > 0); + + BIGLITTLE(n -= len,n += len); + + /* Try using a compare to avoid the first divide */ + r = BIGLITTLE(*n++,*--n); + if (r >= d) + r %= d; + while (--len) + r = lbnMod21_16(r, BIGLITTLE(*n++,*--n), d); + + return r; +} +#elif defined(BNWORD32) && !BN_SLOW_DIVIDE_32 +unsigned +lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d) +{ + BNWORD16 r; + + if (!--len) + return BIGLITTLE(n[-1],n[0]) % d; + + BIGLITTLE(n -= len,n += len); + r = BIGLITTLE(n[-1],n[0]); + + do { + r = (BNWORD16)((((BNWORD32)r<<16) | BIGLITTLE(*n++,*--n)) % d); + } while (--len); + + return r; +} +#elif 16 >= 0x20 +/* + * If the single word size can hold 65535*65536, then this function + * is avilable. + */ +#ifndef highhalf +#define highhalf(x) ( (x) >> 16/2 ) +#define lowhalf(x) ( (x) & ((1 << 16/2)-1) ) +#endif +unsigned +lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d) +{ + BNWORD16 r, x; + + BIGLITTLE(n -= len,n += len); + + r = BIGLITTLE(*n++,*--n); + while (--len) { + x = BIGLITTLE(*n++,*--n); + r = (r%d << 16/2) | highhalf(x); + r = (r%d << 16/2) | lowhalf(x); + } + + return r%d; +} +#else +/* Default case - use lbnDiv21_16 */ +unsigned +lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d) +{ + unsigned i, shift; + BNWORD16 r; + BNWORD16 q; + + assert(len > 0); + + shift = 0; + r = d; + i = 16; + while (i /= 2) { + if (r >> i) + r >>= i; + else + shift += i; + } + assert(d >> (16-1-shift) == 1); + d <<= shift; + + BIGLITTLE(n -= len,n += len); + + r = BIGLITTLE(*n++,*--n); + if (r >= d) + r %= d; + + while (--len) + r = lbnDiv21_16(&q, r, BIGLITTLE(*n++,*--n), d); + + /* + * Final correction for shift - shift the quotient up "shift" + * bits, and merge in the extra bits of quotient. Then reduce + * the final remainder mod the real d. + */ + if (shift) + r %= d >> shift; + + return r; +} +#endif +#endif /* lbnModQ_16 */ + +/* + * Reduce n mod d and return the quotient. That is, find: + * q = n / d; + * n = n % d; + * d is altered during the execution of this subroutine by normalizing it. + * It must already have its most significant word non-zero; it is shifted + * so its most significant bit is non-zero. + * + * The quotient q is nlen-dlen+1 words long. To make it possible to + * overlap the quptient with the input (you can store it in the high dlen + * words), the high word of the quotient is *not* stored, but is returned. + * (If all you want is the remainder, you don't care about it, anyway.) + * + * This uses algorithm D from Knuth (4.3.1), except that we do binary + * (shift) normalization of the divisor. WARNING: This is hairy! + * + * This function is used for some modular reduction, but it is not used in + * the modular exponentiation loops; they use Montgomery form and the + * corresponding, more efficient, Montgomery reduction. This code + * is needed for the conversion to Montgomery form, however, so it + * has to be here and it might as well be reasonably efficient. + * + * The overall operation is as follows ("top" and "up" refer to the + * most significant end of the number; "bottom" and "down", the least): + * + * - Shift the divisor up until the most significant bit is set. + * - Shift the dividend up the same amount. This will produce the + * correct quotient, and the remainder can be recovered by shifting + * it back down the same number of bits. This may produce an overflow + * word, but the word is always strictly less than the most significant + * divisor word. + * - Estimate the first quotient digit qhat: + * - First take the top two words (one of which is the overflow) of the + * dividend and divide by the top word of the divisor: + * qhat = (nh,nm)/dh. This qhat is >= the correct quotient digit + * and, since dh is normalized, it is at most two over. + * - Second, correct by comparing the top three words. If + * (dh,dl) * qhat > (nh,nm,ml), decrease qhat and try again. + * The second iteration can be simpler because there can't be a third. + * The computation can be simplified by subtracting dh*qhat from + * both sides, suitably shifted. This reduces the left side to + * dl*qhat. On the right, (nh,nm)-dh*qhat is simply the + * remainder r from (nh,nm)%dh, so the right is (r,nl). + * This produces qhat that is almost always correct and at + * most (prob ~ 2/2^16) one too high. + * - Subtract qhat times the divisor (suitably shifted) from the dividend. + * If there is a borrow, qhat was wrong, so decrement it + * and add the divisor back in (once). + * - Store the final quotient digit qhat in the quotient array q. + * + * Repeat the quotient digit computation for successive digits of the + * quotient until the whole quotient has been computed. Then shift the + * divisor and the remainder down to correct for the normalization. + * + * TODO: Special case 2-word divisors. + * TODO: Use reciprocals rather than dividing. + */ +#ifndef divn_16 +BNWORD16 +lbnDiv_16(BNWORD16 *q, BNWORD16 *n, unsigned nlen, BNWORD16 *d, unsigned dlen) +{ + BNWORD16 nh,nm,nl; /* Top three words of the dividend */ + BNWORD16 dh,dl; /* Top two words of the divisor */ + BNWORD16 qhat; /* Extimate of quotient word */ + BNWORD16 r; /* Remainder from quotient estimate division */ + BNWORD16 qhigh; /* High word of quotient */ + unsigned i; /* Temp */ + unsigned shift; /* Bits shifted by normalization */ + unsigned qlen = nlen-dlen; /* Size of quotient (less 1) */ +#ifdef mul16_ppmm + BNWORD16 t16; +#elif defined(BNWORD32) + BNWORD32 t32; +#else /* use lbnMulN1_16 */ + BNWORD16 t2[2]; +#define t2high BIGLITTLE(t2[0],t2[1]) +#define t2low BIGLITTLE(t2[1],t2[0]) +#endif + + assert(dlen); + assert(nlen >= dlen); + + /* + * Special cases for short divisors. The general case uses the + * top top 2 digits of the divisor (d) to estimate a quotient digit, + * so it breaks if there are fewer digits available. Thus, we need + * special cases for a divisor of length 1. A divisor of length + * 2 can have a *lot* of administrivia overhead removed removed, + * so it's probably worth special-casing that case, too. + */ + if (dlen == 1) + return lbnDiv1_16(q, BIGLITTLE(n-1,n), n, nlen, + BIGLITTLE(d[-1],d[0])); + +#if 0 + /* + * @@@ This is not yet written... The general loop will do, + * albeit less efficiently + */ + if (dlen == 2) { + /* + * divisor two digits long: + * use the 3/2 technique from Knuth, but we know + * it's exact. + */ + dh = BIGLITTLE(d[-1],d[0]); + dl = BIGLITTLE(d[-2],d[1]); + shift = 0; + if ((sh & ((BNWORD16)1 << 16-1-shift)) == 0) { + do { + shift++; + } while (dh & (BNWORD16)1<<16-1-shift) == 0); + dh = dh << shift | dl >> (16-shift); + dl <<= shift; + + + } + + + for (shift = 0; (dh & (BNWORD16)1 << 16-1-shift)) == 0; shift++) + ; + if (shift) { + } + dh = dh << shift | dl >> (16-shift); + shift = 0; + while (dh + } +#endif + + dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1))); + assert(dh); + + /* Normalize the divisor */ + shift = 0; + r = dh; + i = 16/2; + do { + if (r >> i) + r >>= i; + else + shift += i; + } while ((i /= 2) != 0); + + nh = 0; + if (shift) { + lbnLshift_16(d, dlen, shift); + dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1))); + nh = lbnLshift_16(n, nlen, shift); + } + + /* Assert that dh is now normalized */ + assert(dh >> (16-1)); + + /* Also get the second-most significant word of the divisor */ + dl = BIGLITTLE(*(d-(dlen-1)),*(d+(dlen-2))); + + /* + * Adjust pointers: n to point to least significant end of first + * first subtract, and q to one the most-significant end of the + * quotient array. + */ + BIGLITTLE(n -= qlen,n += qlen); + BIGLITTLE(q -= qlen,q += qlen); + + /* Fetch the most significant stored word of the dividend */ + nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); + + /* + * Compute the first digit of the quotient, based on the + * first two words of the dividend (the most significant of which + * is the overflow word h). + */ + if (nh) { + assert(nh < dh); + r = lbnDiv21_16(&qhat, nh, nm, dh); + } else if (nm >= dh) { + qhat = nm/dh; + r = nm % dh; + } else { /* Quotient is zero */ + qhigh = 0; + goto divloop; + } + + /* Now get the third most significant word of the dividend */ + nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2))); + + /* + * Correct qhat, the estimate of quotient digit. + * qhat can only be high, and at most two words high, + * so the loop can be unrolled and abbreviated. + */ +#ifdef mul16_ppmm + mul16_ppmm(nm, t16, qhat, dl); + if (nm > r || (nm == r && t16 > nl)) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + nm -= (t16 < dl); + t16 -= dl; + if (nm > r || (nm == r && t16 > nl)) + qhat--; + } + } +#elif defined(BNWORD32) + t32 = (BNWORD32)qhat * dl; + if (t32 > ((BNWORD32)r << 16) + nl) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) > dh) { + t32 -= dl; + if (t32 > ((BNWORD32)r << 16) + nl) + qhat--; + } + } +#else /* Use lbnMulN1_16 */ + lbnMulN1_16(BIGLITTLE(t2+2,t2), &dl, 1, qhat); + if (t2high > r || (t2high == r && t2low > nl)) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + t2high -= (t2low < dl); + t2low -= dl; + if (t2high > r || (t2high == r && t2low > nl)) + qhat--; + } + } +#endif + + /* Do the multiply and subtract */ + r = lbnMulSub1_16(n, d, dlen, qhat); + /* If there was a borrow, add back once. */ + if (r > nh) { /* Borrow? */ + (void)lbnAddN_16(n, d, dlen); + qhat--; + } + + /* Remember the first quotient digit. */ + qhigh = qhat; + + /* Now, the main division loop: */ +divloop: + while (qlen--) { + + /* Advance n */ + nh = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); + BIGLITTLE(++n,--n); + nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); + + if (nh == dh) { + qhat = ~(BNWORD16)0; + /* Optimized computation of r = (nh,nm) - qhat * dh */ + r = nh + nm; + if (r < nh) + goto subtract; + } else { + assert(nh < dh); + r = lbnDiv21_16(&qhat, nh, nm, dh); + } + + nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2))); +#ifdef mul16_ppmm + mul16_ppmm(nm, t16, qhat, dl); + if (nm > r || (nm == r && t16 > nl)) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + nm -= (t16 < dl); + t16 -= dl; + if (nm > r || (nm == r && t16 > nl)) + qhat--; + } + } +#elif defined(BNWORD32) + t32 = (BNWORD32)qhat * dl; + if (t32 > ((BNWORD32)r<<16) + nl) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + t32 -= dl; + if (t32 > ((BNWORD32)r << 16) + nl) + qhat--; + } + } +#else /* Use lbnMulN1_16 */ + lbnMulN1_16(BIGLITTLE(t2+2,t2), &dl, 1, qhat); + if (t2high > r || (t2high == r && t2low > nl)) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + t2high -= (t2low < dl); + t2low -= dl; + if (t2high > r || (t2high == r && t2low > nl)) + qhat--; + } + } +#endif + + /* + * As a point of interest, note that it is not worth checking + * for qhat of 0 or 1 and installing special-case code. These + * occur with probability 2^-16, so spending 1 cycle to check + * for them is only worth it if we save more than 2^15 cycles, + * and a multiply-and-subtract for numbers in the 1024-bit + * range just doesn't take that long. + */ +subtract: + /* + * n points to the least significant end of the substring + * of n to be subtracted from. qhat is either exact or + * one too large. If the subtract gets a borrow, it was + * one too large and the divisor is added back in. It's + * a dlen+1 word add which is guaranteed to produce a + * carry out, so it can be done very simply. + */ + r = lbnMulSub1_16(n, d, dlen, qhat); + if (r > nh) { /* Borrow? */ + (void)lbnAddN_16(n, d, dlen); + qhat--; + } + /* Store the quotient digit */ + BIGLITTLE(*q++,*--q) = qhat; + } + /* Tah dah! */ + + if (shift) { + lbnRshift_16(d, dlen, shift); + lbnRshift_16(n, dlen, shift); + } + + return qhigh; +} +#endif + +/* + * Find the negative multiplicative inverse of x (x must be odd!) modulo 2^16. + * + * This just performs Newton's iteration until it gets the + * inverse. The initial estimate is always correct to 3 bits, and + * sometimes 4. The number of valid bits doubles each iteration. + * (To prove it, assume x * y == 1 (mod 2^n), and introduce a variable + * for the error mod 2^2n. x * y == 1 + k*2^n (mod 2^2n) and follow + * the iteration through.) + */ +#ifndef lbnMontInv1_16 +BNWORD16 +lbnMontInv1_16(BNWORD16 const x) +{ + BNWORD16 y = x, z; + + assert(x & 1); + + while ((z = x*y) != 1) + y *= 2 - z; + return -y; +} +#endif /* !lbnMontInv1_16 */ + +#if defined(BNWORD32) && PRODUCT_SCAN +/* + * Test code for product-scanning Montgomery reduction. + * This seems to slow the C code down rather than speed it up. + * + * The first loop computes the Montgomery multipliers, storing them over + * the low half of the number n. + * + * The second half multiplies the upper half, adding in the modulus + * times the Montgomery multipliers. The results of this multiply + * are stored. + */ +void +lbnMontReduce_16(BNWORD16 *n, BNWORD16 const *mod, unsigned mlen, BNWORD16 inv) +{ + BNWORD32 x, y; + BNWORD16 const *pm; + BNWORD16 *pn; + BNWORD16 t; + unsigned carry; + unsigned i, j; + + /* Special case of zero */ + if (!mlen) + return; + + /* Pass 1 - compute Montgomery multipliers */ + /* First iteration can have certain simplifications. */ + t = BIGLITTLE(n[-1],n[0]); + x = t; + t *= inv; + BIGLITTLE(n[-1], n[0]) = t; + x += (BNWORD32)t * BIGLITTLE(mod[-1],mod[0]); /* Can't overflow */ + assert((BNWORD16)x == 0); + x = x >> 16; + + for (i = 1; i < mlen; i++) { + carry = 0; + pn = n; + pm = BIGLITTLE(mod-i-1,mod+i+1); + for (j = 0; j < i; j++) { + y = (BNWORD32)BIGLITTLE(*--pn * *pm++, *pn++ * *--pm); + x += y; + carry += (x < y); + } + assert(BIGLITTLE(pn == n-i, pn == n+i)); + y = t = BIGLITTLE(pn[-1], pn[0]); + x += y; + carry += (x < y); + BIGLITTLE(pn[-1], pn[0]) = t = inv * (BNWORD16)x; + assert(BIGLITTLE(pm == mod-1, pm == mod+1)); + y = (BNWORD32)t * BIGLITTLE(pm[0],pm[-1]); + x += y; + carry += (x < y); + assert((BNWORD16)x == 0); + x = x >> 16 | (BNWORD32)carry << 16; + } + + BIGLITTLE(n -= mlen, n += mlen); + + /* Pass 2 - compute upper words and add to n */ + for (i = 1; i < mlen; i++) { + carry = 0; + pm = BIGLITTLE(mod-i,mod+i); + pn = n; + for (j = i; j < mlen; j++) { + y = (BNWORD32)BIGLITTLE(*--pm * *pn++, *pm++ * *--pn); + x += y; + carry += (x < y); + } + assert(BIGLITTLE(pm == mod-mlen, pm == mod+mlen)); + assert(BIGLITTLE(pn == n+mlen-i, pn == n-mlen+i)); + y = t = BIGLITTLE(*(n-i),*(n+i-1)); + x += y; + carry += (x < y); + BIGLITTLE(*(n-i),*(n+i-1)) = (BNWORD16)x; + x = (x >> 16) | (BNWORD32)carry << 16; + } + + /* Last round of second half, simplified. */ + t = BIGLITTLE(*(n-mlen),*(n+mlen-1)); + x += t; + BIGLITTLE(*(n-mlen),*(n+mlen-1)) = (BNWORD16)x; + carry = (unsigned)(x >> 16); + + while (carry) + carry -= lbnSubN_16(n, mod, mlen); + while (lbnCmp_16(n, mod, mlen) >= 0) + (void)lbnSubN_16(n, mod, mlen); +} +#define lbnMontReduce_16 lbnMontReduce_16 +#endif + +/* + * Montgomery reduce n, modulo mod. This reduces modulo mod and divides by + * 2^(16*mlen). Returns the result in the *top* mlen words of the argument n. + * This is ready for another multiplication using lbnMul_16. + * + * Montgomery representation is a very useful way to encode numbers when + * you're doing lots of modular reduction. What you do is pick a multiplier + * R which is relatively prime to the modulus and very easy to divide by. + * Since the modulus is odd, R is closen as a power of 2, so the division + * is a shift. In fact, it's a shift of an integral number of words, + * so the shift can be implicit - just drop the low-order words. + * + * Now, choose R *larger* than the modulus m, 2^(16*mlen). Then convert + * all numbers a, b, etc. to Montgomery form M(a), M(b), etc using the + * relationship M(a) = a*R mod m, M(b) = b*R mod m, etc. Note that: + * - The Montgomery form of a number depends on the modulus m. + * A fixed modulus m is assumed throughout this discussion. + * - Since R is relaitvely prime to m, multiplication by R is invertible; + * no information about the numbers is lost, they're just scrambled. + * - Adding (and subtracting) numbers in this form works just as usual. + * M(a+b) = (a+b)*R mod m = (a*R + b*R) mod m = (M(a) + M(b)) mod m + * - Multiplying numbers in this form produces a*b*R*R. The problem + * is to divide out the excess factor of R, modulo m as well as to + * reduce to the given length mlen. It turns out that this can be + * done *faster* than a normal divide, which is where the speedup + * in Montgomery division comes from. + * + * Normal reduction chooses a most-significant quotient digit q and then + * subtracts q*m from the number to be reduced. Choosing q is tricky + * and involved (just look at lbnDiv_16 to see!) and is usually + * imperfect, requiring a check for correction after the subtraction. + * + * Montgomery reduction *adds* a multiple of m to the *low-order* part + * of the number to be reduced. This multiple is chosen to make the + * low-order part of the number come out to zero. This can be done + * with no trickery or error using a precomputed inverse of the modulus. + * In this code, the "part" is one word, but any width can be used. + * + * Repeating this step sufficiently often results in a value which + * is a multiple of R (a power of two, remember) but is still (since + * the additions were to the low-order part and thus did not increase + * the value of the number being reduced very much) still not much + * larger than m*R. Then implicitly divide by R and subtract off + * m until the result is in the correct range. + * + * Since the low-order part being cancelled is less than R, the + * multiple of m added must have a multiplier which is at most R-1. + * Assuming that the input is at most m*R-1, the final number is + * at most m*(2*R-1)-1 = 2*m*R - m - 1, so subtracting m once from + * the high-order part, equivalent to subtracting m*R from the + * while number, produces a result which is at most m*R - m - 1, + * which divided by R is at most m-1. + * + * To convert *to* Montgomery form, you need a regular remainder + * routine, although you can just compute R*R (mod m) and do the + * conversion using Montgomery multiplication. To convert *from* + * Montgomery form, just Montgomery reduce the number to + * remove the extra factor of R. + * + * TODO: Change to a full inverse and use Karatsuba's multiplication + * rather than this word-at-a-time. + */ +#ifndef lbnMontReduce_16 +void +lbnMontReduce_16(BNWORD16 *n, BNWORD16 const *mod, unsigned const mlen, + BNWORD16 inv) +{ + BNWORD16 t; + BNWORD16 c = 0; + unsigned len = mlen; + + /* inv must be the negative inverse of mod's least significant word */ + assert((BNWORD16)(inv * BIGLITTLE(mod[-1],mod[0])) == (BNWORD16)-1); + + assert(len); + + do { + t = lbnMulAdd1_16(n, mod, mlen, (BNWORD16)(inv * BIGLITTLE(n[-1],n[0]))); + c += lbnAdd1_16(BIGLITTLE(n-mlen,n+mlen), len, t); + BIGLITTLE(--n,++n); + } while (--len); + + /* + * All that adding can cause an overflow past the modulus size, + * but it's unusual, and never by much, so a subtraction loop + * is the right way to deal with it. + * This subtraction happens infrequently - I've only ever seen it + * invoked once per reduction, and then just under 22.5% of the time. + */ + while (c) + c -= lbnSubN_16(n, mod, mlen); + while (lbnCmp_16(n, mod, mlen) >= 0) + (void)lbnSubN_16(n, mod, mlen); +} +#endif /* !lbnMontReduce_16 */ + +/* + * A couple of helpers that you might want to implement atomically + * in asm sometime. + */ +#ifndef lbnMontMul_16 +/* + * Multiply "num1" by "num2", modulo "mod", all of length "len", and + * place the result in the high half of "prod". "inv" is the inverse + * of the least-significant word of the modulus, modulo 2^16. + * This uses numbers in Montgomery form. Reduce using "len" and "inv". + * + * This is implemented as a macro to win on compilers that don't do + * inlining, since it's so trivial. + */ +#define lbnMontMul_16(prod, n1, n2, mod, len, inv) \ + (lbnMulX_16(prod, n1, n2, len), lbnMontReduce_16(prod, mod, len, inv)) +#endif /* !lbnMontMul_16 */ + +#ifndef lbnMontSquare_16 +/* + * Square "num", modulo "mod", both of length "len", and place the result + * in the high half of "prod". "inv" is the inverse of the least-significant + * word of the modulus, modulo 2^16. + * This uses numbers in Montgomery form. Reduce using "len" and "inv". + * + * This is implemented as a macro to win on compilers that don't do + * inlining, since it's so trivial. + */ +#define lbnMontSquare_16(prod, n, mod, len, inv) \ + (lbnSquare_16(prod, n, len), lbnMontReduce_16(prod, mod, len, inv)) + +#endif /* !lbnMontSquare_16 */ + +/* + * Convert a number to Montgomery form - requires mlen + nlen words + * of memory in "n". + */ +void +lbnToMont_16(BNWORD16 *n, unsigned nlen, BNWORD16 *mod, unsigned mlen) +{ + /* Move n up "mlen" words */ + lbnCopy_16(BIGLITTLE(n-mlen,n+mlen), n, nlen); + lbnZero_16(n, mlen); + /* Do the division - dump the quotient in the high-order words */ + (void)lbnDiv_16(BIGLITTLE(n-mlen,n+mlen), n, mlen+nlen, mod, mlen); +} + +/* + * Convert from Montgomery form. Montgomery reduction is all that is + * needed. + */ +void +lbnFromMont_16(BNWORD16 *n, BNWORD16 *mod, unsigned len) +{ + /* Zero the high words of n */ + lbnZero_16(BIGLITTLE(n-len,n+len), len); + lbnMontReduce_16(n, mod, len, lbnMontInv1_16(BIGLITTLE(mod[-1],mod[0]))); + /* Move n down len words */ + lbnCopy_16(n, BIGLITTLE(n-len,n+len), len); +} + +/* + * The windowed exponentiation algorithm, precomputes a table of odd + * powers of n up to 2^k. It takes 2^(k-1)-1 multiplies to compute + * the table, and (e-1)/(k+1) multiplies (on average) to perform the + * exponentiation. To minimize the sum, k must vary with e. + * The optimal window sizes vary with the exponent length. Here are + * some selected values and the boundary cases. + * (An underscore _ has been inserted into some of the numbers to ensure + * that magic strings like 16 do not appear in this table. It should be + * ignored.) + * + * At e = 1 bits, k=1 (0.000000) is best. + * At e = 2 bits, k=1 (0.500000) is best. + * At e = 4 bits, k=1 (1.500000) is best. + * At e = 8 bits, k=2 (3.333333) < k=1 (3.500000) + * At e = 1_6 bits, k=2 (6.000000) is best. + * At e = 26 bits, k=3 (9.250000) < k=2 (9.333333) + * At e = 3_2 bits, k=3 (10.750000) is best. + * At e = 6_4 bits, k=3 (18.750000) is best. + * At e = 82 bits, k=4 (23.200000) < k=3 (23.250000) + * At e = 128 bits, k=4 (3_2.400000) is best. + * At e = 242 bits, k=5 (55.1_66667) < k=4 (55.200000) + * At e = 256 bits, k=5 (57.500000) is best. + * At e = 512 bits, k=5 (100.1_66667) is best. + * At e = 674 bits, k=6 (127.142857) < k=5 (127.1_66667) + * At e = 1024 bits, k=6 (177.142857) is best. + * At e = 1794 bits, k=7 (287.125000) < k=6 (287.142857) + * At e = 2048 bits, k=7 (318.875000) is best. + * At e = 4096 bits, k=7 (574.875000) is best. + * + * The numbers in parentheses are the expected number of multiplications + * needed to do the computation. The normal russian-peasant modular + * exponentiation technique always uses (e-1)/2. For exponents as + * small as 192 bits (below the range of current factoring algorithms), + * half of the multiplies are eliminated, 45.2 as opposed to the naive + * 95.5. Counting the 191 squarings as 3/4 a multiply each (squaring + * proper is just over half of multiplying, but the Montgomery + * reduction in each case is also a multiply), that's 143.25 + * multiplies, for totals of 188.45 vs. 238.75 - a 21% savings. + * For larger exponents (like 512 bits), it's 483.92 vs. 639.25, a + * 24.3% savings. It asymptotically approaches 25%. + * + * Given that exponents for which k>7 are useful are uncommon, + * a fixed size table for k <= 7 is used for simplicity. + * k = 8 is uzeful at 4610 bits, k = 9 at 11522 bits. + * + * The basic number of squarings needed is e-1, although a k-bit + * window (for k > 1) can save, on average, k-2 of those, too. + * That savings currently isn't counted here. It would drive the + * crossover points slightly lower. + * (Actually, this win is also reduced in the DoubleExpMod case, + * meaning we'd have to split the tables. Except for that, the + * multiplies by powers of the two bases are independent, so + * the same logic applies to each as the single case.) + * + * Table entry i is the largest number of bits in an exponent to + * process with a window size of i+1. So the window never goes above 7 + * bits, requiring 2^(7-1) = 0x40 precomputed multiples. + */ +#define BNEXPMOD_MAX_WINDOW 7 +static unsigned const bnExpModThreshTable[BNEXPMOD_MAX_WINDOW] = { + 7, 25, 81, 241, 673, 1793, (unsigned)-1 +}; + +/* + * Perform modular exponentiation, as fast as possible! This uses + * Montgomery reduction, optimized squaring, and windowed exponentiation. + * The modulus "mod" MUST be odd! + * + * This returns 0 on success, -1 on out of memory. + * + * The window algorithm: + * The idea is to keep a running product of b1 = n^(high-order bits of exp), + * and then keep appending exponent bits to it. The following patterns + * apply to a 3-bit window (k = 3): + * To append 0: square + * To append 1: square, multiply by n^1 + * To append 10: square, multiply by n^1, square + * To append 11: square, square, multiply by n^3 + * To append 100: square, multiply by n^1, square, square + * To append 101: square, square, square, multiply by n^5 + * To append 110: square, square, multiply by n^3, square + * To append 111: square, square, square, multiply by n^7 + * + * Since each pattern involves only one multiply, the longer the pattern + * the better, except that a 0 (no multiplies) can be appended directly. + * We precompute a table of odd powers of n, up to 2^k, and can then + * multiply k bits of exponent at a time. Actually, assuming random + * exponents, there is on average one zero bit between needs to + * multiply (1/2 of the time there's none, 1/4 of the time there's 1, + * 1/8 of the time, there's 2, 1/16 of the time, there's 3, etc.), so + * you have to do one multiply per k+1 bits of exponent. + * + * The loop walks down the exponent, squaring the result buffer as + * it goes. There is a wbits+1 bit lookahead buffer, buf, that is + * filled with the upcoming exponent bits. (What is read after the + * end of the exponent is unimportant, but it is filled with zero here.) + * When the most-significant bit of this buffer becomes set, i.e. + * (buf & tblmask) != 0, we have to decide what pattern to multiply + * by, and when to do it. We decide, remember to do it in future + * after a suitable number of squarings have passed (e.g. a pattern + * of "100" in the buffer requires that we multiply by n^1 immediately; + * a pattern of "110" calls for multiplying by n^3 after one more + * squaring), clear the buffer, and continue. + * + * When we start, there is one more optimization: the result buffer + * is implcitly one, so squaring it or multiplying by it can be + * optimized away. Further, if we start with a pattern like "100" + * in the lookahead window, rather than placing n into the buffer + * and then starting to square it, we have already computed n^2 + * to compute the odd-powers table, so we can place that into + * the buffer and save a squaring. + * + * This means that if you have a k-bit window, to compute n^z, + * where z is the high k bits of the exponent, 1/2 of the time + * it requires no squarings. 1/4 of the time, it requires 1 + * squaring, ... 1/2^(k-1) of the time, it reqires k-2 squarings. + * And the remaining 1/2^(k-1) of the time, the top k bits are a + * 1 followed by k-1 0 bits, so it again only requires k-2 + * squarings, not k-1. The average of these is 1. Add that + * to the one squaring we have to do to compute the table, + * and you'll see that a k-bit window saves k-2 squarings + * as well as reducing the multiplies. (It actually doesn't + * hurt in the case k = 1, either.) + * + * n must have mlen words allocated. Although fewer may be in use + * when n is passed in, all are in use on exit. + */ +int +lbnExpMod_16(BNWORD16 *result, BNWORD16 const *n, unsigned nlen, + BNWORD16 const *e, unsigned elen, BNWORD16 *mod, unsigned mlen) +{ + BNWORD16 *table[1 << (BNEXPMOD_MAX_WINDOW-1)]; + /* Table of odd powers of n */ + unsigned ebits; /* Exponent bits */ + unsigned wbits; /* Window size */ + unsigned tblmask; /* Mask of exponentiation window */ + BNWORD16 bitpos; /* Mask of current look-ahead bit */ + unsigned buf; /* Buffer of exponent bits */ + unsigned multpos; /* Where to do pending multiply */ + BNWORD16 const *mult; /* What to multiply by */ + unsigned i; /* Loop counter */ + int isone; /* Flag: accum. is implicitly one */ + BNWORD16 *a, *b; /* Working buffers/accumulators */ + BNWORD16 *t; /* Pointer into the working buffers */ + BNWORD16 inv; /* mod^-1 modulo 2^16 */ + + assert(mlen); + assert(nlen <= mlen); + + /* First, a couple of trivial cases. */ + elen = lbnNorm_16(e, elen); + if (!elen) { + /* x ^ 0 == 1 */ + lbnZero_16(result, mlen); + BIGLITTLE(result[-1],result[0]) = 1; + return 0; + } + ebits = lbnBits_16(e, elen); + if (ebits == 1) { + /* x ^ 1 == x */ + if (n != result) + lbnCopy_16(result, n, nlen); + if (mlen > nlen) + lbnZero_16(BIGLITTLE(result-nlen,result+nlen), + mlen-nlen); + return 0; + } + + /* Okay, now move the exponent pointer to the most-significant word */ + e = BIGLITTLE(e-elen, e+elen-1); + + /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */ + wbits = 0; + while (ebits > bnExpModThreshTable[wbits]) + wbits++; + + /* Allocate working storage: two product buffers and the tables. */ + LBNALLOC(a, 2*mlen); + if (!a) + return -1; + LBNALLOC(b, 2*mlen); + if (!b) { + LBNFREE(a, 2*mlen); + return -1; + } + + /* Convert to the appropriate table size: tblmask = 1<<(k-1) */ + tblmask = 1u << wbits; + + /* We have the result buffer available, so use it. */ + table[0] = result; + + /* + * Okay, we now have a minimal-sized table - expand it. + * This is allowed to fail! If so, scale back the table size + * and proceed. + */ + for (i = 1; i < tblmask; i++) { + LBNALLOC(t, mlen); + if (!t) /* Out of memory! Quit the loop. */ + break; + table[i] = t; + } + + /* If we stopped, with i < tblmask, shrink the tables appropriately */ + while (tblmask > i) { + wbits--; + tblmask >>= 1; + } + /* Free up our overallocations */ + while (--i > tblmask) + LBNFREE(table[i], mlen); + + /* Okay, fill in the table */ + + /* Compute the necessary modular inverse */ + inv = lbnMontInv1_16(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ + + /* Convert n to Montgomery form */ + + /* Move n up "mlen" words into a */ + t = BIGLITTLE(a-mlen, a+mlen); + lbnCopy_16(t, n, nlen); + lbnZero_16(a, mlen); + /* Do the division - lose the quotient into the high-order words */ + (void)lbnDiv_16(t, a, mlen+nlen, mod, mlen); + /* Copy into first table entry */ + lbnCopy_16(table[0], a, mlen); + + /* Square a into b */ + lbnMontSquare_16(b, a, mod, mlen, inv); + + /* Use high half of b to initialize the table */ + t = BIGLITTLE(b-mlen, b+mlen); + for (i = 1; i < tblmask; i++) { + lbnMontMul_16(a, t, table[i-1], mod, mlen, inv); + lbnCopy_16(table[i], BIGLITTLE(a-mlen, a+mlen), mlen); + } + + /* We might use b = n^2 later... */ + + /* Initialze the fetch pointer */ + bitpos = (BNWORD16)1 << ((ebits-1) & (16-1)); /* Initialize mask */ + + /* This should point to the msbit of e */ + assert((*e & bitpos) != 0); + + /* + * Pre-load the window. Becuase the window size is + * never larger than the exponent size, there is no need to + * detect running off the end of e in here. + * + * The read-ahead is controlled by elen and the bitpos mask. + * Note that this is *ahead* of ebits, which tracks the + * most significant end of the window. The purpose of this + * initialization is to get the two wbits+1 bits apart, + * like they should be. + * + * Note that bitpos and e1len together keep track of the + * lookahead read pointer in the exponent that is used here. + */ + buf = 0; + for (i = 0; i <= wbits; i++) { + buf = (buf << 1) | ((*e & bitpos) != 0); + bitpos >>= 1; + if (!bitpos) { + BIGLITTLE(e++,e--); + bitpos = (BNWORD16)1 << (16-1); + elen--; + } + } + assert(buf & tblmask); + + /* + * Set the pending multiply positions to a location that will + * never be encountered, thus ensuring that nothing will happen + * until the need for a multiply appears and one is scheduled. + */ + multpos = ebits; /* A NULL value */ + mult = 0; /* Force a crash if we use these */ + + /* + * Okay, now begins the real work. The first step is + * slightly magic, so it's done outside the main loop, + * but it's very similar to what's inside. + */ + ebits--; /* Start processing the first bit... */ + isone = 1; + + /* + * This is just like the multiply in the loop, except that + * - We know the msbit of buf is set, and + * - We have the extra value n^2 floating around. + * So, do the usual computation, and if the result is that + * the buffer should be multiplied by n^1 immediately + * (which we'd normally then square), we multiply it + * (which reduces to a copy, which reduces to setting a flag) + * by n^2 and skip the squaring. Thus, we do the + * multiply and the squaring in one step. + */ + assert(buf & tblmask); + multpos = ebits - wbits; + while ((buf & 1) == 0) { + buf >>= 1; + multpos++; + } + /* Intermediates can wrap, but final must NOT */ + assert(multpos <= ebits); + mult = table[buf>>1]; + buf = 0; + + /* Special case: use already-computed value sitting in buffer */ + if (multpos == ebits) + isone = 0; + + /* + * At this point, the buffer (which is the high half of b) holds + * either 1 (implicitly, as the "isone" flag is set), or n^2. + */ + + /* + * The main loop. The procedure is: + * - Advance the window + * - If the most-significant bit of the window is set, + * schedule a multiply for the appropriate time in the + * future (may be immediately) + * - Perform any pending multiples + * - Check for termination + * - Square the buffer + * + * At any given time, the acumulated product is held in + * the high half of b. + */ + for (;;) { + ebits--; + + /* Advance the window */ + assert(buf < tblmask); + buf <<= 1; + /* + * This reads ahead of the current exponent position + * (controlled by ebits), so we have to be able to read + * past the lsb of the exponents without error. + */ + if (elen) { + buf |= ((*e & bitpos) != 0); + bitpos >>= 1; + if (!bitpos) { + BIGLITTLE(e++,e--); + bitpos = (BNWORD16)1 << (16-1); + elen--; + } + } + + /* Examine the window for pending multiplies */ + if (buf & tblmask) { + multpos = ebits - wbits; + while ((buf & 1) == 0) { + buf >>= 1; + multpos++; + } + /* Intermediates can wrap, but final must NOT */ + assert(multpos <= ebits); + mult = table[buf>>1]; + buf = 0; + } + + /* If we have a pending multiply, do it */ + if (ebits == multpos) { + /* Multiply by the table entry remembered previously */ + t = BIGLITTLE(b-mlen, b+mlen); + if (isone) { + /* Multiply by 1 is a trivial case */ + lbnCopy_16(t, mult, mlen); + isone = 0; + } else { + lbnMontMul_16(a, t, mult, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } + + /* Are we done? */ + if (!ebits) + break; + + /* Square the input */ + if (!isone) { + t = BIGLITTLE(b-mlen, b+mlen); + lbnMontSquare_16(a, t, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } /* for (;;) */ + + assert(!isone); + assert(!buf); + + /* DONE! */ + + /* Convert result out of Montgomery form */ + t = BIGLITTLE(b-mlen, b+mlen); + lbnCopy_16(b, t, mlen); + lbnZero_16(t, mlen); + lbnMontReduce_16(b, mod, mlen, inv); + lbnCopy_16(result, t, mlen); + /* + * Clean up - free intermediate storage. + * Do NOT free table[0], which is the result + * buffer. + */ + while (--tblmask) + LBNFREE(table[tblmask], mlen); + LBNFREE(b, 2*mlen); + LBNFREE(a, 2*mlen); + + return 0; /* Success */ +} + +/* + * Compute and return n1^e1 * n2^e2 mod "mod". + * result may be either input buffer, or something separate. + * It must be "mlen" words long. + * + * There is a current position in the exponents, which is kept in e1bits. + * (The exponents are swapped if necessary so e1 is the longer of the two.) + * At any given time, the value in the accumulator is + * n1^(e1>>e1bits) * n2^(e2>>e1bits) mod "mod". + * As e1bits is counted down, this is updated, by squaring it and doing + * any necessary multiplies. + * To decide on the necessary multiplies, two windows, each w1bits+1 bits + * wide, are maintained in buf1 and buf2, which read *ahead* of the + * e1bits position (with appropriate handling of the case when e1bits + * drops below w1bits+1). When the most-significant bit of either window + * becomes set, indicating that something needs to be multiplied by + * the accumulator or it will get out of sync, the window is examined + * to see which power of n1 or n2 to multiply by, and when (possibly + * later, if the power is greater than 1) the multiply should take + * place. Then the multiply and its location are remembered and the + * window is cleared. + * + * If we had every power of n1 in the table, the multiply would always + * be w1bits steps in the future. But we only keep the odd powers, + * so instead of waiting w1bits squarings and then multiplying + * by n1^k, we wait w1bits-k squarings and multiply by n1. + * + * Actually, w2bits can be less than w1bits, but the window is the same + * size, to make it easier to keep track of where we're reading. The + * appropriate number of low-order bits of the window are just ignored. + */ +int +lbnDoubleExpMod_16(BNWORD16 *result, + BNWORD16 const *n1, unsigned n1len, + BNWORD16 const *e1, unsigned e1len, + BNWORD16 const *n2, unsigned n2len, + BNWORD16 const *e2, unsigned e2len, + BNWORD16 *mod, unsigned mlen) +{ + BNWORD16 *table1[1 << (BNEXPMOD_MAX_WINDOW-1)]; + /* Table of odd powers of n1 */ + BNWORD16 *table2[1 << (BNEXPMOD_MAX_WINDOW-1)]; + /* Table of odd powers of n2 */ + unsigned e1bits, e2bits; /* Exponent bits */ + unsigned w1bits, w2bits; /* Window sizes */ + unsigned tblmask; /* Mask of exponentiation window */ + BNWORD16 bitpos; /* Mask of current look-ahead bit */ + unsigned buf1, buf2; /* Buffer of exponent bits */ + unsigned mult1pos, mult2pos; /* Where to do pending multiply */ + BNWORD16 const *mult1, *mult2; /* What to multiply by */ + unsigned i; /* Loop counter */ + int isone; /* Flag: accum. is implicitly one */ + BNWORD16 *a, *b; /* Working buffers/accumulators */ + const BNWORD16 *ct; /* Temp pointer */ + BNWORD16 *t; /* Pointer into the working buffers */ + BNWORD16 inv; /* mod^-1 modulo 2^16 */ + + assert(mlen); + assert(n1len <= mlen); + assert(n2len <= mlen); + + /* First, a couple of trivial cases. */ + e1len = lbnNorm_16(e1, e1len); + e2len = lbnNorm_16(e2, e2len); + + /* Ensure that the first exponent is the longer */ + e1bits = lbnBits_16(e1, e1len); + e2bits = lbnBits_16(e2, e2len); + if (e1bits < e2bits) { + i = e1len; e1len = e2len; e2len = i; + i = e1bits; e1bits = e2bits; e2bits = i; + ct = (const BNWORD16 *)n1; n1 = n2; n2 = ct; + ct = (const BNWORD16 *)e1; e1 = e2; e2 = ct; + } + assert(e1bits >= e2bits); + + /* Handle a trivial case */ + if (!e2len) + return lbnExpMod_16(result, n1, n1len, e1, e1len, mod, mlen); + assert(e2bits); + + /* The code below breaks if the exponents aren't at least 2 bits */ + if (e1bits == 1) { + assert(e2bits == 1); + + LBNALLOC(a, n1len+n2len); + if (!a) + return -1; + + lbnMul_16(a, n1, n1len, n2, n2len); + /* Do a direct modular reduction */ + if (n1len + n2len >= mlen) + (void)lbnDiv_16(a+mlen, a, n1len+n2len, mod, mlen); + lbnCopy_16(result, a, mlen); + LBNFREE(a, n1len+n2len); + return 0; + } + + /* Okay, now move the exponent pointers to the most-significant word */ + e1 = BIGLITTLE(e1-e1len, e1+e1len-1); + e2 = BIGLITTLE(e2-e2len, e2+e2len-1); + + /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */ + w1bits = 0; + while (e1bits > bnExpModThreshTable[w1bits]) + w1bits++; + w2bits = 0; + while (e2bits > bnExpModThreshTable[w2bits]) + w2bits++; + + assert(w1bits >= w2bits); + + /* Allocate working storage: two product buffers and the tables. */ + LBNALLOC(a, 2*mlen); + if (!a) + return -1; + LBNALLOC(b, 2*mlen); + if (!b) { + LBNFREE(a, 2*mlen); + return -1; + } + + /* Convert to the appropriate table size: tblmask = 1<<(k-1) */ + tblmask = 1u << w1bits; + /* Use buf2 for its size, temporarily */ + buf2 = 1u << w2bits; + + LBNALLOC(t, mlen); + if (!t) { + LBNFREE(b, 2*mlen); + LBNFREE(a, 2*mlen); + return -1; + } + table1[0] = t; + table2[0] = result; + + /* + * Okay, we now have some minimal-sized tables - expand them. + * This is allowed to fail! If so, scale back the table sizes + * and proceed. We allocate both tables at the same time + * so if it fails partway through, they'll both be a reasonable + * size rather than one huge and one tiny. + * When i passes buf2 (the number of entries in the e2 window, + * which may be less than the number of entries in the e1 window), + * stop allocating e2 space. + */ + for (i = 1; i < tblmask; i++) { + LBNALLOC(t, mlen); + if (!t) /* Out of memory! Quit the loop. */ + break; + table1[i] = t; + if (i < buf2) { + LBNALLOC(t, mlen); + if (!t) { + LBNFREE(table1[i], mlen); + break; + } + table2[i] = t; + } + } + + /* If we stopped, with i < tblmask, shrink the tables appropriately */ + while (tblmask > i) { + w1bits--; + tblmask >>= 1; + } + /* Free up our overallocations */ + while (--i > tblmask) { + if (i < buf2) + LBNFREE(table2[i], mlen); + LBNFREE(table1[i], mlen); + } + /* And shrink the second window too, if needed */ + if (w2bits > w1bits) { + w2bits = w1bits; + buf2 = tblmask; + } + + /* + * From now on, use the w2bits variable for the difference + * between w1bits and w2bits. + */ + w2bits = w1bits-w2bits; + + /* Okay, fill in the tables */ + + /* Compute the necessary modular inverse */ + inv = lbnMontInv1_16(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ + + /* Convert n1 to Montgomery form */ + + /* Move n1 up "mlen" words into a */ + t = BIGLITTLE(a-mlen, a+mlen); + lbnCopy_16(t, n1, n1len); + lbnZero_16(a, mlen); + /* Do the division - lose the quotient into the high-order words */ + (void)lbnDiv_16(t, a, mlen+n1len, mod, mlen); + /* Copy into first table entry */ + lbnCopy_16(table1[0], a, mlen); + + /* Square a into b */ + lbnMontSquare_16(b, a, mod, mlen, inv); + + /* Use high half of b to initialize the first table */ + t = BIGLITTLE(b-mlen, b+mlen); + for (i = 1; i < tblmask; i++) { + lbnMontMul_16(a, t, table1[i-1], mod, mlen, inv); + lbnCopy_16(table1[i], BIGLITTLE(a-mlen, a+mlen), mlen); + } + + /* Convert n2 to Montgomery form */ + + t = BIGLITTLE(a-mlen, a+mlen); + /* Move n2 up "mlen" words into a */ + lbnCopy_16(t, n2, n2len); + lbnZero_16(a, mlen); + /* Do the division - lose the quotient into the high-order words */ + (void)lbnDiv_16(t, a, mlen+n2len, mod, mlen); + /* Copy into first table entry */ + lbnCopy_16(table2[0], a, mlen); + + /* Square it into a */ + lbnMontSquare_16(a, table2[0], mod, mlen, inv); + /* Copy to b, low half */ + lbnCopy_16(b, t, mlen); + + /* Use b to initialize the second table */ + for (i = 1; i < buf2; i++) { + lbnMontMul_16(a, b, table2[i-1], mod, mlen, inv); + lbnCopy_16(table2[i], t, mlen); + } + + /* + * Okay, a recap: at this point, the low part of b holds + * n2^2, the high part holds n1^2, and the tables are + * initialized with the odd powers of n1 and n2 from 1 + * through 2*tblmask-1 and 2*buf2-1. + * + * We might use those squares in b later, or we might not. + */ + + /* Initialze the fetch pointer */ + bitpos = (BNWORD16)1 << ((e1bits-1) & (16-1)); /* Initialize mask */ + + /* This should point to the msbit of e1 */ + assert((*e1 & bitpos) != 0); + + /* + * Pre-load the windows. Becuase the window size is + * never larger than the exponent size, there is no need to + * detect running off the end of e1 in here. + * + * The read-ahead is controlled by e1len and the bitpos mask. + * Note that this is *ahead* of e1bits, which tracks the + * most significant end of the window. The purpose of this + * initialization is to get the two w1bits+1 bits apart, + * like they should be. + * + * Note that bitpos and e1len together keep track of the + * lookahead read pointer in the exponent that is used here. + * e2len is not decremented, it is only ever compared with + * e1len as *that* is decremented. + */ + buf1 = buf2 = 0; + for (i = 0; i <= w1bits; i++) { + buf1 = (buf1 << 1) | ((*e1 & bitpos) != 0); + if (e1len <= e2len) + buf2 = (buf2 << 1) | ((*e2 & bitpos) != 0); + bitpos >>= 1; + if (!bitpos) { + BIGLITTLE(e1++,e1--); + if (e1len <= e2len) + BIGLITTLE(e2++,e2--); + bitpos = (BNWORD16)1 << (16-1); + e1len--; + } + } + assert(buf1 & tblmask); + + /* + * Set the pending multiply positions to a location that will + * never be encountered, thus ensuring that nothing will happen + * until the need for a multiply appears and one is scheduled. + */ + mult1pos = mult2pos = e1bits; /* A NULL value */ + mult1 = mult2 = 0; /* Force a crash if we use these */ + + /* + * Okay, now begins the real work. The first step is + * slightly magic, so it's done outside the main loop, + * but it's very similar to what's inside. + */ + isone = 1; /* Buffer is implicitly 1, so replace * by copy */ + e1bits--; /* Start processing the first bit... */ + + /* + * This is just like the multiply in the loop, except that + * - We know the msbit of buf1 is set, and + * - We have the extra value n1^2 floating around. + * So, do the usual computation, and if the result is that + * the buffer should be multiplied by n1^1 immediately + * (which we'd normally then square), we multiply it + * (which reduces to a copy, which reduces to setting a flag) + * by n1^2 and skip the squaring. Thus, we do the + * multiply and the squaring in one step. + */ + assert(buf1 & tblmask); + mult1pos = e1bits - w1bits; + while ((buf1 & 1) == 0) { + buf1 >>= 1; + mult1pos++; + } + /* Intermediates can wrap, but final must NOT */ + assert(mult1pos <= e1bits); + mult1 = table1[buf1>>1]; + buf1 = 0; + + /* Special case: use already-computed value sitting in buffer */ + if (mult1pos == e1bits) + isone = 0; + + /* + * The first multiply by a power of n2. Similar, but + * we might not even want to schedule a multiply if e2 is + * shorter than e1, and the window might be shorter so + * we have to leave the low w2bits bits alone. + */ + if (buf2 & tblmask) { + /* Remember low-order bits for later */ + i = buf2 & ((1u << w2bits) - 1); + buf2 >>= w2bits; + mult2pos = e1bits - w1bits + w2bits; + while ((buf2 & 1) == 0) { + buf2 >>= 1; + mult2pos++; + } + assert(mult2pos <= e1bits); + mult2 = table2[buf2>>1]; + buf2 = i; + + if (mult2pos == e1bits) { + t = BIGLITTLE(b-mlen, b+mlen); + if (isone) { + lbnCopy_16(t, b, mlen); /* Copy low to high */ + isone = 0; + } else { + lbnMontMul_16(a, t, b, mod, mlen, inv); + t = a; a = b; b = t; + } + } + } + + /* + * At this point, the buffer (which is the high half of b) + * holds either 1 (implicitly, as the "isone" flag is set), + * n1^2, n2^2 or n1^2 * n2^2. + */ + + /* + * The main loop. The procedure is: + * - Advance the windows + * - If the most-significant bit of a window is set, + * schedule a multiply for the appropriate time in the + * future (may be immediately) + * - Perform any pending multiples + * - Check for termination + * - Square the buffers + * + * At any given time, the acumulated product is held in + * the high half of b. + */ + for (;;) { + e1bits--; + + /* Advance the windows */ + assert(buf1 < tblmask); + buf1 <<= 1; + assert(buf2 < tblmask); + buf2 <<= 1; + /* + * This reads ahead of the current exponent position + * (controlled by e1bits), so we have to be able to read + * past the lsb of the exponents without error. + */ + if (e1len) { + buf1 |= ((*e1 & bitpos) != 0); + if (e1len <= e2len) + buf2 |= ((*e2 & bitpos) != 0); + bitpos >>= 1; + if (!bitpos) { + BIGLITTLE(e1++,e1--); + if (e1len <= e2len) + BIGLITTLE(e2++,e2--); + bitpos = (BNWORD16)1 << (16-1); + e1len--; + } + } + + /* Examine the first window for pending multiplies */ + if (buf1 & tblmask) { + mult1pos = e1bits - w1bits; + while ((buf1 & 1) == 0) { + buf1 >>= 1; + mult1pos++; + } + /* Intermediates can wrap, but final must NOT */ + assert(mult1pos <= e1bits); + mult1 = table1[buf1>>1]; + buf1 = 0; + } + + /* + * Examine the second window for pending multiplies. + * Window 2 can be smaller than window 1, but we + * keep the same number of bits in buf2, so we need + * to ignore any low-order bits in the buffer when + * computing what to multiply by, and recompute them + * later. + */ + if (buf2 & tblmask) { + /* Remember low-order bits for later */ + i = buf2 & ((1u << w2bits) - 1); + buf2 >>= w2bits; + mult2pos = e1bits - w1bits + w2bits; + while ((buf2 & 1) == 0) { + buf2 >>= 1; + mult2pos++; + } + assert(mult2pos <= e1bits); + mult2 = table2[buf2>>1]; + buf2 = i; + } + + + /* If we have a pending multiply for e1, do it */ + if (e1bits == mult1pos) { + /* Multiply by the table entry remembered previously */ + t = BIGLITTLE(b-mlen, b+mlen); + if (isone) { + /* Multiply by 1 is a trivial case */ + lbnCopy_16(t, mult1, mlen); + isone = 0; + } else { + lbnMontMul_16(a, t, mult1, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } + + /* If we have a pending multiply for e2, do it */ + if (e1bits == mult2pos) { + /* Multiply by the table entry remembered previously */ + t = BIGLITTLE(b-mlen, b+mlen); + if (isone) { + /* Multiply by 1 is a trivial case */ + lbnCopy_16(t, mult2, mlen); + isone = 0; + } else { + lbnMontMul_16(a, t, mult2, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } + + /* Are we done? */ + if (!e1bits) + break; + + /* Square the buffer */ + if (!isone) { + t = BIGLITTLE(b-mlen, b+mlen); + lbnMontSquare_16(a, t, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } /* for (;;) */ + + assert(!isone); + assert(!buf1); + assert(!buf2); + + /* DONE! */ + + /* Convert result out of Montgomery form */ + t = BIGLITTLE(b-mlen, b+mlen); + lbnCopy_16(b, t, mlen); + lbnZero_16(t, mlen); + lbnMontReduce_16(b, mod, mlen, inv); + lbnCopy_16(result, t, mlen); + + /* Clean up - free intermediate storage */ + buf2 = tblmask >> w2bits; + while (--tblmask) { + if (tblmask < buf2) + LBNFREE(table2[tblmask], mlen); + LBNFREE(table1[tblmask], mlen); + } + t = table1[0]; + LBNFREE(t, mlen); + LBNFREE(b, 2*mlen); + LBNFREE(a, 2*mlen); + + return 0; /* Success */ +} + +/* + * 2^exp (mod mod). This is an optimized version for use in Fermat + * tests. The input value of n is ignored; it is returned with + * "mlen" words valid. + */ +int +lbnTwoExpMod_16(BNWORD16 *n, BNWORD16 const *exp, unsigned elen, + BNWORD16 *mod, unsigned mlen) +{ + unsigned e; /* Copy of high words of the exponent */ + unsigned bits; /* Assorted counter of bits */ + BNWORD16 const *bitptr; + BNWORD16 bitword, bitpos; + BNWORD16 *a, *b, *a1; + BNWORD16 inv; + + assert(mlen); + + bitptr = BIGLITTLE(exp-elen, exp+elen-1); + bitword = *bitptr; + assert(bitword); + + /* Clear n for future use. */ + lbnZero_16(n, mlen); + + bits = lbnBits_16(exp, elen); + + /* First, a couple of trivial cases. */ + if (bits <= 1) { + /* 2 ^ 0 == 1, 2 ^ 1 == 2 */ + BIGLITTLE(n[-1],n[0]) = (BNWORD16)1< 1); /* a 1-bit modulus is just stupid... */ + + /* + * We start with 1<>= 1; + if (!bitpos) { + if (!--elen) + break; + bitword = BIGLITTLE(*++bitptr,*--bitptr); + bitpos = (BNWORD16)1<<(16-1); + } + e = (e << 1) | ((bitpos & bitword) != 0); + if (e >= bits) { /* Overflow! Back out. */ + e >>= 1; + break; + } + } + /* + * The bit in "bitpos" being examined by the bit buffer has NOT + * been consumed yet. This may be past the end of the exponent, + * in which case elen == 1. + */ + + /* Okay, now, set bit "e" in n. n is already zero. */ + inv = (BNWORD16)1 << (e & (16-1)); + e /= 16; + BIGLITTLE(n[-e-1],n[e]) = inv; + /* + * The effective length of n in words is now "e+1". + * This is used a little bit later. + */ + + if (!elen) + return 0; /* That was easy! */ + + /* + * We have now processed the first few bits. The next step + * is to convert this to Montgomery form for further squaring. + */ + + /* Allocate working storage: two product buffers */ + LBNALLOC(a, 2*mlen); + if (!a) + return -1; + LBNALLOC(b, 2*mlen); + if (!b) { + LBNFREE(a, 2*mlen); + return -1; + } + + /* Convert n to Montgomery form */ + inv = BIGLITTLE(mod[-1],mod[0]); /* LSW of modulus */ + assert(inv & 1); /* Modulus must be odd */ + inv = lbnMontInv1_16(inv); + /* Move n (length e+1, remember?) up "mlen" words into b */ + /* Note that we lie about a1 for a bit - it's pointing to b */ + a1 = BIGLITTLE(b-mlen,b+mlen); + lbnCopy_16(a1, n, e+1); + lbnZero_16(b, mlen); + /* Do the division - dump the quotient into the high-order words */ + (void)lbnDiv_16(a1, b, mlen+e+1, mod, mlen); + /* + * Now do the first squaring and modular reduction to put + * the number up in a1 where it belongs. + */ + lbnMontSquare_16(a, b, mod, mlen, inv); + /* Fix up a1 to point to where it should go. */ + a1 = BIGLITTLE(a-mlen,a+mlen); + + /* + * Okay, now, a1 holds the number being accumulated, and + * b is a scratch register. Start working: + */ + for (;;) { + /* + * Is the bit set? If so, double a1 as well. + * A modular doubling like this is very cheap. + */ + if (bitpos & bitword) { + /* + * Double the number. If there was a carry out OR + * the result is greater than the modulus, subract + * the modulus. + */ + if (lbnDouble_16(a1, mlen) || + lbnCmp_16(a1, mod, mlen) > 0) + (void)lbnSubN_16(a1, mod, mlen); + } + + /* Advance to the next exponent bit */ + bitpos >>= 1; + if (!bitpos) { + if (!--elen) + break; /* Done! */ + bitword = BIGLITTLE(*++bitptr,*--bitptr); + bitpos = (BNWORD16)1<<(16-1); + } + + /* + * The elen/bitword/bitpos bit buffer is known to be + * non-empty, i.e. there is at least one more unconsumed bit. + * Thus, it's safe to square the number. + */ + lbnMontSquare_16(b, a1, mod, mlen, inv); + /* Rename result (in b) back to a (a1, really). */ + a1 = b; b = a; a = a1; + a1 = BIGLITTLE(a-mlen,a+mlen); + } + + /* DONE! Just a little bit of cleanup... */ + + /* + * Convert result out of Montgomery form... this is + * just a Montgomery reduction. + */ + lbnCopy_16(a, a1, mlen); + lbnZero_16(a1, mlen); + lbnMontReduce_16(a, mod, mlen, inv); + lbnCopy_16(n, a1, mlen); + + /* Clean up - free intermediate storage */ + LBNFREE(b, 2*mlen); + LBNFREE(a, 2*mlen); + + return 0; /* Success */ +} + + +/* + * Returns a substring of the big-endian array of bytes representation + * of the bignum array based on two parameters, the least significant + * byte number (0 to start with the least significant byte) and the + * length. I.e. the number returned is a representation of + * (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen). + * + * It is an error if the bignum is not at least buflen + lsbyte bytes + * long. + * + * This code assumes that the compiler has the minimal intelligence + * neded to optimize divides and modulo operations on an unsigned data + * type with a power of two. + */ +void +lbnExtractBigBytes_16(BNWORD16 const *n, unsigned char *buf, + unsigned lsbyte, unsigned buflen) +{ + BNWORD16 t = 0; /* Needed to shut up uninitialized var warnings */ + unsigned shift; + + lsbyte += buflen; + + shift = (8 * lsbyte) % 16; + lsbyte /= (16/8); /* Convert to word offset */ + BIGLITTLE(n -= lsbyte, n += lsbyte); + + if (shift) + t = BIGLITTLE(n[-1],n[0]); + + while (buflen--) { + if (!shift) { + t = BIGLITTLE(*n++,*--n); + shift = 16; + } + shift -= 8; + *buf++ = (unsigned char)(t>>shift); + } +} + +/* + * Merge a big-endian array of bytes into a bignum array. + * The array had better be big enough. This is + * equivalent to extracting the entire bignum into a + * large byte array, copying the input buffer into the + * middle of it, and converting back to a bignum. + * + * The buf is "len" bytes long, and its *last* byte is at + * position "lsbyte" from the end of the bignum. + * + * Note that this is a pain to get right. Fortunately, it's hardly + * critical for efficiency. + */ +void +lbnInsertBigBytes_16(BNWORD16 *n, unsigned char const *buf, + unsigned lsbyte, unsigned buflen) +{ + BNWORD16 t = 0; /* Shut up uninitialized varibale warnings */ + + lsbyte += buflen; + + BIGLITTLE(n -= lsbyte/(16/8), n += lsbyte/(16/8)); + + /* Load up leading odd bytes */ + if (lsbyte % (16/8)) { + t = BIGLITTLE(*--n,*n++); + t >>= (lsbyte * 8) % 16; + } + + /* The main loop - merge into t, storing at each word boundary. */ + while (buflen--) { + t = (t << 8) | *buf++; + if ((--lsbyte % (16/8)) == 0) + BIGLITTLE(*n++,*--n) = t; + } + + /* Merge odd bytes in t into last word */ + lsbyte = (lsbyte * 8) % 16; + if (lsbyte) { + t <<= lsbyte; + t |= (((BNWORD16)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]); + BIGLITTLE(n[0],n[-1]) = t; + } + + return; +} + +/* + * Returns a substring of the little-endian array of bytes representation + * of the bignum array based on two parameters, the least significant + * byte number (0 to start with the least significant byte) and the + * length. I.e. the number returned is a representation of + * (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen). + * + * It is an error if the bignum is not at least buflen + lsbyte bytes + * long. + * + * This code assumes that the compiler has the minimal intelligence + * neded to optimize divides and modulo operations on an unsigned data + * type with a power of two. + */ +void +lbnExtractLittleBytes_16(BNWORD16 const *n, unsigned char *buf, + unsigned lsbyte, unsigned buflen) +{ + BNWORD16 t = 0; /* Needed to shut up uninitialized var warnings */ + + BIGLITTLE(n -= lsbyte/(16/8), n += lsbyte/(16/8)); + + if (lsbyte % (16/8)) { + t = BIGLITTLE(*--n,*n++); + t >>= (lsbyte % (16/8)) * 8 ; + } + + while (buflen--) { + if ((lsbyte++ % (16/8)) == 0) + t = BIGLITTLE(*--n,*n++); + *buf++ = (unsigned char)t; + t >>= 8; + } +} + +/* + * Merge a little-endian array of bytes into a bignum array. + * The array had better be big enough. This is + * equivalent to extracting the entire bignum into a + * large byte array, copying the input buffer into the + * middle of it, and converting back to a bignum. + * + * The buf is "len" bytes long, and its first byte is at + * position "lsbyte" from the end of the bignum. + * + * Note that this is a pain to get right. Fortunately, it's hardly + * critical for efficiency. + */ +void +lbnInsertLittleBytes_16(BNWORD16 *n, unsigned char const *buf, + unsigned lsbyte, unsigned buflen) +{ + BNWORD16 t = 0; /* Shut up uninitialized varibale warnings */ + + /* Move to most-significant end */ + lsbyte += buflen; + buf += buflen; + + BIGLITTLE(n -= lsbyte/(16/8), n += lsbyte/(16/8)); + + /* Load up leading odd bytes */ + if (lsbyte % (16/8)) { + t = BIGLITTLE(*--n,*n++); + t >>= (lsbyte * 8) % 16; + } + + /* The main loop - merge into t, storing at each word boundary. */ + while (buflen--) { + t = (t << 8) | *--buf; + if ((--lsbyte % (16/8)) == 0) + BIGLITTLE(*n++,*--n) = t; + } + + /* Merge odd bytes in t into last word */ + lsbyte = (lsbyte * 8) % 16; + if (lsbyte) { + t <<= lsbyte; + t |= (((BNWORD16)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]); + BIGLITTLE(n[0],n[-1]) = t; + } + + return; +} + +#ifdef DEADCODE /* This was a precursor to the more flexible lbnExtractBytes */ +/* + * Convert a big-endian array of bytes to a bignum. + * Returns the number of words in the bignum. + * Note the expression "16/8" for the number of bytes per word. + * This is so the word-size adjustment will work. + */ +unsigned +lbnFromBytes_16(BNWORD16 *a, unsigned char const *b, unsigned blen) +{ + BNWORD16 t; + unsigned alen = (blen + (16/8-1))/(16/8); + BIGLITTLE(a -= alen, a += alen); + + while (blen) { + t = 0; + do { + t = t << 8 | *b++; + } while (--blen & (16/8-1)); + BIGLITTLE(*a++,*--a) = t; + } + return alen; +} +#endif + +/* + * Computes the GCD of a and b. Modifies both arguments; + * when it returns, one of them is the GCD and the other is trash. + * The return value is the length of the GCD, with the sign telling + * whether it is in a (+ve) or b (-ve). Both inputs must have + * one extra word of precision. alen must be >= blen. + * + * TODO: use the binary algorithm (Knuth section 4.5.2, algorithm B). + * This is based on taking out common powers of 2, then repeatedly: + * gcd(2*u,v) = gcd(u,2*v) = gcd(u,v) - isolated powers of 2 can be deleted. + * gcd(u,v) = gcd(u-v,v) - the numbers can be easily reduced. + * It gets less reduction per step, but the steps are much faster than + * the division case. + */ +int +lbnGcd_16(BNWORD16 *a, unsigned alen, BNWORD16 *b, unsigned blen) +{ + assert(alen >= blen); + + while (blen != 0) { + (void)lbnDiv_16(BIGLITTLE(a-blen,a+blen), a, alen, b, blen); + alen = lbnNorm_16(a, blen); + if (alen == 0) + return -(int)blen; + (void)lbnDiv_16(BIGLITTLE(b-alen,b+alen), b, blen, a, alen); + blen = lbnNorm_16(b, alen); + } + return alen; +} + +/* + * Invert "a" modulo "mod" using the extended Euclidean algorithm. + * Note that this only computes one of the cosequences, and uses the + * theorem that the signs flip every step and the absolute value of + * the cosequence values are always bounded by the modulus to avoid + * having to work with negative numbers. + * gcd(a,mod) had better equal 1. Returns 1 if the GCD is NOT 1. + * a must be one word longer than "mod". It is overwritten with the + * result. + * TODO: Use Richard Schroeppel's *much* faster algorithm. + */ +int +lbnInv_16(BNWORD16 *a, unsigned alen, BNWORD16 const *mod, unsigned mlen) +{ + BNWORD16 *b; /* Hold a copy of mod during GCD reduction */ + BNWORD16 *p; /* Temporary for products added to t0 and t1 */ + BNWORD16 *t0, *t1; /* Inverse accumulators */ + BNWORD16 cy; + unsigned blen, t0len, t1len, plen; + + alen = lbnNorm_16(a, alen); + if (!alen) + return 1; /* No inverse */ + + mlen = lbnNorm_16(mod, mlen); + + assert (alen <= mlen); + + /* Inverse of 1 is 1 */ + if (alen == 1 && BIGLITTLE(a[-1],a[0]) == 1) { + lbnZero_16(BIGLITTLE(a-alen,a+alen), mlen-alen); + return 0; + } + + /* Allocate a pile of space */ + LBNALLOC(b, mlen+1); + if (b) { + /* + * Although products are guaranteed to always be less than the + * modulus, it can involve multiplying two 3-word numbers to + * get a 5-word result, requiring a 6th word to store a 0 + * temporarily. Thus, mlen + 1. + */ + LBNALLOC(p, mlen+1); + if (p) { + LBNALLOC(t0, mlen); + if (t0) { + LBNALLOC(t1, mlen); + if (t1) + goto allocated; + LBNFREE(t0, mlen); + } + LBNFREE(p, mlen+1); + } + LBNFREE(b, mlen+1); + } + return -1; + +allocated: + + /* Set t0 to 1 */ + t0len = 1; + BIGLITTLE(t0[-1],t0[0]) = 1; + + /* b = mod */ + lbnCopy_16(b, mod, mlen); + /* blen = mlen (implicitly) */ + + /* t1 = b / a; b = b % a */ + cy = lbnDiv_16(t1, b, mlen, a, alen); + *(BIGLITTLE(t1-(mlen-alen)-1,t1+(mlen-alen))) = cy; + t1len = lbnNorm_16(t1, mlen-alen+1); + blen = lbnNorm_16(b, alen); + + /* while (b > 1) */ + while (blen > 1 || BIGLITTLE(b[-1],b[0]) != (BNWORD16)1) { + /* q = a / b; a = a % b; */ + if (alen < blen || (alen == blen && lbnCmp_16(a, a, alen) < 0)) + assert(0); + cy = lbnDiv_16(BIGLITTLE(a-blen,a+blen), a, alen, b, blen); + *(BIGLITTLE(a-alen-1,a+alen)) = cy; + plen = lbnNorm_16(BIGLITTLE(a-blen,a+blen), alen-blen+1); + assert(plen); + alen = lbnNorm_16(a, blen); + if (!alen) + goto failure; /* GCD not 1 */ + + /* t0 += q * t1; */ + assert(plen+t1len <= mlen+1); + lbnMul_16(p, BIGLITTLE(a-blen,a+blen), plen, t1, t1len); + plen = lbnNorm_16(p, plen + t1len); + assert(plen <= mlen); + if (plen > t0len) { + lbnZero_16(BIGLITTLE(t0-t0len,t0+t0len), plen-t0len); + t0len = plen; + } + cy = lbnAddN_16(t0, p, plen); + if (cy) { + if (t0len > plen) { + cy = lbnAdd1_16(BIGLITTLE(t0-plen,t0+plen), + t0len-plen, cy); + } + if (cy) { + BIGLITTLE(t0[-t0len-1],t0[t0len]) = cy; + t0len++; + } + } + + /* if (a <= 1) return a ? t0 : FAIL; */ + if (alen <= 1 && BIGLITTLE(a[-1],a[0]) == (BNWORD16)1) { + if (alen == 0) + goto failure; /* FAIL */ + assert(t0len <= mlen); + lbnCopy_16(a, t0, t0len); + lbnZero_16(BIGLITTLE(a-t0len, a+t0len), mlen-t0len); + goto success; + } + + /* q = b / a; b = b % a; */ + if (blen < alen || (blen == alen && lbnCmp_16(b, a, alen) < 0)) + assert(0); + cy = lbnDiv_16(BIGLITTLE(b-alen,b+alen), b, blen, a, alen); + *(BIGLITTLE(b-blen-1,b+blen)) = cy; + plen = lbnNorm_16(BIGLITTLE(b-alen,b+alen), blen-alen+1); + assert(plen); + blen = lbnNorm_16(b, alen); + if (!blen) + goto failure; /* GCD not 1 */ + + /* t1 += q * t0; */ + assert(plen+t0len <= mlen+1); + lbnMul_16(p, BIGLITTLE(b-alen,b+alen), plen, t0, t0len); + plen = lbnNorm_16(p, plen + t0len); + assert(plen <= mlen); + if (plen > t1len) { + lbnZero_16(BIGLITTLE(t1-t1len,t1+t1len), plen-t1len); + t1len = plen; + } + cy = lbnAddN_16(t1, p, plen); + if (cy) { + if (t1len > plen) { + cy = lbnAdd1_16(BIGLITTLE(t1-plen,t0+plen), + t1len-plen, cy); + } + if (cy) { + BIGLITTLE(t1[-t1len-1],t1[t1len]) = cy; + t1len++; + } + } + } + + if (!blen) + goto failure; /* gcd(a, mod) != 1 -- FAIL */ + + /* return mod-t1 */ + lbnCopy_16(a, mod, mlen); + assert(t1len <= mlen); + cy = lbnSubN_16(a, t1, t1len); + if (cy) { + assert(mlen > t1len); + cy = lbnSub1_16(BIGLITTLE(a-t1len, a+t1len), mlen-t1len, cy); + assert(!cy); + } + +success: + LBNFREE(t1, mlen); + LBNFREE(t0, mlen); + LBNFREE(p, mlen+1); + LBNFREE(b, mlen+1); + + return 0; + +failure: + LBNFREE(t1, mlen); + LBNFREE(t0, mlen); + LBNFREE(p, mlen+1); + LBNFREE(b, mlen+1); + + return 1; +} diff --git a/lib/bind/cylink/lbn16.h b/lib/bind/cylink/lbn16.h new file mode 100644 index 0000000000..e011e4e152 --- /dev/null +++ b/lib/bind/cylink/lbn16.h @@ -0,0 +1,181 @@ +#ifndef LBN16_H +#define LBN16_H + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +#include "lbn.h" + +#ifndef BNWORD16 +#error 16-bit bignum library requires a 16-bit data type +#endif + +#ifndef lbnCopy_16 +void lbnCopy_16(BNWORD16 *dest, BNWORD16 const *src, unsigned len); +#endif +#ifndef lbnZero_16 +void lbnZero_16(BNWORD16 *num, unsigned len); +#endif +#ifndef lbnNeg_16 +void lbnNeg_16(BNWORD16 *num, unsigned len); +#endif + +#ifndef lbnAdd1_16 +BNWORD16 lbnAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry); +#endif +#ifndef lbnSub1_16 +BNWORD16 lbnSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow); +#endif + +#ifndef lbnAddN_16 +BNWORD16 lbnAddN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len); +#endif +#ifndef lbnSubN_16 +BNWORD16 lbnSubN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len); +#endif + +#ifndef lbnCmp_16 +int lbnCmp_16(BNWORD16 const *num1, BNWORD16 const *num2, unsigned len); +#endif + +#ifndef lbnMulN1_16 +void lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k); +#endif +#ifndef lbnMulAdd1_16 +BNWORD16 +lbnMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k); +#endif +#ifndef lbnMulSub1_16 +BNWORD16 lbnMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k); +#endif + +#ifndef lbnLshift_16 +BNWORD16 lbnLshift_16(BNWORD16 *num, unsigned len, unsigned shift); +#endif +#ifndef lbnDouble_16 +BNWORD16 lbnDouble_16(BNWORD16 *num, unsigned len); +#endif +#ifndef lbnRshift_16 +BNWORD16 lbnRshift_16(BNWORD16 *num, unsigned len, unsigned shift); +#endif + +#ifndef lbnMul_16 +void lbnMul_16(BNWORD16 *prod, BNWORD16 const *num1, unsigned len1, + BNWORD16 const *num2, unsigned len2); +#endif +#ifndef lbnSquare_16 +void lbnSquare_16(BNWORD16 *prod, BNWORD16 const *num, unsigned len); +#endif + +#ifndef lbnNorm_16 +unsigned lbnNorm_16(BNWORD16 const *num, unsigned len); +#endif +#ifndef lbnBits_16 +unsigned lbnBits_16(BNWORD16 const *num, unsigned len); +#endif + +#ifndef lbnExtractBigBytes_16 +void lbnExtractBigBytes_16(BNWORD16 const *bn, unsigned char *buf, + unsigned lsbyte, unsigned buflen); +#endif +#ifndef lbnInsertBigytes_16 +void lbnInsertBigBytes_16(BNWORD16 *n, unsigned char const *buf, + unsigned lsbyte, unsigned buflen); +#endif +#ifndef lbnExtractLittleBytes_16 +void lbnExtractLittleBytes_16(BNWORD16 const *bn, unsigned char *buf, + unsigned lsbyte, unsigned buflen); +#endif +#ifndef lbnInsertLittleBytes_16 +void lbnInsertLittleBytes_16(BNWORD16 *n, unsigned char const *buf, + unsigned lsbyte, unsigned buflen); +#endif + +#ifndef lbnDiv21_16 +BNWORD16 lbnDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d); +#endif +#ifndef lbnDiv1_16 +BNWORD16 lbnDiv1_16(BNWORD16 *q, BNWORD16 *rem, + BNWORD16 const *n, unsigned len, BNWORD16 d); +#endif +#ifndef lbnModQ_16 +unsigned lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d); +#endif +#ifndef lbnDiv_16 +BNWORD16 +lbnDiv_16(BNWORD16 *q, BNWORD16 *n, unsigned nlen, BNWORD16 *d, unsigned dlen); +#endif + +#ifndef lbnMontInv1_16 +BNWORD16 lbnMontInv1_16(BNWORD16 const x); +#endif +#ifndef lbnMontReduce_16 +void lbnMontReduce_16(BNWORD16 *n, BNWORD16 const *mod, unsigned const mlen, + BNWORD16 inv); +#endif +#ifndef lbnToMont_16 +void lbnToMont_16(BNWORD16 *n, unsigned nlen, BNWORD16 *mod, unsigned mlen); +#endif +#ifndef lbnFromMont_16 +void lbnFromMont_16(BNWORD16 *n, BNWORD16 *mod, unsigned len); +#endif + +#ifndef lbnExpMod_16 +int lbnExpMod_16(BNWORD16 *result, BNWORD16 const *n, unsigned nlen, + BNWORD16 const *exp, unsigned elen, BNWORD16 *mod, unsigned mlen); +#endif +#ifndef lbnDoubleExpMod_16 +int lbnDoubleExpMod_16(BNWORD16 *result, + BNWORD16 const *n1, unsigned n1len, BNWORD16 const *e1, unsigned e1len, + BNWORD16 const *n2, unsigned n2len, BNWORD16 const *e2, unsigned e2len, + BNWORD16 *mod, unsigned mlen); +#endif +#ifndef lbnTwoExpMod_16 +int lbnTwoExpMod_16(BNWORD16 *n, BNWORD16 const *exp, unsigned elen, + BNWORD16 *mod, unsigned mlen); +#endif +#ifndef lbnGcd_16 +int lbnGcd_16(BNWORD16 *a, unsigned alen, BNWORD16 *b, unsigned blen); +#endif +#ifndef lbnInv_16 +int lbnInv_16(BNWORD16 *a, unsigned alen, BNWORD16 const *mod, unsigned mlen); +#endif + +#endif /* LBN16_H */ diff --git a/lib/bind/cylink/lbn32.c b/lib/bind/cylink/lbn32.c new file mode 100644 index 0000000000..44ac41c418 --- /dev/null +++ b/lib/bind/cylink/lbn32.c @@ -0,0 +1,3643 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn32.c - Low-level bignum routines, 32-bit version. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + * + * NOTE: the magic constants "32" and "64" appear in many places in this + * file, including inside identifiers. Because it is not possible to + * ask "#ifdef" of a macro expansion, it is not possible to use the + * preprocessor to conditionalize these properly. Thus, this file is + * intended to be edited with textual search and replace to produce + * alternate word size versions. Any reference to the number of bits + * in a word must be the string "32", and that string must not appear + * otherwise. Any reference to twice this number must appear as "64", + * which likewise must not appear otherwise. Is that clear? + * + * Remember, when doubling the bit size replace the larger number (64) + * first, then the smaller (32). When halving the bit size, do the + * opposite. Otherwise, things will get wierd. Also, be sure to replace + * every instance that appears. (:%s/foo/bar/g in vi) + * + * These routines work with a pointer to the least-significant end of + * an array of WORD32s. The BIG(x), LITTLE(y) and BIGLTTLE(x,y) macros + * defined in lbn.h (which expand to x on a big-edian machine and y on a + * little-endian machine) are used to conditionalize the code to work + * either way. If you have no assembly primitives, it doesn't matter. + * Note that on a big-endian machine, the least-significant-end pointer + * is ONE PAST THE END. The bytes are ptr[-1] through ptr[-len]. + * On little-endian, they are ptr[0] through ptr[len-1]. This makes + * perfect sense if you consider pointers to point *between* bytes rather + * than at them. + * + * Because the array index values are unsigned integers, ptr[-i] + * may not work properly, since the index -i is evaluated as an unsigned, + * and if pointers are wider, zero-extension will produce a positive + * number rahter than the needed negative. The expression used in this + * code, *(ptr-i) will, however, work. (The array syntax is equivalent + * to *(ptr+-i), which is a pretty subtle difference.) + * + * Many of these routines will get very unhappy if fed zero-length inputs. + * They use assert() to enforce this. An higher layer of code must make + * sure that these aren't called with zero-length inputs. + * + * Any of these routines can be replaced with more efficient versions + * elsewhere, by just #defining their names. If one of the names + * is #defined, the C code is not compiled in and no declaration is + * made. Use the BNINCLUDE file to do that. Typically, you compile + * asm subroutines with the same name and just, e.g. + * #define lbnMulAdd1_32 lbnMulAdd1_32 + * + * If you want to write asm routines, start with lbnMulAdd1_32(). + * This is the workhorse of modular exponentiation. lbnMulN1_32() is + * also used a fair bit, although not as much and it's defined in terms + * of lbnMulAdd1_32 if that has a custom version. lbnMulSub1_32 and + * lbnDiv21_32 are used in the usual division and remainder finding. + * (Not the Montgomery reduction used in modular exponentiation, though.) + * Once you have lbnMulAdd1_32 defined, writing the other two should + * be pretty easy. (Just make sure you get the sign of the subtraction + * in lbnMulSub1_32 right - it's dest = dest - source * k.) + * + * The only definitions that absolutely need a double-word (BNWORD64) + * type are lbnMulAdd1_32 and lbnMulSub1_32; if those are provided, + * the rest follows. lbnDiv21_32, however, is a lot slower unless you + * have them, and lbnModQ_32 takes after it. That one is used quite a + * bit for prime sieving. + */ + +#ifndef HAVE_CONFIG_H +#define HAVE_CONFIG_H 0 +#endif +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Some compilers complain about #if FOO if FOO isn't defined, + * so do the ANSI-mandated thing explicitly... + */ +#ifndef NO_ASSERT_H +#define NO_ASSERT_H 0 +#endif +#ifndef NO_STRING_H +#define NO_STRING_H 0 +#endif +#ifndef HAVE_STRINGS_H +#define HAVE_STRINGS_H 0 +#endif +#ifndef NEED_MEMORY_H +#define NEED_MEMORY_H 0 +#endif + +#if !NO_ASSERT_H +#include +#else +#define assert(x) (void)0 +#endif + +#if !NO_STRING_H +#include /* For memcpy */ +#elif HAVE_STRINGS_H +#include +#endif +#if NEED_MEMORY_H +#include +#endif + +#include "lbn.h" +#include "lbn32.h" +#include "lbnmem.h" +#include "legal.h" + +#include "kludge.h" +#include + +#ifndef BNWORD32 +#error 32-bit bignum library requires a 32-bit data type +#endif + +/* Make sure the copyright notice gets included */ +volatile const char * volatile const lbnCopyright_32 = bnCopyright; + +/* + * Most of the multiply (and Montgomery reduce) routines use an outer + * loop that iterates over one of the operands - a so-called operand + * scanning approach. One big advantage of this is that the assembly + * support routines are simpler. The loops can be rearranged to have + * an outer loop that iterates over the product, a so-called product + * scanning approach. This has the advantage of writing less data + * and doing fewer adds to memory, so is supposedly faster. Some + * code has been written using a product-scanning approach, but + * it appears to be slower, so it is turned off by default. Some + * experimentation would be appreciated. + * + * (The code is also annoying to get right and not very well commented, + * one of my pet peeves about math libraries. I'm sorry.) + */ +#ifndef PRODUCT_SCAN +#define PRODUCT_SCAN 0 +#endif + +/* + * Copy an array of words. Thrilling, isn't it? + * This is a good example of how the byte offsets and BIGLITTLE() macros work. + * Another alternative would have been + * memcpy(dest BIG(-len), src BIG(-len), len*sizeof(BNWORD32)), but I find that + * putting operators into conditional macros is confusing. + */ +#ifndef lbnCopy_32 +void +lbnCopy_32(BNWORD32 *dest, BNWORD32 const *src, unsigned len) +{ + memcpy(BIGLITTLE(dest-len,dest), BIGLITTLE(src-len,src), + len * sizeof(*src)); +} +#endif /* !lbnCopy_32 */ + +/* + * Fill n words with zero. This does it manually rather than calling + * memset because it can assume alignment to make things faster while + * memset can't. Note how big-endian numbers are naturally addressed + * using predecrement, while little-endian is postincrement. + */ +#ifndef lbnZero_32 +void +lbnZero_32(BNWORD32 *num, unsigned len) +{ + while (len--) + BIGLITTLE(*--num,*num++) = 0; +} +#endif /* !lbnZero_32 */ + +/* + * Negate an array of words. + * Negation is subtraction from zero. Negating low-order words + * entails doing nothing until a non-zero word is hit. Once that + * is negated, a borrow is generated and never dies until the end + * of the number is hit. Negation with borrow, -x-1, is the same as ~x. + * Repeat that until the end of the number. + * + * Doesn't return borrow out because that's pretty useless - it's + * always set unless the input is 0, which is easy to notice in + * normalized form. + */ +#ifndef lbnNeg_32 +void +lbnNeg_32(BNWORD32 *num, unsigned len) +{ + assert(len); + + /* Skip low-order zero words */ + while (BIGLITTLE(*--num,*num) == 0) { + if (!--len) + return; + LITTLE(num++;) + } + /* Negate the lowest-order non-zero word */ + *num = -*num; + /* Complement all the higher-order words */ + while (--len) { + BIGLITTLE(--num,++num); + *num = ~*num; + } +} +#endif /* !lbnNeg_32 */ + + +/* + * lbnAdd1_32: add the single-word "carry" to the given number. + * Used for minor increments and propagating the carry after + * adding in a shorter bignum. + * + * Technique: If we have a double-width word, presumably the compiler + * can add using its carry in inline code, so we just use a larger + * accumulator to compute the carry from the first addition. + * If not, it's more complex. After adding the first carry, which may + * be > 1, compare the sum and the carry. If the sum wraps (causing a + * carry out from the addition), the result will be less than each of the + * inputs, since the wrap subtracts a number (2^32) which is larger than + * the other input can possibly be. If the sum is >= the carry input, + * return success immediately. + * In either case, if there is a carry, enter a loop incrementing words + * until one does not wrap. Since we are adding 1 each time, the wrap + * will be to 0 and we can test for equality. + */ +#ifndef lbnAdd1_32 /* If defined, it's provided as an asm subroutine */ +#ifdef BNWORD64 +BNWORD32 +lbnAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry) +{ + BNWORD64 t; + assert(len > 0); /* Alternative: if (!len) return carry */ + + t = (BNWORD64)BIGLITTLE(*--num,*num) + carry; + BIGLITTLE(*num,*num++) = (BNWORD32)t; + if ((t >> 32) == 0) + return 0; + while (--len) { + if (++BIGLITTLE(*--num,*num++) != 0) + return 0; + } + return 1; +} +#else /* no BNWORD64 */ +BNWORD32 +lbnAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry) +{ + assert(len > 0); /* Alternative: if (!len) return carry */ + + if ((BIGLITTLE(*--num,*num++) += carry) >= carry) + return 0; + while (--len) { + if (++BIGLITTLE(*--num,*num++) != 0) + return 0; + } + return 1; +} +#endif +#endif/* !lbnAdd1_32 */ + +/* + * lbnSub1_32: subtract the single-word "borrow" from the given number. + * Used for minor decrements and propagating the borrow after + * subtracting a shorter bignum. + * + * Technique: Similar to the add, above. If there is a double-length type, + * use that to generate the first borrow. + * If not, after subtracting the first borrow, which may be > 1, compare + * the difference and the *negative* of the carry. If the subtract wraps + * (causing a borrow out from the subtraction), the result will be at least + * as large as -borrow. If the result < -borrow, then no borrow out has + * appeared and we may return immediately, except when borrow == 0. To + * deal with that case, use the identity that -x = ~x+1, and instead of + * comparing < -borrow, compare for <= ~borrow. + * Either way, if there is a borrow out, enter a loop decrementing words + * until a non-zero word is reached. + * + * Note the cast of ~borrow to (BNWORD32). If the size of an int is larger + * than BNWORD32, C rules say the number is expanded for the arithmetic, so + * the inversion will be done on an int and the value won't be quite what + * is expected. + */ +#ifndef lbnSub1_32 /* If defined, it's provided as an asm subroutine */ +#ifdef BNWORD64 +BNWORD32 +lbnSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow) +{ + BNWORD64 t; + assert(len > 0); /* Alternative: if (!len) return borrow */ + + t = (BNWORD64)BIGLITTLE(*--num,*num) - borrow; + BIGLITTLE(*num,*num++) = (BNWORD32)t; + if ((t >> 32) == 0) + return 0; + while (--len) { + if ((BIGLITTLE(*--num,*num++))-- != 0) + return 0; + } + return 1; +} +#else /* no BNWORD64 */ +BNWORD32 +lbnSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow) +{ + assert(len > 0); /* Alternative: if (!len) return borrow */ + + if ((BIGLITTLE(*--num,*num++) -= borrow) <= (BNWORD32)~borrow) + return 0; + while (--len) { + if ((BIGLITTLE(*--num,*num++))-- != 0) + return 0; + } + return 1; +} +#endif +#endif /* !lbnSub1_32 */ + +/* + * lbnAddN_32: add two bignums of the same length, returning the carry (0 or 1). + * One of the building blocks, along with lbnAdd1, of adding two bignums of + * differing lengths. + * + * Technique: Maintain a word of carry. If there is no double-width type, + * use the same technique as in lbnAdd1, above, to maintain the carry by + * comparing the inputs. Adding the carry sources is used as an OR operator; + * at most one of the two comparisons can possibly be true. The first can + * only be true if carry == 1 and x, the result, is 0. In that case the + * second can't possibly be true. + */ +#ifndef lbnAddN_32 +#ifdef BNWORD64 +BNWORD32 +lbnAddN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len) +{ + BNWORD64 t; + + assert(len > 0); + + t = (BNWORD64)BIGLITTLE(*--num1,*num1) + BIGLITTLE(*--num2,*num2++); + BIGLITTLE(*num1,*num1++) = (BNWORD32)t; + while (--len) { + t = (BNWORD64)BIGLITTLE(*--num1,*num1) + + (BNWORD64)BIGLITTLE(*--num2,*num2++) + (t >> 32); + BIGLITTLE(*num1,*num1++) = (BNWORD32)t; + } + + return (BNWORD32)(t>>32); +} +#else /* no BNWORD64 */ +BNWORD32 +lbnAddN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len) +{ + BNWORD32 x, carry = 0; + + assert(len > 0); /* Alternative: change loop to test at start */ + + do { + x = BIGLITTLE(*--num2,*num2++); + carry = (x += carry) < carry; + carry += (BIGLITTLE(*--num1,*num1++) += x) < x; + } while (--len); + + return carry; +} +#endif +#endif /* !lbnAddN_32 */ + +/* + * lbnSubN_32: add two bignums of the same length, returning the carry (0 or 1). + * One of the building blocks, along with subn1, of subtracting two bignums of + * differing lengths. + * + * Technique: If no double-width type is availble, maintain a word of borrow. + * First, add the borrow to the subtrahend (did you have to learn all those + * awful words in elementary school, too?), and if it overflows, set the + * borrow again. Then subtract the modified subtrahend from the next word + * of input, using the same technique as in subn1, above. + * Adding the borrows is used as an OR operator; at most one of the two + * comparisons can possibly be true. The first can only be true if + * borrow == 1 and x, the result, is 0. In that case the second can't + * possibly be true. + * + * In the double-word case, (BNWORD32)-(t>>32) is subtracted, rather than + * adding t>>32, because the shift would need to sign-extend and that's + * not guaranteed to happen in ANSI C, even with signed types. + */ +#ifndef lbnSubN_32 +#ifdef BNWORD64 +BNWORD32 +lbnSubN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len) +{ + BNWORD64 t; + + assert(len > 0); + + t = (BNWORD64)BIGLITTLE(*--num1,*num1) - BIGLITTLE(*--num2,*num2++); + BIGLITTLE(*num1,*num1++) = (BNWORD32)t; + + while (--len) { + t = (BNWORD64)BIGLITTLE(*--num1,*num1) - + (BNWORD64)BIGLITTLE(*--num2,*num2++) - (BNWORD32)-(t >> 32); + BIGLITTLE(*num1,*num1++) = (BNWORD32)t; + } + + return -(BNWORD32)(t>>32); +} +#else +BNWORD32 +lbnSubN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len) +{ + BNWORD32 x, borrow = 0; + + assert(len > 0); /* Alternative: change loop to test at start */ + + do { + x = BIGLITTLE(*--num2,*num2++); + borrow = (x += borrow) < borrow; + borrow += (BIGLITTLE(*--num1,*num1++) -= x) > (BNWORD32)~x; + } while (--len); + + return borrow; +} +#endif +#endif /* !lbnSubN_32 */ + +#ifndef lbnCmp_32 +/* + * lbnCmp_32: compare two bignums of equal length, returning the sign of + * num1 - num2. (-1, 0 or +1). + * + * Technique: Change the little-endian pointers to big-endian pointers + * and compare from the most-significant end until a difference if found. + * When it is, figure out the sign of the difference and return it. + */ +int +lbnCmp_32(BNWORD32 const *num1, BNWORD32 const *num2, unsigned len) +{ + BIGLITTLE(num1 -= len, num1 += len); + BIGLITTLE(num2 -= len, num2 += len); + + while (len--) { + if (BIGLITTLE(*num1++ != *num2++, *--num1 != *--num2)) { + if (BIGLITTLE(num1[-1] < num2[-1], *num1 < *num2)) + return -1; + else + return 1; + } + } + return 0; +} +#endif /* !lbnCmp_32 */ + +/* + * mul32_ppmmaa(ph,pl,x,y,a,b) is an optional routine that + * computes (ph,pl) = x * y + a + b. mul32_ppmma and mul32_ppmm + * are simpler versions. If you want to be lazy, all of these + * can be defined in terms of the others, so here we create any + * that have not been defined in terms of the ones that have been. + */ + +/* Define ones with fewer a's in terms of ones with more a's */ +#if !defined(mul32_ppmma) && defined(mul32_ppmmaa) +#define mul32_ppmma(ph,pl,x,y,a) mul32_ppmmaa(ph,pl,x,y,a,0) +#endif + +#if !defined(mul32_ppmm) && defined(mul32_ppmma) +#define mul32_ppmm(ph,pl,x,y) mul32_ppmma(ph,pl,x,y,0) +#endif + +/* + * Use this definition to test the mul32_ppmm-based operations on machines + * that do not provide mul32_ppmm. Change the final "0" to a "1" to + * enable it. + */ +#if !defined(mul32_ppmm) && defined(BNWORD64) && 0 /* Debugging */ +#define mul32_ppmm(ph,pl,x,y) \ + ({BNWORD64 _ = (BNWORD64)(x)*(y); (pl) = _; (ph) = _>>32;}) +#endif + +#if defined(mul32_ppmm) && !defined(mul32_ppmma) +#define mul32_ppmma(ph,pl,x,y,a) \ + (mul32_ppmm(ph,pl,x,y), (ph) += ((pl) += (a)) < (a)) +#endif + +#if defined(mul32_ppmma) && !defined(mul32_ppmmaa) +#define mul32_ppmmaa(ph,pl,x,y,a,b) \ + (mul32_ppmma(ph,pl,x,y,a), (ph) += ((pl) += (b)) < (b)) +#endif + +/* + * lbnMulN1_32: Multiply an n-word input by a 1-word input and store the + * n+1-word product. This uses either the mul32_ppmm and mul32_ppmma + * macros, or C multiplication with the BNWORD64 type. This uses mul32_ppmma + * if available, assuming you won't bother defining it unless you can do + * better than the normal multiplication. + */ +#ifndef lbnMulN1_32 +#ifdef lbnMulAdd1_32 /* If we have this asm primitive, use it. */ +void +lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + lbnZero_32(out, len); + BIGLITTLE(*(out-len),*(out+len)) = lbnMulAdd1_32(out, in, len, k); +} +#elif defined(mul32_ppmm) +void +lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + BNWORD32 prod, carry, carryin; + + assert(len > 0); + + BIG(--out;--in;); + mul32_ppmm(carry, *out, *in, k); + LITTLE(out++;in++;) + + while (--len) { + BIG(--out;--in;) + carryin = carry; + mul32_ppmma(carry, *out, *in, k, carryin); + LITTLE(out++;in++;) + } + BIGLITTLE(*--out,*out) = carry; +} +#elif defined(BNWORD64) +void +lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + BNWORD64 p; + + assert(len > 0); + + p = (BNWORD64)BIGLITTLE(*--in,*in++) * k; + BIGLITTLE(*--out,*out++) = (BNWORD32)p; + + while (--len) { + p = (BNWORD64)BIGLITTLE(*--in,*in++) * k + (BNWORD32)(p >> 32); + BIGLITTLE(*--out,*out++) = (BNWORD32)p; + } + BIGLITTLE(*--out,*out) = (BNWORD32)(p >> 32); +} +#else +#error No 32x32 -> 64 multiply available for 32-bit bignum package +#endif +#endif /* lbnMulN1_32 */ + +/* + * lbnMulAdd1_32: Multiply an n-word input by a 1-word input and add the + * low n words of the product to the destination. *Returns the n+1st word + * of the product.* (That turns out to be more convenient than adding + * it into the destination and dealing with a possible unit carry out + * of *that*.) This uses either the mul32_ppmma and mul32_ppmmaa macros, + * or C multiplication with the BNWORD64 type. + * + * If you're going to write assembly primitives, this is the one to + * start with. It is by far the most commonly called function. + */ +#ifndef lbnMulAdd1_32 +#if defined(mul32_ppmm) +BNWORD32 +lbnMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + BNWORD32 prod, carry, carryin; + + assert(len > 0); + + BIG(--out;--in;); + carryin = *out; + mul32_ppmma(carry, *out, *in, k, carryin); + LITTLE(out++;in++;) + + while (--len) { + BIG(--out;--in;); + carryin = carry; + mul32_ppmmaa(carry, prod, *in, k, carryin, *out); + *out = prod; + LITTLE(out++;in++;) + } + + return carry; +} +#elif defined(BNWORD64) +BNWORD32 +lbnMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + BNWORD64 p; + + assert(len > 0); + + p = (BNWORD64)BIGLITTLE(*--in,*in++) * k + BIGLITTLE(*--out,*out); + BIGLITTLE(*out,*out++) = (BNWORD32)p; + + while (--len) { + p = (BNWORD64)BIGLITTLE(*--in,*in++) * k + + (BNWORD32)(p >> 32) + BIGLITTLE(*--out,*out); + BIGLITTLE(*out,*out++) = (BNWORD32)p; + } + + return (BNWORD32)(p >> 32); +} +#else +#error No 32x32 -> 64 multiply available for 32-bit bignum package +#endif +#endif /* lbnMulAdd1_32 */ + +/* + * lbnMulSub1_32: Multiply an n-word input by a 1-word input and subtract the + * n-word product from the destination. Returns the n+1st word of the product. + * This uses either the mul32_ppmm and mul32_ppmma macros, or + * C multiplication with the BNWORD64 type. + * + * This is rather uglier than adding, but fortunately it's only used in + * division which is not used too heavily. + */ +#ifndef lbnMulN1_32 +#if defined(mul32_ppmm) +BNWORD32 +lbnMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + BNWORD32 prod, carry, carryin; + + assert(len > 0); + + BIG(--in;) + mul32_ppmm(carry, prod, *in, k); + LITTLE(in++;) + carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD32)~prod; + + while (--len) { + BIG(--in;); + carryin = carry; + mul32_ppmma(carry, prod, *in, k, carryin); + LITTLE(in++;) + carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD32)~prod; + } + + return carry; +} +#elif defined(BNWORD64) +BNWORD32 +lbnMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + BNWORD64 p; + BNWORD32 carry, t; + + assert(len > 0); + + p = (BNWORD64)BIGLITTLE(*--in,*in++) * k; + t = BIGLITTLE(*--out,*out); + carry = (BNWORD32)(p>>32) + ((BIGLITTLE(*out,*out++)=t-(BNWORD32)p) > t); + + while (--len) { + p = (BNWORD64)BIGLITTLE(*--in,*in++) * k + carry; + t = BIGLITTLE(*--out,*out); + carry = (BNWORD32)(p>>32) + + ( (BIGLITTLE(*out,*out++)=t-(BNWORD32)p) > t ); + } + + return carry; +} +#else +#error No 32x32 -> 64 multiply available for 32-bit bignum package +#endif +#endif /* !lbnMulSub1_32 */ + +/* + * Shift n words left "shift" bits. 0 < shift < 32. Returns the + * carry, any bits shifted off the left-hand side (0 <= carry < 2^shift). + */ +#ifndef lbnLshift_32 +BNWORD32 +lbnLshift_32(BNWORD32 *num, unsigned len, unsigned shift) +{ + BNWORD32 x, carry; + + assert(shift > 0); + assert(shift < 32); + + carry = 0; + while (len--) { + BIG(--num;) + x = *num; + *num = (x<> (32-shift); + } + return carry; +} +#endif /* !lbnLshift_32 */ + +/* + * An optimized version of the above, for shifts of 1. + * Some machines can use add-with-carry tricks for this. + */ +#ifndef lbnDouble_32 +BNWORD32 +lbnDouble_32(BNWORD32 *num, unsigned len) +{ + BNWORD32 x, carry; + + carry = 0; + while (len--) { + BIG(--num;) + x = *num; + *num = (x<<1) | carry; + LITTLE(num++;) + carry = x >> (32-1); + } + return carry; +} +#endif /* !lbnDouble_32 */ + +/* + * Shift n words right "shift" bits. 0 < shift < 32. Returns the + * carry, any bits shifted off the right-hand side (0 <= carry < 2^shift). + */ +#ifndef lbnRshift_32 +BNWORD32 +lbnRshift_32(BNWORD32 *num, unsigned len, unsigned shift) +{ + BNWORD32 x, carry = 0; + + assert(shift > 0); + assert(shift < 32); + + BIGLITTLE(num -= len, num += len); + + while (len--) { + LITTLE(--num;) + x = *num; + *num = (x>>shift) | carry; + BIG(num++;) + carry = x << (32-shift); + } + return carry >> (32-shift); +} +#endif /* !lbnRshift_32 */ + +/* + * Multiply two numbers of the given lengths. prod and num2 may overlap, + * provided that the low len1 bits of prod are free. (This corresponds + * nicely to the place the result is returned from lbnMontReduce_32.) + * + * TODO: Use Karatsuba multiply. The overlap constraints may have + * to get rewhacked. + */ +#ifndef lbnMul_32 +void +lbnMul_32(BNWORD32 *prod, BNWORD32 const *num1, unsigned len1, + BNWORD32 const *num2, unsigned len2) +{ + /* Special case of zero */ + if (!len1 || !len2) { + lbnZero_32(prod, len1+len2); + return; + } + + /* Multiply first word */ + lbnMulN1_32(prod, num1, len1, BIGLITTLE(*--num2,*num2++)); + + /* + * Add in subsequent words, storing the most significant word, + * which is new each time. + */ + while (--len2) { + BIGLITTLE(--prod,prod++); + BIGLITTLE(*(prod-len1-1),*(prod+len1)) = + lbnMulAdd1_32(prod, num1, len1, BIGLITTLE(*--num2,*num2++)); + } +} +#endif /* !lbnMul_32 */ + +/* + * lbnMulX_32 is a square multiply - both inputs are the same length. + * It's normally just a macro wrapper around the general multiply, + * but might be implementable in assembly more efficiently (such as + * when product scanning). + */ +#ifndef lbnMulX_32 +#if defined(BNWORD64) && PRODUCT_SCAN +/* + * Test code to see whether product scanning is any faster. It seems + * to make the C code slower, so PRODUCT_SCAN is not defined. + */ +static void +lbnMulX_32(BNWORD32 *prod, BNWORD32 const *num1, BNWORD32 const *num2, + unsigned len) +{ + BNWORD64 x, y; + BNWORD32 const *p1, *p2; + unsigned carry; + unsigned i, j; + + /* Special case of zero */ + if (!len) + return; + + x = (BNWORD64)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]); + BIGLITTLE(*--prod, *prod++) = (BNWORD32)x; + x >>= 32; + + for (i = 1; i < len; i++) { + carry = 0; + p1 = num1; + p2 = BIGLITTLE(num2-i-1,num2+i+1); + for (j = 0; j <= i; j++) { + BIG(y = (BNWORD64)*--p1 * *p2++;) + LITTLE(y = (BNWORD64)*p1++ * *--p2;) + x += y; + carry += (x < y); + } + BIGLITTLE(*--prod,*prod++) = (BNWORD32)x; + x = (x >> 32) | (BNWORD64)carry << 32; + } + for (i = 1; i < len; i++) { + carry = 0; + p1 = BIGLITTLE(num1-i,num1+i); + p2 = BIGLITTLE(num2-len,num2+len); + for (j = i; j < len; j++) { + BIG(y = (BNWORD64)*--p1 * *p2++;) + LITTLE(y = (BNWORD64)*p1++ * *--p2;) + x += y; + carry += (x < y); + } + BIGLITTLE(*--prod,*prod++) = (BNWORD32)x; + x = (x >> 32) | (BNWORD64)carry << 32; + } + + BIGLITTLE(*--prod,*prod) = (BNWORD32)x; +} +#else /* !defined(BNWORD64) || !PRODUCT_SCAN */ +/* Default trivial macro definition */ +#define lbnMulX_32(prod, num1, num2, len) lbnMul_32(prod, num1, len, num2, len) +#endif /* !defined(BNWORD64) || !PRODUCT_SCAN */ +#endif /* !lbmMulX_32 */ + +#if !defined(lbnMontMul_32) && defined(BNWORD64) && PRODUCT_SCAN +/* + * Test code for product-scanning multiply. This seems to slow the C + * code down rather than speed it up. + * This does a multiply and Montgomery reduction together, using the + * same loops. The outer loop scans across the product, twice. + * The first pass computes the low half of the product and the + * Montgomery multipliers. These are stored in the product array, + * which contains no data as of yet. x and carry add up the columns + * and propagate carries forward. + * + * The second half multiplies the upper half, adding in the modulus + * times the Montgomery multipliers. The results of this multiply + * are stored. + */ +static void +lbnMontMul_32(BNWORD32 *prod, BNWORD32 const *num1, BNWORD32 const *num2, + BNWORD32 const *mod, unsigned len, BNWORD32 inv) +{ + BNWORD64 x, y; + BNWORD32 const *p1, *p2, *pm; + BNWORD32 *pp; + BNWORD32 t; + unsigned carry; + unsigned i, j; + + /* Special case of zero */ + if (!len) + return; + + /* + * This computes directly into the high half of prod, so just + * shift the pointer and consider prod only "len" elements long + * for the rest of the code. + */ + BIGLITTLE(prod -= len, prod += len); + + /* Pass 1 - compute Montgomery multipliers */ + /* First iteration can have certain simplifications. */ + x = (BNWORD64)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]); + BIGLITTLE(prod[-1], prod[0]) = t = inv * (BNWORD32)x; + y = (BNWORD64)t * BIGLITTLE(mod[-1],mod[0]); + x += y; + /* Note: GCC 2.6.3 has a bug if you try to eliminate "carry" */ + carry = (x < y); + assert((BNWORD32)x == 0); + x = x >> 32 | (BNWORD64)carry << 32; + + for (i = 1; i < len; i++) { + carry = 0; + p1 = num1; + p2 = BIGLITTLE(num2-i-1,num2+i+1); + pp = prod; + pm = BIGLITTLE(mod-i-1,mod+i+1); + for (j = 0; j < i; j++) { + y = (BNWORD64)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2); + x += y; + carry += (x < y); + y = (BNWORD64)BIGLITTLE(*--pp * *pm++, *pp++ * *--pm); + x += y; + carry += (x < y); + } + y = (BNWORD64)BIGLITTLE(p1[-1] * p2[0], p1[0] * p2[-1]); + x += y; + carry += (x < y); + assert(BIGLITTLE(pp == prod-i, pp == prod+i)); + BIGLITTLE(pp[-1], pp[0]) = t = inv * (BNWORD32)x; + assert(BIGLITTLE(pm == mod-1, pm == mod+1)); + y = (BNWORD64)t * BIGLITTLE(pm[0],pm[-1]); + x += y; + carry += (x < y); + assert((BNWORD32)x == 0); + x = x >> 32 | (BNWORD64)carry << 32; + } + + /* Pass 2 - compute reduced product and store */ + for (i = 1; i < len; i++) { + carry = 0; + p1 = BIGLITTLE(num1-i,num1+i); + p2 = BIGLITTLE(num2-len,num2+len); + pm = BIGLITTLE(mod-i,mod+i); + pp = BIGLITTLE(prod-len,prod+len); + for (j = i; j < len; j++) { + y = (BNWORD64)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2); + x += y; + carry += (x < y); + y = (BNWORD64)BIGLITTLE(*--pm * *pp++, *pm++ * *--pp); + x += y; + carry += (x < y); + } + assert(BIGLITTLE(pm == mod-len, pm == mod+len)); + assert(BIGLITTLE(pp == prod-i, pp == prod+i)); + BIGLITTLE(pp[0],pp[-1]) = (BNWORD32)x; + x = (x >> 32) | (BNWORD64)carry << 32; + } + + /* Last round of second half, simplified. */ + BIGLITTLE(*(prod-len),*(prod+len-1)) = (BNWORD32)x; + carry = (x >> 32); + + while (carry) + carry -= lbnSubN_32(prod, mod, len); + while (lbnCmp_32(prod, mod, len) >= 0) + (void)lbnSubN_32(prod, mod, len); +} +/* Suppress later definition */ +#define lbnMontMul_32 lbnMontMul_32 +#endif + +#if !defined(lbnSquare_32) && defined(BNWORD64) && PRODUCT_SCAN +/* + * Trial code for product-scanning squaring. This seems to slow the C + * code down rather than speed it up. + */ +void +lbnSquare_32(BNWORD32 *prod, BNWORD32 const *num, unsigned len) +{ + BNWORD64 x, y, z; + BNWORD32 const *p1, *p2; + unsigned carry; + unsigned i, j; + + /* Special case of zero */ + if (!len) + return; + + /* Word 0 of product */ + x = (BNWORD64)BIGLITTLE(num[-1] * num[-1], num[0] * num[0]); + BIGLITTLE(*--prod, *prod++) = (BNWORD32)x; + x >>= 32; + + /* Words 1 through len-1 */ + for (i = 1; i < len; i++) { + carry = 0; + y = 0; + p1 = num; + p2 = BIGLITTLE(num-i-1,num+i+1); + for (j = 0; j < (i+1)/2; j++) { + BIG(z = (BNWORD64)*--p1 * *p2++;) + LITTLE(z = (BNWORD64)*p1++ * *--p2;) + y += z; + carry += (y < z); + } + y += z = y; + carry += carry + (y < z); + if ((i & 1) == 0) { + assert(BIGLITTLE(--p1 == p2, p1 == --p2)); + BIG(z = (BNWORD64)*p2 * *p2;) + LITTLE(z = (BNWORD64)*p1 * *p1;) + y += z; + carry += (y < z); + } + x += y; + carry += (x < y); + BIGLITTLE(*--prod,*prod++) = (BNWORD32)x; + x = (x >> 32) | (BNWORD64)carry << 32; + } + /* Words len through 2*len-2 */ + for (i = 1; i < len; i++) { + carry = 0; + y = 0; + p1 = BIGLITTLE(num-i,num+i); + p2 = BIGLITTLE(num-len,num+len); + for (j = 0; j < (len-i)/2; j++) { + BIG(z = (BNWORD64)*--p1 * *p2++;) + LITTLE(z = (BNWORD64)*p1++ * *--p2;) + y += z; + carry += (y < z); + } + y += z = y; + carry += carry + (y < z); + if ((len-i) & 1) { + assert(BIGLITTLE(--p1 == p2, p1 == --p2)); + BIG(z = (BNWORD64)*p2 * *p2;) + LITTLE(z = (BNWORD64)*p1 * *p1;) + y += z; + carry += (y < z); + } + x += y; + carry += (x < y); + BIGLITTLE(*--prod,*prod++) = (BNWORD32)x; + x = (x >> 32) | (BNWORD64)carry << 32; + } + + /* Word 2*len-1 */ + BIGLITTLE(*--prod,*prod) = (BNWORD32)x; +} +/* Suppress later definition */ +#define lbnSquare_32 lbnSquare_32 +#endif + +/* + * Square a number, using optimized squaring to reduce the number of + * primitive multiples that are executed. There may not be any + * overlap of the input and output. + * + * Technique: Consider the partial products in the multiplication + * of "abcde" by itself: + * + * a b c d e + * * a b c d e + * ================== + * ae be ce de ee + * ad bd cd dd de + * ac bc cc cd ce + * ab bb bc bd be + * aa ab ac ad ae + * + * Note that everything above the main diagonal: + * ae be ce de = (abcd) * e + * ad bd cd = (abc) * d + * ac bc = (ab) * c + * ab = (a) * b + * + * is a copy of everything below the main diagonal: + * de + * cd ce + * bc bd be + * ab ac ad ae + * + * Thus, the sum is 2 * (off the diagonal) + diagonal. + * + * This is accumulated beginning with the diagonal (which + * consist of the squares of the digits of the input), which is then + * divided by two, the off-diagonal added, and multiplied by two + * again. The low bit is simply a copy of the low bit of the + * input, so it doesn't need special care. + * + * TODO: Merge the shift by 1 with the squaring loop. + * TODO: Use Karatsuba. (a*W+b)^2 = a^2 * (W^2+W) + b^2 * (W+1) - (a-b)^2 * W. + */ +#ifndef lbnSquare_32 +void +lbnSquare_32(BNWORD32 *prod, BNWORD32 const *num, unsigned len) +{ + BNWORD32 t; + BNWORD32 *prodx = prod; /* Working copy of the argument */ + BNWORD32 const *numx = num; /* Working copy of the argument */ + unsigned lenx = len; /* Working copy of the argument */ + + if (!len) + return; + + /* First, store all the squares */ + while (lenx--) { +#ifdef mul32_ppmm + BNWORD32 ph, pl; + t = BIGLITTLE(*--numx,*numx++); + mul32_ppmm(ph,pl,t,t); + BIGLITTLE(*--prodx,*prodx++) = pl; + BIGLITTLE(*--prodx,*prodx++) = ph; +#elif defined(BNWORD64) /* use BNWORD64 */ + BNWORD64 p; + t = BIGLITTLE(*--numx,*numx++); + p = (BNWORD64)t * t; + BIGLITTLE(*--prodx,*prodx++) = (BNWORD32)p; + BIGLITTLE(*--prodx,*prodx++) = (BNWORD32)(p>>32); +#else /* Use lbnMulN1_32 */ + t = BIGLITTLE(numx[-1],*numx); + lbnMulN1_32(prodx, numx, 1, t); + BIGLITTLE(--numx,numx++); + BIGLITTLE(prodx -= 2, prodx += 2); +#endif + } + /* Then, shift right 1 bit */ + (void)lbnRshift_32(prod, 2*len, 1); + + /* Then, add in the off-diagonal sums */ + lenx = len; + numx = num; + prodx = prod; + while (--lenx) { + t = BIGLITTLE(*--numx,*numx++); + BIGLITTLE(--prodx,prodx++); + t = lbnMulAdd1_32(prodx, numx, lenx, t); + lbnAdd1_32(BIGLITTLE(prodx-lenx,prodx+lenx), lenx+1, t); + BIGLITTLE(--prodx,prodx++); + } + + /* Shift it back up */ + lbnDouble_32(prod, 2*len); + + /* And set the low bit appropriately */ + BIGLITTLE(prod[-1],prod[0]) |= BIGLITTLE(num[-1],num[0]) & 1; +} +#endif /* !lbnSquare_32 */ + +/* + * lbnNorm_32 - given a number, return a modified length such that the + * most significant digit is non-zero. Zero-length input is okay. + */ +#ifndef lbnNorm_32 +unsigned +lbnNorm_32(BNWORD32 const *num, unsigned len) +{ + BIGLITTLE(num -= len,num += len); + while (len && BIGLITTLE(*num++,*--num) == 0) + --len; + return len; +} +#endif /* lbnNorm_32 */ + +/* + * lbnBits_32 - return the number of significant bits in the array. + * It starts by normalizing the array. Zero-length input is okay. + * Then assuming there's anything to it, it fetches the high word, + * generates a bit length by multiplying the word length by 32, and + * subtracts off 32/2, 32/4, 32/8, ... bits if the high bits are clear. + */ +#ifndef lbnBits_32 +unsigned +lbnBits_32(BNWORD32 const *num, unsigned len) +{ + BNWORD32 t; + unsigned i; + + len = lbnNorm_32(num, len); + if (len) { + t = BIGLITTLE(*(num-len),*(num+(len-1))); + assert(t); + len *= 32; + i = 32/2; + do { + if (t >> i) + t >>= i; + else + len -= i; + } while ((i /= 2) != 0); + } + return len; +} +#endif /* lbnBits_32 */ + +/* + * If defined, use hand-rolled divide rather than compiler's native. + * If the machine doesn't do it in line, the manual code is probably + * faster, since it can assume normalization and the fact that the + * quotient will fit into 32 bits, which a general 64-bit divide + * in a compiler's run-time library can't do. + */ +#ifndef BN_SLOW_DIVIDE_64 +/* Assume that divisors of more than thirty-two bits are slow */ +#define BN_SLOW_DIVIDE_64 (64 > 0x20) +#endif + +/* + * Return (nh<<32|nl) % d, and place the quotient digit into *q. + * It is guaranteed that nh < d, and that d is normalized (with its high + * bit set). If we have a double-width type, it's easy. If not, ooh, + * yuk! + */ +#ifndef lbnDiv21_32 +#if defined(BNWORD64) && !BN_SLOW_DIVIDE_64 +BNWORD32 +lbnDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d) +{ + BNWORD64 n = (BNWORD64)nh << 32 | nl; + + /* Divisor must be normalized */ + assert(d >> (32-1) == 1); + + *q = n / d; + return n % d; +} +#else +/* + * This is where it gets ugly. + * + * Do the division in two halves, using Algorithm D from section 4.3.1 + * of Knuth. Note Theorem B from that section, that the quotient estimate + * is never more than the true quotient, and is never more than two + * too low. + * + * The mapping onto conventional long division is (everything a half word): + * _____________qh___ql_ + * dh dl ) nh.h nh.l nl.h nl.l + * - (qh * d) + * ----------- + * rrrr rrrr nl.l + * - (ql * d) + * ----------- + * rrrr rrrr + * + * The implicit 3/2-digit d*qh and d*ql subtractors are computed this way: + * First, estimate a q digit so that nh/dh works. Subtracting qh*dh from + * the (nh.h nh.l) list leaves a 1/2-word remainder r. Then compute the + * low part of the subtractor, qh * dl. This also needs to be subtracted + * from (nh.h nh.l nl.h) to get the final remainder. So we take the + * remainder, which is (nh.h nh.l) - qh*dl, shift it and add in nl.h, and + * try to subtract qh * dl from that. Since the remainder is 1/2-word + * long, shifting and adding nl.h results in a single word r. + * It is possible that the remainder we're working with, r, is less than + * the product qh * dl, if we estimated qh too high. The estimation + * technique can produce a qh that is too large (never too small), leading + * to r which is too small. In that case, decrement the digit qh, add + * shifted dh to r (to correct for that error), and subtract dl from the + * product we're comparing r with. That's the "correct" way to do it, but + * just adding dl to r instead of subtracting it from the product is + * equivalent and a lot simpler. You just have to watch out for overflow. + * + * The process is repeated with (rrrr rrrr nl.l) for the low digit of the + * quotient ql. + * + * The various uses of 32/2 for shifts are because of the note about + * automatic editing of this file at the very top of the file. + */ +#define highhalf(x) ( (x) >> 32/2 ) +#define lowhalf(x) ( (x) & (((BNWORD32)1 << 32/2)-1) ) +BNWORD32 +lbnDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d) +{ + BNWORD32 dh = highhalf(d), dl = lowhalf(d); + BNWORD32 qh, ql, prod, r; + + /* Divisor must be normalized */ + assert((d >> (32-1)) == 1); + + /* Do first half-word of division */ + qh = nh / dh; + r = nh % dh; + prod = qh * dl; + + /* + * Add next half-word of numerator to remainder and correct. + * qh may be up to two too large. + */ + r = (r << (32/2)) | highhalf(nl); + if (r < prod) { + --qh; r += d; + if (r >= d && r < prod) { + --qh; r += d; + } + } + r -= prod; + + /* Do second half-word of division */ + ql = r / dh; + r = r % dh; + prod = ql * dl; + + r = (r << (32/2)) | lowhalf(nl); + if (r < prod) { + --ql; r += d; + if (r >= d && r < prod) { + --ql; r += d; + } + } + r -= prod; + + *q = (qh << (32/2)) | ql; + + return r; +} +#endif +#endif /* lbnDiv21_32 */ + + +/* + * In the division functions, the dividend and divisor are referred to + * as "n" and "d", which stand for "numerator" and "denominator". + * + * The quotient is (nlen-dlen+1) digits long. It may be overlapped with + * the high (nlen-dlen) words of the dividend, but one extra word is needed + * on top to hold the top word. + */ + +/* + * Divide an n-word number by a 1-word number, storing the remainder + * and n-1 words of the n-word quotient. The high word is returned. + * It IS legal for rem to point to the same address as n, and for + * q to point one word higher. + * + * TODO: If BN_SLOW_DIVIDE_64, add a divnhalf_32 which uses 32-bit + * dividends if the divisor is half that long. + * TODO: Shift the dividend on the fly to avoid the last division and + * instead have a remainder that needs shifting. + * TODO: Use reciprocals rather than dividing. + */ +#ifndef lbnDiv1_32 +BNWORD32 +lbnDiv1_32(BNWORD32 *q, BNWORD32 *rem, BNWORD32 const *n, unsigned len, + BNWORD32 d) +{ + unsigned shift; + unsigned xlen; + BNWORD32 r; + BNWORD32 qhigh; + + assert(len > 0); + assert(d); + + if (len == 1) { + r = *n; + *rem = r%d; + return r/d; + } + + shift = 0; + r = d; + xlen = 32/2; + do { + if (r >> xlen) + r >>= xlen; + else + shift += xlen; + } while ((xlen /= 2) != 0); + assert((d >> (32-1-shift)) == 1); + d <<= shift; + + BIGLITTLE(q -= len-1,q += len-1); + BIGLITTLE(n -= len,n += len); + + r = BIGLITTLE(*n++,*--n); + if (r < d) { + qhigh = 0; + } else { + qhigh = r/d; + r %= d; + } + + xlen = len; + while (--xlen) + r = lbnDiv21_32(BIGLITTLE(q++,--q), r, BIGLITTLE(*n++,*--n), d); + + /* + * Final correction for shift - shift the quotient up "shift" + * bits, and merge in the extra bits of quotient. Then reduce + * the final remainder mod the real d. + */ + if (shift) { + d >>= shift; + qhigh = (qhigh << shift) | lbnLshift_32(q, len-1, shift); + BIGLITTLE(q[-1],*q) |= r/d; + r %= d; + } + *rem = r; + + return qhigh; +} +#endif + +/* + * This function performs a "quick" modulus of a number with a divisor + * d which is guaranteed to be at most sixteen bits, i.e. less than 65536. + * This applies regardless of the word size the library is compiled with. + * + * This function is important to prime generation, for sieving. + */ +#ifndef lbnModQ_32 +/* If there's a custom lbnMod21_32, no normalization needed */ +#ifdef lbnMod21_32 +unsigned +lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d) +{ + unsigned i, shift; + BNWORD32 r; + + assert(len > 0); + + BIGLITTLE(n -= len,n += len); + + /* Try using a compare to avoid the first divide */ + r = BIGLITTLE(*n++,*--n); + if (r >= d) + r %= d; + while (--len) + r = lbnMod21_32(r, BIGLITTLE(*n++,*--n), d); + + return r; +} +#elif defined(BNWORD64) && !BN_SLOW_DIVIDE_64 +unsigned +lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d) +{ + BNWORD32 r; + + if (!--len) + return BIGLITTLE(n[-1],n[0]) % d; + + BIGLITTLE(n -= len,n += len); + r = BIGLITTLE(n[-1],n[0]); + + do { + r = (BNWORD32)((((BNWORD64)r<<32) | BIGLITTLE(*n++,*--n)) % d); + } while (--len); + + return r; +} +#elif 32 >= 0x20 +/* + * If the single word size can hold 65535*65536, then this function + * is avilable. + */ +#ifndef highhalf +#define highhalf(x) ( (x) >> 32/2 ) +#define lowhalf(x) ( (x) & ((1 << 32/2)-1) ) +#endif +unsigned +lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d) +{ + BNWORD32 r, x; + + BIGLITTLE(n -= len,n += len); + + r = BIGLITTLE(*n++,*--n); + while (--len) { + x = BIGLITTLE(*n++,*--n); + r = (r%d << 32/2) | highhalf(x); + r = (r%d << 32/2) | lowhalf(x); + } + + return r%d; +} +#else +/* Default case - use lbnDiv21_32 */ +unsigned +lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d) +{ + unsigned i, shift; + BNWORD32 r; + BNWORD32 q; + + assert(len > 0); + + shift = 0; + r = d; + i = 32; + while (i /= 2) { + if (r >> i) + r >>= i; + else + shift += i; + } + assert(d >> (32-1-shift) == 1); + d <<= shift; + + BIGLITTLE(n -= len,n += len); + + r = BIGLITTLE(*n++,*--n); + if (r >= d) + r %= d; + + while (--len) + r = lbnDiv21_32(&q, r, BIGLITTLE(*n++,*--n), d); + + /* + * Final correction for shift - shift the quotient up "shift" + * bits, and merge in the extra bits of quotient. Then reduce + * the final remainder mod the real d. + */ + if (shift) + r %= d >> shift; + + return r; +} +#endif +#endif /* lbnModQ_32 */ + +/* + * Reduce n mod d and return the quotient. That is, find: + * q = n / d; + * n = n % d; + * d is altered during the execution of this subroutine by normalizing it. + * It must already have its most significant word non-zero; it is shifted + * so its most significant bit is non-zero. + * + * The quotient q is nlen-dlen+1 words long. To make it possible to + * overlap the quptient with the input (you can store it in the high dlen + * words), the high word of the quotient is *not* stored, but is returned. + * (If all you want is the remainder, you don't care about it, anyway.) + * + * This uses algorithm D from Knuth (4.3.1), except that we do binary + * (shift) normalization of the divisor. WARNING: This is hairy! + * + * This function is used for some modular reduction, but it is not used in + * the modular exponentiation loops; they use Montgomery form and the + * corresponding, more efficient, Montgomery reduction. This code + * is needed for the conversion to Montgomery form, however, so it + * has to be here and it might as well be reasonably efficient. + * + * The overall operation is as follows ("top" and "up" refer to the + * most significant end of the number; "bottom" and "down", the least): + * + * - Shift the divisor up until the most significant bit is set. + * - Shift the dividend up the same amount. This will produce the + * correct quotient, and the remainder can be recovered by shifting + * it back down the same number of bits. This may produce an overflow + * word, but the word is always strictly less than the most significant + * divisor word. + * - Estimate the first quotient digit qhat: + * - First take the top two words (one of which is the overflow) of the + * dividend and divide by the top word of the divisor: + * qhat = (nh,nm)/dh. This qhat is >= the correct quotient digit + * and, since dh is normalized, it is at most two over. + * - Second, correct by comparing the top three words. If + * (dh,dl) * qhat > (nh,nm,ml), decrease qhat and try again. + * The second iteration can be simpler because there can't be a third. + * The computation can be simplified by subtracting dh*qhat from + * both sides, suitably shifted. This reduces the left side to + * dl*qhat. On the right, (nh,nm)-dh*qhat is simply the + * remainder r from (nh,nm)%dh, so the right is (r,nl). + * This produces qhat that is almost always correct and at + * most (prob ~ 2/2^32) one too high. + * - Subtract qhat times the divisor (suitably shifted) from the dividend. + * If there is a borrow, qhat was wrong, so decrement it + * and add the divisor back in (once). + * - Store the final quotient digit qhat in the quotient array q. + * + * Repeat the quotient digit computation for successive digits of the + * quotient until the whole quotient has been computed. Then shift the + * divisor and the remainder down to correct for the normalization. + * + * TODO: Special case 2-word divisors. + * TODO: Use reciprocals rather than dividing. + */ +#ifndef divn_32 +BNWORD32 +lbnDiv_32(BNWORD32 *q, BNWORD32 *n, unsigned nlen, BNWORD32 *d, unsigned dlen) +{ + BNWORD32 nh,nm,nl; /* Top three words of the dividend */ + BNWORD32 dh,dl; /* Top two words of the divisor */ + BNWORD32 qhat; /* Extimate of quotient word */ + BNWORD32 r; /* Remainder from quotient estimate division */ + BNWORD32 qhigh; /* High word of quotient */ + unsigned i; /* Temp */ + unsigned shift; /* Bits shifted by normalization */ + unsigned qlen = nlen-dlen; /* Size of quotient (less 1) */ +#ifdef mul32_ppmm + BNWORD32 t32; +#elif defined(BNWORD64) + BNWORD64 t64; +#else /* use lbnMulN1_32 */ + BNWORD32 t2[2]; +#define t2high BIGLITTLE(t2[0],t2[1]) +#define t2low BIGLITTLE(t2[1],t2[0]) +#endif + + assert(dlen); + assert(nlen >= dlen); + + /* + * Special cases for short divisors. The general case uses the + * top top 2 digits of the divisor (d) to estimate a quotient digit, + * so it breaks if there are fewer digits available. Thus, we need + * special cases for a divisor of length 1. A divisor of length + * 2 can have a *lot* of administrivia overhead removed removed, + * so it's probably worth special-casing that case, too. + */ + if (dlen == 1) + return lbnDiv1_32(q, BIGLITTLE(n-1,n), n, nlen, + BIGLITTLE(d[-1],d[0])); + +#if 0 + /* + * @@@ This is not yet written... The general loop will do, + * albeit less efficiently + */ + if (dlen == 2) { + /* + * divisor two digits long: + * use the 3/2 technique from Knuth, but we know + * it's exact. + */ + dh = BIGLITTLE(d[-1],d[0]); + dl = BIGLITTLE(d[-2],d[1]); + shift = 0; + if ((sh & ((BNWORD32)1 << 32-1-shift)) == 0) { + do { + shift++; + } while (dh & (BNWORD32)1<<32-1-shift) == 0); + dh = dh << shift | dl >> (32-shift); + dl <<= shift; + + + } + + + for (shift = 0; (dh & (BNWORD32)1 << 32-1-shift)) == 0; shift++) + ; + if (shift) { + } + dh = dh << shift | dl >> (32-shift); + shift = 0; + while (dh + } +#endif + + dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1))); + assert(dh); + + /* Normalize the divisor */ + shift = 0; + r = dh; + i = 32/2; + do { + if (r >> i) + r >>= i; + else + shift += i; + } while ((i /= 2) != 0); + + nh = 0; + if (shift) { + lbnLshift_32(d, dlen, shift); + dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1))); + nh = lbnLshift_32(n, nlen, shift); + } + + /* Assert that dh is now normalized */ + assert(dh >> (32-1)); + + /* Also get the second-most significant word of the divisor */ + dl = BIGLITTLE(*(d-(dlen-1)),*(d+(dlen-2))); + + /* + * Adjust pointers: n to point to least significant end of first + * first subtract, and q to one the most-significant end of the + * quotient array. + */ + BIGLITTLE(n -= qlen,n += qlen); + BIGLITTLE(q -= qlen,q += qlen); + + /* Fetch the most significant stored word of the dividend */ + nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); + + /* + * Compute the first digit of the quotient, based on the + * first two words of the dividend (the most significant of which + * is the overflow word h). + */ + if (nh) { + assert(nh < dh); + r = lbnDiv21_32(&qhat, nh, nm, dh); + } else if (nm >= dh) { + qhat = nm/dh; + r = nm % dh; + } else { /* Quotient is zero */ + qhigh = 0; + goto divloop; + } + + /* Now get the third most significant word of the dividend */ + nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2))); + + /* + * Correct qhat, the estimate of quotient digit. + * qhat can only be high, and at most two words high, + * so the loop can be unrolled and abbreviated. + */ +#ifdef mul32_ppmm + mul32_ppmm(nm, t32, qhat, dl); + if (nm > r || (nm == r && t32 > nl)) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + nm -= (t32 < dl); + t32 -= dl; + if (nm > r || (nm == r && t32 > nl)) + qhat--; + } + } +#elif defined(BNWORD64) + t64 = (BNWORD64)qhat * dl; + if (t64 > ((BNWORD64)r << 32) + nl) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) > dh) { + t64 -= dl; + if (t64 > ((BNWORD64)r << 32) + nl) + qhat--; + } + } +#else /* Use lbnMulN1_32 */ + lbnMulN1_32(BIGLITTLE(t2+2,t2), &dl, 1, qhat); + if (t2high > r || (t2high == r && t2low > nl)) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + t2high -= (t2low < dl); + t2low -= dl; + if (t2high > r || (t2high == r && t2low > nl)) + qhat--; + } + } +#endif + + /* Do the multiply and subtract */ + r = lbnMulSub1_32(n, d, dlen, qhat); + /* If there was a borrow, add back once. */ + if (r > nh) { /* Borrow? */ + (void)lbnAddN_32(n, d, dlen); + qhat--; + } + + /* Remember the first quotient digit. */ + qhigh = qhat; + + /* Now, the main division loop: */ +divloop: + while (qlen--) { + + /* Advance n */ + nh = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); + BIGLITTLE(++n,--n); + nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); + + if (nh == dh) { + qhat = ~(BNWORD32)0; + /* Optimized computation of r = (nh,nm) - qhat * dh */ + r = nh + nm; + if (r < nh) + goto subtract; + } else { + assert(nh < dh); + r = lbnDiv21_32(&qhat, nh, nm, dh); + } + + nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2))); +#ifdef mul32_ppmm + mul32_ppmm(nm, t32, qhat, dl); + if (nm > r || (nm == r && t32 > nl)) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + nm -= (t32 < dl); + t32 -= dl; + if (nm > r || (nm == r && t32 > nl)) + qhat--; + } + } +#elif defined(BNWORD64) + t64 = (BNWORD64)qhat * dl; + if (t64 > ((BNWORD64)r<<32) + nl) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + t64 -= dl; + if (t64 > ((BNWORD64)r << 32) + nl) + qhat--; + } + } +#else /* Use lbnMulN1_32 */ + lbnMulN1_32(BIGLITTLE(t2+2,t2), &dl, 1, qhat); + if (t2high > r || (t2high == r && t2low > nl)) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + t2high -= (t2low < dl); + t2low -= dl; + if (t2high > r || (t2high == r && t2low > nl)) + qhat--; + } + } +#endif + + /* + * As a point of interest, note that it is not worth checking + * for qhat of 0 or 1 and installing special-case code. These + * occur with probability 2^-32, so spending 1 cycle to check + * for them is only worth it if we save more than 2^15 cycles, + * and a multiply-and-subtract for numbers in the 1024-bit + * range just doesn't take that long. + */ +subtract: + /* + * n points to the least significant end of the substring + * of n to be subtracted from. qhat is either exact or + * one too large. If the subtract gets a borrow, it was + * one too large and the divisor is added back in. It's + * a dlen+1 word add which is guaranteed to produce a + * carry out, so it can be done very simply. + */ + r = lbnMulSub1_32(n, d, dlen, qhat); + if (r > nh) { /* Borrow? */ + (void)lbnAddN_32(n, d, dlen); + qhat--; + } + /* Store the quotient digit */ + BIGLITTLE(*q++,*--q) = qhat; + } + /* Tah dah! */ + + if (shift) { + lbnRshift_32(d, dlen, shift); + lbnRshift_32(n, dlen, shift); + } + + return qhigh; +} +#endif + +/* + * Find the negative multiplicative inverse of x (x must be odd!) modulo 2^32. + * + * This just performs Newton's iteration until it gets the + * inverse. The initial estimate is always correct to 3 bits, and + * sometimes 4. The number of valid bits doubles each iteration. + * (To prove it, assume x * y == 1 (mod 2^n), and introduce a variable + * for the error mod 2^2n. x * y == 1 + k*2^n (mod 2^2n) and follow + * the iteration through.) + */ +#ifndef lbnMontInv1_32 +BNWORD32 +lbnMontInv1_32(BNWORD32 const x) +{ + BNWORD32 y = x, z; + + assert(x & 1); + + while ((z = x*y) != 1) + y *= 2 - z; + return -y; +} +#endif /* !lbnMontInv1_32 */ + +#if defined(BNWORD64) && PRODUCT_SCAN +/* + * Test code for product-scanning Montgomery reduction. + * This seems to slow the C code down rather than speed it up. + * + * The first loop computes the Montgomery multipliers, storing them over + * the low half of the number n. + * + * The second half multiplies the upper half, adding in the modulus + * times the Montgomery multipliers. The results of this multiply + * are stored. + */ +void +lbnMontReduce_32(BNWORD32 *n, BNWORD32 const *mod, unsigned mlen, BNWORD32 inv) +{ + BNWORD64 x, y; + BNWORD32 const *pm; + BNWORD32 *pn; + BNWORD32 t; + unsigned carry; + unsigned i, j; + + /* Special case of zero */ + if (!mlen) + return; + + /* Pass 1 - compute Montgomery multipliers */ + /* First iteration can have certain simplifications. */ + t = BIGLITTLE(n[-1],n[0]); + x = t; + t *= inv; + BIGLITTLE(n[-1], n[0]) = t; + x += (BNWORD64)t * BIGLITTLE(mod[-1],mod[0]); /* Can't overflow */ + assert((BNWORD32)x == 0); + x = x >> 32; + + for (i = 1; i < mlen; i++) { + carry = 0; + pn = n; + pm = BIGLITTLE(mod-i-1,mod+i+1); + for (j = 0; j < i; j++) { + y = (BNWORD64)BIGLITTLE(*--pn * *pm++, *pn++ * *--pm); + x += y; + carry += (x < y); + } + assert(BIGLITTLE(pn == n-i, pn == n+i)); + y = t = BIGLITTLE(pn[-1], pn[0]); + x += y; + carry += (x < y); + BIGLITTLE(pn[-1], pn[0]) = t = inv * (BNWORD32)x; + assert(BIGLITTLE(pm == mod-1, pm == mod+1)); + y = (BNWORD64)t * BIGLITTLE(pm[0],pm[-1]); + x += y; + carry += (x < y); + assert((BNWORD32)x == 0); + x = x >> 32 | (BNWORD64)carry << 32; + } + + BIGLITTLE(n -= mlen, n += mlen); + + /* Pass 2 - compute upper words and add to n */ + for (i = 1; i < mlen; i++) { + carry = 0; + pm = BIGLITTLE(mod-i,mod+i); + pn = n; + for (j = i; j < mlen; j++) { + y = (BNWORD64)BIGLITTLE(*--pm * *pn++, *pm++ * *--pn); + x += y; + carry += (x < y); + } + assert(BIGLITTLE(pm == mod-mlen, pm == mod+mlen)); + assert(BIGLITTLE(pn == n+mlen-i, pn == n-mlen+i)); + y = t = BIGLITTLE(*(n-i),*(n+i-1)); + x += y; + carry += (x < y); + BIGLITTLE(*(n-i),*(n+i-1)) = (BNWORD32)x; + x = (x >> 32) | (BNWORD64)carry << 32; + } + + /* Last round of second half, simplified. */ + t = BIGLITTLE(*(n-mlen),*(n+mlen-1)); + x += t; + BIGLITTLE(*(n-mlen),*(n+mlen-1)) = (BNWORD32)x; + carry = (unsigned)(x >> 32); + + while (carry) + carry -= lbnSubN_32(n, mod, mlen); + while (lbnCmp_32(n, mod, mlen) >= 0) + (void)lbnSubN_32(n, mod, mlen); +} +#define lbnMontReduce_32 lbnMontReduce_32 +#endif + +/* + * Montgomery reduce n, modulo mod. This reduces modulo mod and divides by + * 2^(32*mlen). Returns the result in the *top* mlen words of the argument n. + * This is ready for another multiplication using lbnMul_32. + * + * Montgomery representation is a very useful way to encode numbers when + * you're doing lots of modular reduction. What you do is pick a multiplier + * R which is relatively prime to the modulus and very easy to divide by. + * Since the modulus is odd, R is closen as a power of 2, so the division + * is a shift. In fact, it's a shift of an integral number of words, + * so the shift can be implicit - just drop the low-order words. + * + * Now, choose R *larger* than the modulus m, 2^(32*mlen). Then convert + * all numbers a, b, etc. to Montgomery form M(a), M(b), etc using the + * relationship M(a) = a*R mod m, M(b) = b*R mod m, etc. Note that: + * - The Montgomery form of a number depends on the modulus m. + * A fixed modulus m is assumed throughout this discussion. + * - Since R is relaitvely prime to m, multiplication by R is invertible; + * no information about the numbers is lost, they're just scrambled. + * - Adding (and subtracting) numbers in this form works just as usual. + * M(a+b) = (a+b)*R mod m = (a*R + b*R) mod m = (M(a) + M(b)) mod m + * - Multiplying numbers in this form produces a*b*R*R. The problem + * is to divide out the excess factor of R, modulo m as well as to + * reduce to the given length mlen. It turns out that this can be + * done *faster* than a normal divide, which is where the speedup + * in Montgomery division comes from. + * + * Normal reduction chooses a most-significant quotient digit q and then + * subtracts q*m from the number to be reduced. Choosing q is tricky + * and involved (just look at lbnDiv_32 to see!) and is usually + * imperfect, requiring a check for correction after the subtraction. + * + * Montgomery reduction *adds* a multiple of m to the *low-order* part + * of the number to be reduced. This multiple is chosen to make the + * low-order part of the number come out to zero. This can be done + * with no trickery or error using a precomputed inverse of the modulus. + * In this code, the "part" is one word, but any width can be used. + * + * Repeating this step sufficiently often results in a value which + * is a multiple of R (a power of two, remember) but is still (since + * the additions were to the low-order part and thus did not increase + * the value of the number being reduced very much) still not much + * larger than m*R. Then implicitly divide by R and subtract off + * m until the result is in the correct range. + * + * Since the low-order part being cancelled is less than R, the + * multiple of m added must have a multiplier which is at most R-1. + * Assuming that the input is at most m*R-1, the final number is + * at most m*(2*R-1)-1 = 2*m*R - m - 1, so subtracting m once from + * the high-order part, equivalent to subtracting m*R from the + * while number, produces a result which is at most m*R - m - 1, + * which divided by R is at most m-1. + * + * To convert *to* Montgomery form, you need a regular remainder + * routine, although you can just compute R*R (mod m) and do the + * conversion using Montgomery multiplication. To convert *from* + * Montgomery form, just Montgomery reduce the number to + * remove the extra factor of R. + * + * TODO: Change to a full inverse and use Karatsuba's multiplication + * rather than this word-at-a-time. + */ +#ifndef lbnMontReduce_32 +void +lbnMontReduce_32(BNWORD32 *n, BNWORD32 const *mod, unsigned const mlen, + BNWORD32 inv) +{ + BNWORD32 t; + BNWORD32 c = 0; + unsigned len = mlen; + + /* inv must be the negative inverse of mod's least significant word */ + assert((BNWORD32)(inv * BIGLITTLE(mod[-1],mod[0])) == (BNWORD32)-1); + + assert(len); + + do { + t = lbnMulAdd1_32(n, mod, mlen, inv * BIGLITTLE(n[-1],n[0])); + c += lbnAdd1_32(BIGLITTLE(n-mlen,n+mlen), len, t); + BIGLITTLE(--n,++n); + } while (--len); + + /* + * All that adding can cause an overflow past the modulus size, + * but it's unusual, and never by much, so a subtraction loop + * is the right way to deal with it. + * This subtraction happens infrequently - I've only ever seen it + * invoked once per reduction, and then just under 22.5% of the time. + */ + while (c) + c -= lbnSubN_32(n, mod, mlen); + while (lbnCmp_32(n, mod, mlen) >= 0) + (void)lbnSubN_32(n, mod, mlen); +} +#endif /* !lbnMontReduce_32 */ + +/* + * A couple of helpers that you might want to implement atomically + * in asm sometime. + */ +#ifndef lbnMontMul_32 +/* + * Multiply "num1" by "num2", modulo "mod", all of length "len", and + * place the result in the high half of "prod". "inv" is the inverse + * of the least-significant word of the modulus, modulo 2^32. + * This uses numbers in Montgomery form. Reduce using "len" and "inv". + * + * This is implemented as a macro to win on compilers that don't do + * inlining, since it's so trivial. + */ +#define lbnMontMul_32(prod, n1, n2, mod, len, inv) \ + (lbnMulX_32(prod, n1, n2, len), lbnMontReduce_32(prod, mod, len, inv)) +#endif /* !lbnMontMul_32 */ + +#ifndef lbnMontSquare_32 +/* + * Square "num", modulo "mod", both of length "len", and place the result + * in the high half of "prod". "inv" is the inverse of the least-significant + * word of the modulus, modulo 2^32. + * This uses numbers in Montgomery form. Reduce using "len" and "inv". + * + * This is implemented as a macro to win on compilers that don't do + * inlining, since it's so trivial. + */ +#define lbnMontSquare_32(prod, n, mod, len, inv) \ + (lbnSquare_32(prod, n, len), lbnMontReduce_32(prod, mod, len, inv)) + +#endif /* !lbnMontSquare_32 */ + +/* + * Convert a number to Montgomery form - requires mlen + nlen words + * of memory in "n". + */ +void +lbnToMont_32(BNWORD32 *n, unsigned nlen, BNWORD32 *mod, unsigned mlen) +{ + /* Move n up "mlen" words */ + lbnCopy_32(BIGLITTLE(n-mlen,n+mlen), n, nlen); + lbnZero_32(n, mlen); + /* Do the division - dump the quotient in the high-order words */ + (void)lbnDiv_32(BIGLITTLE(n-mlen,n+mlen), n, mlen+nlen, mod, mlen); +} + +/* + * Convert from Montgomery form. Montgomery reduction is all that is + * needed. + */ +void +lbnFromMont_32(BNWORD32 *n, BNWORD32 *mod, unsigned len) +{ + /* Zero the high words of n */ + lbnZero_32(BIGLITTLE(n-len,n+len), len); + lbnMontReduce_32(n, mod, len, lbnMontInv1_32(BIGLITTLE(mod[-1],mod[0]))); + /* Move n down len words */ + lbnCopy_32(n, BIGLITTLE(n-len,n+len), len); +} + +/* + * The windowed exponentiation algorithm, precomputes a table of odd + * powers of n up to 2^k. It takes 2^(k-1)-1 multiplies to compute + * the table, and (e-1)/(k+1) multiplies (on average) to perform the + * exponentiation. To minimize the sum, k must vary with e. + * The optimal window sizes vary with the exponent length. Here are + * some selected values and the boundary cases. + * (An underscore _ has been inserted into some of the numbers to ensure + * that magic strings like 32 do not appear in this table. It should be + * ignored.) + * + * At e = 1 bits, k=1 (0.000000) is best. + * At e = 2 bits, k=1 (0.500000) is best. + * At e = 4 bits, k=1 (1.500000) is best. + * At e = 8 bits, k=2 (3.333333) < k=1 (3.500000) + * At e = 1_6 bits, k=2 (6.000000) is best. + * At e = 26 bits, k=3 (9.250000) < k=2 (9.333333) + * At e = 3_2 bits, k=3 (10.750000) is best. + * At e = 6_4 bits, k=3 (18.750000) is best. + * At e = 82 bits, k=4 (23.200000) < k=3 (23.250000) + * At e = 128 bits, k=4 (3_2.400000) is best. + * At e = 242 bits, k=5 (55.1_66667) < k=4 (55.200000) + * At e = 256 bits, k=5 (57.500000) is best. + * At e = 512 bits, k=5 (100.1_66667) is best. + * At e = 674 bits, k=6 (127.142857) < k=5 (127.1_66667) + * At e = 1024 bits, k=6 (177.142857) is best. + * At e = 1794 bits, k=7 (287.125000) < k=6 (287.142857) + * At e = 2048 bits, k=7 (318.875000) is best. + * At e = 4096 bits, k=7 (574.875000) is best. + * + * The numbers in parentheses are the expected number of multiplications + * needed to do the computation. The normal russian-peasant modular + * exponentiation technique always uses (e-1)/2. For exponents as + * small as 192 bits (below the range of current factoring algorithms), + * half of the multiplies are eliminated, 45.2 as opposed to the naive + * 95.5. Counting the 191 squarings as 3/4 a multiply each (squaring + * proper is just over half of multiplying, but the Montgomery + * reduction in each case is also a multiply), that's 143.25 + * multiplies, for totals of 188.45 vs. 238.75 - a 21% savings. + * For larger exponents (like 512 bits), it's 483.92 vs. 639.25, a + * 24.3% savings. It asymptotically approaches 25%. + * + * Given that exponents for which k>7 are useful are uncommon, + * a fixed size table for k <= 7 is used for simplicity. + * k = 8 is uzeful at 4610 bits, k = 9 at 11522 bits. + * + * The basic number of squarings needed is e-1, although a k-bit + * window (for k > 1) can save, on average, k-2 of those, too. + * That savings currently isn't counted here. It would drive the + * crossover points slightly lower. + * (Actually, this win is also reduced in the DoubleExpMod case, + * meaning we'd have to split the tables. Except for that, the + * multiplies by powers of the two bases are independent, so + * the same logic applies to each as the single case.) + * + * Table entry i is the largest number of bits in an exponent to + * process with a window size of i+1. So the window never goes above 7 + * bits, requiring 2^(7-1) = 0x40 precomputed multiples. + */ +#define BNEXPMOD_MAX_WINDOW 7 +static unsigned const bnExpModThreshTable[BNEXPMOD_MAX_WINDOW] = { + 7, 25, 81, 241, 673, 1793, (unsigned)-1 +}; + +/* + * Perform modular exponentiation, as fast as possible! This uses + * Montgomery reduction, optimized squaring, and windowed exponentiation. + * The modulus "mod" MUST be odd! + * + * This returns 0 on success, -1 on out of memory. + * + * The window algorithm: + * The idea is to keep a running product of b1 = n^(high-order bits of exp), + * and then keep appending exponent bits to it. The following patterns + * apply to a 3-bit window (k = 3): + * To append 0: square + * To append 1: square, multiply by n^1 + * To append 10: square, multiply by n^1, square + * To append 11: square, square, multiply by n^3 + * To append 100: square, multiply by n^1, square, square + * To append 101: square, square, square, multiply by n^5 + * To append 110: square, square, multiply by n^3, square + * To append 111: square, square, square, multiply by n^7 + * + * Since each pattern involves only one multiply, the longer the pattern + * the better, except that a 0 (no multiplies) can be appended directly. + * We precompute a table of odd powers of n, up to 2^k, and can then + * multiply k bits of exponent at a time. Actually, assuming random + * exponents, there is on average one zero bit between needs to + * multiply (1/2 of the time there's none, 1/4 of the time there's 1, + * 1/8 of the time, there's 2, 1/32 of the time, there's 3, etc.), so + * you have to do one multiply per k+1 bits of exponent. + * + * The loop walks down the exponent, squaring the result buffer as + * it goes. There is a wbits+1 bit lookahead buffer, buf, that is + * filled with the upcoming exponent bits. (What is read after the + * end of the exponent is unimportant, but it is filled with zero here.) + * When the most-significant bit of this buffer becomes set, i.e. + * (buf & tblmask) != 0, we have to decide what pattern to multiply + * by, and when to do it. We decide, remember to do it in future + * after a suitable number of squarings have passed (e.g. a pattern + * of "100" in the buffer requires that we multiply by n^1 immediately; + * a pattern of "110" calls for multiplying by n^3 after one more + * squaring), clear the buffer, and continue. + * + * When we start, there is one more optimization: the result buffer + * is implcitly one, so squaring it or multiplying by it can be + * optimized away. Further, if we start with a pattern like "100" + * in the lookahead window, rather than placing n into the buffer + * and then starting to square it, we have already computed n^2 + * to compute the odd-powers table, so we can place that into + * the buffer and save a squaring. + * + * This means that if you have a k-bit window, to compute n^z, + * where z is the high k bits of the exponent, 1/2 of the time + * it requires no squarings. 1/4 of the time, it requires 1 + * squaring, ... 1/2^(k-1) of the time, it reqires k-2 squarings. + * And the remaining 1/2^(k-1) of the time, the top k bits are a + * 1 followed by k-1 0 bits, so it again only requires k-2 + * squarings, not k-1. The average of these is 1. Add that + * to the one squaring we have to do to compute the table, + * and you'll see that a k-bit window saves k-2 squarings + * as well as reducing the multiplies. (It actually doesn't + * hurt in the case k = 1, either.) + * + * n must have mlen words allocated. Although fewer may be in use + * when n is passed in, all are in use on exit. + */ +int +lbnExpMod_32(BNWORD32 *result, BNWORD32 const *n, unsigned nlen, + BNWORD32 const *e, unsigned elen, BNWORD32 *mod, unsigned mlen) +{ + BNWORD32 *table[1 << (BNEXPMOD_MAX_WINDOW-1)]; + /* Table of odd powers of n */ + unsigned ebits; /* Exponent bits */ + unsigned wbits; /* Window size */ + unsigned tblmask; /* Mask of exponentiation window */ + BNWORD32 bitpos; /* Mask of current look-ahead bit */ + unsigned buf; /* Buffer of exponent bits */ + unsigned multpos; /* Where to do pending multiply */ + BNWORD32 const *mult; /* What to multiply by */ + unsigned i; /* Loop counter */ + int isone; /* Flag: accum. is implicitly one */ + BNWORD32 *a, *b; /* Working buffers/accumulators */ + BNWORD32 *t; /* Pointer into the working buffers */ + BNWORD32 inv; /* mod^-1 modulo 2^32 */ + + assert(mlen); + assert(nlen <= mlen); + + /* First, a couple of trivial cases. */ + elen = lbnNorm_32(e, elen); + if (!elen) { + /* x ^ 0 == 1 */ + lbnZero_32(result, mlen); + BIGLITTLE(result[-1],result[0]) = 1; + return 0; + } + ebits = lbnBits_32(e, elen); + if (ebits == 1) { + /* x ^ 1 == x */ + if (n != result) + lbnCopy_32(result, n, nlen); + if (mlen > nlen) + lbnZero_32(BIGLITTLE(result-nlen,result+nlen), + mlen-nlen); + return 0; + } + + /* Okay, now move the exponent pointer to the most-significant word */ + e = BIGLITTLE(e-elen, e+elen-1); + + /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */ + wbits = 0; + while (ebits > bnExpModThreshTable[wbits]) + wbits++; + + /* Allocate working storage: two product buffers and the tables. */ + LBNALLOC(a, 2*mlen); + if (!a) + return -1; + LBNALLOC(b, 2*mlen); + if (!b) { + LBNFREE(a, 2*mlen); + return -1; + } + + /* Convert to the appropriate table size: tblmask = 1<<(k-1) */ + tblmask = 1u << wbits; + + /* We have the result buffer available, so use it. */ + table[0] = result; + + /* + * Okay, we now have a minimal-sized table - expand it. + * This is allowed to fail! If so, scale back the table size + * and proceed. + */ + for (i = 1; i < tblmask; i++) { + LBNALLOC(t, mlen); + if (!t) /* Out of memory! Quit the loop. */ + break; + table[i] = t; + } + + /* If we stopped, with i < tblmask, shrink the tables appropriately */ + while (tblmask > i) { + wbits--; + tblmask >>= 1; + } + /* Free up our overallocations */ + while (--i > tblmask) + LBNFREE(table[i], mlen); + + /* Okay, fill in the table */ + + /* Compute the necessary modular inverse */ + inv = lbnMontInv1_32(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ + + /* Convert n to Montgomery form */ + + /* Move n up "mlen" words into a */ + t = BIGLITTLE(a-mlen, a+mlen); + lbnCopy_32(t, n, nlen); + lbnZero_32(a, mlen); + /* Do the division - lose the quotient into the high-order words */ + (void)lbnDiv_32(t, a, mlen+nlen, mod, mlen); + /* Copy into first table entry */ + lbnCopy_32(table[0], a, mlen); + + /* Square a into b */ + lbnMontSquare_32(b, a, mod, mlen, inv); + + /* Use high half of b to initialize the table */ + t = BIGLITTLE(b-mlen, b+mlen); + for (i = 1; i < tblmask; i++) { + lbnMontMul_32(a, t, table[i-1], mod, mlen, inv); + lbnCopy_32(table[i], BIGLITTLE(a-mlen, a+mlen), mlen); + } + + /* We might use b = n^2 later... */ + + /* Initialze the fetch pointer */ + bitpos = (BNWORD32)1 << ((ebits-1) & (32-1)); /* Initialize mask */ + + /* This should point to the msbit of e */ + assert((*e & bitpos) != 0); + + /* + * Pre-load the window. Becuase the window size is + * never larger than the exponent size, there is no need to + * detect running off the end of e in here. + * + * The read-ahead is controlled by elen and the bitpos mask. + * Note that this is *ahead* of ebits, which tracks the + * most significant end of the window. The purpose of this + * initialization is to get the two wbits+1 bits apart, + * like they should be. + * + * Note that bitpos and e1len together keep track of the + * lookahead read pointer in the exponent that is used here. + */ + buf = 0; + for (i = 0; i <= wbits; i++) { + buf = (buf << 1) | ((*e & bitpos) != 0); + bitpos >>= 1; + if (!bitpos) { + BIGLITTLE(e++,e--); + bitpos = (BNWORD32)1 << (32-1); + elen--; + } + } + assert(buf & tblmask); + + /* + * Set the pending multiply positions to a location that will + * never be encountered, thus ensuring that nothing will happen + * until the need for a multiply appears and one is scheduled. + */ + multpos = ebits; /* A NULL value */ + mult = 0; /* Force a crash if we use these */ + + /* + * Okay, now begins the real work. The first step is + * slightly magic, so it's done outside the main loop, + * but it's very similar to what's inside. + */ + ebits--; /* Start processing the first bit... */ + isone = 1; + + /* + * This is just like the multiply in the loop, except that + * - We know the msbit of buf is set, and + * - We have the extra value n^2 floating around. + * So, do the usual computation, and if the result is that + * the buffer should be multiplied by n^1 immediately + * (which we'd normally then square), we multiply it + * (which reduces to a copy, which reduces to setting a flag) + * by n^2 and skip the squaring. Thus, we do the + * multiply and the squaring in one step. + */ + assert(buf & tblmask); + multpos = ebits - wbits; + while ((buf & 1) == 0) { + buf >>= 1; + multpos++; + } + /* Intermediates can wrap, but final must NOT */ + assert(multpos <= ebits); + mult = table[buf>>1]; + buf = 0; + + /* Special case: use already-computed value sitting in buffer */ + if (multpos == ebits) + isone = 0; + + /* + * At this point, the buffer (which is the high half of b) holds + * either 1 (implicitly, as the "isone" flag is set), or n^2. + */ + + /* + * The main loop. The procedure is: + * - Advance the window + * - If the most-significant bit of the window is set, + * schedule a multiply for the appropriate time in the + * future (may be immediately) + * - Perform any pending multiples + * - Check for termination + * - Square the buffer + * + * At any given time, the acumulated product is held in + * the high half of b. + */ + for (;;) { + ebits--; + + /* Advance the window */ + assert(buf < tblmask); + buf <<= 1; + /* + * This reads ahead of the current exponent position + * (controlled by ebits), so we have to be able to read + * past the lsb of the exponents without error. + */ + if (elen) { + buf |= ((*e & bitpos) != 0); + bitpos >>= 1; + if (!bitpos) { + BIGLITTLE(e++,e--); + bitpos = (BNWORD32)1 << (32-1); + elen--; + } + } + + /* Examine the window for pending multiplies */ + if (buf & tblmask) { + multpos = ebits - wbits; + while ((buf & 1) == 0) { + buf >>= 1; + multpos++; + } + /* Intermediates can wrap, but final must NOT */ + assert(multpos <= ebits); + mult = table[buf>>1]; + buf = 0; + } + + /* If we have a pending multiply, do it */ + if (ebits == multpos) { + /* Multiply by the table entry remembered previously */ + t = BIGLITTLE(b-mlen, b+mlen); + if (isone) { + /* Multiply by 1 is a trivial case */ + lbnCopy_32(t, mult, mlen); + isone = 0; + } else { + lbnMontMul_32(a, t, mult, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } + + /* Are we done? */ + if (!ebits) + break; + + /* Square the input */ + if (!isone) { + t = BIGLITTLE(b-mlen, b+mlen); + lbnMontSquare_32(a, t, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } /* for (;;) */ + + assert(!isone); + assert(!buf); + + /* DONE! */ + + /* Convert result out of Montgomery form */ + t = BIGLITTLE(b-mlen, b+mlen); + lbnCopy_32(b, t, mlen); + lbnZero_32(t, mlen); + lbnMontReduce_32(b, mod, mlen, inv); + lbnCopy_32(result, t, mlen); + /* + * Clean up - free intermediate storage. + * Do NOT free table[0], which is the result + * buffer. + */ + while (--tblmask) + LBNFREE(table[tblmask], mlen); + LBNFREE(b, 2*mlen); + LBNFREE(a, 2*mlen); + + return 0; /* Success */ +} + +/* + * Compute and return n1^e1 * n2^e2 mod "mod". + * result may be either input buffer, or something separate. + * It must be "mlen" words long. + * + * There is a current position in the exponents, which is kept in e1bits. + * (The exponents are swapped if necessary so e1 is the longer of the two.) + * At any given time, the value in the accumulator is + * n1^(e1>>e1bits) * n2^(e2>>e1bits) mod "mod". + * As e1bits is counted down, this is updated, by squaring it and doing + * any necessary multiplies. + * To decide on the necessary multiplies, two windows, each w1bits+1 bits + * wide, are maintained in buf1 and buf2, which read *ahead* of the + * e1bits position (with appropriate handling of the case when e1bits + * drops below w1bits+1). When the most-significant bit of either window + * becomes set, indicating that something needs to be multiplied by + * the accumulator or it will get out of sync, the window is examined + * to see which power of n1 or n2 to multiply by, and when (possibly + * later, if the power is greater than 1) the multiply should take + * place. Then the multiply and its location are remembered and the + * window is cleared. + * + * If we had every power of n1 in the table, the multiply would always + * be w1bits steps in the future. But we only keep the odd powers, + * so instead of waiting w1bits squarings and then multiplying + * by n1^k, we wait w1bits-k squarings and multiply by n1. + * + * Actually, w2bits can be less than w1bits, but the window is the same + * size, to make it easier to keep track of where we're reading. The + * appropriate number of low-order bits of the window are just ignored. + */ +int +lbnDoubleExpMod_32(BNWORD32 *result, + BNWORD32 const *n1, unsigned n1len, + BNWORD32 const *e1, unsigned e1len, + BNWORD32 const *n2, unsigned n2len, + BNWORD32 const *e2, unsigned e2len, + BNWORD32 *mod, unsigned mlen) +{ + BNWORD32 *table1[1 << (BNEXPMOD_MAX_WINDOW-1)]; + /* Table of odd powers of n1 */ + BNWORD32 *table2[1 << (BNEXPMOD_MAX_WINDOW-1)]; + /* Table of odd powers of n2 */ + unsigned e1bits, e2bits; /* Exponent bits */ + unsigned w1bits, w2bits; /* Window sizes */ + unsigned tblmask; /* Mask of exponentiation window */ + BNWORD32 bitpos; /* Mask of current look-ahead bit */ + unsigned buf1, buf2; /* Buffer of exponent bits */ + unsigned mult1pos, mult2pos; /* Where to do pending multiply */ + BNWORD32 const *mult1, *mult2; /* What to multiply by */ + unsigned i; /* Loop counter */ + int isone; /* Flag: accum. is implicitly one */ + BNWORD32 *a, *b; /* Working buffers/accumulators */ + BNWORD32 *t; /* Pointer into the working buffers */ + BNWORD32 inv; /* mod^-1 modulo 2^32 */ + + assert(mlen); + assert(n1len <= mlen); + assert(n2len <= mlen); + + /* First, a couple of trivial cases. */ + e1len = lbnNorm_32(e1, e1len); + e2len = lbnNorm_32(e2, e2len); + + /* Ensure that the first exponent is the longer */ + e1bits = lbnBits_32(e1, e1len); + e2bits = lbnBits_32(e2, e2len); + if (e1bits < e2bits) { + i = e1len; e1len = e2len; e2len = i; + i = e1bits; e1bits = e2bits; e2bits = i; + t = (BNWORD32 *)n1; n1 = n2; n2 = t; + t = (BNWORD32 *)e1; e1 = e2; e2 = t; + } + assert(e1bits >= e2bits); + + /* Handle a trivial case */ + if (!e2len) + return lbnExpMod_32(result, n1, n1len, e1, e1len, mod, mlen); + assert(e2bits); + + /* The code below breaks if the exponents aren't at least 2 bits */ + if (e1bits == 1) { + assert(e2bits == 1); + + LBNALLOC(a, n1len+n2len); + if (!a) + return -1; + + lbnMul_32(a, n1, n1len, n2, n2len); + /* Do a direct modular reduction */ + if (n1len + n2len >= mlen) + (void)lbnDiv_32(a+mlen, a, n1len+n2len, mod, mlen); + lbnCopy_32(result, a, mlen); + LBNFREE(a, n1len+n2len); + return 0; + } + + /* Okay, now move the exponent pointers to the most-significant word */ + e1 = BIGLITTLE(e1-e1len, e1+e1len-1); + e2 = BIGLITTLE(e2-e2len, e2+e2len-1); + + /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */ + w1bits = 0; + while (e1bits > bnExpModThreshTable[w1bits]) + w1bits++; + w2bits = 0; + while (e2bits > bnExpModThreshTable[w2bits]) + w2bits++; + + assert(w1bits >= w2bits); + + /* Allocate working storage: two product buffers and the tables. */ + LBNALLOC(a, 2*mlen); + if (!a) + return -1; + LBNALLOC(b, 2*mlen); + if (!b) { + LBNFREE(a, 2*mlen); + return -1; + } + + /* Convert to the appropriate table size: tblmask = 1<<(k-1) */ + tblmask = 1u << w1bits; + /* Use buf2 for its size, temporarily */ + buf2 = 1u << w2bits; + + LBNALLOC(t, mlen); + if (!t) { + LBNFREE(b, 2*mlen); + LBNFREE(a, 2*mlen); + return -1; + } + table1[0] = t; + table2[0] = result; + + /* + * Okay, we now have some minimal-sized tables - expand them. + * This is allowed to fail! If so, scale back the table sizes + * and proceed. We allocate both tables at the same time + * so if it fails partway through, they'll both be a reasonable + * size rather than one huge and one tiny. + * When i passes buf2 (the number of entries in the e2 window, + * which may be less than the number of entries in the e1 window), + * stop allocating e2 space. + */ + for (i = 1; i < tblmask; i++) { + LBNALLOC(t, mlen); + if (!t) /* Out of memory! Quit the loop. */ + break; + table1[i] = t; + if (i < buf2) { + LBNALLOC(t, mlen); + if (!t) { + LBNFREE(table1[i], mlen); + break; + } + table2[i] = t; + } + } + + /* If we stopped, with i < tblmask, shrink the tables appropriately */ + while (tblmask > i) { + w1bits--; + tblmask >>= 1; + } + /* Free up our overallocations */ + while (--i > tblmask) { + if (i < buf2) + LBNFREE(table2[i], mlen); + LBNFREE(table1[i], mlen); + } + /* And shrink the second window too, if needed */ + if (w2bits > w1bits) { + w2bits = w1bits; + buf2 = tblmask; + } + + /* + * From now on, use the w2bits variable for the difference + * between w1bits and w2bits. + */ + w2bits = w1bits-w2bits; + + /* Okay, fill in the tables */ + + /* Compute the necessary modular inverse */ + inv = lbnMontInv1_32(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ + + /* Convert n1 to Montgomery form */ + + /* Move n1 up "mlen" words into a */ + t = BIGLITTLE(a-mlen, a+mlen); + lbnCopy_32(t, n1, n1len); + lbnZero_32(a, mlen); + /* Do the division - lose the quotient into the high-order words */ + (void)lbnDiv_32(t, a, mlen+n1len, mod, mlen); + /* Copy into first table entry */ + lbnCopy_32(table1[0], a, mlen); + + /* Square a into b */ + lbnMontSquare_32(b, a, mod, mlen, inv); + + /* Use high half of b to initialize the first table */ + t = BIGLITTLE(b-mlen, b+mlen); + for (i = 1; i < tblmask; i++) { + lbnMontMul_32(a, t, table1[i-1], mod, mlen, inv); + lbnCopy_32(table1[i], BIGLITTLE(a-mlen, a+mlen), mlen); + } + + /* Convert n2 to Montgomery form */ + + t = BIGLITTLE(a-mlen, a+mlen); + /* Move n2 up "mlen" words into a */ + lbnCopy_32(t, n2, n2len); + lbnZero_32(a, mlen); + /* Do the division - lose the quotient into the high-order words */ + (void)lbnDiv_32(t, a, mlen+n2len, mod, mlen); + /* Copy into first table entry */ + lbnCopy_32(table2[0], a, mlen); + + /* Square it into a */ + lbnMontSquare_32(a, table2[0], mod, mlen, inv); + /* Copy to b, low half */ + lbnCopy_32(b, t, mlen); + + /* Use b to initialize the second table */ + for (i = 1; i < buf2; i++) { + lbnMontMul_32(a, b, table2[i-1], mod, mlen, inv); + lbnCopy_32(table2[i], t, mlen); + } + + /* + * Okay, a recap: at this point, the low part of b holds + * n2^2, the high part holds n1^2, and the tables are + * initialized with the odd powers of n1 and n2 from 1 + * through 2*tblmask-1 and 2*buf2-1. + * + * We might use those squares in b later, or we might not. + */ + + /* Initialze the fetch pointer */ + bitpos = (BNWORD32)1 << ((e1bits-1) & (32-1)); /* Initialize mask */ + + /* This should point to the msbit of e1 */ + assert((*e1 & bitpos) != 0); + + /* + * Pre-load the windows. Becuase the window size is + * never larger than the exponent size, there is no need to + * detect running off the end of e1 in here. + * + * The read-ahead is controlled by e1len and the bitpos mask. + * Note that this is *ahead* of e1bits, which tracks the + * most significant end of the window. The purpose of this + * initialization is to get the two w1bits+1 bits apart, + * like they should be. + * + * Note that bitpos and e1len together keep track of the + * lookahead read pointer in the exponent that is used here. + * e2len is not decremented, it is only ever compared with + * e1len as *that* is decremented. + */ + buf1 = buf2 = 0; + for (i = 0; i <= w1bits; i++) { + buf1 = (buf1 << 1) | ((*e1 & bitpos) != 0); + if (e1len <= e2len) + buf2 = (buf2 << 1) | ((*e2 & bitpos) != 0); + bitpos >>= 1; + if (!bitpos) { + BIGLITTLE(e1++,e1--); + if (e1len <= e2len) + BIGLITTLE(e2++,e2--); + bitpos = (BNWORD32)1 << (32-1); + e1len--; + } + } + assert(buf1 & tblmask); + + /* + * Set the pending multiply positions to a location that will + * never be encountered, thus ensuring that nothing will happen + * until the need for a multiply appears and one is scheduled. + */ + mult1pos = mult2pos = e1bits; /* A NULL value */ + mult1 = mult2 = 0; /* Force a crash if we use these */ + + /* + * Okay, now begins the real work. The first step is + * slightly magic, so it's done outside the main loop, + * but it's very similar to what's inside. + */ + isone = 1; /* Buffer is implicitly 1, so replace * by copy */ + e1bits--; /* Start processing the first bit... */ + + /* + * This is just like the multiply in the loop, except that + * - We know the msbit of buf1 is set, and + * - We have the extra value n1^2 floating around. + * So, do the usual computation, and if the result is that + * the buffer should be multiplied by n1^1 immediately + * (which we'd normally then square), we multiply it + * (which reduces to a copy, which reduces to setting a flag) + * by n1^2 and skip the squaring. Thus, we do the + * multiply and the squaring in one step. + */ + assert(buf1 & tblmask); + mult1pos = e1bits - w1bits; + while ((buf1 & 1) == 0) { + buf1 >>= 1; + mult1pos++; + } + /* Intermediates can wrap, but final must NOT */ + assert(mult1pos <= e1bits); + mult1 = table1[buf1>>1]; + buf1 = 0; + + /* Special case: use already-computed value sitting in buffer */ + if (mult1pos == e1bits) + isone = 0; + + /* + * The first multiply by a power of n2. Similar, but + * we might not even want to schedule a multiply if e2 is + * shorter than e1, and the window might be shorter so + * we have to leave the low w2bits bits alone. + */ + if (buf2 & tblmask) { + /* Remember low-order bits for later */ + i = buf2 & ((1u << w2bits) - 1); + buf2 >>= w2bits; + mult2pos = e1bits - w1bits + w2bits; + while ((buf2 & 1) == 0) { + buf2 >>= 1; + mult2pos++; + } + assert(mult2pos <= e1bits); + mult2 = table2[buf2>>1]; + buf2 = i; + + if (mult2pos == e1bits) { + t = BIGLITTLE(b-mlen, b+mlen); + if (isone) { + lbnCopy_32(t, b, mlen); /* Copy low to high */ + isone = 0; + } else { + lbnMontMul_32(a, t, b, mod, mlen, inv); + t = a; a = b; b = t; + } + } + } + + /* + * At this point, the buffer (which is the high half of b) + * holds either 1 (implicitly, as the "isone" flag is set), + * n1^2, n2^2 or n1^2 * n2^2. + */ + + /* + * The main loop. The procedure is: + * - Advance the windows + * - If the most-significant bit of a window is set, + * schedule a multiply for the appropriate time in the + * future (may be immediately) + * - Perform any pending multiples + * - Check for termination + * - Square the buffers + * + * At any given time, the acumulated product is held in + * the high half of b. + */ + for (;;) { + e1bits--; + + /* Advance the windows */ + assert(buf1 < tblmask); + buf1 <<= 1; + assert(buf2 < tblmask); + buf2 <<= 1; + /* + * This reads ahead of the current exponent position + * (controlled by e1bits), so we have to be able to read + * past the lsb of the exponents without error. + */ + if (e1len) { + buf1 |= ((*e1 & bitpos) != 0); + if (e1len <= e2len) + buf2 |= ((*e2 & bitpos) != 0); + bitpos >>= 1; + if (!bitpos) { + BIGLITTLE(e1++,e1--); + if (e1len <= e2len) + BIGLITTLE(e2++,e2--); + bitpos = (BNWORD32)1 << (32-1); + e1len--; + } + } + + /* Examine the first window for pending multiplies */ + if (buf1 & tblmask) { + mult1pos = e1bits - w1bits; + while ((buf1 & 1) == 0) { + buf1 >>= 1; + mult1pos++; + } + /* Intermediates can wrap, but final must NOT */ + assert(mult1pos <= e1bits); + mult1 = table1[buf1>>1]; + buf1 = 0; + } + + /* + * Examine the second window for pending multiplies. + * Window 2 can be smaller than window 1, but we + * keep the same number of bits in buf2, so we need + * to ignore any low-order bits in the buffer when + * computing what to multiply by, and recompute them + * later. + */ + if (buf2 & tblmask) { + /* Remember low-order bits for later */ + i = buf2 & ((1u << w2bits) - 1); + buf2 >>= w2bits; + mult2pos = e1bits - w1bits + w2bits; + while ((buf2 & 1) == 0) { + buf2 >>= 1; + mult2pos++; + } + assert(mult2pos <= e1bits); + mult2 = table2[buf2>>1]; + buf2 = i; + } + + + /* If we have a pending multiply for e1, do it */ + if (e1bits == mult1pos) { + /* Multiply by the table entry remembered previously */ + t = BIGLITTLE(b-mlen, b+mlen); + if (isone) { + /* Multiply by 1 is a trivial case */ + lbnCopy_32(t, mult1, mlen); + isone = 0; + } else { + lbnMontMul_32(a, t, mult1, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } + + /* If we have a pending multiply for e2, do it */ + if (e1bits == mult2pos) { + /* Multiply by the table entry remembered previously */ + t = BIGLITTLE(b-mlen, b+mlen); + if (isone) { + /* Multiply by 1 is a trivial case */ + lbnCopy_32(t, mult2, mlen); + isone = 0; + } else { + lbnMontMul_32(a, t, mult2, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } + + /* Are we done? */ + if (!e1bits) + break; + + /* Square the buffer */ + if (!isone) { + t = BIGLITTLE(b-mlen, b+mlen); + lbnMontSquare_32(a, t, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } /* for (;;) */ + + assert(!isone); + assert(!buf1); + assert(!buf2); + + /* DONE! */ + + /* Convert result out of Montgomery form */ + t = BIGLITTLE(b-mlen, b+mlen); + lbnCopy_32(b, t, mlen); + lbnZero_32(t, mlen); + lbnMontReduce_32(b, mod, mlen, inv); + lbnCopy_32(result, t, mlen); + + /* Clean up - free intermediate storage */ + buf2 = tblmask >> w2bits; + while (--tblmask) { + if (tblmask < buf2) + LBNFREE(table2[tblmask], mlen); + LBNFREE(table1[tblmask], mlen); + } + t = table1[0]; + LBNFREE(t, mlen); + LBNFREE(b, 2*mlen); + LBNFREE(a, 2*mlen); + + return 0; /* Success */ +} + +/* + * 2^exp (mod mod). This is an optimized version for use in Fermat + * tests. The input value of n is ignored; it is returned with + * "mlen" words valid. + */ +int +lbnTwoExpMod_32(BNWORD32 *n, BNWORD32 const *exp, unsigned elen, + BNWORD32 *mod, unsigned mlen) +{ + unsigned e; /* Copy of high words of the exponent */ + unsigned bits; /* Assorted counter of bits */ + BNWORD32 const *bitptr; + BNWORD32 bitword, bitpos; + BNWORD32 *a, *b, *a1; + BNWORD32 inv; + + assert(mlen); + + bitptr = BIGLITTLE(exp-elen, exp+elen-1); + bitword = *bitptr; + assert(bitword); + + /* Clear n for future use. */ + lbnZero_32(n, mlen); + + bits = lbnBits_32(exp, elen); + + /* First, a couple of trivial cases. */ + if (bits <= 1) { + /* 2 ^ 0 == 1, 2 ^ 1 == 2 */ + BIGLITTLE(n[-1],n[0]) = (BNWORD32)1< 1); /* a 1-bit modulus is just stupid... */ + + /* + * We start with 1<>= 1; + if (!bitpos) { + if (!--elen) + break; + bitword = BIGLITTLE(*++bitptr,*--bitptr); + bitpos = (BNWORD32)1<<(32-1); + } + e = (e << 1) | ((bitpos & bitword) != 0); + if (e >= bits) { /* Overflow! Back out. */ + e >>= 1; + break; + } + } + /* + * The bit in "bitpos" being examined by the bit buffer has NOT + * been consumed yet. This may be past the end of the exponent, + * in which case elen == 1. + */ + + /* Okay, now, set bit "e" in n. n is already zero. */ + inv = (BNWORD32)1 << (e & (32-1)); + e /= 32; + BIGLITTLE(n[-e-1],n[e]) = inv; + /* + * The effective length of n in words is now "e+1". + * This is used a little bit later. + */ + + if (!elen) + return 0; /* That was easy! */ + + /* + * We have now processed the first few bits. The next step + * is to convert this to Montgomery form for further squaring. + */ + + /* Allocate working storage: two product buffers */ + LBNALLOC(a, 2*mlen); + if (!a) + return -1; + LBNALLOC(b, 2*mlen); + if (!b) { + LBNFREE(a, 2*mlen); + return -1; + } + + /* Convert n to Montgomery form */ + inv = BIGLITTLE(mod[-1],mod[0]); /* LSW of modulus */ + assert(inv & 1); /* Modulus must be odd */ + inv = lbnMontInv1_32(inv); + /* Move n (length e+1, remember?) up "mlen" words into b */ + /* Note that we lie about a1 for a bit - it's pointing to b */ + a1 = BIGLITTLE(b-mlen,b+mlen); + lbnCopy_32(a1, n, e+1); + lbnZero_32(b, mlen); + /* Do the division - dump the quotient into the high-order words */ + (void)lbnDiv_32(a1, b, mlen+e+1, mod, mlen); + /* + * Now do the first squaring and modular reduction to put + * the number up in a1 where it belongs. + */ + lbnMontSquare_32(a, b, mod, mlen, inv); + /* Fix up a1 to point to where it should go. */ + a1 = BIGLITTLE(a-mlen,a+mlen); + + /* + * Okay, now, a1 holds the number being accumulated, and + * b is a scratch register. Start working: + */ + for (;;) { + /* + * Is the bit set? If so, double a1 as well. + * A modular doubling like this is very cheap. + */ + if (bitpos & bitword) { + /* + * Double the number. If there was a carry out OR + * the result is greater than the modulus, subract + * the modulus. + */ + if (lbnDouble_32(a1, mlen) || + lbnCmp_32(a1, mod, mlen) > 0) + (void)lbnSubN_32(a1, mod, mlen); + } + + /* Advance to the next exponent bit */ + bitpos >>= 1; + if (!bitpos) { + if (!--elen) + break; /* Done! */ + bitword = BIGLITTLE(*++bitptr,*--bitptr); + bitpos = (BNWORD32)1<<(32-1); + } + + /* + * The elen/bitword/bitpos bit buffer is known to be + * non-empty, i.e. there is at least one more unconsumed bit. + * Thus, it's safe to square the number. + */ + lbnMontSquare_32(b, a1, mod, mlen, inv); + /* Rename result (in b) back to a (a1, really). */ + a1 = b; b = a; a = a1; + a1 = BIGLITTLE(a-mlen,a+mlen); + } + + /* DONE! Just a little bit of cleanup... */ + + /* + * Convert result out of Montgomery form... this is + * just a Montgomery reduction. + */ + lbnCopy_32(a, a1, mlen); + lbnZero_32(a1, mlen); + lbnMontReduce_32(a, mod, mlen, inv); + lbnCopy_32(n, a1, mlen); + + /* Clean up - free intermediate storage */ + LBNFREE(b, 2*mlen); + LBNFREE(a, 2*mlen); + + return 0; /* Success */ +} + + +/* + * Returns a substring of the big-endian array of bytes representation + * of the bignum array based on two parameters, the least significant + * byte number (0 to start with the least significant byte) and the + * length. I.e. the number returned is a representation of + * (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen). + * + * It is an error if the bignum is not at least buflen + lsbyte bytes + * long. + * + * This code assumes that the compiler has the minimal intelligence + * neded to optimize divides and modulo operations on an unsigned data + * type with a power of two. + */ +void +lbnExtractBigBytes_32(BNWORD32 const *n, unsigned char *buf, + unsigned lsbyte, unsigned buflen) +{ + BNWORD32 t = 0; /* Needed to shut up uninitialized var warnings */ + unsigned shift; + + lsbyte += buflen; + + shift = (8 * lsbyte) % 32; + lsbyte /= (32/8); /* Convert to word offset */ + BIGLITTLE(n -= lsbyte, n += lsbyte); + + if (shift) + t = BIGLITTLE(n[-1],n[0]); + + while (buflen--) { + if (!shift) { + t = BIGLITTLE(*n++,*--n); + shift = 32; + } + shift -= 8; + *buf++ = (unsigned char)(t>>shift); + } +} + +/* + * Merge a big-endian array of bytes into a bignum array. + * The array had better be big enough. This is + * equivalent to extracting the entire bignum into a + * large byte array, copying the input buffer into the + * middle of it, and converting back to a bignum. + * + * The buf is "len" bytes long, and its *last* byte is at + * position "lsbyte" from the end of the bignum. + * + * Note that this is a pain to get right. Fortunately, it's hardly + * critical for efficiency. + */ +void +lbnInsertBigBytes_32(BNWORD32 *n, unsigned char const *buf, + unsigned lsbyte, unsigned buflen) +{ + BNWORD32 t = 0; /* Shut up uninitialized varibale warnings */ + + lsbyte += buflen; + + BIGLITTLE(n -= lsbyte/(32/8), n += lsbyte/(32/8)); + + /* Load up leading odd bytes */ + if (lsbyte % (32/8)) { + t = BIGLITTLE(*--n,*n++); + t >>= (lsbyte * 8) % 32; + } + + /* The main loop - merge into t, storing at each word boundary. */ + while (buflen--) { + t = (t << 8) | *buf++; + if ((--lsbyte % (32/8)) == 0) + BIGLITTLE(*n++,*--n) = t; + } + + /* Merge odd bytes in t into last word */ + lsbyte = (lsbyte * 8) % 32; + if (lsbyte) { + t <<= lsbyte; + t |= (((BNWORD32)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]); + BIGLITTLE(n[0],n[-1]) = t; + } + + return; +} + +/* + * Returns a substring of the little-endian array of bytes representation + * of the bignum array based on two parameters, the least significant + * byte number (0 to start with the least significant byte) and the + * length. I.e. the number returned is a representation of + * (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen). + * + * It is an error if the bignum is not at least buflen + lsbyte bytes + * long. + * + * This code assumes that the compiler has the minimal intelligence + * neded to optimize divides and modulo operations on an unsigned data + * type with a power of two. + */ +void +lbnExtractLittleBytes_32(BNWORD32 const *n, unsigned char *buf, + unsigned lsbyte, unsigned buflen) +{ + BNWORD32 t = 0; /* Needed to shut up uninitialized var warnings */ + + BIGLITTLE(n -= lsbyte/(32/8), n += lsbyte/(32/8)); + + if (lsbyte % (32/8)) { + t = BIGLITTLE(*--n,*n++); + t >>= (lsbyte % (32/8)) * 8 ; + } + + while (buflen--) { + if ((lsbyte++ % (32/8)) == 0) + t = BIGLITTLE(*--n,*n++); + *buf++ = (unsigned char)t; + t >>= 8; + } +} + +/* + * Merge a little-endian array of bytes into a bignum array. + * The array had better be big enough. This is + * equivalent to extracting the entire bignum into a + * large byte array, copying the input buffer into the + * middle of it, and converting back to a bignum. + * + * The buf is "len" bytes long, and its first byte is at + * position "lsbyte" from the end of the bignum. + * + * Note that this is a pain to get right. Fortunately, it's hardly + * critical for efficiency. + */ +void +lbnInsertLittleBytes_32(BNWORD32 *n, unsigned char const *buf, + unsigned lsbyte, unsigned buflen) +{ + BNWORD32 t = 0; /* Shut up uninitialized varibale warnings */ + + /* Move to most-significant end */ + lsbyte += buflen; + buf += buflen; + + BIGLITTLE(n -= lsbyte/(32/8), n += lsbyte/(32/8)); + + /* Load up leading odd bytes */ + if (lsbyte % (32/8)) { + t = BIGLITTLE(*--n,*n++); + t >>= (lsbyte * 8) % 32; + } + + /* The main loop - merge into t, storing at each word boundary. */ + while (buflen--) { + t = (t << 8) | *--buf; + if ((--lsbyte % (32/8)) == 0) + BIGLITTLE(*n++,*--n) = t; + } + + /* Merge odd bytes in t into last word */ + lsbyte = (lsbyte * 8) % 32; + if (lsbyte) { + t <<= lsbyte; + t |= (((BNWORD32)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]); + BIGLITTLE(n[0],n[-1]) = t; + } + + return; +} + +#ifdef DEADCODE /* This was a precursor to the more flexible lbnExtractBytes */ +/* + * Convert a big-endian array of bytes to a bignum. + * Returns the number of words in the bignum. + * Note the expression "32/8" for the number of bytes per word. + * This is so the word-size adjustment will work. + */ +unsigned +lbnFromBytes_32(BNWORD32 *a, unsigned char const *b, unsigned blen) +{ + BNWORD32 t; + unsigned alen = (blen + (32/8-1))/(32/8); + BIGLITTLE(a -= alen, a += alen); + + while (blen) { + t = 0; + do { + t = t << 8 | *b++; + } while (--blen & (32/8-1)); + BIGLITTLE(*a++,*--a) = t; + } + return alen; +} +#endif + +/* + * Computes the GCD of a and b. Modifies both arguments; + * when it returns, one of them is the GCD and the other is trash. + * The return value is the length of the GCD, with the sign telling + * whether it is in a (+ve) or b (-ve). Both inputs must have + * one extra word of precision. alen must be >= blen. + * + * TODO: use the binary algorithm (Knuth section 4.5.2, algorithm B). + * This is based on taking out common powers of 2, then repeatedly: + * gcd(2*u,v) = gcd(u,2*v) = gcd(u,v) - isolated powers of 2 can be deleted. + * gcd(u,v) = gcd(u-v,v) - the numbers can be easily reduced. + * It gets less reduction per step, but the steps are much faster than + * the division case. + */ +int +lbnGcd_32(BNWORD32 *a, unsigned alen, BNWORD32 *b, unsigned blen) +{ + assert(alen >= blen); + + while (blen != 0) { + (void)lbnDiv_32(BIGLITTLE(a-blen,a+blen), a, alen, b, blen); + alen = lbnNorm_32(a, blen); + if (alen == 0) + return -(int)blen; + (void)lbnDiv_32(BIGLITTLE(b-alen,b+alen), b, blen, a, alen); + blen = lbnNorm_32(b, alen); + } + return alen; +} + +/* + * Invert "a" modulo "mod" using the extended Euclidean algorithm. + * Note that this only computes one of the cosequences, and uses the + * theorem that the signs flip every step and the absolute value of + * the cosequence values are always bounded by the modulus to avoid + * having to work with negative numbers. + * gcd(a,mod) had better equal 1. Returns 1 if the GCD is NOT 1. + * a must be one word longer than "mod". It is overwritten with the + * result. + * TODO: Use Richard Schroeppel's *much* faster algorithm. + */ +int +lbnInv_32(BNWORD32 *a, unsigned alen, BNWORD32 const *mod, unsigned mlen) +{ + BNWORD32 *b; /* Hold a copy of mod during GCD reduction */ + BNWORD32 *p; /* Temporary for products added to t0 and t1 */ + BNWORD32 *t0, *t1; /* Inverse accumulators */ + BNWORD32 cy; + unsigned blen, t0len, t1len, plen; + + alen = lbnNorm_32(a, alen); + if (!alen) + return 1; /* No inverse */ + + mlen = lbnNorm_32(mod, mlen); + + assert (alen <= mlen); + + /* Inverse of 1 is 1 */ + if (alen == 1 && BIGLITTLE(a[-1],a[0]) == 1) { + lbnZero_32(BIGLITTLE(a-alen,a+alen), mlen-alen); + return 0; + } + + /* Allocate a pile of space */ + LBNALLOC(b, mlen+1); + if (b) { + /* + * Although products are guaranteed to always be less than the + * modulus, it can involve multiplying two 3-word numbers to + * get a 5-word result, requiring a 6th word to store a 0 + * temporarily. Thus, mlen + 1. + */ + LBNALLOC(p, mlen+1); + if (p) { + LBNALLOC(t0, mlen); + if (t0) { + LBNALLOC(t1, mlen); + if (t1) + goto allocated; + LBNFREE(t0, mlen); + } + LBNFREE(p, mlen+1); + } + LBNFREE(b, mlen+1); + } + return -1; + +allocated: + + /* Set t0 to 1 */ + t0len = 1; + BIGLITTLE(t0[-1],t0[0]) = 1; + + /* b = mod */ + lbnCopy_32(b, mod, mlen); + /* blen = mlen (implicitly) */ + + /* t1 = b / a; b = b % a */ + cy = lbnDiv_32(t1, b, mlen, a, alen); + *(BIGLITTLE(t1-(mlen-alen)-1,t1+(mlen-alen))) = cy; + t1len = lbnNorm_32(t1, mlen-alen+1); + blen = lbnNorm_32(b, alen); + + /* while (b > 1) */ + while (blen > 1 || BIGLITTLE(b[-1],b[0]) != (BNWORD32)1) { + /* q = a / b; a = a % b; */ + if (alen < blen || (alen == blen && lbnCmp_32(a, a, alen) < 0)) + assert(0); + cy = lbnDiv_32(BIGLITTLE(a-blen,a+blen), a, alen, b, blen); + *(BIGLITTLE(a-alen-1,a+alen)) = cy; + plen = lbnNorm_32(BIGLITTLE(a-blen,a+blen), alen-blen+1); + assert(plen); + alen = lbnNorm_32(a, blen); + if (!alen) + goto failure; /* GCD not 1 */ + + /* t0 += q * t1; */ + assert(plen+t1len <= mlen+1); + lbnMul_32(p, BIGLITTLE(a-blen,a+blen), plen, t1, t1len); + plen = lbnNorm_32(p, plen + t1len); + assert(plen <= mlen); + if (plen > t0len) { + lbnZero_32(BIGLITTLE(t0-t0len,t0+t0len), plen-t0len); + t0len = plen; + } + cy = lbnAddN_32(t0, p, plen); + if (cy) { + if (t0len > plen) { + cy = lbnAdd1_32(BIGLITTLE(t0-plen,t0+plen), + t0len-plen, cy); + } + if (cy) { + BIGLITTLE(t0[-t0len-1],t0[t0len]) = cy; + t0len++; + } + } + + /* if (a <= 1) return a ? t0 : FAIL; */ + if (alen <= 1 && BIGLITTLE(a[-1],a[0]) == (BNWORD32)1) { + if (alen == 0) + goto failure; /* FAIL */ + assert(t0len <= mlen); + lbnCopy_32(a, t0, t0len); + lbnZero_32(BIGLITTLE(a-t0len, a+t0len), mlen-t0len); + goto success; + } + + /* q = b / a; b = b % a; */ + if (blen < alen || (blen == alen && lbnCmp_32(b, a, alen) < 0)) + assert(0); + cy = lbnDiv_32(BIGLITTLE(b-alen,b+alen), b, blen, a, alen); + *(BIGLITTLE(b-blen-1,b+blen)) = cy; + plen = lbnNorm_32(BIGLITTLE(b-alen,b+alen), blen-alen+1); + assert(plen); + blen = lbnNorm_32(b, alen); + if (!blen) + goto failure; /* GCD not 1 */ + + /* t1 += q * t0; */ + assert(plen+t0len <= mlen+1); + lbnMul_32(p, BIGLITTLE(b-alen,b+alen), plen, t0, t0len); + plen = lbnNorm_32(p, plen + t0len); + assert(plen <= mlen); + if (plen > t1len) { + lbnZero_32(BIGLITTLE(t1-t1len,t1+t1len), plen-t1len); + t1len = plen; + } + cy = lbnAddN_32(t1, p, plen); + if (cy) { + if (t1len > plen) { + cy = lbnAdd1_32(BIGLITTLE(t1-plen,t0+plen), + t1len-plen, cy); + } + if (cy) { + BIGLITTLE(t1[-t1len-1],t1[t1len]) = cy; + t1len++; + } + } + } + + if (!blen) + goto failure; /* gcd(a, mod) != 1 -- FAIL */ + + /* return mod-t1 */ + lbnCopy_32(a, mod, mlen); + assert(t1len <= mlen); + cy = lbnSubN_32(a, t1, t1len); + if (cy) { + assert(mlen > t1len); + cy = lbnSub1_32(BIGLITTLE(a-t1len, a+t1len), mlen-t1len, cy); + assert(!cy); + } + +success: + LBNFREE(t1, mlen); + LBNFREE(t0, mlen); + LBNFREE(p, mlen+1); + LBNFREE(b, mlen+1); + + return 0; + +failure: + LBNFREE(t1, mlen); + LBNFREE(t0, mlen); + LBNFREE(p, mlen+1); + LBNFREE(b, mlen+1); + + return 1; +} diff --git a/lib/bind/cylink/lbn32.h b/lib/bind/cylink/lbn32.h new file mode 100644 index 0000000000..2915e9e93f --- /dev/null +++ b/lib/bind/cylink/lbn32.h @@ -0,0 +1,181 @@ +#ifndef LBN32_H +#define LBN32_H + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +#include "lbn.h" + +#ifndef BNWORD32 +#error 32-bit bignum library requires a 32-bit data type +#endif + +#ifndef lbnCopy_32 +void lbnCopy_32(BNWORD32 *dest, BNWORD32 const *src, unsigned len); +#endif +#ifndef lbnZero_32 +void lbnZero_32(BNWORD32 *num, unsigned len); +#endif +#ifndef lbnNeg_32 +void lbnNeg_32(BNWORD32 *num, unsigned len); +#endif + +#ifndef lbnAdd1_32 +BNWORD32 lbnAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry); +#endif +#ifndef lbnSub1_32 +BNWORD32 lbnSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow); +#endif + +#ifndef lbnAddN_32 +BNWORD32 lbnAddN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len); +#endif +#ifndef lbnSubN_32 +BNWORD32 lbnSubN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len); +#endif + +#ifndef lbnCmp_32 +int lbnCmp_32(BNWORD32 const *num1, BNWORD32 const *num2, unsigned len); +#endif + +#ifndef lbnMulN1_32 +void lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k); +#endif +#ifndef lbnMulAdd1_32 +BNWORD32 +lbnMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k); +#endif +#ifndef lbnMulSub1_32 +BNWORD32 lbnMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k); +#endif + +#ifndef lbnLshift_32 +BNWORD32 lbnLshift_32(BNWORD32 *num, unsigned len, unsigned shift); +#endif +#ifndef lbnDouble_32 +BNWORD32 lbnDouble_32(BNWORD32 *num, unsigned len); +#endif +#ifndef lbnRshift_32 +BNWORD32 lbnRshift_32(BNWORD32 *num, unsigned len, unsigned shift); +#endif + +#ifndef lbnMul_32 +void lbnMul_32(BNWORD32 *prod, BNWORD32 const *num1, unsigned len1, + BNWORD32 const *num2, unsigned len2); +#endif +#ifndef lbnSquare_32 +void lbnSquare_32(BNWORD32 *prod, BNWORD32 const *num, unsigned len); +#endif + +#ifndef lbnNorm_32 +unsigned lbnNorm_32(BNWORD32 const *num, unsigned len); +#endif +#ifndef lbnBits_32 +unsigned lbnBits_32(BNWORD32 const *num, unsigned len); +#endif + +#ifndef lbnExtractBigBytes_32 +void lbnExtractBigBytes_32(BNWORD32 const *bn, unsigned char *buf, + unsigned lsbyte, unsigned buflen); +#endif +#ifndef lbnInsertBigytes_32 +void lbnInsertBigBytes_32(BNWORD32 *n, unsigned char const *buf, + unsigned lsbyte, unsigned buflen); +#endif +#ifndef lbnExtractLittleBytes_32 +void lbnExtractLittleBytes_32(BNWORD32 const *bn, unsigned char *buf, + unsigned lsbyte, unsigned buflen); +#endif +#ifndef lbnInsertLittleBytes_32 +void lbnInsertLittleBytes_32(BNWORD32 *n, unsigned char const *buf, + unsigned lsbyte, unsigned buflen); +#endif + +#ifndef lbnDiv21_32 +BNWORD32 lbnDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d); +#endif +#ifndef lbnDiv1_32 +BNWORD32 lbnDiv1_32(BNWORD32 *q, BNWORD32 *rem, + BNWORD32 const *n, unsigned len, BNWORD32 d); +#endif +#ifndef lbnModQ_32 +unsigned lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d); +#endif +#ifndef lbnDiv_32 +BNWORD32 +lbnDiv_32(BNWORD32 *q, BNWORD32 *n, unsigned nlen, BNWORD32 *d, unsigned dlen); +#endif + +#ifndef lbnMontInv1_32 +BNWORD32 lbnMontInv1_32(BNWORD32 const x); +#endif +#ifndef lbnMontReduce_32 +void lbnMontReduce_32(BNWORD32 *n, BNWORD32 const *mod, unsigned const mlen, + BNWORD32 inv); +#endif +#ifndef lbnToMont_32 +void lbnToMont_32(BNWORD32 *n, unsigned nlen, BNWORD32 *mod, unsigned mlen); +#endif +#ifndef lbnFromMont_32 +void lbnFromMont_32(BNWORD32 *n, BNWORD32 *mod, unsigned len); +#endif + +#ifndef lbnExpMod_32 +int lbnExpMod_32(BNWORD32 *result, BNWORD32 const *n, unsigned nlen, + BNWORD32 const *exp, unsigned elen, BNWORD32 *mod, unsigned mlen); +#endif +#ifndef lbnDoubleExpMod_32 +int lbnDoubleExpMod_32(BNWORD32 *result, + BNWORD32 const *n1, unsigned n1len, BNWORD32 const *e1, unsigned e1len, + BNWORD32 const *n2, unsigned n2len, BNWORD32 const *e2, unsigned e2len, + BNWORD32 *mod, unsigned mlen); +#endif +#ifndef lbnTwoExpMod_32 +int lbnTwoExpMod_32(BNWORD32 *n, BNWORD32 const *exp, unsigned elen, + BNWORD32 *mod, unsigned mlen); +#endif +#ifndef lbnGcd_32 +int lbnGcd_32(BNWORD32 *a, unsigned alen, BNWORD32 *b, unsigned blen); +#endif +#ifndef lbnInv_32 +int lbnInv_32(BNWORD32 *a, unsigned alen, BNWORD32 const *mod, unsigned mlen); +#endif + +#endif /* LBN32_H */ diff --git a/lib/bind/cylink/lbn68000.c b/lib/bind/cylink/lbn68000.c new file mode 100644 index 0000000000..2c302caa69 --- /dev/null +++ b/lib/bind/cylink/lbn68000.c @@ -0,0 +1,500 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn68000.c - 16-bit bignum primitives for the 68000 (or 68010) processors. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + * + * This was written for Metrowerks C, and while it should be reasonably + * portable, NOTE that Metrowerks lets a callee trash a0, a1, d0, d1, and d2. + * Some 680x0 compilers make d2 callee-save, so instructions to save it + * will have to be added. + * + * This code supports 16 or 32-bit ints, based on UINT_MAX. + * Regardless of UINT_MAX, only bignums up to 64K words (1 million bits) + * are supported. (68k hackers will recognize this as a consequence of + * using dbra.) + * + * These primitives use little-endian word order. + * (The order of bytes within words is irrelevant to this issue.) + */ + +#include + +#include "lbn.h" /* Should include lbn68000.h */ + +/* + * The Metrowerks C compiler (1.2.2) produces bad 68k code for the + * following input, which happens to be the inner loop of lbnSub1, + * so a few less than critical routines have been recoded in assembly + * to avoid the bug. (Optimizer on or off does not matter.) + * + * unsigned + * decrement(unsigned *num, unsigned len) + * { + * do { + * if ((*num++)-- != 0) + * return 0; + * } while (--len); + * return 1; + * } + */ +asm BNWORD16 +lbnSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow) +{ + movea.l 4(sp),a0 /* num */ +#if UINT_MAX == 0xffff + move.w 10(sp),d0 /* borrow */ +#else + move.w 12(sp),d0 /* borrow */ +#endif + sub.w d0,(a0)+ + bcc done +#if UINT_MAX == 0xffff + move.w 8(sp),d0 /* len */ +#else + move.w 10(sp),d0 /* len */ +#endif + subq.w #2,d0 + bcs done +loop: + subq.w #1,(a0)+ + dbcc d0,loop +done: + moveq.l #0,d0 + addx.w d0,d0 + rts +} + +asm BNWORD16 +lbnAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry) +{ + movea.l 4(sp),a0 /* num */ +#if UINT_MAX == 0xffff + move.w 10(sp),d0 /* carry */ +#else + move.w 12(sp),d0 /* carry */ +#endif + add.w d0,(a0)+ + bcc done +#if UINT_MAX == 0xffff + move.w 8(sp),d0 /* len */ +#else + move.w 10(sp),d0 /* len */ +#endif + subq.w #2,d0 + bcs done +loop: + addq.w #1,(a0)+ + dbcc d0,loop +done: + moveq.l #0,d0 + addx.w d0,d0 + rts +} + +asm void +lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + move.w d3,-(sp) /* 2 bytes of stack frame */ + move.l 2+4(sp),a1 /* out */ + move.l 2+8(sp),a0 /* in */ +#if UINT_MAX == 0xffff + move.w 2+12(sp),d3 /* len */ + move.w 2+14(sp),d2 /* k */ +#else + move.w 2+14(sp),d3 /* len (low 16 bits) */ + move.w 2+16(sp),d2 /* k */ +#endif + + move.w (a0)+,d1 /* First multiply */ + mulu.w d2,d1 + move.w d1,(a1)+ + clr.w d1 + swap d1 + + subq.w #1,d3 /* Setup for loop unrolling */ + lsr.w #1,d3 + bcs.s m16_even + beq.s m16_short + + subq.w #1,d3 /* Set up software pipeline properly */ + move.l d1,d0 + +m16_loop: + move.w (a0)+,d1 + mulu.w d2,d1 + add.l d0,d1 + move.w d1,(a1)+ + clr.w d1 + swap d1 +m16_even: + + move.w (a0)+,d0 + mulu.w d2,d0 + add.l d1,d0 + move.w d0,(a1)+ + clr.w d0 + swap d0 + + dbra d3,m16_loop + + move.w d0,(a1) + move.w (sp)+,d3 + rts +m16_short: + move.w d1,(a1) + move.w (sp)+,d3 + rts +} + + +asm BNWORD16 +lbnMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + move.w d4,-(sp) + clr.w d4 + move.w d3,-(sp) /* 4 bytes of stack frame */ + move.l 4+4(sp),a1 /* out */ + move.l 4+8(sp),a0 /* in */ +#if UINT_MAX == 0xffff + move.w 4+12(sp),d3 /* len */ + move.w 4+14(sp),d2 /* k */ +#else + move.w 4+14(sp),d3 /* len (low 16 bits) */ + move.w 4+16(sp),d2 /* k */ +#endif + + move.w (a0)+,d1 /* First multiply */ + mulu.w d2,d1 + add.w d1,(a1)+ + clr.w d1 + swap d1 + addx.w d4,d1 + + subq.w #1,d3 /* Setup for loop unrolling */ + lsr.w #1,d3 + bcs.s ma16_even + beq.s ma16_short + + subq.w #1,d3 /* Set up software pipeline properly */ + move.l d1,d0 + +ma16_loop: + move.w (a0)+,d1 + mulu.w d2,d1 + add.l d0,d1 + add.w d1,(a1)+ + clr.w d1 + swap d1 + addx.w d4,d1 +ma16_even: + + move.w (a0)+,d0 + mulu.w d2,d0 + add.l d1,d0 + add.w d0,(a1)+ + clr.w d0 + swap d0 + addx.w d4,d0 + + dbra d3,ma16_loop + + move.w (sp)+,d3 + move.w (sp)+,d4 + rts +ma16_short: + move.w (sp)+,d3 + move.l d1,d0 + move.w (sp)+,d4 + rts +} + + + +asm BNWORD16 +lbnMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + move.w d4,-(sp) + clr.w d4 + move.w d3,-(sp) /* 4 bytes of stack frame */ + move.l 4+4(sp),a1 /* out */ + move.l 4+8(sp),a0 /* in */ +#if UINT_MAX == 0xffff + move.w 4+12(sp),d3 /* len */ + move.w 4+14(sp),d2 /* k */ +#else + move.w 4+14(sp),d3 /* len (low 16 bits) */ + move.w 4+16(sp),d2 /* k */ +#endif + + move.w (a0)+,d1 /* First multiply */ + mulu.w d2,d1 + sub.w d1,(a1)+ + clr.w d1 + swap d1 + addx.w d4,d1 + + subq.w #1,d3 /* Setup for loop unrolling */ + lsr.w #1,d3 + bcs.s ms16_even + beq.s ms16_short + + subq.w #1,d3 /* Set up software pipeline properly */ + move.l d1,d0 + +ms16_loop: + move.w (a0)+,d1 + mulu.w d2,d1 + add.l d0,d1 + sub.w d1,(a1)+ + clr.w d1 + swap d1 + addx.w d4,d1 +ms16_even: + + move.w (a0)+,d0 + mulu.w d2,d0 + add.l d1,d0 + sub.w d0,(a1)+ + clr.w d0 + swap d0 + addx.w d4,d0 + + dbra d3,ms16_loop + + move.w (sp)+,d3 + move.w (sp)+,d4 + rts +ms16_short: + move.w (sp)+,d3 + move.l d1,d0 + move.w (sp)+,d4 + rts +} + +/* The generic long/short divide doesn't know that nh < d */ +asm BNWORD16 +lbnDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d) +{ + move.l 8(sp),d0 /* nh *and* nl */ + divu.w 12(sp),d0 + move.l 4(sp),a0 + move.w d0,(a0) + clr.w d0 + swap d0 + rts +} + +asm unsigned +lbnModQ_16(BNWORD16 const *n, unsigned len, BNWORD16 d) +{ + move.l 4(sp),a0 /* n */ + moveq.l #0,d1 +#if UINT_MAX == 0xffff + move.w 8(sp),d1 /* len */ + move.w 10(sp),d2 /* d */ +#else + move.w 10(sp),d1 /* len (low 16 bits) */ + move.w 12(sp),d2 /* d */ +#endif + + add.l d1,a0 + add.l d1,a0 /* n += len */ + moveq.l #0,d0 + subq.w #1,d1 + +mq16_loop: + move.w -(a0),d0 /* Assemble remainder and new word */ + divu.w d2,d0 /* Put remainder in high half of d0 */ + dbra d1,mq16_loop + +mq16_done: + clr.w d0 + swap d0 + rts +} + +/* + * Detect if this is a 32-bit processor (68020+ *or* CPU32). + * Both the 68020+ and CPU32 processors (which have 32x32->64-bit + * multiply, what the 32-bit math library wants) support scaled indexed + * addressing. The 68000 and 68010 ignore the scale selection + * bits, treating it as *1 all the time. So a 32-bit processor + * will evaluate -2(a0,a0.w*2) as 1+1*2-2 = 1. + * A 16-bit processor will compute 1+1-2 = 0. + * + * Thus, the return value will indicate whether the chip this is + * running on supports 32x32->64-bit multiply (mulu.l). + */ +asm int +is68020(void) +{ + machine 68020 + lea 1,a0 +#if 0 + lea -2(a0,a0.w*2),a0 /* Metrowerks won't assemble this, arrgh */ +#else + dc.w 0x41f0, 0x82fe +#endif + move.l a0,d0 + rts +} +/* + * Since I had to hand-assemble that fancy addressing mode, I had to study + * up on 680x0 addressing modes. + * A summary of 680x0 addressing modes. + * A 68000 effective address specifies an operand on an instruction, which + * may be a register or in memory. It is made up of a 3-bit mode and a + * 3-bit register specifier. The meanings of the various modes are: + * + * 000 reg - Dn, n specified by "reg" + * 001 reg - An, n specified by "reg" + * 010 reg - (An) + * 011 reg - (An)+ + * 100 reg - -(An) + * 101 reg - d16(An), one 16-bit displacement word follows, sign-extended + * 110 reg - Fancy addressing mode off of An, see extension word below + * 111 000 - abs.W, one 16-bit signed absolute address follows + * 111 001 - abs.L, one 32-bit absolute address follows + * 111 010 - d16(PC), one 16-bit displacemnt word follows, sign-extended + * 111 011 - Fancy addressing mode off of PC, see extension word below + * 111 100 - #immediate, followed by 16 or 32 bits of immediate value + * 111 101 - unused, reserved + * 111 110 - unused, reserved + * 111 111 - unused, reserved + * + * Memory references are to data space, except that PC-relative references + * are to program space, and are read-only. + * + * Fancy addressing modes are followed by a 16-bit extension word, and come + * in "brief" and "full" forms. + * The "brief" form looks like this. Bit 8 is 0 to indicate this form: + * + * 1 1 1 1 1 1 1 + * 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * |A/D| register |L/W| scale | 0 | 8-bit signed displacement | + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * + * The basic effective address specifies a 32-bit base register - A0 through + * A7 or PC (the address of the following instruction). + * The A/D and register fields specify an index register. A/D is 1 for + * address registers, and 0 for data registers. L/W specifies the length + * of the index register, 1 for 32 bits, and 0 for 16 bits (sign-extended). + * The scale field is a left shift amount (0 to 3 bits) to apply to the + * sign-extended index register. The final address is d8(An,Rn.X*SCALE), + * also written (d8,An,Rn.X*SCALE). X is "W" or "L", SCALE is 1, 2, 4 or 8. + * "*1" may be omitted, as may a d8 of 0. + * + * The 68000 supports this form, but only with a scale field of 0. + * It does NOT (says the MC68030 User's Manual MC68030UM/AD, section 2.7) + * decode the scale field and the following format bit. They are treated + * as 0. + * I recall (I don't have the data book handy) that the CPU32 processor + * core used in the 683xx series processors supports variable scales, + * but only the brief extension word form. I suspect it decodes the + * format bit and traps if it is not zero, but I don't recall. + * + * The "full" form (680x0, x >= 2 processors only) looks like this: + * + * 1 1 1 1 1 1 1 + * 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * |A/D| register |L/W| scale | 1 | BS| IS|BD size| 0 | P |OD size| + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * + * The first 8 bits are interpreted the same way as in the brief form, + * except that bit 8 is set to 1 to indicate the full form. + * BS, Base Suppress, if set, causes a value of 0 to be used in place of + * the base register value. If this is set, the base register + * specified is irrelevant, except that if it is the PC, the fetch is + * still done from program space. The specifier "ZPC" can be used in + * place of "PC" in the effective address mnemonic to represent this + * case. + * IS, Index Suppress, if set, causes a value of 0 to be used in place + * of the scaled index register. In this case, the first 7 bits of the + * extension word are irrelevant. + * BD size specifies the base displacement size. A value of 00 + * in this field is illegal, while 01, 10 and 11 indicate that the + * extension word is followed by 0, 1 or 2 16-bit words of base displacement + * (zero, sign-extended to 32 bits, and most-significant word first, + * respectively) to add to the base register value. + * Bit 3 is unused. + * The P bit is the pre/post indexing bit, and only applies if an outer + * displacement is used. This is explained later. + * OD size specifies the size of an outer displacement. In the simple + * case, this field is set to 00 and the effective address is + * (disp,An,Rn.X*SCALE) or (disp,PC,Rn.X*SCALE). + * In this case the P bit must be 0. Any of those compnents may be + * suppressed, with a BD size of 01, the BS bit, or the IS bit. + * If the OD size is not 00, it encodes an outer displacement in the same + * manner as the BD size, and 0, 1 or 2 16-bit words of outer displacement + * follow the base displacement in the instruction stream. In this case, + * this is a double-indirect addressing mode. The base, base displacement, + * and possibly the index, specify a 32-bit memory word which holds a value + * which is fetched, and the outer displacement and possibly the index are + * added to produce the address of the operand. + * If the P bit is 0, this is pre-indexed, and the index value is added + * before the fetch of the indirect word, producing an effective address + * of ([disp,An,Rn.X*SCALE],disp). If the P bit is 1, the post-indexed case, + * the memory word is fectched from base+base displacement, then the index + * and outer displacement are added to compute the address of the operand. + * This effective address is written ([disp,An],Rn.X*SCALE,disp). + * (In both cases, "An" may also be "PC" or "ZPC".) + * Any of the components may be omitted. If the index is omitted (using the + * IS bit), the P bit is irrelevant, but must be written as 0. + * Thus, legal combinations of IS, P and OD size are: + * 0 0 00 - (disp,An,Rn.X*SCALE), also written disp(An,Rn.X*SCALE) + * 0 0 01 - ([disp,An,Rn.X*SCALE]) + * 0 0 10 - ([disp,An,Rn.X*SCALE],d16) + * 0 0 11 - ([disp,An,Rn.X*SCALE],d32) + * 0 1 01 - ([disp,An],Rn.X*SCALE) + * 0 1 10 - ([disp,An],Rn.X*SCALE,d16) + * 0 1 11 - ([disp,An],Rn.X*SCALE,d32) + * 1 0 00 - (disp,An), also written disp(An) + * 1 0 01 - ([disp,An]) + * 1 0 10 - ([disp,An],d16) + * 1 0 11 - ([disp,An],d32) + */ + +/* 45678901234567890123456789012345678901234567890123456789012345678901234567 */ diff --git a/lib/bind/cylink/lbn68000.h b/lib/bind/cylink/lbn68000.h new file mode 100644 index 0000000000..f52e799608 --- /dev/null +++ b/lib/bind/cylink/lbn68000.h @@ -0,0 +1,74 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn68000.h - 16-bit bignum primitives for the 68000 (or 68010) processors. + * + * These primitives use little-endian word order. + * (The order of bytes within words is irrelevant.) + */ +#define BN_LITTLE_ENDIAN 1 + +typedef unsigned short bnword16 +#define BNWORD16 bnword16 + +bnword16 lbnSub1_16(bnword16 *num, unsigned len, bnword16 borrow); +bnword16 lbnAdd1_16(bnword16 *num, unsigned len, bnword16 carry); +void lbnMulN1_16(bnword16 *out, bnword16 const *in, unsigned len, bnword16 k); +bnword16 +lbnMulAdd1_16(bnword16 *out, bnword16 const *in, unsigned len, bnword16 k); +bnword16 +lbnMulSub1_16(bnword16 *out, bnword16 const *in, unsigned len, bnword16 k); +bnword16 lbnDiv21_16(bnword16 *q, bnword16 nh, bnword16 nl, bnword16 d); +unsigned lbnModQ_16(bnword16 const *n, unsigned len, bnword16 d); + +int is68020(void); + +/* #define the values to exclude the C versions */ +#define lbnSub1_16 lbnSub1_16 +#define lbnAdd1_16 lbnAdd1_16 +#define lbnMulN1_16 lbnMulN1_16 +#define lbnMulAdd1_16 lbnMulAdd1_16 +#define lbnMulSub1_16 lbnMulSub1_16 +#define lbnDiv21_16 lbnDiv21_16 +#define lbnModQ_16 lbnModQ_16 + +/* Also include the 68020 definitions for 16/32 bit switching versions. */ +#include diff --git a/lib/bind/cylink/lbn68020.c b/lib/bind/cylink/lbn68020.c new file mode 100644 index 0000000000..6b52f59ba4 --- /dev/null +++ b/lib/bind/cylink/lbn68020.c @@ -0,0 +1,349 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn68020.c - 32-bit bignum primitives for the 68020+ (0r 683xx) processors. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + * + * This was written for Metrowerks C, and while it should be reasonably + * portable, NOTE that Metrowerks lets a callee trash a0, a1, d0, d1, and d2. + * Some 680x0 compilers make d2 callee-save, so instructions to save it + * will have to be added. + * + * This code supports 16 or 32-bit ints, based on UINT_MAX. + * Regardless of UINT_MAX, only bignums up to 64K words (2 million bits) + * are supported. (68k hackers will recognize this as a consequence of + * using dbra.) + * + * These primitives use little-endian word order. + * (The order of bytes within words is irrelevant to this issue.) + * + * TODO: Schedule this for the 68040's pipeline. (When I get a 68040 manual.) + */ + +#include + +#include "lbn.h" /* Should include lbn68020.h */ + +/* + * The Metrowerks C compiler (1.2.2) produces bad 68k code for the + * following input, which happens to be the inner loop of lbnSub1, + * so a few less than critical routines have been recoded in assembly + * to avoid the bug. (Optimizer on or off does not matter.) + * + * unsigned + * decrement(unsigned *num, unsigned len) + * { + * do { + * if ((*num++)-- != 0) + * return 0; + * } while (--len); + * return 1; + * } + */ +asm BNWORD32 +lbnSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow) +{ + movea.l 4(sp),a0 /* num */ +#if UINT_MAX == 0xffff + move.l 10(sp),d0 /* borrow */ +#else + move.l 12(sp),d0 /* borrow */ +#endif + sub.l d0,(a0)+ + bcc done +#if UINT_MAX == 0xffff + move.w 8(sp),d0 /* len */ +#else + move.w 10(sp),d0 /* len */ +#endif + subq.w #2,d0 + bcs done +loop: + subq.l #1,(a0)+ + dbcc d0,loop +done: + moveq.l #0,d0 + addx.w d0,d0 + rts +} + +asm BNWORD32 +lbnAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry) +{ + movea.l 4(sp),a0 /* num */ +#if UINT_MAX == 0xffff + move.l 10(sp),d0 /* carry */ +#else + move.l 12(sp),d0 /* carry */ +#endif + add.l d0,(a0)+ + bcc done +#if UINT_MAX == 0xffff + move.w 8(sp),d0 /* len */ +#else + move.w 10(sp),d0 /* len */ +#endif + subq.w #2,d0 + bcs done +loop: + addq.l #1,(a0)+ + dbcc d0,loop +done: + moveq.l #0,d0 + addx.w d0,d0 + rts +} + +asm void +lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + machine 68020 + + movem.l d3-d5,-(sp) /* 12 bytes of extra data */ + moveq.l #0,d4 + move.l 16(sp),a1 /* out */ + move.l 20(sp),a0 /* in */ +#if UINT_MAX == 0xffff + move.w 24(sp),d5 /* len */ + move.l 26(sp),d2 /* k */ +#else + move.w 26(sp),d5 /* len */ + move.l 28(sp),d2 /* k */ +#endif + + move.l (a0)+,d3 /* First multiply */ + mulu.l d2,d1:d3 /* dc.w 0x4c02, 0x3401 */ + move.l d3,(a1)+ + + subq.w #1,d5 /* Setup for loop unrolling */ + lsr.w #1,d5 + bcs.s m32_even + beq.s m32_short + + subq.w #1,d5 /* Set up software pipeline properly */ + move.l d1,d0 + +m32_loop: + move.l (a0)+,d3 + mulu.l d2,d1:d3 /* dc.w 0x4c02, 0x3401 */ + add.l d0,d3 + addx.l d4,d1 + move.l d3,(a1)+ +m32_even: + + move.l (a0)+,d3 + mulu.l d2,d0:d3 /* dc.w 0x4c02, 0x3400 */ + add.l d1,d3 + addx.l d4,d0 + move.l d3,(a1)+ + + dbra d5,m32_loop + + move.l d0,(a1) + movem.l (sp)+,d3-d5 + rts +m32_short: + move.l d1,(a1) + movem.l (sp)+,d3-d5 + rts +} + + +asm BNWORD32 +lbnMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + machine 68020 + movem.l d3-d5,-(sp) /* 12 bytes of extra data */ + moveq.l #0,d4 + move.l 16(sp),a1 /* out */ + move.l 20(sp),a0 /* in */ +#if UINT_MAX == 0xffff + move.w 24(sp),d5 /* len */ + move.l 26(sp),d2 /* k */ +#else + move.w 26(sp),d5 /* len */ + move.l 28(sp),d2 /* k */ +#endif + + move.l (a0)+,d3 /* First multiply */ + mulu.l d2,d1:d3 /* dc.w 0x4c02, 0x3401 */ + add.l d3,(a1)+ + addx.l d4,d1 + + subq.w #1,d5 /* Setup for loop unrolling */ + lsr.w #1,d5 + bcs.s ma32_even + beq.s ma32_short + + subq.w #1,d5 /* Set up software pipeline properly */ + move.l d1,d0 + +ma32_loop: + move.l (a0)+,d3 + mulu.l d2,d1:d3 /* dc.w 0x4c02, 0x3401 */ + add.l d0,d3 + addx.l d4,d1 + add.l d3,(a1)+ + addx.l d4,d1 +ma32_even: + + move.l (a0)+,d3 + mulu.l d2,d0:d3 /* dc.w 0x4c02, 0x3400 */ + add.l d1,d3 + addx.l d4,d0 + add.l d3,(a1)+ + addx.l d4,d0 + + dbra d5,ma32_loop + + movem.l (sp)+,d3-d5 + rts +ma32_short: + move.l d1,d0 + movem.l (sp)+,d3-d5 + rts +} + + +asm BNWORD32 +lbnMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + machine 68020 + movem.l d3-d5,-(sp) /* 12 bytes of extra data */ + moveq.l #0,d4 + move.l 16(sp),a1 /* out */ + move.l 20(sp),a0 /* in */ +#if UINT_MAX == 0xffff + move.w 24(sp),d5 /* len */ + move.l 26(sp),d2 /* k */ +#else + move.w 26(sp),d5 /* len */ + move.l 28(sp),d2 /* k */ +#endif + + move.l (a0)+,d3 /* First multiply */ + mulu.l d2,d1:d3 /* dc.w 0x4c02, 0x3401 */ + sub.l d3,(a1)+ + addx.l d4,d1 + + subq.w #1,d5 /* Setup for loop unrolling */ + lsr.w #1,d5 + bcs.s ms32_even + beq.s ms32_short + + subq.w #1,d5 /* Set up software pipeline properly */ + move.l d1,d0 + +ms32_loop: + move.l (a0)+,d3 + mulu.l d2,d1:d3 /* dc.w 0x4c02, 0x3401 */ + add.l d0,d3 + addx.l d4,d1 + sub.l d3,(a1)+ + addx.l d4,d1 +ms32_even: + + move.l (a0)+,d3 + mulu.l d2,d0:d3 /* dc.w 0x4c02, 0x3400 */ + add.l d1,d3 + addx.l d4,d0 + sub.l d3,(a1)+ + addx.l d4,d0 + + dbra d5,ms32_loop + + movem.l (sp)+,d3-d5 + rts + +ms32_short: + move.l d1,d0 + movem.l (sp)+,d3-d5 + rts +} + + +asm BNWORD32 +lbnDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d) +{ + machine 68020 + move.l 8(sp),d0 + move.l 12(sp),d1 + move.l 4(sp),a0 + divu.l 16(sp),d0:d1 /* dc.w 0x4c6f, 0x1400, 16 */ + move.l d1,(a0) + rts +} + +asm unsigned +lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d) +{ + machine 68020 + move.l 4(sp),a0 /* n */ + move.l d3,a1 +#if UINT_MAX == 0xffff + moveq.l #0,d2 + move.w 8(sp),d1 /* len */ + move.w 10(sp),d2 /* d */ +#else + move.w 10(sp),d1 /* len */ + move.l 12(sp),d2 /* d */ +#endif + dc.w 0x41f0, 0x1cfc /* lea -4(a0,d1.L*4),a0 */ + + /* First time, divide 32/32 - may be faster than 64/32 */ + move.l (a0),d3 + divul.l d2,d0:d3 /* dc.w 0x4c02, 0x3000 */ + subq.w #2,d1 + bmi mq32_done + +mq32_loop: + move.l -(a0),d3 + divu.l d2,d0:d3 /* dc.w 0x4c02,0x3400 */ + dbra d1,mq32_loop + +mq32_done: + move.l a1,d3 + rts +} + +/* 45678901234567890123456789012345678901234567890123456789012345678901234567 */ diff --git a/lib/bind/cylink/lbn68020.h b/lib/bind/cylink/lbn68020.h new file mode 100644 index 0000000000..17f6fb2ca8 --- /dev/null +++ b/lib/bind/cylink/lbn68020.h @@ -0,0 +1,69 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn68020.h - 32-bit bignum primitives for the 68020 (or 683xx) processors. + * + * These primitives use little-endian word order. + * (The order of bytes within words is irrelevant.) + */ +#define BN_LITTLE_ENDIAN 1 + +typedef unsigned long bnword32 +#define BNWORD32 bnword32 + +bnword32 lbnSub1_32(bnword32 *num, unsigned len, bnword32 borrow); +bnword32 lbnAdd1_32(bnword32 *num, unsigned len, bnword32 carry); +void lbnMulN1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k); +bnword32 +lbnMulAdd1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k); +bnword32 +lbnMulSub1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k); +bnword32 lbnDiv21_32(bnword32 *q, bnword32 nh, bnword32 nl, bnword32 d); +unsigned lbnModQ_32(bnword32 const *n, unsigned len, unsigned d); + +/* #define the values to exclude the C versions */ +#define lbnSub1_32 lbnSub1_32 +#define lbnAdd1_32 lbnAdd1_32 +#define lbnMulN1_32 lbnMulN1_32 +#define lbnMulAdd1_32 lbnMulAdd1_32 +#define lbnMulSub1_32 lbnMulSub1_32 +#define lbnDiv21_32 lbnDiv21_32 +#define lbnModQ_32 lbnModQ_32 diff --git a/lib/bind/cylink/lbn80386.h b/lib/bind/cylink/lbn80386.h new file mode 100644 index 0000000000..80541743bc --- /dev/null +++ b/lib/bind/cylink/lbn80386.h @@ -0,0 +1,169 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn80386.h - This file defines the interfaces to the 80386 + * assembly primitives. It is intended to be included in "lbn.h" + * via the "#include BNINCLUDE" mechanism. + */ + +#define BN_LITTLE_ENDIAN 1 + +typedef unsigned long bnword32; +#define BNWORD32 bnword32 + +/* MS-DOS needs the calling convention described to it. */ +#ifndef MSDOS +#ifdef __MSDOS__ +#define MSDOS 1 +#endif +#endif + +#ifdef MSDOS +#define CDECL __cdecl +#else +#define CDECL /*nothing*/ +#endif + +#ifdef __cplusplus +/* These assembly-language primitives use C names */ +extern "C" { +#endif + +/* Function prototypes for the asm routines */ +void CDECL +lbnMulN1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k); +#define lbnMulN1_32 lbnMulN1_32 + +bnword32 CDECL +lbnMulAdd1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k); +#define lbnMulAdd1_32 lbnMulAdd1_32 + +bnword32 CDECL +lbnMulSub1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k); +#define lbnMulSub1_32 lbnMulSub1_32 + +bnword32 CDECL +lbnDiv21_32(bnword32 *q, bnword32 nh, bnword32 nl, bnword32 d); +#define lbnDiv21_32 lbnDiv21_32 + +unsigned CDECL +lbnModQ_32(bnword32 const *n, unsigned len, bnword32 d); +#define lbnModQ_32 lbnModQ_32 + +#ifdef __cplusplus +} +#endif + + +#if __GNUC__ +/* + * Use the (massively cool) GNU inline-assembler extension to define + * inline expansions for various operations. + * + * The massively cool part is that the assembler can have inputs + * and outputs, and you specify the operands and which effective + * addresses are legal and they get substituted into the code. + * (For example, some of the code requires a zero. Rather than + * specify an immediate constant, the expansion specifies an operand + * of zero which can be in various places. This lets GCC use an + * immediate zero, or a register which contains zero if it's available.) + * + * The syntax is asm("asm_code" : outputs : inputs : trashed) + * %0, %1 and so on in the asm code are substituted by the operands + * in left-to-right order (outputs, then inputs). + * The operands contain constraint strings and values to use. + * Outputs must be lvalues, inputs may be rvalues. In the constraints: + * "a" means that the operand must be in eax. + * "d" means that the operand must be in edx. + * "g" means that the operand may be any effective address. + * "=" means that the operand is assigned to. + * "%" means that this operand and the following one may be + * interchanged if desirable. + * "bcDSmn" means that the operand must be in ebx, ecx, esi, edi, memory, + * or an immediate constant. (This is almost the same as "g" + * but allowing it in eax wouldn't help because x is already + * assigned there, and it must not be in edx, since edx is + * overwritten by the multiply before a and b are read.) + * + * Note that GCC uses AT&T assembler syntax, which is rather + * different from Intel syntax. The length (b, w or l) of the + * operation is appended to the opcode, and the *second* operand + * is the destination, not the first. Finally, the register names + * are all preceded with "%". (Doubled here because % is a + * magic character.) + */ + +/* (ph<<32) + pl = x*y */ +#define mul32_ppmm(ph,pl,x,y) \ + __asm__("mull %3" : "=d"(ph), "=a"(pl) : "%a"(x), "g"(y)) + +/* (ph<<32) + pl = x*y + a */ +#define mul32_ppmma(ph,pl,x,y,a) \ + __asm__("mull %3\n\t" \ + "addl %4,%%eax\n\t" \ + "adcl %5,%%edx" \ + : "=&d"(ph), "=a"(pl) \ + : "%a"(x), "g"(y), "bcDSmn"(a), "bcDSmn"(0)) + +/* (ph<<32) + pl = x*y + a + b */ +#define mul32_ppmmaa(ph,pl,x,y,a,b) \ + __asm__("mull %3\n\t" \ + "addl %4,%%eax\n\t" \ + "adcl %6,%%edx\n\t" \ + "addl %5,%%eax\n\t" \ + "adcl %6,%%edx" \ + : "=&d"(ph), "=a"(pl) \ + : "%a"(x), "g"(y), "%bcDSmn"(a), "bcDSmn"(b), "bcDSmn"(0)) + +/* q = ((nh<<32) + nl) / d, return remainder. nh guaranteed < d. */ +#undef lbnDiv21_32 +#define lbnDiv21_32(q,nh,nl,d) \ + ({unsigned _; \ + __asm__("divl %4" : "=d"(_), "=a"(*q) : "d"(nh), "a"(nl), "g"(d)); \ + _;}) + +/* No quotient, just return remainder ((nh<<32) + nl) % d */ +#define lbnMod21_32(nh,nl,d) \ + ({unsigned _; \ + __asm__("divl %3" : "=d"(_) : "d"(nh), "a"(nl), "g"(d) : "ax"); \ + _;}) + +#endif /* __GNUC__ */ diff --git a/lib/bind/cylink/lbn8086.h b/lib/bind/cylink/lbn8086.h new file mode 100644 index 0000000000..863c5a0805 --- /dev/null +++ b/lib/bind/cylink/lbn8086.h @@ -0,0 +1,113 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn8086.h - This file defines the interfaces to the 8086 + * assembly primitives for 16-bit MS-DOS environments. + * It is intended to be included in "lbn.h" + * via the "#include BNINCLUDE" mechanism. + */ + +#define BN_LITTLE_ENDIAN 1 + +#ifdef __cplusplus +/* These assembly-language primitives use C names */ +extern "C" { +#endif + +/* Set up the appropriate types */ +typedef unsigned short bnword16; +#define BNWORD16 bnword16 +typedef unsigned long bnword32; +#define BNWORD32 bnword32 + +void __cdecl __far +lbnMulN1_16(bnword16 __far *out, bnword16 const __far *in, + unsigned len, bnword16 k); +#define lbnMulN1_16 lbnMulN1_16 + +bnword16 __cdecl __far +lbnMulAdd1_16(bnword16 __far *out, bnword16 const __far *in, + unsigned len, bnword16 k); +#define lbnMulAdd1_16 lbnMulAdd1_16 + +bnword16 __cdecl __far +lbnMulSub1_16(bnword16 __far *out, bnword16 const __far *in, + unsigned len, bnword16 k); +#define lbnMulSub1_16 lbnMulSub1_16 + +bnword16 __cdecl __far +lbnDiv21_16(bnword16 __far *q, bnword16 nh, bnword16 nl, bnword16 d); +#define lbnDiv21_16 lbnDiv21_16 + +bnword16 __cdecl __far +lbnModQ_16(bnword16 const __far *n, unsigned len, bnword16 d); +#define lbnModQ_16 lbnModQ_16 + + + +void __cdecl __far +lbnMulN1_32(bnword32 __far *out, bnword32 const __far *in, + unsigned len, bnword32 k); +#define lbnMulN1_32 lbnMulN1_32 + +bnword32 __cdecl __far +lbnMulAdd1_32(bnword32 __far *out, bnword32 const __far *in, + unsigned len, bnword32 k); +#define lbnMulAdd1_32 lbnMulAdd1_32 + +bnword32 __cdecl __far +lbnMulSub1_32(bnword32 __far *out, bnword32 const __far *in, + unsigned len, bnword32 k); +#define lbnMulSub1_32 lbnMulSub1_32 + +bnword32 __cdecl __far +lbnDiv21_32(bnword32 __far *q, bnword32 nh, bnword32 nl, bnword32 d); +#define lbnDiv21_32 lbnDiv21_32 + +bnword16 __cdecl __far +lbnModQ_32(bnword32 const __far *n, unsigned len, bnword32 d); +#define lbnModQ_32 lbnModQ_32 + +int __cdecl __far not386(void); + +#ifdef __cplusplus +} +#endif diff --git a/lib/bind/cylink/lbnmem.c b/lib/bind/cylink/lbnmem.c new file mode 100644 index 0000000000..6fac3ed54c --- /dev/null +++ b/lib/bind/cylink/lbnmem.c @@ -0,0 +1,195 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbnmem.c - low-level bignum memory handling. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + * + * Note that in all cases, the pointers passed around + * are pointers to the *least* significant end of the word. + * On big-endian machines, these are pointers to the *end* + * of the allocated range. + * + * BNSECURE is a simple level of security; for more security + * change these function to use locked unswappable memory. + */ + +#include "port_before.h" + +#ifndef HAVE_CONFIG_H +#define HAVE_CONFIG_H 0 +#endif +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Some compilers complain about #if FOO if FOO isn't defined, + * so do the ANSI-mandated thing explicitly... + */ +#ifndef NO_STDLIB_H +#define NO_STDLIB_H 0 +#endif +#ifndef NO_STRING_H +#define NO_STRING_H 0 +#endif +#ifndef HAVE_STRINGS_H +#define HAVE_STRINGS_H 0 +#endif +#ifndef NEED_MEMORY_H +#define NEED_MEMORY_H 0 +#endif + +#if !NO_STDLIB_H +#include /* For malloc() & co. */ +#else +void *malloc(); +void *realloc(); +void free(); +#endif + +#if !NO_STRING_H +#include /* For memset */ +#elif HAVE_STRINGS_H +#include +#endif +#if NEED_MEMORY_H +#include +#endif + +#ifndef DBMALLOC +#define DBMALLOC 0 +#endif +#if DBMALLOC +/* Development debugging */ +#include "../dbmalloc/malloc.h" +#endif + +#include "lbn.h" +#include "lbnmem.h" + +#include "kludge.h" + +#ifndef lbnMemWipe +void +lbnMemWipe(void *ptr, unsigned bytes) +{ + memset(ptr, 0, bytes); +} +#define lbnMemWipe(ptr, bytes) memset(ptr, 0, bytes) +#endif + +#ifndef lbnMemAlloc +void * +lbnMemAlloc(unsigned bytes) +{ + return malloc(bytes); +} +#define lbnMemAlloc(bytes) malloc(bytes) +#endif + +#ifndef lbnMemFree +void +lbnMemFree(void *ptr, unsigned bytes) +{ + lbnMemWipe(ptr, bytes); + free(ptr); +} +#endif + +#ifndef lbnRealloc +#if defined(lbnMemRealloc) || !BNSECURE +void * +lbnRealloc(void *ptr, unsigned oldbytes, unsigned newbytes) +{ + if (ptr) { + BIG(ptr = (char *)ptr - oldbytes;) + if (newbytes < oldbytes) + memmove(ptr, (char *)ptr + oldbytes-newbytes, oldbytes); + } +#ifdef lbnMemRealloc + ptr = lbnMemRealloc(ptr, oldbytes, newbytes); +#else + ptr = realloc(ptr, newbytes); +#endif + if (ptr) { + if (newbytes > oldbytes) + memmove((char *)ptr + newbytes-oldbytes, ptr, oldbytes); + BIG(ptr = (char *)ptr + newbytes;) + } + + return ptr; +} + +#else /* BNSECURE */ + +void * +lbnRealloc(void *oldptr, unsigned oldbytes, unsigned newbytes) +{ + void *newptr = lbnMemAlloc(newbytes); + + if (!newptr) + return newptr; + if (!oldptr) + return BIGLITTLE((char *)newptr+newbytes, newptr); + + /* + * The following copies are a bit non-obvious in the big-endian case + * because one of the pointers points to the *end* of allocated memory. + */ + if (newbytes > oldbytes) { /* Copy all of old into part of new */ + BIG(newptr = (char *)newptr + newbytes;) + BIG(oldptr = (char *)oldptr - oldbytes;) + memcpy(BIGLITTLE((char *)newptr-oldbytes, newptr), oldptr, + oldbytes); + } else { /* Copy part of old into all of new */ + memcpy(newptr, BIGLITTLE((char *)oldptr-newbytes, oldptr), + newbytes); + BIG(newptr = (char *)newptr + newbytes;) + BIG(oldptr = (char *)oldptr - oldbytes;) + } + + lbnMemFree(oldptr, oldbytes); + return newptr; +} +#endif /* BNSECURE */ +#endif /* !lbnRealloc */ diff --git a/lib/bind/cylink/lbnmem.h b/lib/bind/cylink/lbnmem.h new file mode 100644 index 0000000000..a3f15377e4 --- /dev/null +++ b/lib/bind/cylink/lbnmem.h @@ -0,0 +1,102 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * Operations on the usual buffers of bytes + */ +#ifndef BNSECURE +#define BNSECURE 1 +#endif + +/* + * These operations act on buffers of memory, just like malloc & free. + * One exception: it is not legal to pass a NULL pointer to lbnMemFree. + */ + +#ifndef lbnMemAlloc +void *lbnMemAlloc(unsigned bytes); +#endif + +#ifndef lbnMemFree +void lbnMemFree(void *ptr, unsigned bytes); +#endif + +/* This wipes out a buffer of bytes if necessary needed. */ + +#ifndef lbnMemWipe +#if BNSECURE +void lbnMemWipe(void *ptr, unsigned bytes); +#else +#define lbnMemWipe(ptr, bytes) (void)(ptr,bytes) +#endif +#endif /* !lbnMemWipe */ + +/* + * lbnRealloc is NOT like realloc(); it's endian-sensitive! + * If lbnMemRealloc is #defined, lbnRealloc will be defined in terms of it. + * It is legal to pass a NULL pointer to lbnRealloc, although oldbytes + * will always be sero. + */ +#ifndef lbnRealloc +void *lbnRealloc(void *ptr, unsigned oldbytes, unsigned newbytes); +#endif + + +/* + * These macros are the ones actually used most often in the math library. + * They take and return pointers to the *end* of the given buffer, and + * take sizes in terms of words, not bytes. + * + * Note that LBNALLOC takes the pointer as an argument instead of returning + * the value. + * + * Note also that these macros are only useable if you have included + * lbn.h (for the BIG and BIGLITTLE macros), which this file does NOT include. + */ + +#define LBNALLOC(p,words) BIGLITTLE( \ + if ( ((p) = lbnMemAlloc((words)*sizeof*(p))) != 0) (p) += (words), \ + (p) = lbnMemAlloc((words) * sizeof*(p)) \ + ) +#define LBNFREE(p,words) lbnMemFree((p) BIG(-(words)), (words) * sizeof*(p)) +#define LBNREALLOC(p,old,new) \ + lbnRealloc(p, (old) * sizeof*(p), (new) * sizeof*(p)) +#define LBNWIPE(p,words) lbnMemWipe((p) BIG(-(words)), (words) * sizeof*(p)) + diff --git a/lib/bind/cylink/lbnppc.c b/lib/bind/cylink/lbnppc.c new file mode 100644 index 0000000000..ed44e17e5a --- /dev/null +++ b/lib/bind/cylink/lbnppc.c @@ -0,0 +1,358 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +#include "lbnppc.h" + +/* + * lbnppc.c - Assembly primitives for the bignum library, PowerPC version. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c + * + * Register usage during function calls is: + * r0 - volatile + * r1 - stack pointer, preserved + * r2 - TOC pointer, preserved + * r3 - First argument and return value register + * r4-r10 - More argument registers, volatile + * r11-r12 - Volatile + * r13-r31 - Preserved + * LR, CTR, XER and MQ are all volatile. + * LR holds return address on entry. + * + * On the PPC 601, unrolling the loops more doesn't seem to speed things + * up at all. I'd be curious if other chips differed. + */ +#if __MWERKS__ < 0x800 + +#include "ppcasm.h" /* PowerPC assembler */ + +/* + * MulN1 expects (*out, *in, len, k), count >= 1 + * r3 r4 r5 r6 + */ +static const unsigned mulN1[] = { + PPC_LWZ(7,4,0), /* Load first word of in in r7 */ + PPC_MULLW(8,7,6), /* Low half of multiply in r8 */ + PPC_MTCTR(5), /* Move len into CTR */ + PPC_ADDIC(0,0,0), /* Clear carry bit for loop */ + PPC_MULHWU(5,7,6), /* High half of multiply in r5 */ + PPC_STW(8,3,0), + PPC_BC(18,31,7), /* Branch to Label if --ctr == 0 */ +/* Loop: */ + PPC_LWZU(7,4,4), /* r7 = *++in */ + PPC_MULLW(8,7,6), /* r8 = low word of product */ + PPC_ADDE(8,8,5), /* Add carry word r5 and bit CF to r8 */ + PPC_STWU(8,3,4), /* *++out = r8 */ + PPC_MULHWU(5,7,6), /* r5 is high word of product, for carry word */ + PPC_BC(16,31,-5), /* Branch to Loop if --ctr != 0 */ +/* Label: */ + PPC_ADDZE(5,5), /* Add carry flag to r5 */ + PPC_STW(5,3,4), /* out[1] = r5 */ + PPC_BLR() +}; + +/* + * MulAdd1 expects (*out, *in, len, k), count >= 1 + * r3 r4 r5 r6 + */ +static unsigned const mulAdd1[] = { + PPC_LWZ(7,4,0), /* Load first word of in in r7 */ + PPC_LWZ(0,3,0), /* Load first word of out into r0 */ + PPC_MULLW(8,7,6), /* Low half of multiply in r8 */ + PPC_MTCTR(5), /* Move len into CTR */ + PPC_MULHWU(5,7,6), /* High half of multiply in r5 */ + PPC_ADDC(8,8,0), /* r8 = r8 + r0 */ + PPC_STW(8,3,0), /* Store result to memory */ + PPC_BC(18,31,10), /* Branch to Label if --ctr == 0 */ +/* Loop: */ + PPC_LWZU(7,4,4), /* r7 = *++in */ + PPC_LWZU(0,3,4), /* r0 = *++out */ + PPC_MULLW(8,7,6), /* r8 = low word of product */ + PPC_ADDE(8,8,5), /* Add carry word r5 and carry bit CF to r8 */ + PPC_MULHWU(5,7,6), /* r5 is high word of product, for carry word */ + PPC_ADDZE(5,5), /* Add carry bit from low add to r5 */ + PPC_ADDC(8,8,0), /* r8 = r8 + r0 */ + PPC_STW(8,3,0), /* *out = r8 */ + PPC_BC(16,31,-8), /* Branch to Loop if --ctr != 0 */ +/* Label: */ + PPC_ADDZE(3,5), /* Add carry flag to r5 and move to r3 */ + PPC_BLR() +}; + +/* + * MulSub1 expects (*out, *in, len, k), count >= 1 + * r3 r4 r5 r6 + * + * Multiply and subtract is rather a pain. If the subtract of the + * low word of the product from out[i] generates a borrow, we want to + * increment the carry word (initially in the range 0..0xfffffffe). + * However, the PPC's carry bit CF is *clear* after a subtract, so + * we want to add (1-CF) to the carry word. This is done using two + * instructions: + * + * SUBFME, subtract from minus one extended. This computes + * rD = ~rS + 0xffffffff + CF. Since rS is from 0 to 0xfffffffe, + * ~rS is from 1 through 0xffffffff, and the sum with 0xffffffff+CF is + * from 0 through 0xfffffffff, setting the carry flag unconditionally, and + * NOR, which is used as a bitwise invert NOT instruction. + * + * The SUBFME performs the computation rD = ~rS + 0xffffffff + CF, + * = (-rS - 1) + (CF - 1) = -(rS - CF + 1) - 1 = ~(rS + 1-CF), + * which is the bitwise complement of the value we want. + * We want to add the complement of that result to the low word of the + * product, which is just what a subtract would do, if only we could get + * the carry flag clear. But it's always set, except for SUBFE, and the + * operation we just performed unconditionally *sets* the carry flag. Ugh. + * So find the complement in a separate instruction. + */ +static unsigned const mulSub1[] = { + PPC_LWZ(7,4,0), /* Load first word of in in r7 */ + PPC_LWZ(0,3,0), /* Load first word of out into r0 */ + PPC_MTCTR(5), /* Move len into CTR */ + PPC_MULLW(8,7,6), /* Low half of multiply in r8 */ + PPC_MULHWU(5,7,6), /* High half of multiply in r5 */ + PPC_SUBFC(8,8,0), /* r8 = r0 - r8, setting CF */ + PPC_STW(8,3,0), /* Store result to memory */ + PPC_SUBFME(5,5), /* First of two insns to add (1-CF) to r5 */ + PPC_BC(18,31,12), /* Branch to Label if --ctr == 0 */ +/* Loop: */ + PPC_LWZU(7,4,4), /* r7 = *++in */ + PPC_LWZU(0,3,4), /* r0 = *++out */ + PPC_NOR(5,5,5), /* Second of two insns to add (1-CF) to r5 */ + PPC_MULLW(8,7,6), /* r8 = low word of product */ + PPC_ADDC(8,8,5), /* Add carry word r5 to r8 */ + PPC_MULHWU(5,7,6), /* r5 is high word of product, for carry word */ + PPC_ADDZE(5,5), /* Add carry bit from low add to r5 */ + PPC_SUBFC(8,8,0), /* r8 = r0 - r8, setting CF */ + PPC_STW(8,3,0), /* *out = r8 */ + PPC_SUBFME(5,5), /* First of two insns to add (1-CF) to r5 */ + PPC_BC(16,31,-10), /* Branch to Loop if --ctr != 0 */ +/* Label: */ + PPC_NOR(3,5,5), /* Finish adding (1-CF) to r5, store in r3 */ + PPC_BLR() +}; + +#if 0 +/* + * Args: BNWORD32 *n, BNWORD32 const *mod, unsigned mlen, BNWORD32 inv) + * r3 r4 r5 r6 + * r7, r8 and r9 are the triple-width accumulator. + * r0 and r10 are temporary registers. + * r11 and r12 are temporary pointers into n and mod, respectively. + * r2 (!) is another temporary register. + */ +static unsigned const montReduce[] = { + PPC_MTCTR(5), /* ??? */ + PPC_LWZ(7,3,0), /* Load low word of n into r7 */ + PPC_LWZ(10,4,0), /* Fetch low word of mod */ + PPC_MULLW(0,7,6), /* Invert r7 into r0 */ + PPC_STW(0,3,0), /* Store back for future use */ + PPC_MULHWU(8,10,7), /* Get high word of whatnot */ + PPC_MULLW(10,10,7), /* Get low word of it */ + PPC_ADDC(7,7,10), /* Add low word of product to r7 */ + PPC_ADDZE(8,8), /* Add carry to high word */ + PPC_ + + + PPC_MULHW(8,7,6), + PPC_ADDC(7,7,0), /* Add inverse back to r7 */ + PPC_ADDZE(8,8), + PPC_ + + PPC_LWZU( +/* Loop: */ + PPC_LWZU(0,11,4), + PPC_LWZU(10,23,-4), + PPC_MULLW(2,0,10), + PPC_ADDC(7,7,2), + PPC_MULHWU(0,0,10), + PPC_ADDE(8,8,0), + PPC_ADDZE(9,9), + PPC_BC(16,31,-7), /* Branch to Loop if --ctr != 0 */ + + PPC_ADDIC_(count,-1), + PPC_LWZU(0,x,4), + PPC_ADDC(0,7,0), + PPC_STW(0,x,0), + PPC_ADDZE(7,8), + PPC_ADDZE(8,9), + PPC_LI(9,0), + PPC_BC(xx,2,yy), + +}; +#endif + +/* + * Three overlapped transition vectors for three functions. + * A PowerPC transition vector for a (potentially) inter-module + * jump or call consists of two words, an instruction address + * and a Table Of Contents (TOC) pointer, which is loaded into + * r1. Since none of the routines here have global variables, + * they don't need a TOC pointer, so the value is unimportant. + * This array places an unintersting 32-bit value after each address. + */ +unsigned const * const lbnPPC_tv[] = { + mulN1, + mulAdd1, + mulSub1, + 0 +}; + +#else /* __MWERKS >= 0x800 */ + +/* + * MulN1 expects (*out, *in, len, k), count >= 1 + * r3 r4 r5 r6 + */ +asm void +lbnMulN1_32(register unsigned *out, register unsigned const *in, + register unsigned len, register unsigned k) +{ + lwz r7,0(in) /* Load first word of in in r7 */ + mtctr len /* Move len into CTR */ + mullw r8,r7,k /* Low half of multiply in r8 */ + addic r0,r0,0 /* Clear carry bit for loop */ + mulhwu len,r7,k /* High half of multiply in len */ + stw r8,0(out) /* *out = r8 */ + mulhwu len,r7,k /* len is high word of product, for carry */ + bdz- label /* Branch to Label if --ctr == 0 */ +loop: + lwzu r7,4(in) /* r7 = *++in */ + mullw r8,r7,k /* Low half of multiply in r8 */ + adde r8,r8,len /* Add carry word len and bit CF to r8 */ + stwu r8,4(out) /* *++out = r8 */ + mulhwu len,r7,k /* len is high word of product, for carry */ + bdnz+ loop /* Branch to Loop if --ctr != 0 */ +label: + addze len,len /* Add carry flag to carry word */ + stw len,4(out) + blr +} + +/* + * MulAdd1 expects (*out, *in, len, k), count >= 1 + * r3 r4 r5 r6 + */ +asm unsigned +lbnMulAdd1_32(register unsigned *out, register unsigned const *in, + register unsigned len, register unsigned k) +{ + lwz r7,0(in) /* Load first word of in in r7 */ + lwz r0,0(out) /* Load first word of out into r0 */ + mullw r8,r7,k /* Low half of multiply in r8 */ + mtctr len /* Move len into CTR */ + mulhwu len,r7,k /* High half of multiply in len */ + addc r8,r8,r0 /* r8 = r8 + r0 */ + stw r8,0(out) /* Store result to memory */ + bdz- label /* Branch to Label if --ctr == 0 */ +loop: + lwzu r7,4(in) /* r7 = *++in */ + lwzu r0,4(out) /* r0 = *++out */ + mullw r8,r7,k /* r8 = low word of product */ + adde r8,r8,len /* Add carry word len and carry bit CF to r8 */ + mulhwu len,r7,k /* len is high word of product, for carry */ + addze len,len /* Add carry bit from low add to r5 */ + addc r8,r8,r0 /* r8 = r8 + r0 */ + stw r8,0(out) /* *out = r8 */ + bdnz+ loop /* Branch to Loop if --ctr != 0 */ +label: + addze r3,r5 /* Add carry flag to r5 and move to r3 */ + blr +} + +/* + * MulSub1 expects (*out, *in, len, k), count >= 1 + * r3 r4 r5 r6 + * + * Multiply and subtract is rather a pain. If the subtract of the + * low word of the product from out[i] generates a borrow, we want to + * increment the carry word (initially in the range 0..0xfffffffe). + * However, the PPC's carry bit CF is *clear* after a subtract, so + * we want to add (1-CF) to the carry word. This is done using two + * instructions: + * + * SUBFME, subtract from minus one extended. This computes + * rD = ~rS + 0xffffffff + CF. Since rS is from 0 to 0xfffffffe, + * ~rS is from 1 through 0xffffffff, and the sum with 0xffffffff+CF is + * from 0 through 0xfffffffff, setting the carry flag unconditionally, and + * NOR, which is used as a bitwise invert NOT instruction. + * + * The SUBFME performs the computation rD = ~rS + 0xffffffff + CF, + * = (-rS - 1) + (CF - 1) = -(rS - CF + 1) - 1 = ~(rS + 1-CF), + * which is the bitwise complement of the value we want. + * We want to add the complement of that result to the low word of the + * product, which is just what a subtract would do, if only we could get + * the carry flag clear. But it's always set, except for SUBFE, and the + * operation we just performed unconditionally *sets* the carry flag. Ugh. + * So find the complement in a separate instruction. + */ +asm unsigned +lbnMulSub1_32(register unsigned *out, register unsigned const *in, + register unsigned len, register unsigned k) +{ + lwz r7,0(in) /* Load first word of in in r7 */ + lwz r0,0(out) /* Load first word of out into r0 */ + mtctr len /* Move len into CTR */ + mullw r8,r7,k /* Low half of multiply in r8 */ + mulhwu len,r7,k /* High half of multiply in len */ + subfc r8,r8,r0 /* r8 = r0 - r8, setting CF */ + stw r8,0(out) /* Store result to memory */ + subfme len,len /* First of two insns to add (1-CF) to len */ + bdz- label /* Branch to Label if --ctr == 0 */ +loop: + lwzu r7,4(in) /* r7 = *++in */ + lwzu r0,4(out) /* r0 = *++out */ + nor len,len,len /* Second of two insns to add (1-CF) to len */ + mullw r8,r7,k /* r8 = low word of product */ + addc r8,r8,len /* Add carry word len to r8 */ + mulhwu len,r7,k /* len is high word of product, for carry */ + addze len,len /* Add carry bit from low add to len */ + subfc r8,r8,r0 /* r8 = r0 - r8 */ + stw r8,0(out) /* *out = r8 */ + subfme len,len /* First of two insns to add (1-CF) to len */ + bdnz+ loop /* Branch to Loop if --ctr != 0 */ +label: + nor r3,r5,r5 /* Finish adding (1-CF) to len, store in r3 */ + blr +} + +#endif /* __MWERKS >= 0x800 */ +/* 45678901234567890123456789012345678901234567890123456789012345678901234567 */ diff --git a/lib/bind/cylink/lbnppc.h b/lib/bind/cylink/lbnppc.h new file mode 100644 index 0000000000..6d03d21839 --- /dev/null +++ b/lib/bind/cylink/lbnppc.h @@ -0,0 +1,98 @@ +#ifndef LBNPPC_H +#define LBNPPC_H +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + + +/* + * Assembly-language routines for the Power PC processor. + * Annoyingly, the Power PC does not have 64/32->32 bit divide, + * so the C code should be reasonably fast. But it does have + * 32x32->64-bit multiplies, and these routines provide access + * to that. + * + * In versions of CodeWarrior before 8.0, there was no PPC assembler, + * so a kludged-up one in CPP is used. This requires casting an + * array of unsigneds to function pointer type, and a function pointer + * is not a pointer to the code, but rather a pointer to a (code,TOC) + * pointer pair which we fake up. + * + * CodeWarrior 8.0 supports PCC assembly, which is used directly. + */ + +/* + * Bignums are stored in arrays of 32-bit words, and the least + * significant 32-bit word has the lowest address, thus "little-endian". + * The C code is slightly more efficient this way, so unless the + * processor cares (the PowerPC, like most RISCs, doesn't), it is + * best to use BN_LITTLE_ENDIAN. + * Note that this has NOTHING to do with the order of bytes within a 32-bit + * word; the math library is insensitive to that. + */ +#define BN_LITTLE_ENDIAN 1 + +typedef unsigned bnword32; +#define BNWORD32 bnword32 + +#if __MWERKS__ < 0x800 + +/* Shared transition vector array */ +extern unsigned const * const lbnPPC_tv[]; + +/* A function pointer on the PowerPC is a pointer to a transition vector */ +#define lbnMulN1_32 \ +((void (*)(bnword32 *, bnword32 const *, unsigned, bnword32))(lbnPPC_tv+0)) +#define lbnMulAdd1_32 \ +((bnword32 (*)(bnword32 *, bnword32 const *, unsigned, bnword32))(lbnPPC_tv+1)) +#define lbnMulSub1_32 \ +((bnword32 (*)(bnword32 *, bnword32 const *, unsigned, bnword32))(lbnPPC_tv+2)) + +#else /* __MWERKS__ >= 0x800 */ + +void lbnMulN1_32(bnword32 *, bnword32 const *, unsigned, bnword32); +#define lbnMulN1_32 lbnMulN1_32 +bnword32 lbnMulAdd1_32(bnword32 *, bnword32 const *, unsigned, bnword32); +#define lbnMulAdd1_32 lbnMulAdd1_32 +bnword32 lbnMulSub1_32(bnword32 *, bnword32 const *, unsigned, bnword32); +#define lbnMulSub1_32 lbnMulSub1_32 + +#endif /* __MWERKS__ >= 0x800 */ + +#endif /* LBNPPC_H */ diff --git a/lib/bind/cylink/legal.c b/lib/bind/cylink/legal.c new file mode 100644 index 0000000000..f750ed89f5 --- /dev/null +++ b/lib/bind/cylink/legal.c @@ -0,0 +1,45 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + + +/* Force inclusion of this... */ +#include "legal.h" +volatile const char bnCopyright[] = + "bnlib 1.0.1 Copyright (c) 1995,1996 Colin Plumb."; diff --git a/lib/bind/cylink/legal.h b/lib/bind/cylink/legal.h new file mode 100644 index 0000000000..51d8552bd6 --- /dev/null +++ b/lib/bind/cylink/legal.h @@ -0,0 +1,47 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * ANSI C standard, section 3.5.3: "An object that has volatile-qualified + * type may be modified in ways unknown to the implementation or have + * other unknown side effects." Yes, we can't expect a compiler to + * understand law... + */ +extern volatile const char bnCopyright[]; diff --git a/lib/bind/cylink/math.c b/lib/bind/cylink/math.c new file mode 100644 index 0000000000..2f3a800021 --- /dev/null +++ b/lib/bind/cylink/math.c @@ -0,0 +1,1151 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: math.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Math Routines for the ToolKit +* +* PUBLIC FUNCTIONS: +* +* int Sum_big (ord *X, +* ord *Y, +* ord *Z, +* u_int16_t len_X ) +* +* int Sub_big (ord *X, +* ord *Y, +* ord *Z, +* u_int16_t len_X ) +* +* void Mul_big( ord *X, ord *Y,ord *XY, +* u_int16_t lx, u_int16_t ly) +* +* +* PRIVATE FUNCTIONS: +* +* REVISION HISTORY: +* +* 14 Oct 94 GKL Initial release +* 26 Oct 94 GKL (alignment for big endian support ) +* +****************************************************************************/ + +/**************************************************************************** +* INCLUDE FILES +****************************************************************************/ +/* bn files */ +#include "port_before.h" +#include "bn.h" +/* system files */ +#ifdef VXD +#include +#else +#include +#include +#endif +/* program files */ +#include "cylink.h" +#include "ctk_endian.h" +#include "toolkit.h" +#include "port_after.h" + +/**************************************************************************** +* NAME: void BigNumInit( void ) +* +* +* DESCRIPTION: Initialize BigNum +* +* INPUTS: +* PARAMETERS: +* OUTPUT: +* PARAMETERS: +* +* RETURN: +* +* +* REVISION HISTORY: +* +* 29 Sep 96 Initial release +* +****************************************************************************/ + +void BigNumInit() +{ +static int bignuminit = 0; +if(!bignuminit){ + bnInit(); + bignuminit = 1; + } +} +/**************************************************************************** +* NAME: int Sum_big (ord *X, +* ord *Y, +* ord *Z, +* u_int16_t len_X ) +* +* DESCRIPTION: Compute addition. +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to first array +* ord *Y Pointer to second array +* int len_X Number of longs in X_l +* OUTPUT: +* PARAMETERS: +* ord *Z Pointer to result arrray +* +* RETURN: +* Carry bit +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + + int Sum_big (ord *X, + ord *Y, + ord *Z, + u_int16_t len_X ) +{ + +struct BigNum src2,temp_bn; +ord *temp; +BigNumInit(); + +/*bnInit(); +bnBegin(&src2); +bnBegin(&temp_bn); +*/ +temp = (ord *) malloc((len_X*sizeof(ord)) + sizeof(ord)); +temp_bn.size = len_X; +temp_bn.ptr = temp; +temp_bn.allocated = len_X + 1; + +src2.ptr = Y; +src2.size = len_X; +src2.allocated = len_X; + +memcpy(temp,X,len_X*sizeof(ord)); +bnAdd(&temp_bn,&src2); +memcpy(Z,temp_bn.ptr,len_X*sizeof(ord)); +/*bn package increments the size of dest by 1 if the carry bit is 1*/ +free(temp); +if (temp_bn.size > len_X) + return 1; +else + return 0; +} + + int Sum (ord *X, ord *Y, u_int16_t len_X ) +{ + +struct BigNum dest,src; +/*ord *temp;*/ +BigNumInit(); +#if 0 +bnInit(); +bnBegin(&src2); +bnBegin(&temp_bn); + +temp = (ord *) malloc((len_X*sizeof(ord)) + sizeof(ord)); +temp_bn.size = len_X; +temp_bn.ptr = temp; +temp_bn.allocated = len_X + 1; +#endif + +dest.ptr = X; +dest.size = len_X-1; +dest.allocated = len_X; + +src.ptr = Y; +src.size = len_X; +src.allocated = len_X; + +/*memcpy(temp,X,len_X*sizeof(ord));*/ +bnAdd(&dest,&src); +/*memcpy(Z,temp_bn.ptr,len_X*sizeof(ord));*/ +/*bn package increments the size of dest by 1 if the carry bit is 1*/ +/*free(temp);*/ +if (dest.size > (u_int16_t)(len_X -1)) + return 1; +else + return 0; +} + + +/**************************************************************************** +* NAME: int Sum_Q(ord *X, +* u_int16_t src, +* u_int16_t len_X ) +* DESCRIPTION: Compute addition X += src. +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to first array +* u_int16_t src Second operand must be <65535 +* int len_X Number of ords in X_l +* OUTPUT: +* PARAMETERS: +* ord *X Pointer to result arrray +* +* RETURN: +* SUCCESS or -1 +* +* REVISION HISTORY: +* +* 21 Sep 96 AAB Initial release +****************************************************************************/ + int Sum_Q(ord *X, u_int16_t src, u_int16_t len_X ) + { + int status = SUCCESS; + struct BigNum des; + BigNumInit(); + /*bnInit();*/ + des.ptr = X; + des.size = len_X; + des.allocated = len_X; + status = bnAddQ(&des, src); + return status; + } + + +/**************************************************************************** +* NAME: int Sub_big (ord *X, +* ord *Y, +* ord *Z, +* u_int16_t len_X ) +* +* +* DESCRIPTION: Compute subtraction. +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to first array +* ord *Y Pointer to second array +* u_int16_t len_X Number of longs in X_l +* OUTPUT: +* PARAMETERS: +* ord *Z Pointer to result arrray +* +* RETURN: +* Carry bit +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +int Sub_big (ord *X, + ord *Y, + ord *Z, + u_int16_t len_X ) +{ +/* carry is not returned in bn version */ +struct BigNum dest, src; +int status; +ord *temp; +BigNumInit(); +/*bnInit(); +bnBegin(&dest); +bnBegin(&src); +*/ +src.ptr = Y; +src.size = len_X; +src.allocated = len_X; + +temp = (ord*)malloc(len_X*sizeof(ord)); +dest.ptr = temp; +dest.size = len_X; +dest.allocated = len_X; +memcpy(dest.ptr,X,len_X*sizeof(ord)); + +status = bnSub(&dest,&src); +memcpy(Z,dest.ptr,len_X*sizeof(ord)); +free(temp); +return status; +} + +#if 0 +/**************************************************************************** +* NAME: void Mul_big( ord *X, ord *Y, ord *XY, +* u_int16_t lx, u_int16_t ly) +* +* +* +* DESCRIPTION: Compute a product. +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to first long array +* ord *Y Pointer to second long array +* u_int16_t lx Leftmost non zero element of first array +* u_int16_t ly Leftmost non zero element of second array +* OUTPUT: +* PARAMETERS: +* ord *XY Pointer to result +* +* RETURN: +* +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 08 Sep 95 AAB Comment out calloc and discard the elements_in_X, +* elements_in_Y +****************************************************************************/ +void Mul_big( ord *X, ord *Y, ord *XY, + u_int16_t lx, u_int16_t ly ) +{ +struct BigNum dest, src1, src2; +BigNumInit(); +/*bnInit();*/ +bnBegin(&dest); +/* +bnBegin(&src1); +bnBegin(&src2); +*/ +src1.size = lx + 1; +src1.ptr = X; +src1.allocated = lx + 1; + +src2.ptr = Y; +src2.size = ly + 1; +src2.allocated = ly + 1; + +dest.ptr = XY; +dest.size = lx + ly + 2; +dest.allocated = lx + ly + 2; + +/* Call bn routine */ +bnMul(&dest, &src1,&src2); +} + +#endif +/**************************************************************************** +* NAME: void Mul_big_1( ord X, ord *Y, ord *XY, +* u_int16_t lx, u_int16_t ly ) +* +* +* +* DESCRIPTION: Compute a product. +* +* INPUTS: +* PARAMETERS: +* ord X Number +* ord *Y Pointer to long array +* u_int16_t ly Leftmost non zero element of second array +* OUTPUT: +* PARAMETERS: +* ord *XY Pointer to result +* +* RETURN: +* +* +* REVISION HISTORY: +* +* 08 Oct 95 AAB Initial relaese +* +****************************************************************************/ +void Mul_big_1( ord X, ord *Y, ord *XY, + u_int16_t ly ) +{ +struct BigNum dest, src; +BigNumInit(); +/*bnInit(); +bnBegin(&dest); +bnBegin(&src); +*/ +src.ptr = Y; +src.size = ly + 1; +src.allocated = ly + 1; + +dest.ptr = XY; +dest.size = ly + 2; +dest.allocated = ly + 2; + +bnMulQ(&dest, &src, (unsigned)X); + +} + +/**************************************************************************** +* NAME: int Mul( u_int16_t X_bytes, +* ord *X, +* u_int16_t Y_bytes, +* ord *Y, +* u_int16_t P_bytes, +* ord *P, +* ord *Z ) +* +* DESCRIPTION: Compute a modulo product +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to first operand +* u_int16_t X_bytes Number of bytes in X +* ord *Y Pointer to second operand +* u_int16_t Y_bytes Number of bytes in Y +* ord *P Pointer to modulo +* u_int16_t P_bytes Number of bytes in P +* +* OUTPUT: +* PARAMETERS: +* ord *Z Pointer to result +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data (zero bytes) +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +int Mul( u_int16_t X_bytes, + ord *X, + u_int16_t Y_bytes, + ord *Y, + u_int16_t P_bytes, + ord *P, + ord *Z ) + +{ + int status = SUCCESS; /*function return status*/ + u_int16_t X_longs; /*number of longs in X*/ + u_int16_t Y_longs; /*number of longs in Y*/ + ord *XY; /*pointer to product (temporary)*/ + + +struct BigNum dest, src1,src2, mod; +BigNumInit(); +/*bnInit(); +bnBegin(&dest); +bnBegin(&src1); +bnBegin(&src2); +bnBegin(&mod); +*/ + +src1.size = X_bytes/sizeof(ord); +src1.ptr = X; +src1.allocated = X_bytes/sizeof(ord); + +src2.size = Y_bytes/sizeof(ord); +src2.ptr = Y; +src2.allocated =Y_bytes/sizeof(ord); + +mod.size = P_bytes/sizeof(ord); +mod.ptr = P; +mod.allocated = P_bytes/sizeof(ord); + + if ( P_bytes == 0 || X_bytes == 0 || Y_bytes == 0 ) + { + status = ERR_INPUT_LEN; + return status; + } + if ( (X_bytes % sizeof(ord) != 0) || + (Y_bytes % sizeof(ord) != 0) || + (P_bytes % sizeof(ord) != 0) ) + { + status = ERR_INPUT_LEN; + return status; + } + X_longs = (u_int16_t) (X_bytes / sizeof(ord)); + Y_longs = (u_int16_t) (Y_bytes / sizeof(ord)); + XY = (ord *)calloc( X_longs + Y_longs, sizeof(ord) ); + if( !XY ) + { + return ERR_ALLOC; + } +dest.size = X_longs + Y_longs; +dest.ptr = XY; +dest.allocated = X_longs + Y_longs; + +bnMul (&dest,&src1,&src2); + +status = bnMod(&dest, &dest, &mod); +memcpy(Z, dest.ptr, P_bytes); +free( XY ); + return status; +} + +/**************************************************************************** +* NAME: int Square( u_int16_t X_bytes, +* ord *X, +* u_int16_t P_bytes, +* ord *P, +* ord *Z ) +* +* DESCRIPTION: Compute a modulo square +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to array to be squared +* u_int16_t X_bytes Number of bytes in X +* ord *P Pointer to modulo +* u_int16_t P_bytes Number of bytes in P +* +* OUTPUT: +* PARAMETERS: +* ord *Z Pointer to result +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data (zero bytes) +* +* REVISION HISTORY: +* +* 1 Sep 95 AAB Initial release +****************************************************************************/ + +int Square( u_int16_t X_bytes, + ord *X, + u_int16_t P_bytes, + ord *P, + ord *Z ) + +{ + int status = SUCCESS; /*function return status*/ + +ord *XY; +struct BigNum dest, src, mod; +BigNumInit(); +/*bnInit(); +bnBegin(&dest); +bnBegin(&src); +bnBegin(&mod); +*/ + if ( P_bytes == 0 || X_bytes == 0 ) + { + status = ERR_INPUT_LEN; + return status; + } + if ( (X_bytes % sizeof(ord) != 0) || + (P_bytes % sizeof(ord) != 0) ) + { + status = ERR_INPUT_LEN; + return status; + } + XY = (ord *)malloc( 2*X_bytes ); + if( !XY ) + { + return ERR_ALLOC; + } + +src.size = X_bytes/sizeof(ord); +src.ptr = X; +src.allocated = X_bytes/sizeof(ord); + +dest.size = 2*X_bytes/sizeof(ord); +dest.ptr = XY; +dest.allocated = 2*X_bytes/sizeof(ord); + +mod.size = P_bytes/sizeof(ord); +mod.ptr = P; +mod.allocated = P_bytes/sizeof(ord); + +status = bnSquare(&dest, &src); +status = bnMod(&dest, &dest, &mod); +memcpy(Z, dest.ptr, P_bytes); +free(XY); +return status; +} + + +/**************************************************************************** +* NAME: int PartReduct( u_int16_t X_bytes, +* ord *X, +* u_int16_t P_bytes, +* ord *P, +* ord *Z ) +* +* DESCRIPTION: Compute a modulo +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to array +* u_int16_t X_bytes Number of bytes in X +* ord *P Pointer to modulo +* u_int16_t P_bytes Number of bytes in P +* +* OUTPUT: +* PARAMETERS: +* ord *Z Pointer to result +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data (zero bytes) +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +int PartReduct( u_int16_t X_bytes, + ord *X, + u_int16_t P_bytes, + ord *P, + ord *Z ) +{ + int status = SUCCESS; /*function return status */ + + +struct BigNum dest, /*src,*/ d; +ord *temp; +BigNumInit(); +/*bnInit(); +bnBegin(&dest); +bnBegin(&src); +bnBegin(&d); + +src.size = X_bytes/sizeof(ord); +src.ptr = X; +src.allocated = X_bytes/sizeof(ord); +*/ +d.size = P_bytes/sizeof(ord); +d.ptr = P; +d.allocated = P_bytes/sizeof(ord); + +temp = (ord*)malloc(X_bytes); +dest.size = X_bytes/sizeof(ord); +dest.ptr = temp; +dest.allocated = X_bytes/sizeof(ord); +memcpy(dest.ptr, X, X_bytes); + +status = bnMod(&dest, &dest, &d); + +memcpy(Z, dest.ptr, P_bytes); +free(temp); + +return status; + +} + +/**************************************************************************** +* NAME: int Expo( u_int16_t X_bytes, +* ord *X, +* u_int16_t Y_bytes, +* ord *Y, +* u_int16_t P_bytes, +* ord *P, +* ord *Z, +* YIELD_context *yield_cont ) +* +* DESCRIPTION: Compute a modulo exponent +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to base array +* u_int16_t X_bytes Number of bytes in base +* ord *Y Pointer to exponent array +* u_int16_t Y_bytes Number of bytes in exponent +* ord *P Pointer to modulo +* u_int16_t P_bytes Number of bytes in P +* YIELD_context *yield_cont Pointer to yield_cont structure (NULL if not used) +* +* OUTPUT: +* PARAMETERS: +* ord *Z Pointer to result +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data(zero bytes) +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 08 Dec 94 GKL Added YIELD_context +* 01 Sep 95 Fast exponentation algorithm +****************************************************************************/ + +int Expo( u_int16_t X_bytes, ord *X, + u_int16_t Y_bytes, ord *Y, + u_int16_t P_bytes, ord *P, + ord *Z ) +{ + +int status = SUCCESS; /*function return status*/ + +struct BigNum dest, n, exp, mod; +BigNumInit(); +#if 0 +/*bnInit();*/ +bnBegin(&dest); +bnBegin(&n); +bnBegin(&exp); +bnBegin(&mod); +#endif + +n.size = X_bytes/sizeof(ord); +n.ptr = X; +n.allocated = X_bytes/sizeof(ord); + +exp.ptr = Y; +exp.size = Y_bytes/sizeof(ord); +exp.allocated = Y_bytes/sizeof(ord); + +mod.ptr = P; +mod.size = P_bytes/sizeof(ord); +mod.allocated = P_bytes/sizeof(ord); + +dest.ptr = Z; +dest.size = P_bytes/sizeof(ord); +dest.allocated = P_bytes/sizeof(ord); + +/* Call bn routine */ + +status = bnExpMod(&dest, &n, + &exp, &mod); + +return status; +} + + +/**************************************************************************** +* NAME: int DoubleExpo( u_int16_t X1_bytes, +* ord *X1, +* u_int16_t Y1_bytes, +* ord *Y1, +* u_int16_t X2_bytes, +* ord *X2, +* u_int16_t Y2_bytes, +* ord *Y2, +* u_int16_t P_bytes, +* ord *P, +* ord *Z) +* +* DESCRIPTION: Compute a modulo exponent +* +* INPUTS: +* PARAMETERS: +* ord *X1 Pointer to first base array +* u_int16_t X1_bytes Number of bytes in first base +* ord *Y1 Pointer to first exponent array +* u_int16_t Y1_bytes Number of bytes in first exponent +* ord *X2 Pointer to second base array +* u_int16_t X2_bytes Number of bytes in second base +* ord *Y2 Pointer to second exponent array +* u_int16_t Y2_bytes Number of bytes in second exponent ord *P Pointer to modulo +* ord *P Pointer to modulo +* u_int16_t P_bytes Number of bytes in +* +* OUTPUT: +* PARAMETERS: +* ord *Z Pointer to result +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data(zero bytes) +* +* REVISION HISTORY: +* +* 21 Aug 96 AAB Initial release +****************************************************************************/ + + +int DoubleExpo( u_int16_t X1_bytes,ord *X1, + u_int16_t Y1_bytes,ord *Y1, + u_int16_t X2_bytes,ord *X2, + u_int16_t Y2_bytes,ord *Y2, + u_int16_t P_bytes,ord *P, + ord *Z) +{ +int status = SUCCESS; /*function return status*/ +struct BigNum res, n1, e1, n2, e2, mod; +BigNumInit(); + +n1.size = X1_bytes/sizeof(ord); +n1.ptr = X1; +n1.allocated = X1_bytes/sizeof(ord); + +e1.size = Y1_bytes/sizeof(ord); +e1.ptr = Y1; +e1.allocated = Y1_bytes/sizeof(ord); + +n2.size = X2_bytes/sizeof(ord); +n2.ptr = X2; +n2.allocated = X2_bytes/sizeof(ord); + +e2.size = Y2_bytes/sizeof(ord); +e2.ptr = Y2; +e2.allocated = Y2_bytes/sizeof(ord); + +mod.ptr = P; +mod.size = P_bytes/sizeof(ord); +mod.allocated = P_bytes/sizeof(ord); + +res.ptr = Z; +res.size = P_bytes/sizeof(ord); +res.allocated = P_bytes/sizeof(ord); +status = bnDoubleExpMod(&res, &n1, &e1, &n2, &e2, &mod); +return status; +} + +/**************************************************************************** +* NAME: int Inverse( u_int16_t X_bytes, +* ord *X, +* u_int16_t P_bytes, +* ord *P, +* ord *Z ) +* +* +* +* +* DESCRIPTION: Compute a modulo inverse element +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to array +* u_int16_t X_bytes Number of bytes in array +* ord *P Pointer to modulo +* u_int16_t P_bytes Number of bytes in P +* +* OUTPUT: +* PARAMETERS: +* ord *Z Pointer to result +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data(zero bytes) +* ERR_INPUT_VALUE Invalid input value +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 08 Nov 94 GKL Added input parameters check +* 01 Sep 95 Improve fuction +****************************************************************************/ + +int Inverse( u_int16_t X_bytes, + ord *X, + u_int16_t P_bytes, + ord *P, + ord *Z ) +{ +int status = SUCCESS; /* function return status */ + +struct BigNum dest, src, mod; +BigNumInit(); +/*bnInit(); +bnBegin(&dest); +bnBegin(&src); +bnBegin(&mod); +*/ +src.size = X_bytes/sizeof(ord); +src.ptr = X; +src.allocated = X_bytes/sizeof(ord); + +mod.ptr = P; +mod.size = P_bytes/sizeof(ord); +mod.allocated = P_bytes/sizeof(ord); + +dest.ptr = Z; +dest.size = (P_bytes/sizeof(ord)) ; +dest.allocated = (P_bytes/sizeof(ord)) + 1; +status = bnInv(&dest,&src,&mod); +return status; +} + + +/**************************************************************************** +* NAME: void Add( ord *X, +* ord *Y, +* u_int16_t P_len, +* ord *P, +* ord *Z ) + +* +* DESCRIPTION: Compute modulo addition +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to first operand +* ord *Y Pointer to second operand +* u_int16_t P_len Length of modulo +* ord *P Pointer to modulo +* OUTPUT: +* ord *Z Pointer to result +* RETURN: +* +* REVISION HISTORY: +* +* 24 sep 94 KPZ Initial release +* 10 Oct 94 KPZ Fixed bugs +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + /* + int Add( ord *X, + ord *Y, + u_int16_t P_len, + ord *P, + ord *Z ) +{ + int status = SUCCESS; + ord *temp; + struct BigNum dest, src, mod; + +bnInit(); +bnBegin(&dest); +bnBegin(&src); +bnBegin(&mod); + +temp = (ord*)malloc(P_len + sizeof(ord)); +memcpy(temp, X, P_len); + +dest.size = P_len/sizeof(ord); +dest.ptr = temp; +dest.allocated = P_len/sizeof(ord) + 1; + +src.ptr = Y; +src.size = P_len/sizeof(ord); +src.allocated = P_len/sizeof(ord); + +mod.ptr = P; +mod.size = P_len/sizeof(ord); +mod.allocated = P_len/sizeof(ord); + +status = bnAdd(&dest,&src); +status = bnMod(&dest,&dest,&mod); +memcpy(Z,temp,P_len); +free(temp); +return status; +} + */ + int Add( ord *X, + ord *Y, + u_int16_t P_len, + ord *P) +{ + int status = SUCCESS; +/* ord *temp;*/ + struct BigNum dest, src, mod; + +BigNumInit(); +/*bnInit(); +bnBegin(&dest); +bnBegin(&src); +bnBegin(&mod); +*/ +/* +temp = (ord*)malloc(P_len + sizeof(ord)); +memcpy(temp, X, P_len); +*/ +dest.size = P_len/sizeof(ord); +/*dest.ptr = temp;*/ +dest.ptr = X; +dest.allocated = P_len/sizeof(ord) + 1; + +src.ptr = Y; +src.size = P_len/sizeof(ord); +src.allocated = P_len/sizeof(ord); + +mod.ptr = P; +mod.size = P_len/sizeof(ord); +mod.allocated = P_len/sizeof(ord); + +status = bnAdd(&dest,&src); +status = bnMod(&dest,&dest,&mod); +/* +memcpy(Z,temp,P_len); +free(temp); +*/ +return status; +} + + + + +/**************************************************************************** +* NAME: int SteinGCD( ord *m, +* ord *b +* u_int16_t len ) +* +* DESCRIPTION: Compute great common divisor +* +* INPUTS: +* PARAMETERS: +* ord *m Pointer to first number +* ord *b Pointer to second number +* u_int16_t len Number of elements in number +* OUTPUT: +* +* RETURN: +* TRUE if gcd != 1 +* FALSE if gcd == 1 +* REVISION HISTORY: +* +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 01 Sep 95 AAB Speed up +* +****************************************************************************/ + + +/* test if GCD equal 1 */ +int SteinGCD ( ord *m, + ord *n, + u_int16_t len ) +{ + +int status; +struct BigNum dest, a, b; +ord *temp; +BigNumInit(); +/*bnInit(); +bnBegin(&dest); +bnBegin(&a); +bnBegin(&b); +*/ +a.size = len; +a.ptr = m; +a.allocated = len; + +b.size = len; +b.ptr = n; +b.allocated = len; + +temp = (ord*)malloc((len+1)*sizeof(ord)); +dest.size = len; +dest.ptr = temp; +dest.allocated = len+1; + +status = bnGcd(&dest, &a, &b); + +if (*(ord *)(dest.ptr) == 0x01 && dest.size == 1) + status = 0; +else + status = 1; + +free(temp); + +return status; + +} + + +/**************************************************************************** +* NAME: int DivRem( u_int16_t X_bytes, +* ord *X, +* u_int16_t P_bytes, +* ord *P, +* ord *Z, +* ord *D) +* +* DESCRIPTION: Compute a modulo and quotient +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to array +* u_int16_t X_bytes Number of bytes in X +* ord *P Pointer to modulo +* u_int16_t P_bytes Number of bytes in P +* +* OUTPUT: +* PARAMETERS: +* ord *Z Pointer to result +* ord *D Pointer to quotient +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data (zero bytes) +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 10 Oct 94 KPZ Fixed bugs +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +int DivRem( u_int16_t X_bytes, + ord *X, + u_int16_t P_bytes, + ord *P, + ord *Z, + ord *D) +{ + int status = SUCCESS; /* function return status */ + +struct BigNum q, r, /*n,*/ d; +ord *temp; +BigNumInit(); +/*bnInit(); +bnBegin(&q); +bnBegin(&r); +bnBegin(&n); +bnBegin(&d); + +n.size = X_bytes/sizeof(ord); +n.ptr = X; +n.allocated = X_bytes/sizeof(ord); +*/ +d.size = P_bytes/sizeof(ord); +d.ptr = P; +d.allocated = P_bytes/sizeof(ord); + +q.size = (X_bytes/sizeof(ord)) - (P_bytes/sizeof(ord)) + 1; +q.ptr = D; +q.allocated = (X_bytes/sizeof(ord)) - (P_bytes/sizeof(ord)) + 1; + +temp = (ord *)malloc(X_bytes); +r.size = X_bytes/sizeof(ord); +r.ptr = temp; +r.allocated = X_bytes/sizeof(ord); +memcpy(r.ptr, X, X_bytes); + +status = bnDivMod(&q, &r, &r, &d); + +memcpy(Z, r.ptr, P_bytes); +free(temp); + +return status; + +} diff --git a/lib/bind/cylink/ppcasm.h b/lib/bind/cylink/ppcasm.h new file mode 100644 index 0000000000..ad55cfe889 --- /dev/null +++ b/lib/bind/cylink/ppcasm.h @@ -0,0 +1,575 @@ +#ifndef PPCASM_H +#define PPCASM_H +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * A PowerPC assembler in the C preprocessor. + * This assumes that ints are 32 bits, and uses them for the values. + * + * An assembly-language routine is simply an array of unsigned ints, + * initialized with the macros defined here. + * + * In the PowerPC, a generic function pointer does *not* point to the + * first word of code, but to a two (or possibly more) word "transition + * vector." The first word of the TV points to the function's code. + * The second word is the function's TOC (Table Of Contents) pointer, + * which is loaded into r2. The function's global variables are + * accessed via the TOC pointed to by r2. TOC pointers are changed, + * for example, when a dynamically linked library is called, so the + * library can have private global variables. + * + * Saving r2 and reloading r2 each function call is a hassle that + * I'd really rather avoid, since a lot of useful assembly language routines + * can be written without global variables at all, so they don't need a TOC + * pointer. But I haven't figured out how to persuade CodeWarrior 7 to + * generate an intra-TOC call to an array. (CodeWarrior 8 supports + * PowerPC asm, which obviates the need to do the cast-to-function-pointer + * trick, which obviates the need for cross-TOC calls.) + * + * The basic PowerPC calling conventions for integers are: + * r0 - scratch. May be modified by function calls. + * r1 - stack pointer. Must be preserved across function calls. + * See IMPORTANT notes on stack frame format below. + * This must *ALWAYS*, at every instruction boundary, be 16-byte + * aligned and point to a valid stack frame. If a procedure + * needs to create a stack frame, the recommended way is to do: + * stwu r1,-frame_size(r1) + * and on exit, recover with one of: + * addi r1,r1,frame_size, OR + * lwz r1,0(r1) + * r2 - TOC pointer. Points to the current table of contents. + * Must be preserved across function calls. + * r3 - First argument register and return value register. + * Arguments are passed in r3 through r10, and values returned in + * r3 through r6, as needed. (Usually only r3 for single word.) + * r4-r10 - More argument registers + * r11 - Scratch, may be modified by function calls. + * On entry to indirect function calls, this points to the + * transition vector, and additional words may be loaded + * at offsets from it. Some conventions use r12 instead. + * r12 - Scratch, may be modified by function calls. + * r13-r31 - Callee-save registers, may not be modified by function + * calls. + * The LR, CTR and XER may be modified by function calls, as may the MQ + * register, on those processors for which it is implemented. + * CR fields 0, 1, 5, 6 and 7 are scratch and may be modified by function + * calls. CR fields 2, 3 and 4 must be preserved across function calls. + * + * Stack frame format - READ + * + * r1 points to a stack frame, which must *ALWAYS*, meaning after each and + * every instruction, without excpetion, point to a valid 16-byte-aligned + * stack frame, defined as follows: + * - The 296 bytes below r1 (from -296(r1) to -1(r1)) are the so-called Red + * Zone reserved for leaf procedures, which may use it without allocating + * a stack frame and without decrementing r1. The size comes from the room + * needed to store all the callee-save registers: 19 64-bit integer registers + * and 18 64-bit floating-point registers. (18+19)*8 = 296. So any + * procedure can save all the registers it needs to save before creating + * a stack frame and moving r1. + * The bytes at -297(r1) and below may be used by interrupt and exception + * handlers *at any time*. Anything placed there may disappear before + * the next instruction. + * The word at 0(r1) is the previous r1, and so on in a linked list. + * This is the minimum needed to be a valid stack frame, but some other + * offsets from r1 are preallocated by the calling procedure for the called + * procedure's use. These are: + * Offset 0: Link to previous stack frame - saved r1, if the called + * procedure alters it. + * Offset 4: Saved CR, if the called procedure alters the callee-save + * fields. There's no important reason to save it here, + * but the space is reserved and you might as well use it + * for its intended purpose unless you have good reason to + * do otherwise. (This may help some debuggers.) + * Offset 8: Saved LR, if the called procedure needs to save it for + * later function return. Saving the LR here helps a debugger + * track the chain of return addresses on the stack. + * Note that a called procedure does not need to preserve the + * LR for it's caller's sake, but it uually wants to preserve + * the value for its own sake until it finishes and it's + * time to return. At that point, this is usually loaded + * back into the LR and the branch accomplished with BLR. + * However, if you want to be preverse, you could load it + * into the CTR and use BCTR instead. + * Offset 12: Reserved to compiler. I can't find what this is for. + * Offset 16: Reserved to compiler. I can't find what this is for. + * Offset 20: Saved TOC pointer. In a cross-TOC call, the old TOC (r2) + * is saved here before r2 is loaded with the new TOC value. + * Again, it's not important to use this slot for this, but + * you might as well. + * Beginning at offset 24 is the argument area. This area is at least 8 words + * (32 bytes; I don't know what happens with 64 bits) long, and may be longer, + * up to the length of the longest argument list in a function called by + * the function which allocated this stack frame. Generally, arguments + * to functions are passed in registers, but if those functions notice + * the address of the arguments being taken, the registers are stored + * into the space reserved for them in this area and then used from memory. + * Additional arguments that will not fit into registers are also stored + * here. Variadic functions (like printf) generally start by saving + * all the integer argument registers from the "..." onwards to this space. + * For that reason, the space must be large enough to store all the argument + * registers, even if they're never used. + * (It could probably be safely shrunk if you're not calling any variadic + * functions, but be careful!) + * + * Offsets above that are private to the calling function and shouldn't + * be messed with. Generally, what appears there is locals, then saved + * registers. + * + * + * The floating-point instruction set isn't implemented yet (I'm too + * lazy, as I don't need it yet), but for when it is, the register + * usage convention is: + * FPSCR - Scratch, except for floating point exception enable fields, + * which should only be modified by functions defined to do so. + * fr0 - scratch + * fr1 - first floating point parameter and return value, scratch + * fr2 - second floating point parameter and return value (if needed), scratch + * fr3 - third floating point parameter and return value (if needed), scratch + * fr4 - fourth floating point parameter and return value (if needed), scratch + * fr5-fr13 - More floating point argument registers, scratch + * fr14-fr31 - Callee-save registers, may not be modified across a function call + * + * Complex values store the real part in the lower-numberd register of a pair. + * When mixing floating-point and integer arguments, reserve space (one register + * for single-precision, two for double-precision values) in the integer + * argument list for the floating-point values. Those integer registers + * generally have undefined values, UNLESS there is no prototype for the call, + * in which case they should contain a copy of the floating-point value's + * bit pattern to cope with wierd software. + * If the floating point arguments go past the end of the integer registers, + * they are stored in the argument area as well as being passed in here. + * + * After the argument area comes the calling function's private storage. + * Typically, there are locals, followed by saved GP rgisters, followed + * by saved FP registers. + * + * Suggested instruction for allocating a stack frame: + * stwu r1,-frame_size(r1) + * Suggested instructions for deallocating a stack frame: + * addi r1,r1,frame_size + * or + * lwz r1,0(r1) + * If frame_size is too big, you'll have to load the offset into a temp + * register, but be sure that r1 is updated atomically. + * + * + * Basic PowerPC instructions look like this: + * + * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | | | | | | | | | | | | | | | | | | | | | | | | | | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Branch instructions look like this: + * + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | Branch offset |A|L| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * The L, or LK, or Link bit indicates that the return address for the + * branch should be copied to the link register (LR). + * The A, or AA, or absolute address bit, indicates that the address + * of the current instruction (NOTE: not next instruction!) should NOT + * be added to the branch offset; it is relative to address 0. + * + * Conditional branches looks like this: + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | BO | BI | Branch offset |A|L| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * The BI field specifies the condition bit of interest (from the CR). + * The BO field specifies what's interesting. You can branch on a + * combination of a bit of the condition register and --ctr, the CTR + * register. Two bits encode the branch condition to use: + * BRANCH IF + * 00--- = Bit BI is 0 + * 01--- = Bit BI is 1 + * 1z--- = don't care about bit BI (always true) + * AND + * --00- = --ctr != 0 + * --01- = --ctr == 0 + * --1z- = don't decrement ctr (always true) + * The last bit us used as a branch prediction bit. If set, it reverses + * the usual backward-branch-taken heuristic. + * + * y = branch prediction bit. z = unused, must be 0 + * 0000y - branch if --ctr != 0 && BI == 0 + * don't branch if --ctr == 0 || BI != 0 + * 0001y - branch if --ctr == 0 && BI == 0 + * don't branch if --ctr != 0 || BI != 0 + * 001zy - branch if BI == 0 + * don't branch if BI != 0 + * 0100y - branch if --ctr != 0 && BI != 0 + * don't branch if --ctr == 0 || BI == 0 + * 0101y - branch if --ctr == 0 && BI != 0 + * don't branch if --ctr != 0 || BI == 0 + * 011zy - branch if BI != 0 + * don't branch if BI == 0 + * 1z00y - branch if --ctr != 0 + * don't branch if --ctr == 0 + * 1z01y - branch if --ctr == 0 + * don't branch if --ctr != 0 + * 1z1zz - branch always + * If y is 1, the usual branch prediction (usually not taken, taken for + * backwards branches with immediate offsets) is reversed. + * + * Instructions with 2 operands and a 16-bit immediate field look like this: + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | D | A | 16-bit immediate value | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Now, there are three variations of note. In some instructions, the 16-bit + * value is sign-extended. In others, it's zero-extended. These are noted + * below as "simm" (signed immediate) and "uimm", respectively. Also, which + * field is the destination and which is the source sometimes switches. + * Sometimes it's d = a OP imm, and sometimes it's a = s OP imm. In the + * latter cases, the "d" field is referred to as "s" ("source" instead of + * "destination". These are logical and shift instructions. (Store also + * refers to the s register, but that's the source of the value to be stored.) + * The assembly mnemonics, however, always lists the destination first, + * swapping the order in the instruction if necessary. + * Third, quite often, if r0 is specified for the source a, then the constant + * value 0 is used instead. Thus, r0 is of limited use - it can be used for + * some things, but not all. + * + * Instructions with three register operands look like this: + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | D | A | B | Subopcode |C| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * For most of the instructions of interest the Opcode is 31 and the subopcode + * determines what the instruction does. For a few instructions (mostly loads + * and stores), if the A field is 0, the constant 0 is used. The "C" + * bit (also known as the "RC" bit) controls whether or not the condition + * codes are updated. If it is set (indicated by a "." suffix on the official + * PowerPC opcodes, and a "_" suffix on these macros), condition code register + * field 0 (for integer instructions; field 1 for floating point) is updated + * to reflect the result of the operation. + * Some arithmetic instructions use the most significant bit of the subopcode + * field as an overflow enable bit (o suffix). + * + * Then there are the rotate and mask instructions, which have 5 operands, and + * fill the subopcode field with 2 more 5-bit fields. See below for them. + * + * NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE + * These macros fully parenthesize their arguments, but are not themselves + * fully parenthesized. They are intended to be used for initializer lists, + * and if you want to do tricks with their numeric values, wrap them in + * parentheses. + */ + +#define PPC_MAJOR(x) ((x)<<26) /* Major opcode (0..63) */ +#define PPC_MINOR(x) ((x)<<1) /* Minor opcode (0..1023) */ +#define PPC_RC 1 /* Record carry (. suffix, represented as _) */ +#define PPC_OE 1024 /* Overflow enable (o suffix) */ +#define PPC_DEST(reg) ((reg)<<21) /* Dest register field */ +#define PPC_SRCA(reg) ((reg)<<16) /* First source register field */ +#define PPC_SRCB(reg) ((reg)<<11) /* Second source register field */ +#define PPC_AA 2 /* Branch is absolute, relative to address 0 */ +#define PPC_LK 1 /* Branch with link (L suffix) */ + +/* Unconditional branch (dest is 26 bits, +/- 2^25 bytes) */ +#define PPC_B(dest) PPC_MAJOR(18)|(((dest)<<2) & 0x03fffffc) +#define PPC_BA(dest) PPC_B(dest)|PPC_AA +#define PPC_BL(dest) PPC_B(dest)|PPC_LK +#define PPC_BLA(dest) PPC_B(dest)|PPC_AA|PPC_LK + +/* Three-operand instructions */ +#define PPC_TYPE31(minor,d,a,b) \ + PPC_MAJOR(31)|PPC_DEST(d)|PPC_SRCA(a)|PPC_SRCB(b)|PPC_MINOR(minor) +#define PPC_ADD(d,a,b) PPC_TYPE31(266,d,a,b) +#define PPC_ADD_(d,a,b) PPC_TYPE31(266,d,a,b)|PPC_RC +#define PPC_ADDO(d,a,b) PPC_TYPE31(266,d,a,b)|PPC_OE +#define PPC_ADDO_(d,a,b) PPC_TYPE31(266,d,a,b)|PPC_OE|PPC_RC +#define PPC_ADDC(d,a,b) PPC_TYPE31(10,d,a,b) +#define PPC_ADDC_(d,a,b) PPC_TYPE31(10,d,a,b)|PPC_RC +#define PPC_ADDCO(d,a,b) PPC_TYPE31(10,d,a,b)|PPC_OE +#define PPC_ADDCO_(d,a,b) PPC_TYPE31(10,d,a,b)|PPC_OE|PPC_RC +#define PPC_ADDE(d,a,b) PPC_TYPE31(138,d,a,b) +#define PPC_ADDE_(d,a,b) PPC_TYPE31(138,d,a,b)|PPC_RC +#define PPC_ADDEO(d,a,b) PPC_TYPE31(138,d,a,b)|PPC_OE +#define PPC_ADDEO_(d,a,b) PPC_TYPE31(138,d,a,b)|PPC_OE|PPC_RC +#define PPC_ADDME(d,a) PPC_TYPE31(234,d,a,0) +#define PPC_ADDME_(d,a) PPC_TYPE31(234,d,a,0)|PPC_RC +#define PPC_ADDMEO(d,a) PPC_TYPE31(234,d,a,0)|PPC_OE +#define PPC_ADDMEO_(d,a) PPC_TYPE31(234,d,a,0)|PPC_OE|PPC_RC +#define PPC_ADDZE(d,a) PPC_TYPE31(202,d,a,0) +#define PPC_ADDZE_(d,a) PPC_TYPE31(202,d,a,0)|PPC_RC +#define PPC_ADDZEO(d,a) PPC_TYPE31(202,d,a,0)|PPC_OE +#define PPC_ADDZEO_(d,a) PPC_TYPE31(202,d,a,0)|PPC_OE|PPC_RC +#define PPC_AND(a,s,b) PPC_TYPE31(28,s,a,b) +#define PPC_AND_(a,s,b) PPC_TYPE31(28,s,a,b)|PPC_RC +#define PPC_ANDC(a,s,b) PPC_TYPE31(60,s,a,b) +#define PPC_ANDC_(a,s,b) PPC_TYPE31(60,s,a,b)|PPC_RC +#define PPC_CMP(cr,a,b) PPC_TYPE31(0,(cr)<<2,a,b) +#define PPC_CMPL(cr,a,b) PPC_TYPE31(32,(cr)<<2,a,b) +#define PPC_CNTLZW(a,s) PPC_TYPE31(26,s,a,0) +#define PPC_CNTLZW_(a,s) PPC_TYPE31(26,s,a,0)|PPC_RC +#define PPC_DCBF(a,b) PPC_TYPE31(86,0,a,b) +#define PPC_DCBI(a,b) PPC_TYPE31(470,0,a,b) +#define PPC_DCBST(a,b) PPC_TYPE31(54,0,a,b) +#define PPC_DCBT(a,b) PPC_TYPE31(278,0,a,b) +#define PPC_DCBTST(a,b) PPC_TYPE31(246,0,a,b) +#define PPC_DCBZ(a,b) PPC_TYPE31(1014,0,a,b) +#define PPC_DIVW(d,a,b) PPC_TYPE31(491,d,a,b) +#define PPC_DIVW_(d,a,b) PPC_TYPE31(491,d,a,b)|PPC_RC +#define PPC_DIVWO(d,a,b) PPC_TYPE31(491,d,a,b)|PPC_OE +#define PPC_DIVWO_(d,a,b) PPC_TYPE31(491,d,a,b)|PPC_OE|PPC_RC +#define PPC_DIVWU(d,a,b) PPC_TYPE31(459,d,a,b) +#define PPC_DIVWU_(d,a,b) PPC_TYPE31(459,d,a,b)|PPC_RC +#define PPC_DIVWUO(d,a,b) PPC_TYPE31(459,d,a,b)|PPC_OE +#define PPC_DIVWUO_(d,a,b) PPC_TYPE31(459,d,a,b)|PPC_OE|PPC_RC +#define PPC_EIEIO() PPC_TYPE31(854,0,0,0) +#define PPC_EQV(a,s,b) PPC_TYPE31(284,s,a,b) +#define PPC_EQV_(a,s,b) PPC_TYPE31(284,s,a,b)|PPC_RC +#define PPC_EXTSB(a,s,b) PPC_TYPE31(954,s,a,b) +#define PPC_EXTSB_(a,s,b) PPC_TYPE31(954,s,a,b)|PPC_RC +#define PPC_EXTSH(a,s,b) PPC_TYPE31(922,s,a,b) +#define PPC_EXTSH_(a,s,b) PPC_TYPE31(922,s,a,b)|PPC_RC +#define PPC_ICBI(a,b) PPC_TYPE31(982,0,a,b) +#define PPC_ISYNC() PPC_TYPE31(150,0,0,0) +#define PPC_LBZUX(d,a,b) PPC_TYPE31(119,d,a,b) +#define PPC_LBZX(d,a,b) PPC_TYPE31(87,d,a,b) +#define PPC_LHAUX(d,a,b) PPC_TYPE31(375,d,a,b) +#define PPC_LHAX(d,a,b) PPC_TYPE31(343,d,a,b) +#define PPC_LHBRX(d,a,b) PPC_TYPE31(790,d,a,b) +#define PPC_LHZUX(d,a,b) PPC_TYPE31(311,d,a,b) +#define PPC_LHZX(d,a,b) PPC_TYPE31(279,d,a,b) +#define PPC_LSWI(d,a,nb) PPC_TYPE31(597,d,a,nb) +#define PPC_LSWX(d,a,b) PPC_TYPE31(533,d,a,b) +#define PPC_LSARX(d,a,b) PPC_TYPE31(20,d,a,b) +#define PPC_LSBRX(d,a,b) PPC_TYPE31(534,d,a,b) +#define PPC_MCRXR(crd) PPC_TYPE31(512,(crd)<<2,0,0) +#define PPC_MFCR(d) PPC_TYPE31(19,d,0,0) +#define PPC_MFSPR(d,spr) PPC_TYPE31(339,d,(spr)&31,(spr)>>5) +#define PPC_MFTB(d) PPC_TYPE31(371,d,12,8) +#define PPC_MFTBU(d) PPC_TYPE31(371,d,13,8) +#define PPC_MTCRF(mask,s) PPC_TYPE31(144,s,0,(mask)&0xff) +#define PPC_MTSPR(s,spr) PPC_TYPE31(467,s,(spr)&31,(spr)>>5) +#define PPC_MULHW(d,a,b) PPC_TYPE31(75,d,a,b) +#define PPC_MULHW_(d,a,b) PPC_TYPE31(75,d,a,b)|PPC_RC +#define PPC_MULHWU(d,a,b) PPC_TYPE31(11,d,a,b) +#define PPC_MULHWU_(d,a,b) PPC_TYPE31(11,d,a,b)|PPC_RC +#define PPC_MULLW(d,a,b) PPC_TYPE31(235,d,a,b) +#define PPC_MULLW_(d,a,b) PPC_TYPE31(235,d,a,b)|PPC_RC +#define PPC_MULLWO(d,a,b) PPC_TYPE31(235,d,a,b)|PPC_OE +#define PPC_MULLWO_(d,a,b) PPC_TYPE31(235,d,a,b)|PPC_OE|PPC_RC +#define PPC_NAND(a,s,b) PPC_TYPE31(476,s,a,b) +#define PPC_NAND_(a,s,b) PPC_TYPE31(476,s,a,b)|PPC_RC +#define PPC_NEG(d,a) PPC_TYPE31(104,d,a,b) +#define PPC_NEG_(d,a) PPC_TYPE31(104,d,a,b)|PPC_RC +#define PPC_NEGO(d,a) PPC_TYPE31(104,d,a,b)|PPC_OE +#define PPC_NEGO_(d,a) PPC_TYPE31(104,d,a,b)|PPC_OE|PPC_RC +#define PPC_NOR(a,s,b) PPC_TYPE31(124,s,a,b) +#define PPC_NOR_(a,s,b) PPC_TYPE31(124,s,a,b)|PPC_RC +#define PPC_OR(a,s,b) PPC_TYPE31(444,s,a,b) +#define PPC_OR_(a,s,b) PPC_TYPE31(444,s,a,b)|PPC_RC +#define PPC_ORC(a,s,b) PPC_TYPE31(412,s,a,b) +#define PPC_ORC_(a,s,b) PPC_TYPE31(412,s,a,b)|PPC_RC +#define PPC_SLW(a,s,b) PPC_TYPE31(24,s,a,b) +#define PPC_SLW_(a,s,b) PPC_TYPE31(24,s,a,b)|PPC_RC +#define PPC_SRAW(a,s,b) PPC_TYPE31(792,s,a,b) +#define PPC_SRAW_(a,s,b) PPC_TYPE31(792,s,a,b)|PPC_RC +#define PPC_SRAWI(a,s,sh) PPC_TYPE31(824,s,a,sh) +#define PPC_SRAWI_(a,s,sh) PPC_TYPE31(824,s,a,sh)|PPC_RC +#define PPC_SRW(a,s,b) PPC_TYPE31(536,s,a,b) +#define PPC_SRW_(a,s,b) PPC_TYPE31(536,s,a,b)|PPC_RC +#define PPC_STBUX(s,a,b) PPC_TYPE31(247,s,a,b) +#define PPC_STBX(s,a,b) PPC_TYPE31(215,s,a,b) +#define PPC_STHBRX(s,a,b) PPC_TYPE31(918,s,a,b) +#define PPC_STHUX(s,a,b) PPC_TYPE31(439,s,a,b) +#define PPC_STHX(s,a,b) PPC_TYPE31(407,s,a,b) +#define PPC_STSWI(s,a,nb) PPC_TYPE31(725,s,a,nb) +#define PPC_STSWX(s,a,b) PPC_TYPE31(661,s,a,b) +#define PPC_STWBRX(s,a,b) PPC_TYPE31(662,s,a,b) +#define PPC_STWCX_(s,a,b) PPC_TYPE31(150,s,a,b)|PPC_RC +#define PPC_STWUX(s,a,b) PPC_TYPE31(183,s,a,b) +#define PPC_STWX(s,a,b) PPC_TYPE31(151,s,a,b) +#define PPC_SUBF(d,a,b) PPC_TYPE31(40,d,a,b) +#define PPC_SUBF_(d,a,b) PPC_TYPE31(40,d,a,b)|PPC_RC +#define PPC_SUBFO(d,a,b) PPC_TYPE31(40,d,a,b)|PPC_OE +#define PPC_SUBFO_(d,a,b) PPC_TYPE31(40,d,a,b)|PPC_OE|PPC_RC +#define PPC_SUB(d,b,a) PPC_SUBF(d,a,b) +#define PPC_SUB_(d,b,a) PPC_SUBF_(d,a,b) +#define PPC_SUBO(d,b,a) PPC_SUBFO(d,a,b) +#define PPC_SUBO_(d,b,a) PPC_SUBFO_(d,a,b) +#define PPC_SUBFC(d,a,b) PPC_TYPE31(8,d,a,b) +#define PPC_SUBFC_(d,a,b) PPC_TYPE31(8,d,a,b)|PPC_RC +#define PPC_SUBFCO(d,a,b) PPC_TYPE31(8,d,a,b)|PPC_OE +#define PPC_SUBFCO_(d,a,b) PPC_TYPE31(8,d,a,b)|PPC_OE|PPC_RC +#define PPC_SUBFE(d,a,b) PPC_TYPE31(136,d,a,b) +#define PPC_SUBFE_(d,a,b) PPC_TYPE31(136,d,a,b)|PPC_RC +#define PPC_SUBFEO(d,a,b) PPC_TYPE31(136,d,a,b)|PPC_OE +#define PPC_SUBFEO_(d,a,b) PPC_TYPE31(136,d,a,b)|PPC_OE|PPC_RC +#define PPC_SUBFME(d,a) PPC_TYPE31(232,d,a,0) +#define PPC_SUBFME_(d,a) PPC_TYPE31(232,d,a,0)|PPC_RC +#define PPC_SUBFMEO(d,a) PPC_TYPE31(232,d,a,0)|PPC_OE +#define PPC_SUBFMEO_(d,a) PPC_TYPE31(232,d,a,0)|PPC_OE|PPC_RC +#define PPC_SUBFZE(d,a) PPC_TYPE31(200,d,a,0) +#define PPC_SUBFZE_(d,a) PPC_TYPE31(200,d,a,0)|PPC_RC +#define PPC_SUBFZEO(d,a) PPC_TYPE31(200,d,a,0)|PPC_OE +#define PPC_SUBFZEO_(d,a) PPC_TYPE31(200,d,a,0)|PPC_OE|PPC_RC +#define PPC_SYNC() PPC_TYPE31(598,0,0,0) +#define PPC_TW(to,a,b) PPC_TYPE31(4,to,a,b) +#define PPC_XOR(a,s,b) PPC_TYPE31(316,s,a,b) + +/* Immediate-operand instructions. Take a 16-bit immediate operand */ +#define PPC_IMM(major,d,a,imm) \ + PPC_MAJOR(major)|PPC_DEST(d)|PPC_SRCA(a)|((imm)&0xffff) +/* Trap word immediate */ +#define PPV_TWI(to,a,simm) PPC_IMM(3,to,a,simm) +/* Integer arithmetic */ +#define PPC_MULLI(d,a,simm) PPC_IMM(7,d,a,simm) +#define PPC_SUBFIC(s,a,simm) PPC_IMM(8,s,a,simm) +#define PPC_CMPLI(cr,a,uimm) PPC_IMM(10,(cr)<<2,a,uimm) +#define PPC_CMPI(cr,a,simm) PPC_IMM(11,(cr)<<2,a,simm) +#define PPC_ADDIC(d,a,simm) PPC_IMM(12,d,a,simm) +#define PPC_ADDIC_(d,a,simm) PPC_IMM(13,d,a,simm) +#define PPC_ADDI(d,a,simm) PPC_IMM(14,d,a,simm) +#define PPC_ADDIS(d,a,simm) PPC_IMM(15,d,a,simm) + +/* Conditional branch (dest is 16 bits, +/- 2^15 bytes) */ +#define PPC_BC(bo,bi,dest) PPC_IMM(16,bo,bi,((dest)<<2)&0xfffc) +#define PPC_BCA(bo,bi,dest) PPC_BC(bo,bi,dest)|PPC_AA +#define PPC_BCL(bo,bi,dest) PPC_BC(bo,bi,dest)|PPC_LK +#define PPC_BCLA(bo,bi,dest) PPC_BC(bo,bi,dest)|PPC_AA|PPC_LK + +/* Logical operations */ +#define PPC_ORI(a,s,uimm) PPC_IMM(24,s,a,uimm) +#define PPC_ORIS(a,s,uimm) PPC_IMM(25,s,a,uimm) +#define PPC_XORI(a,s,uimm) PPC_IMM(26,s,a,uimm) +#define PPC_XORIS(a,s,uimm) PPC_IMM(27,s,a,uimm) +#define PPC_ANDI_(a,s,uimm) PPC_IMM(28,s,a,uimm) +#define PPC_ANDIS(a,s,uimm) PPC_IMM(29,s,a,uimm) + +/* Load/store */ +#define PPC_LWZ(d,a,simm) PPC_IMM(32,d,a,simm) +#define PPC_LWZU(d,a,simm) PPC_IMM(33,d,a,simm) +#define PPC_LBZ(d,a,simm) PPC_IMM(34,d,a,simm) +#define PPC_LBZU(d,a,simm) PPC_IMM(35,d,a,simm) +#define PPC_STW(s,a,simm) PPC_IMM(36,s,a,simm) +#define PPC_STWU(s,a,simm) PPC_IMM(37,s,a,simm) +#define PPC_STB(s,a,simm) PPC_IMM(38,s,a,simm) +#define PPC_STBU(s,a,simm) PPC_IMM(39,s,a,simm) +#define PPC_LHZ(d,a,simm) PPC_IMM(40,d,a,simm) +#define PPC_LHZU(d,a,simm) PPC_IMM(41,d,a,simm) +#define PPC_LHA(d,a,simm) PPC_IMM(42,d,a,simm) +#define PPC_STH(s,a,simm) PPC_IMM(44,s,a,simm) +#define PPC_STHU(s,a,simm) PPC_IMM(45,s,a,simm) +#define PPC_LHAU(d,a,simm) PPC_IMM(43,d,a,simm) +#define PPC_LMW(d,a,simm) PPC_IMM(46,d,a,simm) +#define PPC_STMW(s,a,simm) PPC_IMM(47,s,a,simm) + +/* Major number = 19 - condition register operations. d, a and b are CR bits */ +#define PPC_TYPE19(minor,d,a,b) \ + PPC_MAJOR(19)|PPC_DEST(d)|PPC_SRCA(a)|PPC_SRCB(b)|PPC_MINOR(minor) +#define PPC_MCRF(d,s) PPC_TYPE19(0,(d)<<2,(s)<<2,0) +#define PPC_CRNOR(d,a,b) PPC_TYPE19(33,d,a,b) +#define PPC_CRANDC(d,a,b) PPC_TYPE19(129,d,a,b) +#define PPC_CRXOR(d,a,b) PPC_TYPE19(193,d,a,b) +#define PPC_CRNAND(d,a,b) PPC_TYPE19(225,d,a,b) +#define PPC_CRAND(d,a,b) PPC_TYPE19(257,d,a,b) +#define PPC_CREQV(d,a,b) PPC_TYPE19(289,d,a,b) +#define PPC_CRORC(d,a,b) PPC_TYPE19(417,d,a,b) +#define PPC_CROR(d,a,b) PPC_TYPE19(449,d,a,b) + +/* Indirect conditional branch */ +#define PPC_BCLR(bo,bi) PPC_TYPE19(16,bo,bi,0) +#define PPC_BCLRL(bo,bi) PPC_TYPE19(16,bo,bi,0)|PPC_LK +#define PPC_BCCTR(bo,bi) PPC_TYPE19(528,bo,bi,0) +#define PPC_BCCTRL(bo,bi) PPC_TYPE19(528,bo,bi,0)|PPC_LK +#define PPC_BLR() PPC_BCLR(20,31) +#define PPC_BCTR() PPC_BCCTR(20,31) + +/* Other */ +#define PPC_RLWIMI(a,s,sh,mb,me) \ + PPC_MAJOR(20)|PPC_DEST(s)|PPC_SRCA(A)|PPC_SRCB(sh)|(mb)<<6|(me)<<1 +#define PPC_RLWIMI_(a,s,sh,mb,me) PPC_RLWIMI(a,s,sh,mb,me)|PPC_RC +#define PPC_RLWINM(a,s,sh,mb,me) \ + PPC_MAJOR(21)|PPC_DEST(s)|PPC_SRCA(A)|PPC_SRCB(sh)|(mb)<<6|(me)<<1 +#define PPC_RLWINM_(a,s,sh,mb,me) PPC_RLWINM(a,s,sh,mb,me)|PPC_RC +#define PPC_RLWNM(a,s,b,mb,me) \ + PPC_MAJOR(23)|PPC_DEST(s)|PPC_SRCA(A)|PPC_SRCB(b)|(mb)<<6|(me)<<1 +#define PPC_RLWNM_(a,s,b,mb,me) PPC_RLWNM(a,s,b,mb,me)|PPC_RC + +#define PPC_SC() PPC_MAJOR(17)|2 +/* Major number = 63 Floating-point operations (not implemented for now) */ + +/* Simplified Mnemonics */ +/* Fabricate immediate subtract out of add negative */ +#define PPC_SUBI(d,a,simm) PPC_ADDI(d,a,-(simm)) +#define PPC_SUBIS(d,a,simm) PPC_ADDIS(d,a,-(simm)) +#define PPC_SUBIC(d,a,simm) PPC_ADDIC(d,a,-(simm)) +#define PPC_SUBIC_(d,a,simm) PPC_ADDIC_(d,a,-(simm)) +/* Fabricate subtract out of subtract from */ +#define PPC_SUBC(d,b,a) PPC_SUBFC(d,a,b) +#define PPC_SUBC_(d,b,a) PPC_SUBFC_(d,a,b) +#define PPC_SUBCO(d,b,a) PPC_SUBFCO(d,a,b) +#define PPC_SUBCO_(d,b,a) PPC_SUBFCO_(d,a,b) +/* Messy compare bits omitted */ +/* Shift and rotate omitted */ +/* Branch coding omitted */ +#define PPC_CRSET(d) PPC_CREQV(d,d,d) +#define PPC_CRCLR(d) PPC_CRXOR(d,d,d) +#define PPC_CRMOVE(d,s) PPC_CROR(d,s,s) +#define PPC_CRNOT(d,s) PPC_CRNOR(d,s,s) +/* Trap menmonics omitted */ +/* Menmonics for user-accessible SPRs */ +#define PPC_MFXER(d) PPC_MFSPR(d,1) +#define PPC_MFLR(d) PPC_MFSPR(d,8) +#define PPC_MFCTR(d) PPC_MFSPR(d,9) +#define PPC_MTXER(s) PPC_MTSPR(s,1) +#define PPC_MTLR(s) PPC_MTSPR(s,8) +#define PPC_MTCTR(s) PPC_MTSPR(s,9) +/* Recommended mnemonics */ +#define PPC_NOP() PPC_ORI(0,0,0) +#define PPC_LI(d,simm) PPC_ADDI(d,0,simm) +#define PPC_LIS(d,simm) PPC_ADDIS(d,0,simm) +#define PPC_LA(d,a,simm) PPC_ADDI(d,a,simm) +#define PPC_MR(d,s) PPC_OR(d,s,s) +#define PPC_NOT(d,s) PPC_NOR(d,s,s) +#define PPC_MTCR(s) PPC_MTCRF(0xff,s) + +#endif /* PPCASM_H */ + +/* 45678901234567890123456789012345678901234567890123456789012345678901234567 */ diff --git a/lib/bind/cylink/rand.c b/lib/bind/cylink/rand.c new file mode 100644 index 0000000000..7051482bba --- /dev/null +++ b/lib/bind/cylink/rand.c @@ -0,0 +1,333 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: rand.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Cryptographic Toolkit Functions File +* Random Number Generation Files +* PUBLIC FUNCTIONS: +* int InitRand( u_int16_t SEED_bytes, uchar *SEED, +* uchar *RVAL ) +* int GenRand( u_int16_t A_bytes, uchar *A, +* uchar *RVAL ) +* int MyGenRand( u_int16_t A_bytes, +* ord *A, +* ord *RVAL ) + +* Copyright (c) Cylink Corporation 1994. All rights reserved. +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 10 Oct 94 KPZ Added Shamir Key Sharing functions +* 10 Oct 94 KPZ Modified SHA functions for arbitrary message length +* 12 Oct 94 KPZ Modified SHA functions (new standard) +* 14 Oct 94 GKL Second version (big endian support) +* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC) +* +****************************************************************************/ + +/**************************************************************************** +* INCLUDE FILES +****************************************************************************/ + +#include "port_before.h" + +/* system files */ +#ifdef VXD +#include +#else +#include +#include +#endif + +/* program files */ +#ifdef VXD +#include "tkvxd.h" +#endif +#include "cylink.h" +#include "ctk_endian.h" +#include "toolkit.h" +#include "cencrint.h" +#include "sha.h" + +#include "port_after.h" +extern u_int16_t DataOrder; +/**************************************************************************** +* PUBLIC FUNCTIONS DEFINITIONS +****************************************************************************/ + +/**************************************************************************** +* NAME: int InitRand( u_int16_t SEED_bytes, +* uchar *SEED, +* uchar *RVAL) +* +* DESCRIPTION: Initialize Random number Generator +* +* INPUTS: +* PARAMETERS: +* u_int16_t SEED_bytes Length of SEED +* uchar *SEED Pointer to SEED value +* +* OUTPUT: +* PARAMETERS: +* uchar *RVAL Pointer to RVAL +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data +* ERR_DATA Generic data error +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* +****************************************************************************/ + +int InitRand( u_int16_t SEED_bytes, + uchar *SEED, + uchar *RVAL ) +{ + int status = SUCCESS; /* function return status */ + if ( SEED_bytes == 0 ) + { + status = ERR_INPUT_LEN; + return status; + } + if ( SEED_bytes < SHA_LENGTH ) + { + status = ERR_DATA; + return status; + } + memcpy( RVAL, SEED, SHA_LENGTH); + return status; +} + + +/**************************************************************************** +* NAME: int GenRand( u_int16_t A_bytes, +* uchar *A, +* uchar *RVAL) +* +* DESCRIPTION: Generate random number. +* +* INPUTS: +* PARAMETERS: +* u_int16_t A_bytes Length of A +* uchar *A Pointer to A value +* +* OUTPUT: +* PARAMETERS: +* uchar *RVAL Pointer to RVAL +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data +* ERR_DATA Generic data error +* ERR_ALLOC Insufficient memory +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC) +* +****************************************************************************/ +int GenRand( u_int16_t A_bytes, + uchar *A, + uchar *RVAL ) +{ + int status = SUCCESS; /* function return status */ + ord *RVAL_a; + SHA_context hash_context; /* SHA context structure */ + uchar M[DSS_LENGTH_MIN]; /* message block */ + uchar hash_result[SHA_LENGTH]; + u_int16_t i; + u_int16_t sha_block; /* number of sha blocks */ + u_int16_t sha_rem; /* size of last block */ + if ( A_bytes == 0 ) + { + status = ERR_INPUT_LEN; + return status; + } + sha_block = (u_int16_t) (A_bytes / SHA_LENGTH); /* number of sha blocks */ + sha_rem = (u_int16_t) (A_bytes % SHA_LENGTH); /* size of last block */ + if ( sha_rem == 0 ) /* last block = SHA_LENGTH */ + { + sha_block--; + } + for ( i = 0; i <= sha_block; i++) + { + SHAInit ( &hash_context ); + memcpy( M, RVAL, SHA_LENGTH); + memset( M + SHA_LENGTH, 0, DSS_LENGTH_MIN - SHA_LENGTH ); + if ( (status = SHAUpdate( &hash_context, M, DSS_LENGTH_MIN )) + != SUCCESS ) + { + return status; /* error */ + } + if ( (status=MySHAFinal (&hash_context, hash_result )) != SUCCESS ) + { + return status; /* error */ + } + + BigSwap(RVAL, SHA_LENGTH); + ALIGN_CALLOC_COPY(RVAL, RVAL_a, SHA_LENGTH); + if ( status != SUCCESS ) + { + ALIGN_COPY_FREE(RVAL_a,RVAL,SHA_LENGTH); + BigSwap(RVAL, SHA_LENGTH); + return status; /* ERR_ALLOC insufficient memory */ + } + Sum_Q( RVAL_a, 1, SHA_LENGTH / sizeof(ord) ); + Sum_big( RVAL_a, /* RVAL=RVAL+hash_result*/ + (ord *)hash_result, + RVAL_a, SHA_LENGTH / sizeof(ord) ); + ALIGN_COPY_FREE(RVAL_a,RVAL,SHA_LENGTH); + BigSwap(RVAL, SHA_LENGTH); +#ifdef CTK_BIG_ENDIAN + ByteSwap(hash_result,SHA_LENGTH); +#endif + BigSwap(hash_result, SHA_LENGTH); + if ( i == sha_block && sha_rem != 0 ) /* last block < SHA_LENGTH*/ + { + memcpy( A + i * SHA_LENGTH, hash_result, + sha_rem * sizeof (uchar)); + } + else /* last block = SHA_LENGTH*/ + { + memcpy( A + i * SHA_LENGTH, hash_result, + SHA_LENGTH * sizeof (uchar)); + } + } + return status; +} + + + +/**************************************************************************** +* NAME: int MyGenRand( u_int16_t A_bytes, +* ord *A, +* ord *RVAL) +* +* DESCRIPTION: Generate random number. +* +* INPUTS: +* PARAMETERS: +* u_int16_t A_bytes Length of A +* ord *A Pointer to A value +* +* OUTPUT: +* PARAMETERS: +* ord *RVAL Pointer to RVAL +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data +* ERR_DATA Generic data error +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ +int MyGenRand( u_int16_t A_bytes, + ord *A, + ord *RVAL ) +{ + int status = SUCCESS; /* function return status */ + SHA_context hash_context; /* SHA context structure */ + uchar M[DSS_LENGTH_MIN]; /* message block */ + uchar hash_result[SHA_LENGTH]; + u_int16_t i; + u_int16_t sha_block; /* number of sha blocks */ + u_int16_t sha_rem; /* size of last block */ + if ( A_bytes == 0 ) + { + status = ERR_INPUT_LEN; + return status; + } + sha_block = (u_int16_t) (A_bytes / SHA_LENGTH); /* number of sha blocks */ + sha_rem = (u_int16_t) (A_bytes % SHA_LENGTH); /* size of last block */ + if ( sha_rem == 0 ) /* last block = SHA_LENGTH */ + { + sha_block--; + } + for ( i = 0; i <= sha_block; i++) + { + SHAInit ( &hash_context ); + memcpy( M, RVAL, SHA_LENGTH); + memset( M + SHA_LENGTH, 0, DSS_LENGTH_MIN - SHA_LENGTH ); + if ( (status = SHAUpdate( &hash_context, M, DSS_LENGTH_MIN )) + != SUCCESS ) + { + return status; /* error */ + } + if ( (status=MySHAFinal (&hash_context, hash_result )) != SUCCESS ) + { + return status; /* error */ + } +#ifdef CTK_BIG_ENDIAN + ByteSwap((uchar*)RVAL,SHA_LENGTH); +#endif + BigSwap((uchar*)RVAL, SHA_LENGTH); + Sum_Q(RVAL, 1,SHA_LENGTH / sizeof(ord)); + Sum_big( RVAL, /* RVAL=RVAL+hash_result*/ + (ord*)hash_result, + RVAL, SHA_LENGTH / sizeof(ord) ); + BigSwap((uchar*)RVAL, SHA_LENGTH); +#ifdef CTK_BIG_ENDIAN + ByteSwap((uchar*)RVAL,SHA_LENGTH); +#endif + if ( i == sha_block && sha_rem != 0 ) /* last block < SHA_LENGTH*/ + { + memcpy( &A[ i*SHA_LENGTH / sizeof(ord)], hash_result, + sha_rem * sizeof (uchar)); + } + else /* last block = SHA_LENGTH*/ + { + memcpy( &A[ i*SHA_LENGTH / sizeof(ord)], hash_result, + SHA_LENGTH * sizeof (uchar)); + } + } + return status; +} + diff --git a/lib/bind/cylink/sha.c b/lib/bind/cylink/sha.c new file mode 100644 index 0000000000..5d94f3639c --- /dev/null +++ b/lib/bind/cylink/sha.c @@ -0,0 +1,698 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: cencrint.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Cryptographic Toolkit Internal Functions File +* +* PRIVATE FUNCTIONS: +* +* +* void shaTransform( u_int32_t *state, uchar *block ) +* void SHAInitK( SHA_context *hash_context ) +* int MySHA( uchar *message, u_int16_t message_bytes, +* uchar *hash_result ) +* int MySHAFinal( SHA_context *hash_context, uchar *hash_result ) +* +* +* Copyright (c) Cylink Corporation 1994. All rights reserved. +* +* REVISION HISTORY: +* +* +* 24 Sep 94 KPZ Initial release +* 10 Oct 94 KPZ Fixed bugs in Add(), DivRem() +* 12 Oct 94 KPZ Modified shaTransform() +* 14 Oct 94 GKL Second version (big endian support) +* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC) +* 08 Nov 94 GKL Added input parameters check to Inverse +* 08 Dec 94 GKL Added YIELD_context to Expo, VerPrime and GenPrime +* +****************************************************************************/ + +/**************************************************************************** +* INCLUDE FILES +****************************************************************************/ + +#include "port_before.h" +#include + +/* system files */ +#ifdef VXD +#include +#else +#include +#include +#include +#endif + +/* program files */ +#include "cylink.h" +#include "ctk_endian.h" +#include "toolkit.h" +#include "cencrint.h" +#include "sha.h" +#include "port_after.h" +extern u_int16_t DataOrder; + +/**************************************************************************** +* NAME: int SHA( uchar *message, +* u_int16_t message_bytes, +* uchar *hash_result ) +* +* DESCRIPTION: Compute a Secure Hash Function. +* +* INPUTS: +* PARAMETERS: +* uchar *message Pointer to message +* u_int16_t message_bytes Number of bytes in message +* uchar *hash_result Pointer to message digest +* +* OUTPUT: +* PARAMETERS: +* uchar *hash_result Message digest +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data(zero bytes) +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* +****************************************************************************/ + +int SHA( uchar *message, + u_int16_t message_bytes, + uchar *hash_result ) +{ + SHA_context hash_context; /* SHA context structure */ + int status = SUCCESS; /* function return status */ + if (message_bytes == 0 ) + { + status = ERR_INPUT_LEN; + return status; /* invalid length for input data */ + } + SHAInit ( &hash_context ); /* initialize SHA */ + if ( (status = SHAUpdate( &hash_context, message, message_bytes )) + != SUCCESS ) + { + return status; /* error */ + } + if ((status=SHAFinal (&hash_context, hash_result)) != SUCCESS ) + { + return status; /* error */ + } + + return status; +} + +/**************************************************************************** +* PRIVATE FUNCTIONS DEFINITIONS +****************************************************************************/ + + +/**************************************************************************** +* NAME: void shaTransform( u_int32_t *state, +* uchar *block ) +* +* DESCRIPTION: Perform SHS transformation. +* +* INPUTS: +* PARAMETERS: +* SHA_context *hash_context Pointer to SHA_context structure +* OUTPUT: +* +* SHA_context *hash_context Pointer to SHA_context structure +* (updated) +* REVISION HISTORY: +* +* 24 sep 94 KPZ Initial release +* 12 Oct 94 KPZ Modified buffers copy +* 14 Oct 94 GKL Second version (big endian support) +* 1 Sep 95 AAB Speedup the function +****************************************************************************/ + + void shaTransform( u_int32_t *state, + const uchar *block ) +{ + u_int32_t W[80]; + u_int32_t A,B,C,D,E; /*,temp;*/ + memcpy( W, block, 64); /*TKL00201*/ +#ifdef CTK_LITTLE_ENDIAN /*TKL00201*/ + ByteSwap32( (uchar *)W, 64); /*TKL00201*/ +#endif /*TKL00201*/ + /* Expand the 16 words into 80 words */ + expand(16);expand(17);expand(18);expand(19);expand(20);expand(21); + expand(22);expand(23);expand(24);expand(25);expand(26);expand(27); + expand(28);expand(29);expand(30);expand(31);expand(32);expand(33); + expand(34);expand(35);expand(36);expand(37);expand(38);expand(39); + expand(40);expand(41);expand(42);expand(43);expand(44);expand(45); + expand(46);expand(47);expand(48);expand(49);expand(50);expand(51); + expand(52);expand(53);expand(54);expand(55);expand(56);expand(57); + expand(58);expand(59);expand(60);expand(61);expand(62);expand(63); + expand(64);expand(65);expand(66);expand(67);expand(68);expand(69); + expand(70);expand(71);expand(72);expand(73);expand(74);expand(75); + expand(76);expand(77);expand(78);expand(79); + /*Set up first buffer*/ + A = state[0]; + B = state[1]; + C = state[2]; + D = state[3]; + E = state[4]; + + /* Heavy mangling, in 4 sub-rounds of 20 iterations each. */ + subRound( A, B, C, D, E, f1, k1SHA, W[ 0] ); + subRound( E, A, B, C, D, f1, k1SHA, W[ 1] ); + subRound( D, E, A, B, C, f1, k1SHA, W[ 2] ); + subRound( C, D, E, A, B, f1, k1SHA, W[ 3] ); + subRound( B, C, D, E, A, f1, k1SHA, W[ 4] ); + subRound( A, B, C, D, E, f1, k1SHA, W[ 5] ); + subRound( E, A, B, C, D, f1, k1SHA, W[ 6] ); + subRound( D, E, A, B, C, f1, k1SHA, W[ 7] ); + subRound( C, D, E, A, B, f1, k1SHA, W[ 8] ); + subRound( B, C, D, E, A, f1, k1SHA, W[ 9] ); + subRound( A, B, C, D, E, f1, k1SHA, W[10] ); + subRound( E, A, B, C, D, f1, k1SHA, W[11] ); + subRound( D, E, A, B, C, f1, k1SHA, W[12] ); + subRound( C, D, E, A, B, f1, k1SHA, W[13] ); + subRound( B, C, D, E, A, f1, k1SHA, W[14] ); + subRound( A, B, C, D, E, f1, k1SHA, W[15] ); + subRound( E, A, B, C, D, f1, k1SHA, W[16] ); + subRound( D, E, A, B, C, f1, k1SHA, W[17] ); + subRound( C, D, E, A, B, f1, k1SHA, W[18] ); + subRound( B, C, D, E, A, f1, k1SHA, W[19] ); + + subRound( A, B, C, D, E, f2, k2SHA, W[20]); + subRound( E, A, B, C, D, f2, k2SHA, W[21]); + subRound( D, E, A, B, C, f2, k2SHA, W[22]); + subRound( C, D, E, A, B, f2, k2SHA, W[23]); + subRound( B, C, D, E, A, f2, k2SHA, W[24]); + subRound( A, B, C, D, E, f2, k2SHA, W[25]); + subRound( E, A, B, C, D, f2, k2SHA, W[26]); + subRound( D, E, A, B, C, f2, k2SHA, W[27]); + subRound( C, D, E, A, B, f2, k2SHA, W[28]); + subRound( B, C, D, E, A, f2, k2SHA, W[29]); + subRound( A, B, C, D, E, f2, k2SHA, W[30]); + subRound( E, A, B, C, D, f2, k2SHA, W[31]); + subRound( D, E, A, B, C, f2, k2SHA, W[32]); + subRound( C, D, E, A, B, f2, k2SHA, W[33]); + subRound( B, C, D, E, A, f2, k2SHA, W[34]); + subRound( A, B, C, D, E, f2, k2SHA, W[35]); + subRound( E, A, B, C, D, f2, k2SHA, W[36]); + subRound( D, E, A, B, C, f2, k2SHA, W[37]); + subRound( C, D, E, A, B, f2, k2SHA, W[38]); + subRound( B, C, D, E, A, f2, k2SHA, W[39]); + + subRound( A, B, C, D, E, f3, k3SHA, W[40]); + subRound( E, A, B, C, D, f3, k3SHA, W[41]); + subRound( D, E, A, B, C, f3, k3SHA, W[42]); + subRound( C, D, E, A, B, f3, k3SHA, W[43]); + subRound( B, C, D, E, A, f3, k3SHA, W[44]); + subRound( A, B, C, D, E, f3, k3SHA, W[45]); + subRound( E, A, B, C, D, f3, k3SHA, W[46]); + subRound( D, E, A, B, C, f3, k3SHA, W[47]); + subRound( C, D, E, A, B, f3, k3SHA, W[48]); + subRound( B, C, D, E, A, f3, k3SHA, W[49]); + subRound( A, B, C, D, E, f3, k3SHA, W[50]); + subRound( E, A, B, C, D, f3, k3SHA, W[51]); + subRound( D, E, A, B, C, f3, k3SHA, W[52]); + subRound( C, D, E, A, B, f3, k3SHA, W[53]); + subRound( B, C, D, E, A, f3, k3SHA, W[54]); + subRound( A, B, C, D, E, f3, k3SHA, W[55]); + subRound( E, A, B, C, D, f3, k3SHA, W[56]); + subRound( D, E, A, B, C, f3, k3SHA, W[57]); + subRound( C, D, E, A, B, f3, k3SHA, W[58]); + subRound( B, C, D, E, A, f3, k3SHA, W[59]); + + subRound( A, B, C, D, E, f4, k4SHA, W[60]); + subRound( E, A, B, C, D, f4, k4SHA, W[61]); + subRound( D, E, A, B, C, f4, k4SHA, W[62]); + subRound( C, D, E, A, B, f4, k4SHA, W[63]); + subRound( B, C, D, E, A, f4, k4SHA, W[64]); + subRound( A, B, C, D, E, f4, k4SHA, W[65]); + subRound( E, A, B, C, D, f4, k4SHA, W[66]); + subRound( D, E, A, B, C, f4, k4SHA, W[67]); + subRound( C, D, E, A, B, f4, k4SHA, W[68]); + subRound( B, C, D, E, A, f4, k4SHA, W[69]); + subRound( A, B, C, D, E, f4, k4SHA, W[70]); + subRound( E, A, B, C, D, f4, k4SHA, W[71]); + subRound( D, E, A, B, C, f4, k4SHA, W[72]); + subRound( C, D, E, A, B, f4, k4SHA, W[73]); + subRound( B, C, D, E, A, f4, k4SHA, W[74]); + subRound( A, B, C, D, E, f4, k4SHA, W[75]); + subRound( E, A, B, C, D, f4, k4SHA, W[76]); + subRound( D, E, A, B, C, f4, k4SHA, W[77]); + subRound( C, D, E, A, B, f4, k4SHA, W[78]); + subRound( B, C, D, E, A, f4, k4SHA, W[79]); + + state[0] += A; + state[1] += B; + state[2] += C; + state[3] += D; + state[4] += E; + +} + + + + +/**************************************************************************** +* NAME: void SHAInitK( SHA_context *hash_context ) +* +* DESCRIPTION: Initialize Secure Hash Function for generate +* random number for DSS. +* +* INPUTS: +* PARAMETERS: +* SHA_context *hash_context SHA context structure +* OUTPUT: +* PARAMETERS: +* SHA_context *hash_context Initialized SHA context structure +* +* RETURN: +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +void SHAInitK( SHA_context *hash_context ) +{ +/*Set up first buffer*/ + hash_context->state[0] = 0xEFCDAB89L; + hash_context->state[1] = 0x98BADCFEL; + hash_context->state[2] = 0x10325476L; + hash_context->state[3] = 0xC3D2E1F0L; + hash_context->state[4] = 0x67452301L; +/*Initialise buffer */ + memset( hash_context->buffer, 0, sizeof(hash_context->buffer)); + memset( hash_context->count, 0, sizeof(hash_context->count)); +} + + +/**************************************************************************** +* NAME: int MySHA( uchar *message, +* u_int16_t message_bytes, +* uchar *hash_result ) +* +* DESCRIPTION: Compute a Secure Hash Function. +* +* INPUTS: +* PARAMETERS: +* uchar *message Pointer to message +* u_int16_t message_bytes Number of bytes in message +* uchar *hash_result Pointer to message digest +* +* OUTPUT: +* PARAMETERS: +* uchar *hash_result Message digest +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data(zero bytes) +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* +****************************************************************************/ +int MySHA( uchar *message, + u_int16_t message_bytes, + uchar *hash_result ) +{ + SHA_context hash_context; /* SHA context structure */ + int status = SUCCESS; /* function return status */ + if (message_bytes == 0 ) + { + status = ERR_INPUT_LEN; + return status; /* invalid length for input data */ + } + SHAInit ( &hash_context ); /* initialize SHA */ +#ifdef CTK_BIG_ENDIAN + ByteSwap(message,message_bytes); +#endif + status = SHAUpdate( &hash_context, message, message_bytes ); +#ifdef CTK_BIG_ENDIAN + ByteSwap(message,message_bytes); +#endif + if ( status != SUCCESS ) + { + return status; /* error */ + } + if ((status=MySHAFinal (&hash_context, hash_result)) != SUCCESS ) + { + return status; /* error */ + } + return status; +} + +/**************************************************************************** +* NAME: int MySHAFinal( SHA_context *hash_context, +* uchar *hash_result ) +* DESCRIPTION: Finalize Secure Hash Function +* +* INPUTS: +* PARAMETERS: +* SHA_context *hash_context SHA context structure +* uchar *hash_result Pointer to hash +* OUTPUT: +* PARAMETERS: +* uchar *hash_result Final value +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data (zero bytes) +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 10 Oct 94 KPZ Modified for arbitrary message length +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + int MySHAFinal( SHA_context *hash_context, + uchar *hash_result ) +{ + int status = SUCCESS; /* function return status */ + uchar bits[8]; + u_int16_t index, padLen; + u_int32_t ex; + uchar PADDING[64] = { /* padding string */ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + if ( hash_context->count[0] == 0 && hash_context->count[1] == 0 ) + { + status= ERR_INPUT_LEN; + return status; + } + /* Save number of bits */ + LongByte( &hash_context->count[1] , 4, bits ); + LongByte( &hash_context->count[0] , 4, bits + 4 ); + ByteSwap32( bits, 8 ); + /* Pad out to 56 mod 64.*/ + index = (u_int16_t )((hash_context->count[0] >> 3) & 0x3f); + padLen = (u_int16_t) ((index < 56) ? (56 - index) : (120 - index)); + SHAUpdate( hash_context, PADDING, padLen ); + + /* Append length (before padding) */ + SHAUpdate (hash_context, bits, 8); + + /* Set order of hash_context */ + ex = hash_context->state[0]; + hash_context->state[0] = hash_context->state[4]; + hash_context->state[4] = ex; + ex = hash_context->state[1]; + hash_context->state[1] = hash_context->state[3]; + hash_context->state[3] = ex; + /* Store state in digest */ + memcpy(hash_result,hash_context->state,SHA_LENGTH); + /* Zeroize sensitive information.*/ + memset( hash_context, 0, sizeof(hash_context) ); +#if defined ( ORD_16 ) && defined( CTK_BIG_ENDIAN ) + WordSwap(hash_result,SHA_LENGTH); +#endif + return status; +} + + +/**************************************************************************** +* NAME: int SHAUpdate( SHA_context *hash_context, +* uchar *message, +* u_int16_t message_bytes ) +* DESCRIPTION: Update Secure Hash Function +* +* INPUTS: +* PARAMETERS: +* SHA_context *hash_context SHA context structure +* uchar *message Pointer to message +* u_int16_t message_bytes Number of bytes +* OUTPUT: +* PARAMETERS: +* SHA_context *hash_context Updated SHA context structure +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data (zero bytes) +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 10 Oct 94 KPZ Modified for arbitrary message length +* +****************************************************************************/ + +int SHAUpdate( SHA_context *hash_context, + const uchar *message, + u_int16_t message_bytes ) + +{ + int status = SUCCESS; /* function return status */ + u_int16_t i, index, partLen; + if ( message_bytes == 0 ) + { + status = ERR_INPUT_LEN; /*invalid length for input data (zero bytes)*/ + return status; + } + + /* Compute number of bytes mod 64 */ + index = (u_int16_t)((hash_context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ( (hash_context->count[0] += ((u_int32_t )message_bytes << 3)) + < ((u_int32_t )message_bytes << 3) ) + { + hash_context->count[1]++; + } + hash_context->count[1] += ((u_int32_t )message_bytes >> 29); + + partLen = (u_int16_t) (64 - index); + /* Transform as many times as possible.*/ + if ( message_bytes >= partLen ) + { + memcpy( &hash_context->buffer[index], message, partLen ); + shaTransform( hash_context->state, hash_context->buffer ); + + for ( i = partLen; (u_int16_t)(i + 63) < message_bytes; i += 64 ) + { + shaTransform ( hash_context->state, &message[i] ); + } + index = 0; + } + else + { + i = 0; + } + /* Buffer remaining input */ + memcpy( &hash_context->buffer[index], &message[i], + message_bytes - i ); + return status; +} + + +/**************************************************************************** +* NAME: void SHAInit( SHA_context *hash_context ) +* +* DESCRIPTION: Initialize Secure Hash Function +* +* INPUTS: +* PARAMETERS: +* SHA_context *hash_context SHA context structure +* OUTPUT: +* PARAMETERS: +* SHA_context *hash_context Initialized SHA context structure +* +* RETURN: +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* +****************************************************************************/ + +void SHAInit( SHA_context *hash_context ) +{ +/*Set up first buffer*/ + hash_context->state[0] = h0SHA; + hash_context->state[1] = h1SHA; + hash_context->state[2] = h2SHA; + hash_context->state[3] = h3SHA; + hash_context->state[4] = h4SHA; + +/* Initialise buffer */ + memset( hash_context->buffer, 0, sizeof(hash_context->buffer)); + /*Initialize bit count*/ + hash_context->count[0] = hash_context->count[1] = 0; +} + +/**************************************************************************** +* NAME: int SHAFinal( SHA_context *hash_context, +* uchar *hash_result ) +* DESCRIPTION: Finalize Secure Hash Function +* +* INPUTS: +* PARAMETERS: +* SHA_context *hash_context SHA context structure +* uchar *hash_result Pointer to hash +* OUTPUT: +* PARAMETERS: +* uchar *hash_result Final value +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data (zero bytes) +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 10 Oct 94 KPZ Modified for arbitrary message length +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + + +int SHAFinal( SHA_context *hash_context, + uchar *hash_result ) +{ + int status = SUCCESS; /* function return status */ + status = MySHAFinal( hash_context, hash_result ); +#ifdef CTK_BIG_ENDIAN + if (status == SUCCESS) + { + ByteSwap(hash_result, SHA_LENGTH); + } +#endif + if (DataOrder) + { + BigSwap(hash_result, SHA_LENGTH); + } + return status; +} + +/**************************************************************************** +* NAME: int GetPasswordKeySHA( u_int16_t Password_bytes, +* uchar *Password, +* uchar *salt, +* u_int16_t Count, +* uchar *K, +* uchar *IV ) +* +* DESCRIPTION: Get Password-Based DES/KAPPA Key by SHA +* +* INPUTS: +* PARAMETERS: +* u_int16_t Password_bytes Number of bytes in password +* uchar *Password Pointer to password +* uchar *salt Pointer to salt(8-byte) +* u_int16_t Count Number of iteration +* OUTPUT: +* PARAMETERS: +* uchar *K Pointer to DES/KAPPA key +* uchar *IV Pointer to initialization vector +* RETURN: +* SUCCESS No errors +* ERR_COUNT Invalid iteration count (zero) +* ERR_INPUT_LEN Invalid length for input data(zero bytes) +* ERR_ALLOC Insufficient memory +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 26 Oct 94 GKL (ERR_ALLOC) +* +****************************************************************************/ + int GetPasswordKeySHA( u_int16_t Password_bytes, + uchar *Password, + uchar *salt, + u_int16_t Count, + uchar *K, + uchar *IV ) + +{ + int status = SUCCESS; /* function return status */ + uchar digest[SHA_LENGTH]; + uchar *buf; + if ( Count == 0 ) /* invalid iteration count (zero) */ + { + status = ERR_COUNT; + return status; + } + CALLOC(buf,uchar,Password_bytes + 8); + if ( status != SUCCESS ) + { + return status; /* ERR_ALLOC insufficient memory */ + } + if ( Password_bytes != 0 ) /* if number of bytes password non equals zero */ + { + memcpy( buf, Password, Password_bytes ); + } + memcpy( buf + Password_bytes, salt, 8); +/* Compute message digest */ + status = SHA( buf, (u_int16_t)(Password_bytes + 8), digest); + if (!DataOrder) + { + BigSwap(digest, SHA_LENGTH); + } + + if ( status != SUCCESS ) + { + free ( buf ); + return status; + } + Count --; /* decrement Count */ +/* Count times compute message digest */ + while ( Count != 0 ) + { + if ( (status = SHA( digest, SHA_LENGTH, digest)) != SUCCESS ) + { + free ( buf ); + return status; + } + if (!DataOrder) + { + BigSwap(digest, SHA_LENGTH); + } + Count --; + } + memcpy( K, digest, 8 ); + memcpy( IV, digest + SHA_LENGTH -8, 8 ); + free ( buf ); + return status; +} diff --git a/lib/bind/cylink/sha.h b/lib/bind/cylink/sha.h new file mode 100644 index 0000000000..a8606086ef --- /dev/null +++ b/lib/bind/cylink/sha.h @@ -0,0 +1,148 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: sha.h PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Cryptographic Toolkit Internal Functions Header File +* +* USAGE: File should be included in Toolkit functions files +* +* +* Copyright (c) Cylink Corporation 1994. All rights reserved. +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* +****************************************************************************/ +#ifndef SHA_H +#define SHA_H +#include "cylink.h" + +#define SHS_BLOCKSIZE 64 +/* +#define FSHA(x,y,z) ( ( x & y ) | ( ~x & z ) ) +#define GSHA(x,y,z) ( x ^ y ^ z ) +#define HSHA(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) +#define ISHA(x,y,z) (x ^ y ^ z) +*/ +/*#define f1(x,y,z) ( (x & y) | (~x & z) ) // Rounds 0-19 */ +#define f1(x,y,z) ( z ^ (x & (y ^ z) ) ) /* Rounds 0-19 */ +#define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ +/*#define f3(x,y,z) ( (x & y) | (x & z) | (y & z) ) // Rounds 40-59 */ +#define f3(x,y,z) ( (x & y) | (z & (x | y) ) ) /* Rounds 40-59 */ +#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ + + +#define RotateLeft(x,n) (( x << n )|( x >> (32-n) ) ) /*Circular left shift operation*/ + +/*SHS Constants */ +#define k1SHA 0x5a827999L +#define k2SHA 0x6ed9eba1L +#define k3SHA 0x8f1bbcdcL +#define k4SHA 0xca62c1d6L + +/*SHS initial value */ +#define h0SHA 0x67452301L +#define h1SHA 0xefcdab89L +#define h2SHA 0x98badcfeL +#define h3SHA 0x10325476L +#define h4SHA 0xc3d2e1f0L + +/*The initial expanding function*/ +#define expand(count) \ + {\ + W[count] = W[count-3] ^ W[count-8] ^ W[count-14] ^ W[count-16];\ + W[count] = RotateLeft( W[count], 1 );\ + } + +/*New variant */ +#define subRound(a, b, c, d, e, f, k, data) \ + ( e += RotateLeft(a,5) + f(b, c, d) + k + data, b = RotateLeft( b,30) ) + + + +/*The four sub_rounds*/ +/* +#define subR1(count) \ + {\ + temp=RotateLeft(A,5) + FSHA(B,C,D) + E +W[count] +k1SHA;\ + E = D; \ + D = C; \ + C = RotateLeft(B,30); \ + B = A; \ + A = temp; \ + } + +#define subR2(count) \ + {\ + temp=RotateLeft(A,5) + GSHA(B,C,D) + E +W[count] +k2SHA;\ + E = D; \ + D = C; \ + C = RotateLeft(B,30);\ + B = A; \ + A = temp; \ + } + +#define subR3(count) \ + {\ + temp=RotateLeft(A,5) + HSHA(B,C,D) + E +W[count] +k3SHA;\ + E = D; \ + D = C; \ + C = RotateLeft(B,30);\ + B = A; \ + A = temp; \ + } + +#define subR4(count) \ + {\ + temp=RotateLeft(A,5) + ISHA(B,C,D) + E + W[count] +k4SHA;\ + E = D; \ + D = C; \ + C = RotateLeft(B,30);\ + B = A; \ + A = temp; \ + } +*/ +#endif /* SHA_H */ + diff --git a/lib/bind/cylink/sizetest.c b/lib/bind/cylink/sizetest.c new file mode 100644 index 0000000000..8d219f54b0 --- /dev/null +++ b/lib/bind/cylink/sizetest.c @@ -0,0 +1,51 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +#include "bnsize00.h" + +#if BNSIZE16 +#error Using 16-bit math library +#elif BNSIZE32 +#error Using 32-bit math library +#elif BNSIZE64 +#error Using 64-bit math library +#else +#error No math library size defined +#endif diff --git a/lib/bind/cylink/swap.c b/lib/bind/cylink/swap.c new file mode 100644 index 0000000000..e37c67e052 --- /dev/null +++ b/lib/bind/cylink/swap.c @@ -0,0 +1,211 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + + +/**************************************************************************** +* FILENAME: swap.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Byte and Word Swap functions +* +* PUBLIC FUNCTIONS: +* +* +* PRIVATE FUNCTIONS: +* +* REVISION HISTORY: +* +* 14 Oct 94 GKL Initial release +* 26 Oct 94 GKL (alignment for big endian support ) +* +****************************************************************************/ + +/**************************************************************************** +* INCLUDE FILES +****************************************************************************/ +/* system files */ + +#include "port_before.h" +#ifdef VXD +#include +#else +#include +#include +#endif +/* program files */ +#include "cylink.h" +#include "ctk_endian.h" +#include "toolkit.h" +#include "port_after.h" + +u_int16_t DataOrder = 0; + +/*Reset bytes in long*/ +/*extern void ByteSwap32_asm( uchar *X, u_int16_t X_len );*/ /*kz*/ + +/**************************************************************************** +* NAME: void ByteSwap32 (uchar *array, +* u_int16_t X_len ) +* +* DESCRIPTION: Perform byte reversal on an array of longword. +* +* INPUTS: +* PARAMETERS: +* uchar *X Pointer to array +* u_int16_t X_len Number of bytes +* OUTPUT: +* uchar *X Pointer to array +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + + +void ByteSwap32( uchar *X, u_int16_t X_len ) +{ + u_int16_t i; /*counter*/ + uchar a; /*temporary char*/ + for ( i = 0; i < X_len; i += 4) + { + a = X[i]; + X[i] = X[i+3]; + X[i+3] = a; + a = X[i+1]; + X[i+1] = X[i+2]; + X[i+2] = a; + } +/*#endif*/ /*kz*/ +} + + +/**************************************************************************** +* NAME: void ByteSwap (uchar *array, +* u_int16_t X_len ) +* +* DESCRIPTION: Perform byte reversal on an array of longword or shortword. +* +* INPUTS: +* PARAMETERS: +* uchar *X Pointer to array +* u_int16_t X_len Number of bytes +* OUTPUT: +* uchar *X Pointer to array +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +void ByteSwap( uchar *X, + u_int16_t X_len ) +{ +#ifdef ORD_16 + u_int16_t i; /*counter*/ + uchar a; /*tempriory char for revers*/ + for ( i = 0; i < X_len; i += 2) + { + a = X[i]; + X[i] = X[i+1]; + X[i+1] = a; + } +#endif +#ifdef ORD_32 + ByteSwap32(X,X_len); +#endif +} + +/*kz longbyte deleted */ + +/**************************************************************************** +* NAME: void WordSwap (uchar *array, +* u_int16_t X_len ) +* +* DESCRIPTION: Perform short reversal on an array of longword. +* +* INPUTS: +* PARAMETERS: +* uchar *X Pointer to array +* u_int16_t X_len Number of bytes +* OUTPUT: +* uchar *X Pointer to array +* +* REVISION HISTORY: +* +* 14 Oct 94 GKL Initial release +* +****************************************************************************/ +void WordSwap( uchar *X, + u_int16_t X_len ) +{ + u_int16_t i; /*counter*/ + u_int16_t a; /*tempriory u_int16_t*/ + + for ( i = 0; i < X_len; i += 4) + { + a = *(u_int16_t*)(&X[i]); + *(u_int16_t*)(&X[i])=*(u_int16_t*)(&X[i+2]); + *(u_int16_t*)(&X[i+2])=a; + } +} + +void BigSwap( uchar *buffer, + u_int16_t bufferLength) +{ + uchar temp; + u_int16_t i; + + for (i = 0; i < (u_int16_t)(bufferLength/2); i++) + { + temp = buffer[i]; + buffer[i] = buffer[bufferLength - 1 - i]; + buffer[bufferLength - 1 - i] = temp; + } +} + +void SetDataOrder ( u_int16_t dataOrder) +{ + DataOrder = dataOrder; +} diff --git a/lib/bind/cylink/toolkit.h b/lib/bind/cylink/toolkit.h new file mode 100644 index 0000000000..9497f3e49e --- /dev/null +++ b/lib/bind/cylink/toolkit.h @@ -0,0 +1,393 @@ +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: toolkit.h PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Cryptographic Toolkit Functions Header File +* +* USAGE: File should be included to use Toolkit Functions +* +* +* Copyright (c) Cylink Corporation 1994. All rights reserved. +* +* REVISION HISTORY: +* +* 23 Aug 94 KPZ Initial release +* 24 Sep 94 KPZ Added prototypes of Toolkit functions +* 14 Oct 94 GKL Second version (big endian support) +* 08 Dec 94 GKL Added YIELD_context to GenDSSParameters +* +****************************************************************************/ + +#ifndef TOOLKIT_H /* Prevent multiple inclusions of same header file */ +#define TOOLKIT_H + + +/* Error types */ + +#define SUCCESS 0 /* no errors */ +#define ERR_DATA -1 /* generic data error */ +#define ERR_ALLOC -2 /* insufficient memory */ +#define ERR_INPUT_LEN -3 /* invalid length for input data (zero bytes) */ +#define ERR_DSS_LEN -4 /* invalid length for dss_p */ +#define ERR_DH_LEN -5 /* invalid length for DH_modulus */ +#define ERR_BLOCK_LEN -7 /* invalid length for input block for ECB/CBC */ +#define ERR_HASH_LEN -8 /* invalid length for hash_result */ +#define ERR_MODE -9 /* invalid value of encryption mode */ +#define ERR_NUMBER -10 /* invalid number of testings (zero) */ +#define ERR_POSITION -11 /* invalid value of triplet_position */ +#define ERR_COUNT -12 /* invalid iteration count (zero) */ +#define ERR_SIGNATURE -21 /* signature is not valid */ +#define ERR_PRIME -22 /* number is not prime */ +#define ERR_WEAK -23 /* weak key */ +#define ERR_INPUT_VALUE -24 /* invalid input value */ +/* additional error types for CEPA */ +#define ERR_KEY_LENGTH -25 /* invalid value of key length */ +#define ERR_ROUNDS -26 /* invalid value of rounds number */ +#define ERR_CANCEL -30 /* canceled by user */ +#define ERR_MODULUS_ZERO -31 /* invalid modulo */ +#define ERR_UNSUPPORTED -40 /* unsupported crypto method */ +#define ERR_OP_CODE -41 /*invalid operation code*/ + + + +/* Lengths of variables */ +#define DH_LENGTH_MIN 64 /* 512-bit minimal length for DH functions */ +#define DSS_LENGTH_MIN 64 /* 512-bit minimal length for DSS functions */ +#define DSS_LENGTH_MAX 128 /* 1024-bit maximal length for DSS functions */ +#define SHA_LENGTH 20 /* 160-bit length for SHA hash result */ + +/* Number of random bases for Miller test */ +#define TEST_COUNT 40 + +#define LITTLE_ORDER 0 +#define BIG_ORDER 1 + +/* Key lengths */ /* add to toolkit.h */ +#define KEY_40BIT 40 /* 40-bit key */ +#define KEY_64BIT 64 /* 64-bit key */ +#define KEY_128BIT 128 /* 128-bit key */ +#define CEPA_MAX_ROUNDS 12 + +/* Operation codes for MultiPrecArithm() */ +#define EXPO 0x21 +#define MUL 0x22 +/*#define ADD 0x23*/ + +/**************************************************************************** +* INCLUDE FILES +****************************************************************************/ + +/* system files */ +#include "cylink.h" +#include "ctk_endian.h" +/* callback function */ +#ifdef VXD +typedef int (* YIELD_PROC)( void ); +#else +typedef int (* YIELD_PROC)(int ); /*TKL00601*/ +#endif + +typedef struct { /*TKL00601*/ + YIELD_PROC yield_proc; + void * handle; /* Application specific information */ +}YIELD_context; + + +/* Secure Hash Algorithm structure */ +typedef struct +{ + u_int32_t state[ 5 ]; /* state */ + u_int32_t count[ 2 ]; /* number of bits */ + uchar buffer[ 64 ]; /* input buffer */ +} SHA_context; + + +#ifdef __cplusplus +extern "C" { +#endif +/* Copy Cylink DSS Common Parameters */ /*TKL01201*/ + int GetDSSPQG(u_int16_t dss_p_bytes, + uchar *dss_p, + uchar *dss_q, + uchar *dss_g); + +/* Compute a Secure Hash Function */ + int SHA( uchar *message, u_int16_t message_bytes, + uchar *hash_result ); +/* Initialize Secure Hash Function */ + void SHAInit( SHA_context *hash_context ); + +/* Update Secure Hash Function */ + int SHAUpdate( SHA_context *hash_context, + const uchar *message, + u_int16_t message_bytes ); +/* Finalize Secure Hash Function */ + int SHAFinal( SHA_context *hash_context, + uchar *hash_result ); +/* Compute a DSS Signature */ + int GenDSSSignature( u_int16_t dss_p_bytes, uchar *dss_p, + uchar *dss_q, uchar *dss_g, + uchar *dss_x, uchar *dss_k, + uchar *r, uchar *s, + uchar *hash_result ); +/* Verify a DSS Signature */ + int VerDSSSignature( u_int16_t dss_p_bytes, uchar *dss_p, + uchar *dss_q, uchar *dss_g, + uchar *dss_y, uchar *r, + uchar *s, uchar *hash_result); +/* Initialize Random number Generator */ + int InitRand( u_int16_t SEED_bytes, uchar *SEED, + uchar *RVAL ); +/* Generate random number */ + int GenRand( u_int16_t A_bytes, uchar *A, + uchar *RVAL ); +/* Compute DSS public/secret number pair */ + int GenDSSKey( u_int16_t dss_p_bytes, uchar *dss_p, + uchar *dss_q, uchar *dss_g, + uchar *dss_x, uchar *dss_y, + uchar *XKEY ); +/* Generate secret number */ + int GenDSSNumber( uchar *dss_k, uchar *dss_q, + uchar *KKEY ); + +/* Compute a Diffie-Hellman Shared number */ + int GetDHSharedNumber( u_int16_t DH_modulus_bytes, uchar *DH_secret, + uchar *DH_public, uchar *DH_shared, + uchar *DH_modulus ); +/* Set Key by Diffie_Hellman shared number */ + int SetDESKAPPAKey( u_int16_t DH_modulus_bytes, uchar *DH_shared, + uchar *K ); +/* Expand DES key */ + void DESKeyExpand( uchar *key, uchar *K1 ); + +/* Encrypt a block of data with single DES */ + int DESEncrypt( uchar *des_iv, uchar *des_key, + u_int16_t des_mode, uchar *input_array, + uchar *output_array, u_int16_t input_array_bytes ); + +/* Decrypt a block of data with single DES */ + int DESDecrypt( uchar *des_iv, uchar *des_key, + u_int16_t des_mode, uchar *data_array, + u_int16_t data_array_bytes ); + +/* One-Time-Pad Signature with a Diffie-Hellman shared number */ + int DHOneTimePad( u_int16_t DH_modulus_bytes, uchar *DH_shared, + uchar *X, uchar *Y ); + +/* Compute a Diffie-Hellman pair */ + int GenDHPair( u_int16_t DH_modulus_bytes, uchar *DH_secret, + uchar *DH_public, uchar *DH_base, + uchar *DH_modulus, uchar *RVAL ); + + int GetPasswordKeySHA( u_int16_t Password_bytes, uchar *Password, + uchar *salt, u_int16_t Count, + uchar *K, uchar *IV ); + +/* Generate DSS Common Parameters */ + int GenDSSParameters( u_int16_t dss_p_bytes, uchar *dss_p, + uchar *dss_q, uchar *dss_g, + uchar *RVAL, YIELD_context *yield_cont ); /*TKL00701*/ + +/* Produce a Shamir Key-Sharing Triplet for Secret Number */ +int GenShamirTriplet( u_int16_t SecretNumber_bytes, uchar *SecretNumber, + uchar *first_value, uchar *second_value, + uchar *third_value, uchar *RVAL ); + +/* Reconstract a Secret Number from Shamir Key-Sharing Duplex */ +int GetNumberShamirDuplex( u_int16_t SecretNumber_bytes, + uchar *value_A, + u_int16_t A_position, uchar *value_B, + u_int16_t B_position, + uchar *SecretNumber ); +int SFDHEncrypt( u_int16_t DH_modulus_bytes, + uchar *DH_modulus, + uchar *DH_base, + uchar *DH_public, + uchar *DH_random_public, + uchar *DH_shared, + uchar *RVAL ); +int SFDHDecrypt( u_int16_t DH_modulus_bytes, + uchar *DH_modulus, + uchar *DH_secret, + uchar *DH_random_public, + uchar *DH_shared ); +/* Check DES key weakness */ +int CheckDESKeyWeakness( uchar *key ); + +int SetCipherKey( u_int16_t DH_shared_bytes, + uchar *DH_shared, + uchar *Key, + u_int16_t cryptoMethod ); +/* Non-Pipelined Triple DES encrypt*/ +int TDESEncrypt( uchar *des_iv, + uchar *des_key1,uchar *des_key2, uchar *des_key3, + u_int16_t des_mode, + uchar *input_array, + uchar *output_array, + u_int16_t input_array_bytes ); +/* Non-Pipelined Triple DES decrypt*/ +int TDESDecrypt( uchar *des_iv, + uchar *des_key1,uchar *des_key2, uchar *des_key3, + u_int16_t des_mode, + uchar *data_array, + u_int16_t data_array_bytes ); +/*Pipeline Triple DES encrypt*/ +int PTDESEncrypt( uchar *iv1, uchar *iv2, uchar *iv3, + uchar *des_key1,uchar *des_key2, uchar *des_key3, + u_int16_t des_mode, + uchar *input_array, + uchar *output_array, + u_int16_t input_array_bytes ); +/*Pipeline Triple DES decrypt*/ +int PTDESDecrypt( uchar *iv1, uchar *iv2, uchar *iv3, + uchar *des_key1,uchar *des_key2, uchar *des_key3, + u_int16_t des_mode, + uchar *data_array, + u_int16_t input_array_bytes ); + int PCBC1Encrypt( uchar *iv1, uchar *iv2, uchar *iv3, + uchar *des_key1,uchar *des_key2, uchar *des_key3, + uchar *msg1,uchar *msg2, uchar *msg3, + uchar *out1,uchar *out2, uchar *out3, + u_int16_t input_array_bytes ); + int PCBC1Decrypt( uchar *iv1, uchar *iv2, uchar *iv3, + uchar *des_key1,uchar *des_key2, uchar *des_key3, + uchar *out1,uchar *out2, uchar *out3, + u_int16_t input_array_bytes ); + +/*CEPA enc/dec */ +int CepaKeyExpand( uchar *key, + u_int16_t key_length, + u_int16_t number_of_rounds, + uchar *expanded_key ); + +int CepaCsp( u_int16_t key_length, + uchar *csp); + +int CepaEncrypt( uchar *iv, + uchar *key, + u_int16_t mode, + uchar *csp, + u_int16_t r, + uchar *input_array, + uchar *output_array, + u_int16_t input_array_bytes ); + +int CepaDecrypt( uchar *iv, + uchar *key, + u_int16_t mode, + uchar *csp, + u_int16_t r, + uchar *data_array, + u_int16_t data_array_bytes ); +void BigNumInit(void); +void SetDataOrder ( u_int16_t dataOrder); + +int GetDHSecretShared( u_int16_t DH_modulus_bytes, u_int16_t DH_secret_bytes, uchar *DH_secret, + uchar *DH_public, uchar *DH_shared, + uchar *DH_modulus); +int GenDHKey( u_int16_t DH_modulus_bytes, u_int16_t DH_secret_bytes, uchar *DH_secret, + uchar *DH_public, uchar *DH_base, + uchar *DH_modulus, uchar *RVAL ); +int SFDHInitiate( u_int16_t DH_modulus_bytes, u_int16_t DH_secret_bytes, + uchar *DH_modulus, uchar *DH_base, + uchar *DH_public, uchar *DH_random_public, + uchar *DH_shared, uchar *RVAL ); +int SFDHComplete( u_int16_t DH_modulus_bytes, u_int16_t DH_secret_bytes, + uchar *DH_modulus, + uchar *DH_secret, uchar *DH_random_public, + uchar *DH_shared ); + +int SplitKey( u_int16_t Secretnumber_bytes, uchar *SecretNumber, + uchar *first_value, uchar *second_value, + uchar *third_value, uchar *RVAL ); +int UnsplitKey( u_int16_t Secretnumber_bytes, uchar *value_A, + u_int16_t A_position, uchar *value_B, + u_int16_t B_position, uchar *SecretNumber ); +int SAFERKeyExpand( uchar *key, u_int16_t key_length, + uchar *expanded_key ); +int SAFEREncrypt( uchar *iv, uchar *key, u_int16_t mode, u_int16_t key_length, + uchar *input_array, uchar *output_array, u_int16_t input_array_bytes ); +int SAFERDecrypt( uchar *iv, uchar *key, u_int16_t mode, u_int16_t r_length, + uchar *data_array, u_int16_t data_array_bytes ); + + + void ByteSwap( uchar *X, u_int16_t X_len); + void ByteSwap32( uchar *X, u_int16_t X_len); + void WordSwap( uchar *X, u_int16_t X_len); + void BigSwap( uchar *buffer, u_int16_t bufferLength); + int Sum_big (ord *X, ord *Y, ord *Z, u_int16_t len_X); + int Sum_Q(ord *X, u_int16_t src, u_int16_t len_X); + void LShiftL_big( ord *X, u_int32_t len_X, u_int32_t n_bit ); + int Sub_big (ord *X, ord *Y, ord *Z, u_int16_t len_X); + int DivRem( u_int16_t X_bytes, ord *X, u_int16_t P_bytes, ord *P, + ord *Z, ord *D); + int SteinGCD (ord *m, ord *n, u_int16_t len); + int Add( ord *X, ord *Y, u_int16_t P_len, ord *P); + int Inverse(u_int16_t X_bytes, ord *X, u_int16_t P_bytes, ord *P, + ord *Z); + int DoubleExpo(u_int16_t X1_bytes, ord *X1, u_int16_t Y1_bytes, + ord *Y1, u_int16_t X2_bytes, ord *X2, + u_int16_t Y2_bytes, ord *Y2, u_int16_t P_bytes, + ord *P, ord *Z); + int Sum (ord *X, ord *Y, u_int16_t len_X); + void Mul_big_1( ord X, ord *Y, ord *XY, u_int16_t ly); + int Mul( u_int16_t X_bytes, ord *X, u_int16_t Y_bytes, ord *Y, + u_int16_t P_bytes, ord *P, ord *Z ); + + int Square(u_int16_t X_bytes, ord *X, u_int16_t P_bytes, ord *P, + ord *Z); + + int PartReduct(u_int16_t X_bytes, ord *X, u_int16_t P_bytes, ord *P, + ord *Z); + int Expo(u_int16_t X_bytes, ord *X, u_int16_t Y_bytes, ord *Y, + u_int16_t P_bytes, ord *P, ord *Z); + + +#ifdef __cplusplus +} +#endif + + +#endif /* TOOLKIT_H */ + diff --git a/lib/bind/dnssafe/Makefile.in b/lib/bind/dnssafe/Makefile.in new file mode 100644 index 0000000000..a79417da7c --- /dev/null +++ b/lib/bind/dnssafe/Makefile.in @@ -0,0 +1,41 @@ +OBJS= ahcbcpad.@O@ ahchdig.@O@ ahchencr.@O@ ahchgen.@O@ ahchrand.@O@ \ + ahdigest.@O@ ahencryp.@O@ ahgen.@O@ ahrandom.@O@ ahrsaenc.@O@ \ + ahrsaepr.@O@ ahrsaepu.@O@ aichdig.@O@ aichenc8.@O@ aichencn.@O@ \ + aichencr.@O@ aichgen.@O@ aichrand.@O@ aimd5.@O@ aimd5ran.@O@ \ + ainfotyp.@O@ ainull.@O@ airsaepr.@O@ airsaepu.@O@ airsakgn.@O@ \ + airsaprv.@O@ airsapub.@O@ algchoic.@O@ algobj.@O@ amcrte.@O@ \ + ammd5.@O@ ammd5r.@O@ amrkg.@O@ amrsae.@O@ balg.@O@ bgclrbit.c \ + bgmdmpyx.@O@ bgmdsqx.@O@ bgmodexp.@O@ bgpegcd.@O@ big2exp.@O@ \ + bigabs.@O@ bigacc.@O@ bigarith.@O@ bigcmp.@O@ bigconst.@O@ \ + biginv.@O@ biglen.@O@ bigmodx.@O@ bigmpy.@O@ bigpdiv.@O@ \ + bigpmpy.@O@ bigpmpyh.@O@ bigpmpyl.@O@ bigpsq.@O@ bigqrx.@O@ \ + bigsmod.@O@ bigtocan.@O@ bigu.@O@ bigunexp.@O@ binfocsh.@O@ \ + bkey.@O@ bmempool.@O@ cantobig.@O@ crt2.@O@ digest.@O@ \ + digrand.@O@ encrypt.@O@ generate.@O@ intbits.@O@ intitem.@O@ \ + keyobj.@O@ ki8byte.@O@ kifulprv.@O@ kiitem.@O@ kinfotyp.@O@ \ + kipkcrpr.@O@ kirsacrt.@O@ kirsapub.@O@ md5.@O@ md5rand.@O@ \ + prime.@O@ random.@O@ rsa.@O@ rsakeygn.@O@ seccbcd.@O@ \ + seccbce.@O@ surrendr.@O@ + +SRCS= ahcbcpad.c ahchdig.c ahchencr.c ahchgen.c ahchrand.c ahdigest.c \ + ahencryp.c ahgen.c ahrandom.c ahrsaenc.c ahrsaepr.c ahrsaepu.c \ + aichdig.c aichenc8.c aichencn.c aichencr.c aichgen.c aichrand.c \ + aimd5.c aimd5ran.c ainfotyp.c ainull.c airsaepr.c airsaepu.c \ + airsakgn.c airsaprv.c airsapub.c algchoic.c algobj.c amcrte.c \ + ammd5.c ammd5r.c amrkg.c amrsae.c balg.c bgclrbit.c bgmdmpyx.c \ + bgmdsqx.c bgmodexp.c bgpegcd.c big2exp.c bigabs.c bigacc.c \ + bigarith.c bigcmp.c bigconst.c biginv.c biglen.c bigmodx.c \ + bigmpy.c bigpdiv.c bigpmpy.c bigpmpyh.c bigpmpyl.c bigpsq.c \ + bigqrx.c bigsmod.c bigtocan.c bigu.c bigunexp.c binfocsh.c \ + bkey.c bmempool.c cantobig.c crt2.c digest.c digrand.c encrypt.c \ + generate.c intbits.c intitem.c keyobj.c ki8byte.c kifulprv.c \ + kiitem.c kinfotyp.c kipkcrpr.c kirsacrt.c kirsapub.c md5.c \ + md5rand.c prime.c random.c rsa.c rsakeygn.c seccbcd.c seccbce.c \ + surrendr.c + +TARGETS= ${OBJS} + +CINCLUDES= -I.. -I../include +CWARNINGS= -Werror + +@BIND9_MAKE_RULES@ diff --git a/lib/bind/dnssafe/ahcbcpad.c b/lib/bind/dnssafe/ahcbcpad.c new file mode 100644 index 0000000000..27635831e0 --- /dev/null +++ b/lib/bind/dnssafe/ahcbcpad.c @@ -0,0 +1,176 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +/* Define this so that the type of the 'this' pointer in the + virtual functions will be correct for this derived class. + */ +struct AHSecretCBCPad; +#define THIS_ENCRYPT_DECRYPT struct AHSecretCBCPad + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahcbcpad.h" +#include "port_after.h" + +#define GENERATE_BREAK(type) { \ + status = type; \ + break; \ + } + +/* Inherit the base class destructor, block size, + and decrypt init and update routines. + */ +static AHEncryptDecryptVTable V_TABLE = { + AHChooseEncryptDestructor, AHChooseEncryptGetBlockLen, + AHSecretCBCPadEncryptInit, AHChooseEncryptDecryptInit, + AHSecretCBCPadEncryptUpdate, AHChooseEncryptDecryptUpdate, + AHSecretCBCPadEncryptFinal, AHSecretCBCPadDecryptFinal +}; + +AHSecretCBCPad *AHSecretCBCPadConstructor2 (handler, infoType, info) +AHSecretCBCPad *handler; +struct B_AlgorithmInfoType *infoType; +POINTER info; +{ + if (handler == (AHSecretCBCPad *)NULL_PTR) { + /* This constructor is being used to do a new */ + if ((handler = (AHSecretCBCPad *)T_malloc (sizeof (*handler))) + == (AHSecretCBCPad *)NULL_PTR) + return (handler); + } + + /* Construct base class with the infoType and info. */ + AHChooseEncryptConstructor2 + (&handler->chooseEncryptDecrypt, infoType, info); + + handler->chooseEncryptDecrypt.encryptDecrypt.vTable = &V_TABLE; + return (handler); +} + +int AHSecretCBCPadEncryptInit (handler, key, chooser, surrenderContext) +AHSecretCBCPad *handler; +B_Key *key; +B_ALGORITHM_CHOOSER chooser; +A_SURRENDER_CTX *surrenderContext; +{ + /* For encryption, we need to track the input length */ + handler->_inputRemainder = 0; + + return (AHChooseEncryptEncryptInit + (handler, key, chooser, surrenderContext)); +} + +int AHSecretCBCPadEncryptUpdate + (handler, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + randomAlgorithm, surrenderContext) +AHSecretCBCPad *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +const unsigned char *partIn; +unsigned int partInLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + /* For encryption, we need to track the input length */ + handler->_inputRemainder = (handler->_inputRemainder + partInLen) % 8; + + return (AHChooseEncryptEncryptUpdate + (handler, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + randomAlgorithm, surrenderContext)); +} + +int AHSecretCBCPadEncryptFinal + (handler, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +AHSecretCBCPad *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned char finalBuffer[8]; + unsigned int padLen, dummyPartOutLen; + + padLen = 8 - handler->_inputRemainder; + T_memset ((POINTER)finalBuffer, padLen, padLen); + + /* Add the pad bytes. This should force the output of the final block. + */ + if ((status = AHChooseEncryptEncryptUpdate + (handler, partOut, partOutLen, maxPartOutLen, finalBuffer, padLen, + randomAlgorithm, surrenderContext)) != 0) + return (status); + + /* The encrypt final operation should have no output. */ + if ((status = AHChooseEncryptEncryptFinal + (handler, (unsigned char *)NULL_PTR, &dummyPartOutLen, 0, + (B_Algorithm *)NULL_PTR, (A_SURRENDER_CTX *)NULL_PTR)) != 0) + return (status); + + /* Restart the context. */ + handler->_inputRemainder = 0; + + /* No need to zeroize the finalBuffer since it only contains pad bytes. */ + return (0); +} + +int AHSecretCBCPadDecryptFinal + (handler, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +AHSecretCBCPad *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned char finalBuffer[16], *padBuffer; + unsigned int padLen, localPartOutLen, i; + + do { + /* For now, the DecrypyFinal operations is set to output 16 bytes. + */ + if ((status = AHChooseEncryptDecryptFinal + (handler, finalBuffer, &localPartOutLen, sizeof (finalBuffer), + randomAlgorithm, surrenderContext)) != 0) + break; + + if (localPartOutLen == 8) + padBuffer = finalBuffer; + else if (localPartOutLen == 16) + padBuffer = finalBuffer + 8; + else + GENERATE_BREAK (BE_INPUT_LEN); + + /* Check that padding is one 1 to eight 8's. + */ + if ((padLen = (unsigned int)padBuffer[7]) == 0 || padLen > 8) + GENERATE_BREAK (BE_INPUT_DATA); + for (i = 8 - padLen; i < 8; i++) { + if ((unsigned int)padBuffer[i] != padLen) + GENERATE_BREAK (BE_INPUT_DATA); + } + + if ((*partOutLen = localPartOutLen - padLen) > maxPartOutLen) + GENERATE_BREAK (BE_OUTPUT_LEN); + + T_memcpy + ((POINTER)partOut, (POINTER)finalBuffer, *partOutLen); + } while (0); + + T_memset ((POINTER)finalBuffer, 0, sizeof (finalBuffer)); + return (status); +} + diff --git a/lib/bind/dnssafe/ahcbcpad.h b/lib/bind/dnssafe/ahcbcpad.h new file mode 100644 index 0000000000..70c300b7ec --- /dev/null +++ b/lib/bind/dnssafe/ahcbcpad.h @@ -0,0 +1,37 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHCBCPAD_H_ +#define _AHCBCPAD_H_ + +#include "ahchencr.h" + +typedef struct AHSecretCBCPad { + AHChooseEncryptDecrypt chooseEncryptDecrypt; /* base class */ + + unsigned int _inputRemainder; /* Used for encrypt to compute pad length */ +} AHSecretCBCPad; + +AHSecretCBCPad *AHSecretCBCPadConstructor2 PROTO_LIST + ((AHSecretCBCPad *, struct B_AlgorithmInfoType *, POINTER)); + +int AHSecretCBCPadEncryptInit PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, B_Key *, B_ALGORITHM_CHOOSER, + A_SURRENDER_CTX *)); +int AHSecretCBCPadEncryptUpdate PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, const unsigned char *, unsigned int, B_Algorithm *, + A_SURRENDER_CTX *)); +int AHSecretCBCPadEncryptFinal PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); +int AHSecretCBCPadDecryptFinal PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); + +#endif diff --git a/lib/bind/dnssafe/ahchdig.c b/lib/bind/dnssafe/ahchdig.c new file mode 100644 index 0000000000..43e15306ce --- /dev/null +++ b/lib/bind/dnssafe/ahchdig.c @@ -0,0 +1,132 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +/* Define this so that the type of the 'this' pointer in the + virtual functions will be correct for this derived class. + */ +struct AHChooseDigest; +#define THIS_DIGEST struct AHChooseDigest + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "balgmeth.h" +#include "ahchdig.h" +#include "amdigest.h" +#include "port_after.h" + +static int InitDigestAlga PROTO_LIST + ((AlgaChoice *, POINTER, B_ALGORITHM_METHOD *, A_SURRENDER_CTX *)); + +static AHDigestVTable V_TABLE = { + AHChooseDigestDestructor, AHChooseDigestInit, AHChooseDigestUpdate, + AHChooseDigestFinal +}; + +AHChooseDigest *AHChooseDigestConstructor2 (handler, infoType, info) +AHChooseDigest *handler; +struct B_AlgorithmInfoType *infoType; +POINTER info; +{ + if (handler == (AHChooseDigest *)NULL_PTR) { + /* This constructor is being used to do a new */ + if ((handler = (AHChooseDigest *)T_malloc (sizeof (*handler))) + == (AHChooseDigest *)NULL_PTR) + return (handler); + } + + /* Construct base class */ + AHDigestConstructor (&handler->digest); + + ALGA_CHOICE_Constructor (&handler->algaChoice, InitDigestAlga); + handler->algaChoice._algorithmInfoType = infoType; + handler->algaChoice._algorithmInfo = info; + + handler->digest.vTable = &V_TABLE; + + return (handler); +} + +void AHChooseDigestDestructor (handler) +AHChooseDigest *handler; +{ + ALGA_CHOICE_Destructor (&handler->algaChoice); + /* There is no desructor to call for the base class. */ +} + +int AHChooseDigestInit (handler, key, chooser, surrenderContext) +AHChooseDigest *handler; +B_Key *key; +B_ALGORITHM_CHOOSER chooser; +A_SURRENDER_CTX *surrenderContext; +{ + return (AlgaChoiceChoose + (&handler->algaChoice, 0, key, chooser, surrenderContext)); +} + +int AHChooseDigestUpdate (handler, partIn, partInLen, surrenderContext) +AHChooseDigest *handler; +const unsigned char *partIn; +unsigned int partInLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = (*((A_DIGEST_ALGA *)handler->algaChoice._alga)->Update) + (handler->algaChoice.context.z.context, partIn, partInLen, + surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + +int AHChooseDigestFinal + (handler, partOut, partOutLen, maxPartOutLen, surrenderContext) +AHChooseDigest *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = (*((A_DIGEST_ALGA *)handler->algaChoice._alga)->Final) + (handler->algaChoice.context.z.context, partOut, partOutLen, + maxPartOutLen, surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + +static int InitDigestAlga + (algaChoice, keyInfo, algorithmMethod, surrenderContext) +AlgaChoice *algaChoice; +POINTER keyInfo; +B_ALGORITHM_METHOD *algorithmMethod; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned int contextSize; + +UNUSED_ARG (keyInfo) + if ((status = (*((A_DIGEST_ALGA *)algorithmMethod->alga)->Query) + (&contextSize, algaChoice->_algorithmInfo)) != 0) + return (ConvertAlgaeError (status)); + + if ((status = ResizeContextMakeNewContext + (&algaChoice->context, contextSize)) != 0) + return (status); + + if ((status = (*((A_DIGEST_ALGA *)algorithmMethod->alga)->Init) + (algaChoice->context.z.context, algaChoice->_algorithmInfo, + surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + + return (0); +} diff --git a/lib/bind/dnssafe/ahchdig.h b/lib/bind/dnssafe/ahchdig.h new file mode 100644 index 0000000000..627422b5f8 --- /dev/null +++ b/lib/bind/dnssafe/ahchdig.h @@ -0,0 +1,32 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHCHDIG_H_ +#define _AHCHDIG_H_ 1 + +#include "ahdigest.h" +#include "algchoic.h" + +typedef struct AHChooseDigest { + AHDigest digest; /* base class */ + AlgaChoice algaChoice; +} AHChooseDigest; + +AHChooseDigest *AHChooseDigestConstructor2 PROTO_LIST + ((AHChooseDigest *, struct B_AlgorithmInfoType *, POINTER)); +void AHChooseDigestDestructor PROTO_LIST ((THIS_DIGEST *)); + +int AHChooseDigestInit PROTO_LIST + ((THIS_DIGEST *, B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int AHChooseDigestUpdate PROTO_LIST + ((THIS_DIGEST *, const unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int AHChooseDigestFinal PROTO_LIST + ((THIS_DIGEST *, unsigned char *, unsigned int *, unsigned int, + A_SURRENDER_CTX *)); + +#endif diff --git a/lib/bind/dnssafe/ahchencr.c b/lib/bind/dnssafe/ahchencr.c new file mode 100644 index 0000000000..af839ff456 --- /dev/null +++ b/lib/bind/dnssafe/ahchencr.c @@ -0,0 +1,268 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +/* Define this so that the type of the 'this' pointer in the + virtual functions will be correct for this derived class. + */ +struct AHChooseEncryptDecrypt; +#define THIS_ENCRYPT_DECRYPT struct AHChooseEncryptDecrypt + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "balgmeth.h" +#include "ahchencr.h" +#include "amencdec.h" +#include "port_after.h" + +static int InitEncryptDecryptAlga PROTO_LIST + ((AlgaChoice *, POINTER, B_ALGORITHM_METHOD *, A_SURRENDER_CTX *)); + +static AHEncryptDecryptVTable V_TABLE = { + AHChooseEncryptDestructor, AHChooseEncryptGetBlockLen, + AHChooseEncryptEncryptInit, AHChooseEncryptDecryptInit, + AHChooseEncryptEncryptUpdate, AHChooseEncryptDecryptUpdate, + AHChooseEncryptEncryptFinal, AHChooseEncryptDecryptFinal +}; + +/* In C++: +AHChooseEncryptDecrypt::AHChooseEncryptDecrypt + (B_AlgorithmInfoType *infoType, POINTER info) + : algaChoice (InitEncryptDecryptAlga) +{ + algaChoice.setAlgorithmInfoType (infoType); + algaChoice.setAlgorithmInfo (info); +} + */ +AHChooseEncryptDecrypt *AHChooseEncryptConstructor2 (handler, infoType, info) +AHChooseEncryptDecrypt *handler; +struct B_AlgorithmInfoType *infoType; +POINTER info; +{ + if (handler == (AHChooseEncryptDecrypt *)NULL_PTR) { + /* This constructor is being used to do a new */ + if ((handler = (AHChooseEncryptDecrypt *)T_malloc (sizeof (*handler))) + == (AHChooseEncryptDecrypt *)NULL_PTR) + return (handler); + } + + /* Construct base class */ + AHEncryptDecryptConstructor (&handler->encryptDecrypt); + + ALGA_CHOICE_Constructor (&handler->algaChoice, InitEncryptDecryptAlga); + handler->algaChoice._algorithmInfoType = infoType; + handler->algaChoice._algorithmInfo = info; + + handler->encryptDecrypt.vTable = &V_TABLE; + + return (handler); +} + +void AHChooseEncryptDestructor (handler) +AHChooseEncryptDecrypt *handler; +{ + ALGA_CHOICE_Destructor (&handler->algaChoice); + /* There is no desructor to call for the base class. */ +} + +int AHChooseEncryptGetBlockLen (handler, blockLen) +AHChooseEncryptDecrypt *handler; +unsigned int *blockLen; +{ + int status; + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)handler->algaChoice._alga)-> + GetBlockLen) + (handler->algaChoice.context.z.context, blockLen)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + +/* In C++: +int AHChooseEncryptDecrypt::encryptInit + (B_Key *key, B_ALGORITHM_CHOOSER chooser, A_SURRENDER_CTX *surrenderContext) +{ + return (algaChoice.choose (1, key, chooser, surrenderContext)); +} + */ +int AHChooseEncryptEncryptInit (handler, key, chooser, surrenderContext) +AHChooseEncryptDecrypt *handler; +B_Key *key; +B_ALGORITHM_CHOOSER chooser; +A_SURRENDER_CTX *surrenderContext; +{ + return (AlgaChoiceChoose + (&handler->algaChoice, 1, key, chooser, surrenderContext)); +} + +int AHChooseEncryptDecryptInit (handler, key, chooser, surrenderContext) +AHChooseEncryptDecrypt *handler; +B_Key *key; +B_ALGORITHM_CHOOSER chooser; +A_SURRENDER_CTX *surrenderContext; +{ + return (AlgaChoiceChoose + (&handler->algaChoice, 0, key, chooser, surrenderContext)); +} + +/* In C++: +int AHChooseEncryptDecrypt::encryptUpdate + (unsigned char *partOut, unsigned int *partOutLen, + unsigned int maxPartOutLen, unsigned char *partIn, unsigned int partInLen, + B_Algorithm *randomAlgorithm, A_SURRENDER_CTX *surrenderContext) +{ + int status; + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)algaChoice.alga ()) ->Update) + (algaChoice.context (), partOut, partOutLen, maxPartOutLen, + partIn, partInLen, surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + */ +int AHChooseEncryptEncryptUpdate + (handler, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + randomAlgorithm, surrenderContext) +AHChooseEncryptDecrypt *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +const unsigned char *partIn; +unsigned int partInLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + +UNUSED_ARG (randomAlgorithm) + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)handler->algaChoice._alga)-> + Update) + (handler->algaChoice.context.z.context, partOut, partOutLen, + maxPartOutLen, partIn, partInLen, surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + +int AHChooseEncryptDecryptUpdate + (handler, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + randomAlgorithm, surrenderContext) +AHChooseEncryptDecrypt *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +const unsigned char *partIn; +unsigned int partInLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + +UNUSED_ARG (randomAlgorithm) + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)handler->algaChoice._alga)-> + Update) + (handler->algaChoice.context.z.context, partOut, partOutLen, + maxPartOutLen, partIn, partInLen, surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + +int AHChooseEncryptEncryptFinal + (handler, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +AHChooseEncryptDecrypt *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + +UNUSED_ARG (randomAlgorithm) + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)handler->algaChoice._alga)->Final) + (handler->algaChoice.context.z.context, partOut, partOutLen, + maxPartOutLen, surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + +int AHChooseEncryptDecryptFinal + (handler, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +AHChooseEncryptDecrypt *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + +UNUSED_ARG (randomAlgorithm) + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)handler->algaChoice._alga)->Final) + (handler->algaChoice.context.z.context, partOut, partOutLen, + maxPartOutLen, surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + +/* In C++: +static int InitEncryptDecryptAlga + (AlgaChoice *algaChoice, POINTER keyInfo, POINTER alga, + A_SURRENDER_CTX *surrenderContext) +{ + int status; + unsigned int contextSize; + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)alga)->Query) + (&contextSize, keyInfo, algaChoice->algorithmInfo ())) != 0) + return (ConvertAlgaeError (status)); + + if ((status = algaChoice->makeNewContext (contextSize)) != 0) + return (status); + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)alga)->Init) + (algaChoice->context (), keyInfo, algaChoice->algorithmInfo (), + surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + + return (0); +} + */ +static int InitEncryptDecryptAlga + (algaChoice, keyInfo, algorithmMethod, surrenderContext) +AlgaChoice *algaChoice; +POINTER keyInfo; +B_ALGORITHM_METHOD *algorithmMethod; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned int contextSize; + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)algorithmMethod->alga)->Query) + (&contextSize, keyInfo, algaChoice->_algorithmInfo)) != 0) + return (ConvertAlgaeError (status)); + + if ((status = ResizeContextMakeNewContext + (&algaChoice->context, contextSize)) != 0) + return (status); + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)algorithmMethod->alga)->Init) + (algaChoice->context.z.context, keyInfo, algaChoice->_algorithmInfo, + surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + + return (0); +} diff --git a/lib/bind/dnssafe/ahchencr.h b/lib/bind/dnssafe/ahchencr.h new file mode 100644 index 0000000000..9672e3fbbb --- /dev/null +++ b/lib/bind/dnssafe/ahchencr.h @@ -0,0 +1,74 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHCHENCR_H_ +#define _AHCHENCR_H_ 1 + +#include "ahencryp.h" +#include "algchoic.h" + +/* In C++: +class AHChooseEncryptDecrypt : public AHEncryptDecrypt { +public: + AHChooseEncryptDecrypt (B_AlgorithmInfoType *, POINTER); + virtual ~AHChooseEncryptDecrypt () {}; + + virtual int getBlockLen (unsigned int *); + virtual int encryptInit (B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *); + virtual int decryptInit (B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *); + virtual int encryptUpdate + (unsigned char *, unsigned int *, unsigned int, unsigned char *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *); + virtual int decryptUpdate + (unsigned char *, unsigned int *, unsigned int, unsigned char *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *); + virtual int encryptFinal + (unsigned char *, unsigned int *, unsigned int, B_Algorithm *, + A_SURRENDER_CTX *); + virtual int decryptFinal + (unsigned char *, unsigned int *, unsigned int, B_Algorithm *, + A_SURRENDER_CTX *); + +private: + AlgaChoice algaChoice; +}; + */ + +typedef struct AHChooseEncryptDecrypt { + AHEncryptDecrypt encryptDecrypt; /* base class */ + AlgaChoice algaChoice; +} AHChooseEncryptDecrypt; + +AHChooseEncryptDecrypt *AHChooseEncryptConstructor2 PROTO_LIST + ((AHChooseEncryptDecrypt *, struct B_AlgorithmInfoType *, POINTER)); +void AHChooseEncryptDestructor PROTO_LIST ((THIS_ENCRYPT_DECRYPT *)); + +int AHChooseEncryptGetBlockLen PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned int *)); +int AHChooseEncryptEncryptInit PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, B_Key *, B_ALGORITHM_CHOOSER, + A_SURRENDER_CTX *)); +int AHChooseEncryptDecryptInit PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, B_Key *, B_ALGORITHM_CHOOSER, + A_SURRENDER_CTX *)); +int AHChooseEncryptEncryptUpdate PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, const unsigned char *, unsigned int, B_Algorithm *, + A_SURRENDER_CTX *)); +int AHChooseEncryptDecryptUpdate PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, const unsigned char *, unsigned int, B_Algorithm *, + A_SURRENDER_CTX *)); +int AHChooseEncryptEncryptFinal PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); +int AHChooseEncryptDecryptFinal PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); + +#endif diff --git a/lib/bind/dnssafe/ahchgen.c b/lib/bind/dnssafe/ahchgen.c new file mode 100644 index 0000000000..a524a4bff7 --- /dev/null +++ b/lib/bind/dnssafe/ahchgen.c @@ -0,0 +1,218 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +/* Define this so that the type of the 'this' pointer in the + virtual functions will be correct for this derived class. + */ +struct AHChooseGenerate; +#define THIS_GENERATE struct AHChooseGenerate + +/* Define this so that the type of the AlgaChoice pointer in the + INIT_ALGA functions will be correct for this derived class. + */ +struct GenerateAlgaChoice; +#define THIS_ALGA_CHOICE struct GenerateAlgaChoice + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "balgmeth.h" +#include "ahchgen.h" +#include "amgen.h" +#include "port_after.h" + +static int InitGenerateAlga PROTO_LIST + ((GenerateAlgaChoice *, POINTER, B_ALGORITHM_METHOD *, A_SURRENDER_CTX *)); +static int GenerateResult PROTO_LIST + ((GenerateAlgaChoice *, POINTER *, B_Algorithm *, A_SURRENDER_CTX *)); + +static AHGenerateVTable V_TABLE = { + AHChooseGenerateDestructor, AHChooseGenerateInit, AHChooseGenerateKeypair, + AHChooseGenerateParameters +}; + +AHChooseGenerate *AHChooseGenerateConstructor2 (handler, infoType, info) +AHChooseGenerate *handler; +struct B_AlgorithmInfoType *infoType; +POINTER info; +{ + if (handler == (AHChooseGenerate *)NULL_PTR) { + /* This constructor is being used to do a new */ + if ((handler = (AHChooseGenerate *)T_malloc (sizeof (*handler))) + == (AHChooseGenerate *)NULL_PTR) + return (handler); + } + + /* Construct base class */ + AHGenerateConstructor (&handler->generate); + + ALGA_CHOICE_Constructor + (&handler->generateAlgaChoice.algaChoice, InitGenerateAlga); + ResizeContextConstructor (&handler->generateAlgaChoice.secondContext); + ResizeContextConstructor (&handler->generateAlgaChoice.randomBlock); + + /* Set algaChoice. + */ + handler->generateAlgaChoice.algaChoice._algorithmInfoType = infoType; + handler->generateAlgaChoice.algaChoice._algorithmInfo = info; + + handler->generate.vTable = &V_TABLE; + + return (handler); +} + +void AHChooseGenerateDestructor (handler) +AHChooseGenerate *handler; +{ + ResizeContextDestructor (&handler->generateAlgaChoice.secondContext); + ResizeContextDestructor (&handler->generateAlgaChoice.randomBlock); + ALGA_CHOICE_Destructor (&handler->generateAlgaChoice.algaChoice); + /* There is no desructor to call for the base class. */ +} + +int AHChooseGenerateInit (handler, chooser, surrenderContext) +AHChooseGenerate *handler; +B_ALGORITHM_CHOOSER chooser; +A_SURRENDER_CTX *surrenderContext; +{ + return (AlgaChoiceChoose + (&handler->generateAlgaChoice.algaChoice, 0, (B_Key *)NULL_PTR, + chooser, surrenderContext)); +} + +int AHChooseGenerateKeypair + (handler, publicKey, privateKey, randomAlgorithm, surrenderContext) +AHChooseGenerate *handler; +B_Key *publicKey; +B_Key *privateKey; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + POINTER result; + int status; + + if ((status = GenerateResult + (&handler->generateAlgaChoice, &result, randomAlgorithm, + surrenderContext)) != 0) + return (status); + if ((status = B_KeySetInfo + (publicKey, handler->generateAlgaChoice._resultInfoType, result)) != 0) + return (status); + return (B_KeySetInfo + (privateKey, handler->generateAlgaChoice._resultInfoType, result)); +} + +int AHChooseGenerateParameters + (handler, resultAlgorithm, randomAlgorithm, surrenderContext) +AHChooseGenerate *handler; +B_Algorithm *resultAlgorithm; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + POINTER result; + int status; + + if ((status = GenerateResult + (&handler->generateAlgaChoice, &result, randomAlgorithm, + surrenderContext)) != 0) + return (status); + + /* Force the resultInfoType into a B_AlgorithmInfoType since it is + supplied in the chooser as a B_KeyInfoType. */ + return (B_AlgorithmSetInfo + (resultAlgorithm, (struct B_AlgorithmInfoType *) + handler->generateAlgaChoice._resultInfoType, result)); +} + +static int InitGenerateAlga + (generateAlgaChoice, keyInfo, algorithmMethod, surrenderContext) +GenerateAlgaChoice *generateAlgaChoice; +POINTER keyInfo; +B_ALGORITHM_METHOD *algorithmMethod; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned int contextSize, secondContextSize; + +UNUSED_ARG (keyInfo) + /* Note that this also gets the resultInfoType which will be used later + by GenerateResult. */ + if ((status = (*((A_GENERATE_ALGA *)algorithmMethod->alga)->Query) + (&contextSize, &secondContextSize, &generateAlgaChoice->_randomBlockLen, + &generateAlgaChoice->_resultInfoType, + generateAlgaChoice->algaChoice._algorithmInfo)) != 0) + return (ConvertAlgaeError (status)); + + /* Create the context. + */ + if ((status = ResizeContextMakeNewContext + (&generateAlgaChoice->algaChoice.context, contextSize)) != 0) + return (status); + + /* Create the second context which is only passed during Init, but + must persist for all operations. */ + if ((status = ResizeContextMakeNewContext + (&generateAlgaChoice->secondContext, secondContextSize)) != 0) + return (status); + + /* Create randomBlock which will be filled in during GenerateResult. */ + if ((status = ResizeContextMakeNewContext + (&generateAlgaChoice->randomBlock, generateAlgaChoice->_randomBlockLen)) + != 0) + return (status); + + if ((status = (*((A_GENERATE_ALGA *)algorithmMethod->alga)->Init) + (generateAlgaChoice->algaChoice.context.z.context, + generateAlgaChoice->secondContext.z.context, + generateAlgaChoice->algaChoice._algorithmInfo, surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + + return (0); +} + +/* Call the generate procedure repeatedly with a new random block + until it succeeds. + */ +static int GenerateResult + (generateAlgaChoice, result, randomAlgorithm, surrenderContext) +GenerateAlgaChoice *generateAlgaChoice; +POINTER *result; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + /* Fill in the random block and try generating as long as the + the generate operation returns BE_NEED_RANDOM. + */ + while (1) { + if ((status = B_AlgorithmGenerateRandomBytes + (randomAlgorithm, + (unsigned char *)generateAlgaChoice->randomBlock.z.context, + generateAlgaChoice->_randomBlockLen, surrenderContext)) != 0) + return (status); + + if ((status = (*((A_GENERATE_ALGA *) + generateAlgaChoice->algaChoice._alga)->Generate) + (generateAlgaChoice->algaChoice.context.z.context, result, + (unsigned char *)generateAlgaChoice->randomBlock.z.context, + surrenderContext)) != 0) { + if (status != AE_NEED_RANDOM) + return (ConvertAlgaeError (status)); + + /* Else continue and try again */ + } + else + /* Success, so return */ + return (0); + } +} + diff --git a/lib/bind/dnssafe/ahchgen.h b/lib/bind/dnssafe/ahchgen.h new file mode 100644 index 0000000000..8e7ecf3dc4 --- /dev/null +++ b/lib/bind/dnssafe/ahchgen.h @@ -0,0 +1,44 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHCHGEN_H_ +#define _AHCHGEN_H_ 1 + +#include "ahgen.h" +#include "algchoic.h" + +/* Make a new class derived from an AlgaChoice which records the + result algorithm info type and needed randomBlockLen. + */ +typedef struct GenerateAlgaChoice { + AlgaChoice algaChoice; /* base class */ + + struct B_KeyInfoType *_resultInfoType; + ResizeContext secondContext; /* used for scratch */ + ResizeContext randomBlock; + unsigned int _randomBlockLen; +} GenerateAlgaChoice; + +typedef struct AHChooseGenerate { + AHGenerate generate; /* base class */ + + GenerateAlgaChoice generateAlgaChoice; +} AHChooseGenerate; + +AHChooseGenerate *AHChooseGenerateConstructor2 PROTO_LIST + ((AHChooseGenerate *, struct B_AlgorithmInfoType *, POINTER)); +void AHChooseGenerateDestructor PROTO_LIST ((THIS_GENERATE *)); + +int AHChooseGenerateInit PROTO_LIST + ((THIS_GENERATE *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int AHChooseGenerateKeypair PROTO_LIST + ((THIS_GENERATE *, B_Key *, B_Key *, B_Algorithm *, A_SURRENDER_CTX *)); +int AHChooseGenerateParameters PROTO_LIST + ((THIS_GENERATE *, B_Algorithm *, B_Algorithm *, A_SURRENDER_CTX *)); + +#endif diff --git a/lib/bind/dnssafe/ahchrand.c b/lib/bind/dnssafe/ahchrand.c new file mode 100644 index 0000000000..579a7b237b --- /dev/null +++ b/lib/bind/dnssafe/ahchrand.c @@ -0,0 +1,130 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +/* Define this so that the type of the 'this' pointer in the + virtual functions will be correct for this derived class. + */ +struct AHChooseRandom; +#define THIS_RANDOM struct AHChooseRandom + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "balgmeth.h" +#include "ahchrand.h" +#include "amrandom.h" +#include "port_after.h" + +static int InitRandomAlga PROTO_LIST + ((AlgaChoice *, POINTER, B_ALGORITHM_METHOD *, A_SURRENDER_CTX *)); + +static AHRandomVTable V_TABLE = { + AHChooseRandomDestructor, AHChooseRandomInit, AHChooseRandomUpdate, + AHChooseRandomGenerateBytes +}; + +AHChooseRandom *AHChooseRandomConstructor2 (handler, infoType, info) +AHChooseRandom *handler; +struct B_AlgorithmInfoType *infoType; +POINTER info; +{ + if (handler == (AHChooseRandom *)NULL_PTR) { + /* This constructor is being used to do a new */ + if ((handler = (AHChooseRandom *)T_malloc (sizeof (*handler))) + == (AHChooseRandom *)NULL_PTR) + return (handler); + } + + /* Construct base class */ + AHRandomConstructor (&handler->random); + + ALGA_CHOICE_Constructor (&handler->algaChoice, InitRandomAlga); + handler->algaChoice._algorithmInfoType = infoType; + handler->algaChoice._algorithmInfo = info; + + handler->random.vTable = &V_TABLE; + + return (handler); +} + +void AHChooseRandomDestructor (handler) +AHChooseRandom *handler; +{ + ALGA_CHOICE_Destructor (&handler->algaChoice); + /* There is no desructor to call for the base class. */ +} + +int AHChooseRandomInit (handler, chooser, surrenderContext) +AHChooseRandom *handler; +B_ALGORITHM_CHOOSER chooser; +A_SURRENDER_CTX *surrenderContext; +{ + return (AlgaChoiceChoose + (&handler->algaChoice, 0, (B_Key *)NULL_PTR, chooser, + surrenderContext)); +} + +int AHChooseRandomUpdate (handler, input, inputLen, surrenderContext) +AHChooseRandom *handler; +unsigned char *input; +unsigned int inputLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = (*((A_RANDOM_ALGA *)handler->algaChoice._alga)->Update) + (handler->algaChoice.context.z.context, input, inputLen, + surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + +int AHChooseRandomGenerateBytes (handler, output, outputLen, surrenderContext) +AHChooseRandom *handler; +unsigned char *output; +unsigned int outputLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = (*((A_RANDOM_ALGA *)handler->algaChoice._alga)->Generate) + (handler->algaChoice.context.z.context, output, outputLen, + surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + +static int InitRandomAlga + (algaChoice, keyInfo, algorithmMethod, surrenderContext) +AlgaChoice *algaChoice; +POINTER keyInfo; +B_ALGORITHM_METHOD *algorithmMethod; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned int contextSize; + +UNUSED_ARG (keyInfo) + if ((status = (*((A_RANDOM_ALGA *)algorithmMethod->alga)->Query) + (&contextSize, algaChoice->_algorithmInfo)) != 0) + return (ConvertAlgaeError (status)); + + if ((status = ResizeContextMakeNewContext + (&algaChoice->context, contextSize)) != 0) + return (status); + + if ((status = (*((A_RANDOM_ALGA *)algorithmMethod->alga)->Init) + (algaChoice->context.z.context, algaChoice->_algorithmInfo, + surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + + return (0); +} diff --git a/lib/bind/dnssafe/ahchrand.h b/lib/bind/dnssafe/ahchrand.h new file mode 100644 index 0000000000..51e0f9847d --- /dev/null +++ b/lib/bind/dnssafe/ahchrand.h @@ -0,0 +1,31 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHCHRAND_H_ +#define _AHCHRAND_H_ 1 + +#include "ahrandom.h" +#include "algchoic.h" + +typedef struct AHChooseRandom { + AHRandom random; /* base class */ + AlgaChoice algaChoice; +} AHChooseRandom; + +AHChooseRandom *AHChooseRandomConstructor2 PROTO_LIST + ((AHChooseRandom *, struct B_AlgorithmInfoType *, POINTER)); +void AHChooseRandomDestructor PROTO_LIST ((THIS_RANDOM *)); + +int AHChooseRandomInit PROTO_LIST + ((THIS_RANDOM *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int AHChooseRandomUpdate PROTO_LIST + ((THIS_RANDOM *, unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int AHChooseRandomGenerateBytes PROTO_LIST + ((THIS_RANDOM *, unsigned char *, unsigned int, A_SURRENDER_CTX *)); + +#endif diff --git a/lib/bind/dnssafe/ahdigest.c b/lib/bind/dnssafe/ahdigest.c new file mode 100644 index 0000000000..c7411632b5 --- /dev/null +++ b/lib/bind/dnssafe/ahdigest.c @@ -0,0 +1,93 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahdigest.h" +#include "port_after.h" + +static void TypedAHDigestDestructor PROTO_LIST ((B_TypeCheck *)); + +void AHDigestConstructor (handler) +AHDigest *handler; +{ + /* Construct base class, setting type tag. */ + B_TYPE_CHECK_Constructor + (&handler->typeCheck, TypedAHDigestDestructor); + + /* Don't set vTable since this is a pure virtual base class. */ +} + +int B_AlgorithmDigestInit + (algorithm, key, algorithmChooser, surrenderContext) +B_Algorithm *algorithm; +B_Key *key; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckType + (algorithm, TypedAHDigestDestructor)) != 0) + return (status); + + if ((status = + (*((AHDigest *)algorithm->z.handler)->vTable->DigestInit) + ((AHDigest *)algorithm->z.handler, key, algorithmChooser, + surrenderContext)) != 0) + return (status); + + algorithm->z.initFlag = 1; + return (0); +} + +int B_AlgorithmDigestUpdate (algorithm, partIn, partInLen, surrenderContext) +B_Algorithm *algorithm; +const unsigned char *partIn; +unsigned int partInLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHDigestDestructor)) != 0) + return (status); + + return ((*((AHDigest *)algorithm->z.handler)->vTable->DigestUpdate) + ((AHDigest *)algorithm->z.handler, partIn, partInLen, + surrenderContext)); +} + +int B_AlgorithmDigestFinal + (algorithm, partOut, partOutLen, maxPartOutLen, surrenderContext) +B_Algorithm *algorithm; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHDigestDestructor)) != 0) + return (status); + + return ((*((AHDigest *)algorithm->z.handler)->vTable->DigestFinal) + ((AHDigest *)algorithm->z.handler, partOut, partOutLen, + maxPartOutLen, surrenderContext)); +} + +static void TypedAHDigestDestructor (typeCheck) +B_TypeCheck *typeCheck; +{ + (*((AHDigest *)typeCheck)->vTable->Destructor) ((AHDigest *)typeCheck); +} + diff --git a/lib/bind/dnssafe/ahdigest.h b/lib/bind/dnssafe/ahdigest.h new file mode 100644 index 0000000000..fe0299a7c4 --- /dev/null +++ b/lib/bind/dnssafe/ahdigest.h @@ -0,0 +1,48 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHDIGEST_H_ +#define _AHDIGEST_H_ 1 + +#include "btypechk.h" + +/* Use the THIS_DIGEST macro to define the type of object in the + virtual function prototype. It defaults to the most base class, but + derived modules may define the macro to a more derived class before + including this header file. + */ +#ifndef THIS_DIGEST +#define THIS_DIGEST struct AHDigest +#endif + +struct AHDigest; + +typedef struct { + void (*Destructor) PROTO_LIST ((THIS_DIGEST *)); + int (*DigestInit) PROTO_LIST + ((THIS_DIGEST *, B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); + int (*DigestUpdate) PROTO_LIST + ((THIS_DIGEST *, const unsigned char *, unsigned int, A_SURRENDER_CTX *)); + int (*DigestFinal) PROTO_LIST + ((THIS_DIGEST *, unsigned char *, unsigned int *, unsigned int, + A_SURRENDER_CTX *)); +} AHDigestVTable; + +typedef struct AHDigest { + B_TypeCheck typeCheck; /* inherited */ + AHDigestVTable *vTable; /* pure virtual */ +} AHDigest; + +/* The constructor does not set the vTable since this is a pure base class. + */ +void AHDigestConstructor PROTO_LIST ((AHDigest *)); +/* No destructor because it is pure virtual. Also, do not call destructor + for B_TypeCheck, since this will just re-invoke this virtual + destructor. */ + +#endif diff --git a/lib/bind/dnssafe/ahencryp.c b/lib/bind/dnssafe/ahencryp.c new file mode 100644 index 0000000000..acb8014aad --- /dev/null +++ b/lib/bind/dnssafe/ahencryp.c @@ -0,0 +1,171 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahencryp.h" +#include "port_after.h" + +static void TypedAHEncryptDecryptDestructor PROTO_LIST ((B_TypeCheck *)); + +void AHEncryptDecryptConstructor (handler) +AHEncryptDecrypt *handler; +{ + /* Construct base class, setting type tag. */ + B_TYPE_CHECK_Constructor + (&handler->typeCheck, TypedAHEncryptDecryptDestructor); + + /* Don't set vTable since this is a pure virtual base class. */ +} + +int B_AlgorithmEncryptInit + (algorithm, key, algorithmChooser, surrenderContext) +B_Algorithm *algorithm; +B_Key *key; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckType + (algorithm, TypedAHEncryptDecryptDestructor)) != 0) + return (status); + + if ((status = + (*((AHEncryptDecrypt *)algorithm->z.handler)->vTable->EncryptInit) + ((AHEncryptDecrypt *)algorithm->z.handler, key, algorithmChooser, + surrenderContext)) != 0) + return (status); + + algorithm->z.initFlag = 1; + return (0); +} + +int B_AlgorithmDecryptInit + (algorithm, key, algorithmChooser, surrenderContext) +B_Algorithm *algorithm; +B_Key *key; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckType + (algorithm, TypedAHEncryptDecryptDestructor)) != 0) + return (status); + + if ((status = + (*((AHEncryptDecrypt *)algorithm->z.handler)->vTable->DecryptInit) + ((AHEncryptDecrypt *)algorithm->z.handler, key, algorithmChooser, + surrenderContext)) != 0) + return (status); + + algorithm->z.initFlag = 1; + return (0); +} + +int B_AlgorithmEncryptUpdate + (algorithm, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + randomAlgorithm, surrenderContext) +B_Algorithm *algorithm; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +unsigned char *partIn; +unsigned int partInLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHEncryptDecryptDestructor)) != 0) + return (status); + + return ((*((AHEncryptDecrypt *)algorithm->z.handler)->vTable->EncryptUpdate) + ((AHEncryptDecrypt *)algorithm->z.handler, partOut, partOutLen, + maxPartOutLen, partIn, partInLen, randomAlgorithm, + surrenderContext)); +} + +int B_AlgorithmDecryptUpdate + (algorithm, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + randomAlgorithm, surrenderContext) +B_Algorithm *algorithm; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +const unsigned char *partIn; +unsigned int partInLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHEncryptDecryptDestructor)) != 0) + return (status); + + return ((*((AHEncryptDecrypt *)algorithm->z.handler)->vTable->DecryptUpdate) + ((AHEncryptDecrypt *)algorithm->z.handler, partOut, partOutLen, + maxPartOutLen, partIn, partInLen, randomAlgorithm, + surrenderContext)); +} + +int B_AlgorithmEncryptFinal + (algorithm, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +B_Algorithm *algorithm; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHEncryptDecryptDestructor)) != 0) + return (status); + + return ((*((AHEncryptDecrypt *)algorithm->z.handler)->vTable->EncryptFinal) + ((AHEncryptDecrypt *)algorithm->z.handler, partOut, partOutLen, + maxPartOutLen, randomAlgorithm, surrenderContext)); +} + +int B_AlgorithmDecryptFinal + (algorithm, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +B_Algorithm *algorithm; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHEncryptDecryptDestructor)) != 0) + return (status); + + return ((*((AHEncryptDecrypt *)algorithm->z.handler)->vTable->DecryptFinal) + ((AHEncryptDecrypt *)algorithm->z.handler, partOut, partOutLen, + maxPartOutLen, randomAlgorithm, surrenderContext)); +} + +static void TypedAHEncryptDecryptDestructor (typeCheck) +B_TypeCheck *typeCheck; +{ + (*((AHEncryptDecrypt *)typeCheck)->vTable->Destructor) + ((AHEncryptDecrypt *)typeCheck); +} + diff --git a/lib/bind/dnssafe/ahencryp.h b/lib/bind/dnssafe/ahencryp.h new file mode 100644 index 0000000000..b02c514a5f --- /dev/null +++ b/lib/bind/dnssafe/ahencryp.h @@ -0,0 +1,85 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHENCRYP_H_ +#define _AHENCRYP_H_ 1 + +#include "btypechk.h" + +/* In C++: +class AHEncryptDecrypt : public B_TypeCheck { + AHEncryptDecrypt (); + virtual ~AHEncryptDecrypt () = 0; + + virtual int getBlockLen (unsigned int *) = 0; + virtual int encryptInit + (B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *) = 0; + virtual int decryptInit + (B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *) = 0; + virtual int encryptUpdate + (unsigned char *, unsigned int *, unsigned int, unsigned char *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *) = 0; + virtual int decryptUpdate + (unsigned char *, unsigned int *, unsigned int, unsigned char *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *) = 0; + virtual int encryptFinal + (unsigned char *, unsigned int *, unsigned int, B_Algorithm *, + A_SURRENDER_CTX *) = 0; + virtual int decryptFinal + (unsigned char *, unsigned int *, unsigned int, B_Algorithm *, + A_SURRENDER_CTX *) = 0; +}; + */ + +/* Use the THIS_ENCRYPT_DECRYPT macro to define the type of object in the + virtual function prototype. It defaults to the most base class, but + derived modules may define the macro to a more derived class before + including this header file. + */ +#ifndef THIS_ENCRYPT_DECRYPT +#define THIS_ENCRYPT_DECRYPT struct AHEncryptDecrypt +#endif + +struct AHEncryptDecrypt; + +typedef struct { + void (*Destructor) PROTO_LIST ((THIS_ENCRYPT_DECRYPT *)); + int (*GetBlockLen) PROTO_LIST ((THIS_ENCRYPT_DECRYPT *, unsigned int *)); + int (*EncryptInit) PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, B_Key *, B_ALGORITHM_CHOOSER, + A_SURRENDER_CTX *)); + int (*DecryptInit) PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, B_Key *, B_ALGORITHM_CHOOSER, + A_SURRENDER_CTX *)); + int (*EncryptUpdate) PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); + int (*DecryptUpdate) PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); + int (*EncryptFinal) PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, unsigned int, + B_Algorithm *, A_SURRENDER_CTX *)); + int (*DecryptFinal) PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, unsigned int, + B_Algorithm *, A_SURRENDER_CTX *)); +} AHEncryptDecryptVTable; + +typedef struct AHEncryptDecrypt { + B_TypeCheck typeCheck; /* inherited */ + AHEncryptDecryptVTable *vTable; /* pure virtual */ +} AHEncryptDecrypt; + +/* The constructor does not set the vTable since this is a pure base class. + */ +void AHEncryptDecryptConstructor PROTO_LIST ((AHEncryptDecrypt *)); +/* No destructor because it is pure virtual. Also, do not call destructor + for B_TypeCheck, since this will just re-invoke this virtual + destructor. */ + +#endif diff --git a/lib/bind/dnssafe/ahgen.c b/lib/bind/dnssafe/ahgen.c new file mode 100644 index 0000000000..518dc6926e --- /dev/null +++ b/lib/bind/dnssafe/ahgen.c @@ -0,0 +1,92 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahgen.h" +#include "port_after.h" + +static void TypedAHGenerateDestructor PROTO_LIST ((B_TypeCheck *)); + +void AHGenerateConstructor (handler) +AHGenerate *handler; +{ + /* Construct base class, setting type tag. */ + B_TYPE_CHECK_Constructor + (&handler->typeCheck, TypedAHGenerateDestructor); + + /* Don't set vTable since this is a pure virtual base class. */ +} + +int B_AlgorithmGenerateInit (algorithm, algorithmChooser, surrenderContext) +B_Algorithm *algorithm; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckType + (algorithm, TypedAHGenerateDestructor)) != 0) + return (status); + + if ((status = + (*((AHGenerate *)algorithm->z.handler)->vTable->GenerateInit) + ((AHGenerate *)algorithm->z.handler, algorithmChooser, + surrenderContext)) != 0) + return (status); + + algorithm->z.initFlag = 1; + return (0); +} + +int B_AlgorithmGenerateKeypair + (algorithm, publicKey, privateKey, randomAlgorithm, surrenderContext) +B_Algorithm *algorithm; +B_Key *publicKey; +B_Key *privateKey; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHGenerateDestructor)) != 0) + return (status); + + return ((*((AHGenerate *)algorithm->z.handler)->vTable->GenerateKeypair) + ((AHGenerate *)algorithm->z.handler, publicKey, privateKey, + randomAlgorithm, surrenderContext)); +} + +int B_AlgorithmGenerateParameters + (algorithm, resultAlgorithm, randomAlgorithm, surrenderContext) +B_Algorithm *algorithm; +B_Algorithm *resultAlgorithm; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHGenerateDestructor)) != 0) + return (status); + + return ((*((AHGenerate *)algorithm->z.handler)->vTable->GenerateParameters) + ((AHGenerate *)algorithm->z.handler, resultAlgorithm, + randomAlgorithm, surrenderContext)); +} + +static void TypedAHGenerateDestructor (typeCheck) +B_TypeCheck *typeCheck; +{ + (*((AHGenerate *)typeCheck)->vTable->Destructor) ((AHGenerate *)typeCheck); +} + diff --git a/lib/bind/dnssafe/ahgen.h b/lib/bind/dnssafe/ahgen.h new file mode 100644 index 0000000000..7240e2e1f2 --- /dev/null +++ b/lib/bind/dnssafe/ahgen.h @@ -0,0 +1,47 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHGEN_H_ +#define _AHGEN_H_ 1 + +#include "btypechk.h" + +/* Use the THIS_GENERATE macro to define the type of object in the + virtual function prototype. It defaults to the most base class, but + derived modules may define the macro to a more derived class before + including this header file. + */ +#ifndef THIS_GENERATE +#define THIS_GENERATE struct AHGenerate +#endif + +struct AHGenerate; + +typedef struct { + void (*Destructor) PROTO_LIST ((THIS_GENERATE *)); + int (*GenerateInit) PROTO_LIST + ((THIS_GENERATE *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); + int (*GenerateKeypair) PROTO_LIST + ((THIS_GENERATE *, B_Key *, B_Key *, B_Algorithm *, A_SURRENDER_CTX *)); + int (*GenerateParameters) PROTO_LIST + ((THIS_GENERATE *, B_Algorithm *, B_Algorithm *, A_SURRENDER_CTX *)); +} AHGenerateVTable; + +typedef struct AHGenerate { + B_TypeCheck typeCheck; /* inherited */ + AHGenerateVTable *vTable; /* pure virtual */ +} AHGenerate; + +/* The constructor does not set the vTable since this is a pure base class. + */ +void AHGenerateConstructor PROTO_LIST ((AHGenerate *)); +/* No destructor because it is pure virtual. Also, do not call destructor + for B_TypeCheck, since this will just re-invoke this virtual + destructor. */ + +#endif diff --git a/lib/bind/dnssafe/ahrandom.c b/lib/bind/dnssafe/ahrandom.c new file mode 100644 index 0000000000..304b14bc4c --- /dev/null +++ b/lib/bind/dnssafe/ahrandom.c @@ -0,0 +1,99 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahrandom.h" +#include "port_after.h" + +static void TypedAHRandomDestructor PROTO_LIST ((B_TypeCheck *)); + +void AHRandomConstructor (handler) +AHRandom *handler; +{ + /* Construct base class, setting type tag. */ + B_TYPE_CHECK_Constructor + (&handler->typeCheck, TypedAHRandomDestructor); + + /* Don't set vTable since this is a pure virtual base class. */ +} + +int B_AlgorithmRandomInit (algorithm, algorithmChooser, surrenderContext) +B_Algorithm *algorithm; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckType (algorithm, TypedAHRandomDestructor)) + != 0) + return (status); + + if ((status = + (*((AHRandom *)algorithm->z.handler)->vTable->RandomInit) + ((AHRandom *)algorithm->z.handler, algorithmChooser, surrenderContext)) + != 0) + return (status); + + algorithm->z.initFlag = 1; + return (0); +} + +int B_AlgorithmRandomUpdate (algorithm, input, inputLen, surrenderContext) +B_Algorithm *algorithm; +unsigned char *input; +unsigned int inputLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHRandomDestructor)) != 0) + return (status == BE_ALGORITHM_NOT_INITIALIZED ? + BE_RANDOM_NOT_INITIALIZED : status); + + return ((*((AHRandom *)algorithm->z.handler)->vTable->RandomUpdate) + ((AHRandom *)algorithm->z.handler, input, inputLen, + surrenderContext)); +} + +int B_AlgorithmGenerateRandomBytes + (algorithm, output, outputLen, surrenderContext) +B_Algorithm *algorithm; +unsigned char *output; +unsigned int outputLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + /* As a special case, check here for a null this pointer when the object + is actually being used since many routines take a "dummy" null + random algorithm. + */ + if (algorithm == (B_Algorithm *)NULL_PTR) + return (BE_RANDOM_OBJ); + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHRandomDestructor)) != 0) + return (status == BE_ALGORITHM_NOT_INITIALIZED ? + BE_RANDOM_NOT_INITIALIZED : status); + + return ((*((AHRandom *)algorithm->z.handler)->vTable->GenerateBytes) + ((AHRandom *)algorithm->z.handler, output, outputLen, + surrenderContext)); +} + +static void TypedAHRandomDestructor (typeCheck) +B_TypeCheck *typeCheck; +{ + (*((AHRandom *)typeCheck)->vTable->Destructor) ((AHRandom *)typeCheck); +} + diff --git a/lib/bind/dnssafe/ahrandom.h b/lib/bind/dnssafe/ahrandom.h new file mode 100644 index 0000000000..aeb4f3b01c --- /dev/null +++ b/lib/bind/dnssafe/ahrandom.h @@ -0,0 +1,47 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHRANDOM_H_ +#define _AHRANDOM_H_ 1 + +#include "btypechk.h" + +/* Use the THIS_RANDOM macro to define the type of object in the + virtual function prototype. It defaults to the most base class, but + derived modules may define the macro to a more derived class before + including this header file. + */ +#ifndef THIS_RANDOM +#define THIS_RANDOM struct AHRandom +#endif + +struct AHRandom; + +typedef struct { + void (*Destructor) PROTO_LIST ((THIS_RANDOM *)); + int (*RandomInit) PROTO_LIST + ((THIS_RANDOM *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); + int (*RandomUpdate) PROTO_LIST + ((THIS_RANDOM *, unsigned char *, unsigned int, A_SURRENDER_CTX *)); + int (*GenerateBytes) PROTO_LIST + ((THIS_RANDOM *, unsigned char *, unsigned int, A_SURRENDER_CTX *)); +} AHRandomVTable; + +typedef struct AHRandom { + B_TypeCheck typeCheck; /* inherited */ + AHRandomVTable *vTable; /* pure virtual */ +} AHRandom; + +/* The constructor does not set the vTable since this is a pure base class. + */ +void AHRandomConstructor PROTO_LIST ((AHRandom *)); +/* No destructor because it is pure virtual. Also, do not call destructor + for B_TypeCheck, since this will just re-invoke this virtual + destructor. */ + +#endif diff --git a/lib/bind/dnssafe/ahrsaenc.c b/lib/bind/dnssafe/ahrsaenc.c new file mode 100644 index 0000000000..c345d91695 --- /dev/null +++ b/lib/bind/dnssafe/ahrsaenc.c @@ -0,0 +1,244 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +/* Define this so that the type of the 'this' pointer in the + virtual functions will be correct for this derived class. + */ +struct AH_RSAEncryption; +#define THIS_ENCRYPT_DECRYPT struct AH_RSAEncryption + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahrsaenc.h" +#include "port_after.h" + +static int AH_RSAEncryptionInitHelper PROTO_LIST ((AH_RSAEncryption *, int)); + +static AHEncryptDecryptVTable V_TABLE = { + AH_RSAEncryptionDestructor, AH_RSAEncryptionGetBlockLen, + AH_RSAEncryptionEncryptInit, AH_RSAEncryptionDecryptInit, + AH_RSAEncryptionUpdate, + AH_RSAEncryptionUpdate, + AH_RSAEncryptionEncryptFinal, AH_RSAEncryptionDecryptFinal +}; + +void AH_RSAEncryptionConstructor1 (handler, infoType) +AH_RSAEncryption *handler; +struct B_AlgorithmInfoType *infoType; +{ + /* Construct base class with the infoType. Assume info is NULL_PTR. */ + AHChooseEncryptConstructor2 + (&handler->chooseEncryptDecrypt, infoType, NULL_PTR); + + T_memset ((POINTER)&handler->z, 0, sizeof (handler->z)); + /* Set the AHEncryptDecrypt vTable, but don't set the RSAEncryption vTable + since it is pure virtual. */ + handler->chooseEncryptDecrypt.encryptDecrypt.vTable = &V_TABLE; +} + +void AH_RSAEncryptionDestructor (handler) +AH_RSAEncryption *handler; +{ + T_memset ((POINTER)handler->z.block, 0, handler->z.blockLen); + T_free ((POINTER)handler->z.block); + + /* Call base class destructor */ + AHChooseEncryptDestructor (handler); +} + +int AH_RSAEncryptionGetBlockLen (handler, blockLen) +AH_RSAEncryption *handler; +unsigned int *blockLen; +{ +UNUSED_ARG (handler) +UNUSED_ARG (blockLen) + return (BE_NOT_SUPPORTED); +} + +int AH_RSAEncryptionEncryptInit (handler, key, chooser, surrenderContext) +AH_RSAEncryption *handler; +B_Key *key; +B_ALGORITHM_CHOOSER chooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AHChooseEncryptEncryptInit + (handler, key, chooser, surrenderContext)) != 0) + return (status); + + return (AH_RSAEncryptionInitHelper (handler, 1)); +} + +int AH_RSAEncryptionDecryptInit (handler, key, chooser, surrenderContext) +AH_RSAEncryption *handler; +B_Key *key; +B_ALGORITHM_CHOOSER chooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AHChooseEncryptDecryptInit + (handler, key, chooser, surrenderContext)) != 0) + return (status); + + return (AH_RSAEncryptionInitHelper (handler, 0)); +} + +/* Accumulate into the z.block. + */ +int AH_RSAEncryptionUpdate + (handler, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + randomAlgorithm, surrenderContext) +AH_RSAEncryption *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +const unsigned char *partIn; +unsigned int partInLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (partOut) +UNUSED_ARG (maxPartOutLen) +UNUSED_ARG (randomAlgorithm) +UNUSED_ARG (surrenderContext) + *partOutLen = 0; + + if (handler->_inputLen + partInLen > handler->_maxInputLen) + return (BE_INPUT_LEN); + T_memcpy + ((POINTER)(handler->z.block + handler->_inputLen), (CPOINTER)partIn, + partInLen); + handler->_inputLen += partInLen; + return (0); +} + +int AH_RSAEncryptionEncryptFinal + (handler, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +AH_RSAEncryption *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned int dummyPartOutLen; + + /* Encode methodContext in place. */ + if ((status = (*handler->vTable->EncodeBlock) + (handler, randomAlgorithm, surrenderContext)) != 0) + return (status); + + /* This should not return BE_INPUT_DATA since it is well-formatted. */ + if ((status = AHChooseEncryptEncryptUpdate + (handler, partOut, partOutLen, maxPartOutLen, handler->z.block, + handler->z.blockLen, (B_Algorithm *)NULL_PTR, surrenderContext)) != 0) + return (status); + + /* Expect final to return zero bytes. */ + if ((status = AHChooseEncryptEncryptFinal + (handler, (unsigned char *)NULL_PTR, &dummyPartOutLen, 0, + (B_Algorithm *)NULL_PTR, surrenderContext)) != 0) + return (status); + + /* Restart the handle for new input. */ + handler->_inputLen = 0; + return (0); +} + +int AH_RSAEncryptionDecryptFinal + (handler, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +AH_RSAEncryption *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + ITEM output; + int status; + unsigned int decryptedLen, dummyPartOutLen; + +UNUSED_ARG (randomAlgorithm) + /* Decrypt block in place. The block lenghts are already within limits. + */ + if ((status = AHChooseEncryptDecryptUpdate + (handler, handler->z.block, &decryptedLen, handler->z.blockLen, + handler->z.block, handler->_inputLen, (B_Algorithm *)NULL_PTR, + surrenderContext)) != 0) + return (status); + /* Expect final to return zero bytes. */ + if ((status = AHChooseEncryptDecryptFinal + (handler, (unsigned char *)NULL_PTR, &dummyPartOutLen, 0, + (B_Algorithm *)NULL_PTR, surrenderContext)) != 0) + return (status); + + /* Restart the handle for new input. */ + handler->_inputLen = 0; + + /* Now decode the block and copy the result to the partOut. + */ + if ((status = (*handler->vTable->DecodeBlock) + (handler, &output, decryptedLen)) != 0) + return (status); + + if (output.len > handler->z.blockLen - 11) + /* This implies that the block was encrypted with less than + 8 bytes of padding */ + return (BE_INPUT_DATA); + + if ((*partOutLen = output.len) > maxPartOutLen) + return (BE_OUTPUT_LEN); + T_memcpy ((POINTER)partOut, (POINTER)output.data, output.len); + + return (0); +} + +static int AH_RSAEncryptionInitHelper (handler, encryptFlag) +AH_RSAEncryption *handler; +int encryptFlag; +{ + int status; + unsigned int newBlockLen; + + if ((status = AHChooseEncryptGetBlockLen (handler, &newBlockLen)) != 0) + return (status); + + if (newBlockLen < 12) + /* PKCS Requires at least 12 bytes of modulus */ + return (BE_NOT_SUPPORTED); + + /* During encrypt, this will ensure that there are 8 bytes of padding. + During decrypt, the DecodeBlock procedure must check that the block + was encrypted with 8 bytes of padding. + */ + handler->_maxInputLen = encryptFlag ? (newBlockLen - 11) : newBlockLen; + + handler->_inputLen = 0; + + /* Zeroize old block and realloc to new size. + */ + T_memset ((POINTER)handler->z.block, 0, handler->z.blockLen); + if ((handler->z.block = (unsigned char *)T_realloc + ((POINTER)handler->z.block, newBlockLen)) + == (unsigned char *)NULL_PTR) { + handler->z.blockLen = 0; + return (BE_ALLOC); + } + + handler->z.blockLen = newBlockLen; + return (0); +} + diff --git a/lib/bind/dnssafe/ahrsaenc.h b/lib/bind/dnssafe/ahrsaenc.h new file mode 100644 index 0000000000..5abb1e3c23 --- /dev/null +++ b/lib/bind/dnssafe/ahrsaenc.h @@ -0,0 +1,68 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHRSAENC_H_ +#define _AHRSAENC_H_ + +#include "ahchencr.h" + +struct AH_RSAEncryption; + +/* For EncodeBlock, the block to encode is left justified in the + z.block with length given by z._inputLen. EncodeBlock encodes the block + in place to fill it out to z.blockLen. + For DecodeBlock, return the contents in the given ITEM by decoding + the z.block value which has length given by decryptedLen. This + procedure must also ensure that the block was encrypted with 8 bytes + of padding. + */ +typedef struct { + int (*EncodeBlock) PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, B_Algorithm * /* randomAlgorithm */, + A_SURRENDER_CTX *)); + int (*DecodeBlock) PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, ITEM *, unsigned int /* decryptedLen */)); +} AH_RSAEncryptionVTable; + +typedef struct AH_RSAEncryption { + AHChooseEncryptDecrypt chooseEncryptDecrypt; /* base class */ + + struct { + unsigned char *block; + unsigned int blockLen; + } z; /* Zeroized by constructor */ + + unsigned int _inputLen; /* Length of data accumulated by Update */ + unsigned int _maxInputLen; /* used during update to check for overflow */ + AH_RSAEncryptionVTable *vTable; /* pure virtual */ +} AH_RSAEncryption; + +void AH_RSAEncryptionConstructor1 PROTO_LIST + ((AH_RSAEncryption *, struct B_AlgorithmInfoType *)); +void AH_RSAEncryptionDestructor PROTO_LIST ((AH_RSAEncryption *)); + +int AH_RSAEncryptionGetBlockLen PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned int *)); +int AH_RSAEncryptionEncryptInit PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, B_Key *, B_ALGORITHM_CHOOSER, + A_SURRENDER_CTX *)); +int AH_RSAEncryptionDecryptInit PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, B_Key *, B_ALGORITHM_CHOOSER, + A_SURRENDER_CTX *)); +int AH_RSAEncryptionUpdate PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, const unsigned char *, unsigned int, B_Algorithm *, + A_SURRENDER_CTX *)); +int AH_RSAEncryptionEncryptFinal PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); +int AH_RSAEncryptionDecryptFinal PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); + +#endif diff --git a/lib/bind/dnssafe/ahrsaepr.c b/lib/bind/dnssafe/ahrsaepr.c new file mode 100644 index 0000000000..3105868259 --- /dev/null +++ b/lib/bind/dnssafe/ahrsaepr.c @@ -0,0 +1,101 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +/* Define this so that the type of the 'this' pointer in the + virtual functions will be correct for this derived class. + */ +struct AH_RSAEncryption; +#define THIS_ENCRYPT_DECRYPT struct AH_RSAEncryption + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahrsaepr.h" +#include "port_after.h" + +static int EncodeBlock1 PROTO_LIST + ((AH_RSAEncryptionPrivate *, B_Algorithm *, A_SURRENDER_CTX *)); +static int DecodeBlock2 PROTO_LIST + ((AH_RSAEncryptionPrivate *, ITEM *, unsigned int)); + +static AH_RSAEncryptionVTable ENCRYPTION_V_TABLE = + {EncodeBlock1, DecodeBlock2}; + +extern struct B_AlgorithmInfoType AIT_RSAPrivate; + +AH_RSAEncryptionPrivate *AH_RSAEncrypPrivateConstructor (handler) +AH_RSAEncryptionPrivate *handler; +{ + if (handler == (AH_RSAEncryptionPrivate *)NULL_PTR) { + /* This constructor is being used to do a new */ + if ((handler = (AH_RSAEncryptionPrivate *)T_malloc (sizeof (*handler))) + == (AH_RSAEncryptionPrivate *)NULL_PTR) + return (handler); + } + + /* Construct base class */ + AH_RSAEncryptionConstructor1 (handler, &AIT_RSAPrivate); + + handler->vTable = &ENCRYPTION_V_TABLE; + return (handler); +} + +/* block1 starts out with the input bytes of length inputLen left-justified. + Returns 0, BE_INPUT_LEN. + */ +static int EncodeBlock1 (handler, randomAlgorithm, surrenderContext) +AH_RSAEncryptionPrivate *handler; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + unsigned int padLen; + +UNUSED_ARG (randomAlgorithm) +UNUSED_ARG (surrenderContext) + if ((handler->_inputLen + 3) > handler->z.blockLen) + /* input is too large to make a block 1 */ + return (BE_INPUT_LEN); + + padLen = handler->z.blockLen - (handler->_inputLen + 3); + T_memmove + ((POINTER)(handler->z.block + padLen + 3), (POINTER)handler->z.block, + handler->_inputLen); + + handler->z.block[0] = 0; + handler->z.block[1] = 1; + T_memset ((POINTER)(handler->z.block + 2), 0xff, padLen); + handler->z.block[2 + padLen] = 0; + return (0); +} + +static int DecodeBlock2 (handler, output, block2Len) +AH_RSAEncryptionPrivate *handler; +ITEM *output; +unsigned int block2Len; +{ + unsigned int i; + + if ((handler->z.block[0] != 0) || (handler->z.block[1] != 2)) + return (BE_INPUT_DATA); + + /* Should be able to find the data after the first zero byte following + the random bytes. */ + for (i = 2; i < block2Len && handler->z.block[i] != 0; i++); + i++; + + if (i > block2Len) + /* The data is not zero terminated. */ + return (BE_INPUT_DATA); + + output->len = block2Len - i; + output->data = handler->z.block + i; + return (0); +} + diff --git a/lib/bind/dnssafe/ahrsaepr.h b/lib/bind/dnssafe/ahrsaepr.h new file mode 100644 index 0000000000..f5847bc636 --- /dev/null +++ b/lib/bind/dnssafe/ahrsaepr.h @@ -0,0 +1,20 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHRSAEPR_H_ +#define _AHRSAEPR_H_ + +#include "ahrsaenc.h" + +/* structure is identical to base class, so just re-typedef. */ +typedef AH_RSAEncryption AH_RSAEncryptionPrivate; + +AH_RSAEncryptionPrivate *AH_RSAEncrypPrivateConstructor PROTO_LIST + ((AH_RSAEncryptionPrivate *)); + +#endif diff --git a/lib/bind/dnssafe/ahrsaepu.c b/lib/bind/dnssafe/ahrsaepu.c new file mode 100644 index 0000000000..b290d5a7c0 --- /dev/null +++ b/lib/bind/dnssafe/ahrsaepu.c @@ -0,0 +1,114 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +/* Define this so that the type of the 'this' pointer in the + virtual functions will be correct for this derived class. + */ +struct AH_RSAEncryption; +#define THIS_ENCRYPT_DECRYPT struct AH_RSAEncryption + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahrsaepu.h" +#include "port_after.h" + +static int EncodeBlock2 PROTO_LIST + ((AH_RSAEncryptionPublic *, B_Algorithm *, A_SURRENDER_CTX *)); +static int DecodeBlock1 PROTO_LIST + ((AH_RSAEncryptionPublic *, ITEM *, unsigned int)); + +static AH_RSAEncryptionVTable ENCRYPTION_V_TABLE = + {EncodeBlock2, DecodeBlock1}; + +extern struct B_AlgorithmInfoType AIT_RSAPublic; + +AH_RSAEncryptionPublic *AH_RSAEncrypPublicConstructor (handler) +AH_RSAEncryptionPublic *handler; +{ + if (handler == (AH_RSAEncryptionPublic *)NULL_PTR) { + /* This constructor is being used to do a new */ + if ((handler = (AH_RSAEncryptionPublic *)T_malloc (sizeof (*handler))) + == (AH_RSAEncryptionPublic *)NULL_PTR) + return (handler); + } + + /* Construct base class */ + AH_RSAEncryptionConstructor1 (handler, &AIT_RSAPublic); + + handler->vTable = &ENCRYPTION_V_TABLE; + return (handler); +} + +/* block starts out with the input bytes of length inputLen left-justified. + */ +static int EncodeBlock2 (handler, randomAlgorithm, surrenderContext) +AH_RSAEncryptionPublic *handler; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned char randomByte; + unsigned int padLen, i; + + if ((handler->_inputLen + 3) > handler->z.blockLen) + /* input is too large to make a block 2 */ + return (BE_INPUT_LEN); + + padLen = handler->z.blockLen - (handler->_inputLen + 3); + T_memmove + ((POINTER)(handler->z.block + padLen + 3), (POINTER)handler->z.block, + handler->_inputLen); + + handler->z.block[0] = 0; + handler->z.block[1] = 2; + + /* Pad out with random bytes, making sure that none of the bytes is zero. + */ + for (i = 2; i < (padLen + 2); i++) { + do { + if ((status = B_AlgorithmGenerateRandomBytes + (randomAlgorithm, &randomByte, 1, surrenderContext)) != 0) + return (status); + } while (randomByte == 0); + + handler->z.block[i] = randomByte; + } + + handler->z.block[2 + padLen] = 0; + return (0); +} + +static int DecodeBlock1 (handler, output, block1Len) +AH_RSAEncryptionPublic *handler; +ITEM *output; +unsigned int block1Len; +{ + unsigned int i; + + /* Locate the digestInfo within the PKCS block 1. + */ + if (handler->z.block[0] != 0 || handler->z.block[1] != 1) + return (BE_INPUT_DATA); + + /* Should be able to find the data after the first zero byte following + the 0xff. */ + for (i = 2; i < block1Len && handler->z.block[i] == 0xff; i++); + i++; + + if (i > block1Len || handler->z.block[i - 1] != 0) + /* The data is not zero terminated, or a byte other than 0xff. */ + return (BE_INPUT_DATA); + + output->len = block1Len - i; + output->data = handler->z.block + i; + return (0); +} + diff --git a/lib/bind/dnssafe/ahrsaepu.h b/lib/bind/dnssafe/ahrsaepu.h new file mode 100644 index 0000000000..0c13e204d7 --- /dev/null +++ b/lib/bind/dnssafe/ahrsaepu.h @@ -0,0 +1,20 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHRSAEPU_H_ +#define _AHRSAEPU_H_ + +#include "ahrsaenc.h" + +/* structure is identical to base class, so just re-typedef. */ +typedef AH_RSAEncryption AH_RSAEncryptionPublic; + +AH_RSAEncryptionPublic *AH_RSAEncrypPublicConstructor PROTO_LIST + ((AH_RSAEncryptionPublic *)); + +#endif diff --git a/lib/bind/dnssafe/aichdig.c b/lib/bind/dnssafe/aichdig.c new file mode 100644 index 0000000000..d0bc944b15 --- /dev/null +++ b/lib/bind/dnssafe/aichdig.c @@ -0,0 +1,38 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahchdig.h" +#include "aichdig.h" +#include "port_after.h" + +B_TypeCheck *AITChooseDigestNullNewHandler PROTO_LIST + ((B_AlgorithmInfoType *, B_Algorithm *)); + +B_AlgorithmInfoTypeVTable AITChooseDigestNull_V_TABLE = + {AITNullAddInfo, AITChooseDigestNullNewHandler, + B_AlgorithmInfoTypeMakeError}; + +/* This always uses NULL_PTR for the info. + */ +B_TypeCheck *AITChooseDigestNullNewHandler (infoType, algorithm) +B_AlgorithmInfoType *infoType; +B_Algorithm *algorithm; +{ +UNUSED_ARG (algorithm) + + /* Pass in NULL_PTR so that constructor will allocate. + */ + return ((B_TypeCheck *)AHChooseDigestConstructor2 + ((AHChooseDigest *)NULL_PTR, infoType, NULL_PTR)); +} + diff --git a/lib/bind/dnssafe/aichdig.h b/lib/bind/dnssafe/aichdig.h new file mode 100644 index 0000000000..e8228d911e --- /dev/null +++ b/lib/bind/dnssafe/aichdig.h @@ -0,0 +1,17 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AICHDIG_H_ +#define _AICHDIG_H_ 1 + +#include "ainfotyp.h" +#include "ainull.h" + +extern B_AlgorithmInfoTypeVTable AITChooseDigestNull_V_TABLE; + +#endif diff --git a/lib/bind/dnssafe/aichenc8.c b/lib/bind/dnssafe/aichenc8.c new file mode 100644 index 0000000000..595812a6ce --- /dev/null +++ b/lib/bind/dnssafe/aichenc8.c @@ -0,0 +1,35 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "aichenc8.h" +#include "port_after.h" + +B_AlgorithmInfoTypeVTable AITChooseEncrypt8_V_TABLE = + {AIT_8AddInfo, AITChooseEncryptNewHandler, B_AlgorithmInfoTypeMakeError}; + +int AIT_8AddInfo (infoType, algorithm, info) +B_AlgorithmInfoType *infoType; +B_Algorithm *algorithm; +POINTER info; +{ + POINTER newInfo; + int status; + + if ((status = B_MemoryPoolAllocAndCopy + (&algorithm->infoCache.memoryPool, &newInfo, info, 8)) != 0) + return (status); + + return (B_InfoCacheAddInfo + (&algorithm->infoCache, (POINTER)infoType, newInfo)); +} + diff --git a/lib/bind/dnssafe/aichenc8.h b/lib/bind/dnssafe/aichenc8.h new file mode 100644 index 0000000000..4c2096bd5f --- /dev/null +++ b/lib/bind/dnssafe/aichenc8.h @@ -0,0 +1,19 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AICHENC8_H_ +#define _AICHENC8_H_ 1 + +#include "aichencr.h" + +extern B_AlgorithmInfoTypeVTable AITChooseEncrypt8_V_TABLE; + +int AIT_8AddInfo PROTO_LIST + ((THIS_ALGORITHM_INFO_TYPE *, B_Algorithm *, POINTER)); + +#endif diff --git a/lib/bind/dnssafe/aichencn.c b/lib/bind/dnssafe/aichencn.c new file mode 100644 index 0000000000..40e71dfa0e --- /dev/null +++ b/lib/bind/dnssafe/aichencn.c @@ -0,0 +1,19 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "aichencn.h" +#include "port_after.h" + +B_AlgorithmInfoTypeVTable AITChooseEncryptNull_V_TABLE = + {AITNullAddInfo, AITChooseEncryptNewHandler, B_AlgorithmInfoTypeMakeError}; + diff --git a/lib/bind/dnssafe/aichencn.h b/lib/bind/dnssafe/aichencn.h new file mode 100644 index 0000000000..113015730f --- /dev/null +++ b/lib/bind/dnssafe/aichencn.h @@ -0,0 +1,17 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AICHENCN_H_ +#define _AICHENCN_H_ 1 + +#include "aichencr.h" +#include "ainull.h" + +extern B_AlgorithmInfoTypeVTable AITChooseEncryptNull_V_TABLE; + +#endif diff --git a/lib/bind/dnssafe/aichencr.c b/lib/bind/dnssafe/aichencr.c new file mode 100644 index 0000000000..bc13242137 --- /dev/null +++ b/lib/bind/dnssafe/aichencr.c @@ -0,0 +1,33 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahchencr.h" +#include "aichencr.h" +#include "port_after.h" + +B_TypeCheck *AITChooseEncryptNewHandler (infoType, algorithm) +B_AlgorithmInfoType *infoType; +B_Algorithm *algorithm; +{ + POINTER info; + + if (B_InfoCacheFindInfo (&algorithm->infoCache, &info, (POINTER)infoType) + != 0) + /* This really shouldn't happen since the info was just added. */ + return ((B_TypeCheck *)NULL_PTR); + + /* Pass in NULL_PTR so that constructor will allocate. */ + return ((B_TypeCheck *)AHChooseEncryptConstructor2 + ((AHChooseEncryptDecrypt *)NULL_PTR, infoType, info)); +} + diff --git a/lib/bind/dnssafe/aichencr.h b/lib/bind/dnssafe/aichencr.h new file mode 100644 index 0000000000..2d99bfb009 --- /dev/null +++ b/lib/bind/dnssafe/aichencr.h @@ -0,0 +1,17 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AICHENCR_H_ +#define _AICHENCR_H_ 1 + +#include "ainfotyp.h" + +struct B_TypeCheck *AITChooseEncryptNewHandler PROTO_LIST + ((B_AlgorithmInfoType *, B_Algorithm *)); + +#endif diff --git a/lib/bind/dnssafe/aichgen.c b/lib/bind/dnssafe/aichgen.c new file mode 100644 index 0000000000..66bd4c318e --- /dev/null +++ b/lib/bind/dnssafe/aichgen.c @@ -0,0 +1,33 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahchgen.h" +#include "aichgen.h" +#include "port_after.h" + +B_TypeCheck *AITChooseGenerateNewHandler (infoType, algorithm) +B_AlgorithmInfoType *infoType; +B_Algorithm *algorithm; +{ + POINTER info; + + if (B_InfoCacheFindInfo (&algorithm->infoCache, &info, (POINTER)infoType) + != 0) + /* This really shouldn't happen since the info was just added. */ + return ((B_TypeCheck *)NULL_PTR); + + /* Pass in NULL_PTR so that constructor will allocate. */ + return ((B_TypeCheck *)AHChooseGenerateConstructor2 + ((AHChooseGenerate *)NULL_PTR, infoType, info)); +} + diff --git a/lib/bind/dnssafe/aichgen.h b/lib/bind/dnssafe/aichgen.h new file mode 100644 index 0000000000..eebd9b7261 --- /dev/null +++ b/lib/bind/dnssafe/aichgen.h @@ -0,0 +1,17 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AICHGEN_H_ +#define _AICHGEN_H_ 1 + +#include "ainfotyp.h" + +struct B_TypeCheck *AITChooseGenerateNewHandler PROTO_LIST + ((B_AlgorithmInfoType *, B_Algorithm *)); + +#endif diff --git a/lib/bind/dnssafe/aichrand.c b/lib/bind/dnssafe/aichrand.c new file mode 100644 index 0000000000..8f4ec72aa9 --- /dev/null +++ b/lib/bind/dnssafe/aichrand.c @@ -0,0 +1,38 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahchrand.h" +#include "aichrand.h" +#include "port_after.h" + +B_TypeCheck *AITChooseRandomNullNewHandler PROTO_LIST + ((B_AlgorithmInfoType *, B_Algorithm *)); + +B_AlgorithmInfoTypeVTable AITChooseRandomNull_V_TABLE = + {AITNullAddInfo, AITChooseRandomNullNewHandler, + B_AlgorithmInfoTypeMakeError}; + +/* This always uses NULL_PTR for the info. + */ +B_TypeCheck *AITChooseRandomNullNewHandler (infoType, algorithm) +B_AlgorithmInfoType *infoType; +B_Algorithm *algorithm; +{ +UNUSED_ARG (algorithm) + + /* Pass in NULL_PTR so that constructor will allocate. + */ + return ((B_TypeCheck *)AHChooseRandomConstructor2 + ((AHChooseRandom *)NULL_PTR, infoType, NULL_PTR)); +} + diff --git a/lib/bind/dnssafe/aichrand.h b/lib/bind/dnssafe/aichrand.h new file mode 100644 index 0000000000..6f188e18ea --- /dev/null +++ b/lib/bind/dnssafe/aichrand.h @@ -0,0 +1,17 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AICHRAND_H_ +#define _AICHRAND_H_ 1 + +#include "ainfotyp.h" +#include "ainull.h" + +extern B_AlgorithmInfoTypeVTable AITChooseRandomNull_V_TABLE; + +#endif diff --git a/lib/bind/dnssafe/aimd5.c b/lib/bind/dnssafe/aimd5.c new file mode 100644 index 0000000000..520fb401f4 --- /dev/null +++ b/lib/bind/dnssafe/aimd5.c @@ -0,0 +1,27 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "aichdig.h" +#include "port_after.h" + +B_AlgorithmInfoType AIT_MD5 = {&AITChooseDigestNull_V_TABLE}; + +int AI_MD5 (infoType) +POINTER *infoType; +{ + *infoType = (POINTER)&AIT_MD5; + + /* Return 0 to indicate a B_AlgorithmInfoType, not a B_KeyInfoType */ + return (0); +} + diff --git a/lib/bind/dnssafe/aimd5ran.c b/lib/bind/dnssafe/aimd5ran.c new file mode 100644 index 0000000000..7a2cd2be6c --- /dev/null +++ b/lib/bind/dnssafe/aimd5ran.c @@ -0,0 +1,27 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "aichrand.h" +#include "port_after.h" + +B_AlgorithmInfoType AIT_MD5Random = {&AITChooseRandomNull_V_TABLE}; + +int AI_MD5Random (infoType) +POINTER *infoType; +{ + *infoType = (POINTER)&AIT_MD5Random; + + /* Return 0 to indicate a B_AlgorithmInfoType, not a B_KeyInfoType */ + return (0); +} + diff --git a/lib/bind/dnssafe/ainfotyp.c b/lib/bind/dnssafe/ainfotyp.c new file mode 100644 index 0000000000..4d077a6632 --- /dev/null +++ b/lib/bind/dnssafe/ainfotyp.c @@ -0,0 +1,32 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ainfotyp.h" +#include "port_after.h" + +/* This is the default routine which algorithm info types point MakeInfo to + if not redefined by a derived class. + */ +int B_AlgorithmInfoTypeMakeError (infoType, info, algorithm) +B_AlgorithmInfoType *infoType; +POINTER *info; +B_Algorithm *algorithm; +{ +UNUSED_ARG (infoType) +UNUSED_ARG (info) +UNUSED_ARG (algorithm) + + /* Should already have been found in the cache. */ + return (BE_WRONG_ALGORITHM_INFO); +} + diff --git a/lib/bind/dnssafe/ainfotyp.h b/lib/bind/dnssafe/ainfotyp.h new file mode 100644 index 0000000000..fa9f4a6476 --- /dev/null +++ b/lib/bind/dnssafe/ainfotyp.h @@ -0,0 +1,39 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AINFOTYP_H_ +#define _AINFOTYP_H_ 1 + +/* Use the THIS_ALGORITHM_INFO_TYPE macro to define the type of object in the + virtual function prototype. It defaults to the most base class, but + derived modules may define the macro to a more derived class before + including this header file. + */ +#ifndef THIS_ALGORITHM_INFO_TYPE +#define THIS_ALGORITHM_INFO_TYPE struct B_AlgorithmInfoType +#endif + +struct B_AlgorithmInfoType; + +typedef struct { + int (*AddInfo) PROTO_LIST + ((THIS_ALGORITHM_INFO_TYPE *, B_Algorithm *, POINTER)); + struct B_TypeCheck * (*NewHandler) PROTO_LIST + ((THIS_ALGORITHM_INFO_TYPE *, B_Algorithm *)); + int (*MakeInfo) PROTO_LIST + ((THIS_ALGORITHM_INFO_TYPE *, POINTER *, B_Algorithm *)); +} B_AlgorithmInfoTypeVTable; + +typedef struct B_AlgorithmInfoType { + B_AlgorithmInfoTypeVTable *vTable; +} B_AlgorithmInfoType; + +int B_AlgorithmInfoTypeMakeError PROTO_LIST + ((THIS_ALGORITHM_INFO_TYPE *, POINTER *, B_Algorithm *)); + +#endif diff --git a/lib/bind/dnssafe/ainull.c b/lib/bind/dnssafe/ainull.c new file mode 100644 index 0000000000..9a6b322b31 --- /dev/null +++ b/lib/bind/dnssafe/ainull.c @@ -0,0 +1,28 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ainfotyp.h" +#include "ainull.h" +#include "port_after.h" + +int AITNullAddInfo (infoType, algorithm, info) +B_AlgorithmInfoType *infoType; +B_Algorithm *algorithm; +POINTER info; +{ +UNUSED_ARG (info) + /* Cache null parameters. */ + return (B_InfoCacheAddInfo + (&algorithm->infoCache, (POINTER)infoType, NULL_PTR)); +} + diff --git a/lib/bind/dnssafe/ainull.h b/lib/bind/dnssafe/ainull.h new file mode 100644 index 0000000000..3b48901a0a --- /dev/null +++ b/lib/bind/dnssafe/ainull.h @@ -0,0 +1,10 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +int AITNullAddInfo PROTO_LIST + ((THIS_ALGORITHM_INFO_TYPE *, B_Algorithm *, POINTER)); diff --git a/lib/bind/dnssafe/airsaepr.c b/lib/bind/dnssafe/airsaepr.c new file mode 100644 index 0000000000..0de3340485 --- /dev/null +++ b/lib/bind/dnssafe/airsaepr.c @@ -0,0 +1,47 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ainfotyp.h" +#include "ainull.h" +#include "ahrsaepr.h" +#include "port_after.h" + +B_TypeCheck *AIT_PKCS_RSAPrivateNewHandler PROTO_LIST + ((B_AlgorithmInfoType *, B_Algorithm *)); + +static B_AlgorithmInfoTypeVTable V_TABLE = + {AITNullAddInfo, AIT_PKCS_RSAPrivateNewHandler, + B_AlgorithmInfoTypeMakeError}; + +B_AlgorithmInfoType AIT_PKCS_RSAPrivate = {&V_TABLE}; + +int AI_PKCS_RSAPrivate (infoType) +POINTER *infoType; +{ + *infoType = (POINTER)&AIT_PKCS_RSAPrivate; + + /* Return 0 to indicate a B_AlgorithmInfoType, not a B_KeyInfoType */ + return (0); +} + +B_TypeCheck *AIT_PKCS_RSAPrivateNewHandler (infoType, algorithm) +B_AlgorithmInfoType *infoType; +B_Algorithm *algorithm; +{ +UNUSED_ARG (infoType) +UNUSED_ARG (algorithm) + /* Pass in NULL_PTR so that constructor will allocate. */ + return ((B_TypeCheck *)AH_RSAEncrypPrivateConstructor + ((AH_RSAEncryptionPrivate *)NULL_PTR)); +} + diff --git a/lib/bind/dnssafe/airsaepu.c b/lib/bind/dnssafe/airsaepu.c new file mode 100644 index 0000000000..2521d98aa6 --- /dev/null +++ b/lib/bind/dnssafe/airsaepu.c @@ -0,0 +1,47 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ainfotyp.h" +#include "ainull.h" +#include "ahrsaepu.h" +#include "port_after.h" + +B_TypeCheck *AIT_PKCS_RSAPublicNewHandler PROTO_LIST + ((B_AlgorithmInfoType *, B_Algorithm *)); + +static B_AlgorithmInfoTypeVTable V_TABLE = + {AITNullAddInfo, AIT_PKCS_RSAPublicNewHandler, + B_AlgorithmInfoTypeMakeError}; + +B_AlgorithmInfoType AIT_PKCS_RSAPublic = {&V_TABLE}; + +int AI_PKCS_RSAPublic (infoType) +POINTER *infoType; +{ + *infoType = (POINTER)&AIT_PKCS_RSAPublic; + + /* Return 0 to indicate a B_AlgorithmInfoType, not a B_KeyInfoType */ + return (0); +} + +B_TypeCheck *AIT_PKCS_RSAPublicNewHandler (infoType, algorithm) +B_AlgorithmInfoType *infoType; +B_Algorithm *algorithm; +{ +UNUSED_ARG (infoType) +UNUSED_ARG (algorithm) + /* Pass in NULL_PTR so that constructor will allocate. */ + return ((B_TypeCheck *)AH_RSAEncrypPublicConstructor + ((AH_RSAEncryptionPublic *)NULL_PTR)); +} + diff --git a/lib/bind/dnssafe/airsakgn.c b/lib/bind/dnssafe/airsakgn.c new file mode 100644 index 0000000000..3ac76574c5 --- /dev/null +++ b/lib/bind/dnssafe/airsakgn.c @@ -0,0 +1,62 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "intitem.h" +#include "aichgen.h" +#include "port_after.h" + +int AIT_RSAKeyGenAddInfo PROTO_LIST + ((THIS_ALGORITHM_INFO_TYPE *, B_Algorithm *, POINTER)); + +static A_RSA_KEY_GEN_PARAMS STATIC_KEY_GEN_PARAMS; +static ITEM *KEY_GEN_PARAMS_ITEMS[] = {&STATIC_KEY_GEN_PARAMS.publicExponent}; + +static B_AlgorithmInfoTypeVTable V_TABLE = + {AIT_RSAKeyGenAddInfo, AITChooseGenerateNewHandler, + B_AlgorithmInfoTypeMakeError}; + +B_AlgorithmInfoType AIT_RSAKeyGen = {&V_TABLE}; + +int AI_RSAKeyGen (infoType) +POINTER *infoType; +{ + *infoType = (POINTER)&AIT_RSAKeyGen; + + /* Return 0 to indicate a B_AlgorithmInfoType, not a B_KeyInfoType */ + return (0); +} + +int AIT_RSAKeyGenAddInfo (infoType, algorithm, info) +B_AlgorithmInfoType *infoType; +B_Algorithm *algorithm; +POINTER info; +{ + A_RSA_KEY_GEN_PARAMS *newInfo; + int status; + + if ((status = B_MemoryPoolAlloc + (&algorithm->infoCache.memoryPool, (POINTER *)&newInfo, + sizeof (A_RSA_KEY_GEN_PARAMS))) != 0) + return (status); + if ((status = AllocAndCopyIntegerItems + ((POINTER)newInfo, info, (POINTER)&STATIC_KEY_GEN_PARAMS, + KEY_GEN_PARAMS_ITEMS, + sizeof (KEY_GEN_PARAMS_ITEMS) / sizeof (KEY_GEN_PARAMS_ITEMS[0]), + &algorithm->infoCache.memoryPool)) != 0) + return (status); + + newInfo->modulusBits = ((A_RSA_KEY_GEN_PARAMS *)info)->modulusBits; + return (B_InfoCacheAddInfo + (&algorithm->infoCache, (POINTER)infoType, (POINTER)newInfo)); +} + diff --git a/lib/bind/dnssafe/airsaprv.c b/lib/bind/dnssafe/airsaprv.c new file mode 100644 index 0000000000..36b6b820fe --- /dev/null +++ b/lib/bind/dnssafe/airsaprv.c @@ -0,0 +1,27 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "aichencn.h" +#include "port_after.h" + +B_AlgorithmInfoType AIT_RSAPrivate = {&AITChooseEncryptNull_V_TABLE}; + +int AI_RSAPrivate (infoType) +POINTER *infoType; +{ + *infoType = (POINTER)&AIT_RSAPrivate; + + /* Return 0 to indicate a B_AlgorithmInfoType, not a B_KeyInfoType */ + return (0); +} + diff --git a/lib/bind/dnssafe/airsapub.c b/lib/bind/dnssafe/airsapub.c new file mode 100644 index 0000000000..7ff5acbb6d --- /dev/null +++ b/lib/bind/dnssafe/airsapub.c @@ -0,0 +1,27 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "aichencn.h" +#include "port_after.h" + +B_AlgorithmInfoType AIT_RSAPublic = {&AITChooseEncryptNull_V_TABLE}; + +int AI_RSAPublic (infoType) +POINTER *infoType; +{ + *infoType = (POINTER)&AIT_RSAPublic; + + /* Return 0 to indicate a B_AlgorithmInfoType, not a B_KeyInfoType */ + return (0); +} + diff --git a/lib/bind/dnssafe/algae.h b/lib/bind/dnssafe/algae.h new file mode 100644 index 0000000000..db4d5bc086 --- /dev/null +++ b/lib/bind/dnssafe/algae.h @@ -0,0 +1,66 @@ +/* Copyright (C) RSA Data Security, Inc. created 1992, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _ALGAE_H_ +#define _ALGAE_H_ 1 + +#ifndef T_CALL +#define T_CALL +#endif + +/* Used to reduce the stack size in routines with big scratch buffers. + If set to 1, this will make ALGAE allocate these buffers on the heap. + */ +#ifndef USE_ALLOCED_FRAME +#define USE_ALLOCED_FRAME 1 +#endif + +#include "atypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define AE_CANCEL 0x0001 +#define AE_DATA 0x0002 +#define AE_EXPONENT_EVEN 0x0003 +#define AE_EXPONENT_LEN 0x0004 +#define AE_INPUT_DATA 0x0005 +#define AE_INPUT_LEN 0x0006 +#define AE_MODULUS_LEN 0x0007 +#define AE_NEED_RANDOM 0x0008 +#define AE_NOT_SUPPORTED 0x0009 +#define AE_OUTPUT_LEN 0x000a +#define AE_NOT_INITIALIZED 0x000b +#define AE_KEY_LEN 0x000c +#define AE_KEY_INFO 0x000d +#define AE_SEQUENCE 0x000e +#define AE_PARAMS 0x000f + +#if USE_ALLOCED_FRAME +/* Needed only for big number code heap allocation of scratch arrays. + */ +#define AE_ALLOC 0x0080 +POINTER T_malloc PROTO_LIST ((unsigned int)); +void T_free PROTO_LIST ((POINTER)); +#endif + +/* Routines supplied by the implementor. + */ +void T_memset PROTO_LIST ((POINTER, int, unsigned int)); +void T_memcpy PROTO_LIST ((POINTER, CPOINTER, unsigned int)); +void T_memmove PROTO_LIST ((POINTER, POINTER, unsigned int)); +int T_memcmp PROTO_LIST ((CPOINTER, CPOINTER, unsigned int)); + +unsigned int A_IntegerBits PROTO_LIST ((const unsigned char *, unsigned int)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/bind/dnssafe/algchoic.c b/lib/bind/dnssafe/algchoic.c new file mode 100644 index 0000000000..2943ca81c6 --- /dev/null +++ b/lib/bind/dnssafe/algchoic.c @@ -0,0 +1,169 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "algae.h" +#include "balgmeth.h" +#include "bkey.h" +#include "algchoic.h" +#include "port_after.h" + +/* In C++: +ResizeContext::ResizeContext () +{ + T_memset ((POINTER)&z, 0, sizeof (z)); +} + */ +void ResizeContextConstructor (resizeContext) +ResizeContext *resizeContext; +{ + T_memset ((POINTER)&resizeContext->z, 0, sizeof (resizeContext->z)); +} + +/* In C++: +ResizeContext::~ResizeContext () +{ + T_memset (z.context, 0, z.contextSize); + T_free (z.context); +} + */ +void ResizeContextDestructor (resizeContext) +ResizeContext *resizeContext; +{ + T_memset (resizeContext->z.context, 0, resizeContext->z.contextSize); + T_free (resizeContext->z.context); +} + +/* If the resizeContext's context is already the requested size, do nothing. + Otherwise, this memsets the existing context to zero, then allocates + the context as a buffer of the requested size. + If the allocate fails, the context size is set to + zero so that later calls will not zeroize non-existing buffers. + */ +int ResizeContextMakeNewContext (resizeContext, contextSize) +ResizeContext *resizeContext; +unsigned int contextSize; +{ + if (resizeContext->z.contextSize == contextSize) + return (0); + + /* Take care of zeroizing the previous context. + */ + T_memset (resizeContext->z.context, 0, resizeContext->z.contextSize); + + if ((resizeContext->z.context = T_realloc + (resizeContext->z.context, contextSize)) == NULL_PTR) { + resizeContext->z.contextSize = 0; + return (BE_ALLOC); + } + + resizeContext->z.contextSize = contextSize; + return (0); +} + +int AlgaChoiceChoose (algaChoice, encryptFlag, key, chooser, surrenderContext) +AlgaChoice *algaChoice; +int encryptFlag; +B_Key *key; +B_ALGORITHM_CHOOSER chooser; +A_SURRENDER_CTX *surrenderContext; +{ + POINTER keyInfo; + int status, overallStatus; + + /* Each alga init callback returns BE_NOT_SUPPORTED if the Query fails. + Each also may return a more specific error like BE_MODULUS_LEN if the + method is not supported, so return the more specific error if possible. + */ + overallStatus = BE_METHOD_NOT_IN_CHOOSER; + + for (; *chooser != (B_ALGORITHM_METHOD *)NULL_PTR; chooser++) { + if ((*chooser)->algorithmInfoType != algaChoice->_algorithmInfoType || + (*chooser)->encryptFlag != encryptFlag) + /* Wrong type of algorithm, or the encryptFlag is wrong */ + continue; + + if ((*chooser)->keyInfoType != (struct B_KeyInfoType *)NULL_PTR) { + if ((status = B_KeyGetInfo + (key, &keyInfo, (*chooser)->keyInfoType)) != 0) { + if (IS_FATAL_BSAFE_ERROR (status)) + return (status); + + /* Update the overall status with this more specific error. */ + overallStatus = status; + continue; + } + } + else + keyInfo = NULL_PTR; + + if ((status = (*algaChoice->_InitAlga) + (algaChoice, keyInfo, *chooser, surrenderContext)) != 0) { + if (IS_FATAL_BSAFE_ERROR (status)) + return (status); + + /* Update the overall status with this more specific error. */ + overallStatus = status; + continue; + } + + /* Succeeded */ + algaChoice->_alga = (*chooser)->alga; + return (0); + } + + return (overallStatus); +} + +/* Convert the ALGAE error to a BSAFE2 error. + This does not check for zero since BSAFE should not bother to call + this function if there is no error. + */ +int ConvertAlgaeError (type) +int type; +{ + switch (type) { + case AE_CANCEL: + return (BE_CANCEL); + case AE_DATA: + return (BE_DATA); + case AE_EXPONENT_EVEN: + return (BE_EXPONENT_EVEN); + case AE_EXPONENT_LEN: + return (BE_EXPONENT_LEN); + case AE_INPUT_DATA: + return (BE_INPUT_DATA); + case AE_INPUT_LEN: + return (BE_INPUT_LEN); + case AE_KEY_INFO: + return (BE_KEY_INFO); + case AE_KEY_LEN: + return (BE_KEY_LEN); + case AE_MODULUS_LEN: + return (BE_MODULUS_LEN); + case AE_NOT_INITIALIZED: + return (BE_NOT_INITIALIZED); + case AE_NOT_SUPPORTED: + return (BE_NOT_SUPPORTED); + case AE_OUTPUT_LEN: + return (BE_OUTPUT_LEN); + case AE_PARAMS: + return (BE_ALGORITHM_INFO); + +#if USE_ALLOCED_FRAME + case AE_ALLOC: + return (BE_ALLOC); +#endif + + default: + return (BE_DATA); + } +} + diff --git a/lib/bind/dnssafe/algchoic.h b/lib/bind/dnssafe/algchoic.h new file mode 100644 index 0000000000..5743441d45 --- /dev/null +++ b/lib/bind/dnssafe/algchoic.h @@ -0,0 +1,111 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _ALGCHOICE_H_ +#define _ALGCHOICE_H_ 1 + +#define IS_FATAL_BSAFE_ERROR(status) \ + (status == BE_ALLOC || status == BE_HARDWARE || status == BE_CANCEL) + +/* Use the THIS_ALGA_CHOICE macro to define the type of object in the + INIT_ALGA prototype. It defaults to the AlgaChoice, but + derived modules may define the macro to a more derived class before + including this header file. + */ +struct AlgaChoice; +#ifndef THIS_ALGA_CHOICE +#define THIS_ALGA_CHOICE struct AlgaChoice +#endif + +/* In C++: +class ResizeContext { +public: + ResizeContext (); + ~ResizeContext (); + int makeNewContext (unsigned int contextSize); + POINTER context () {return z.context;} + +private: + struct { + POINTER context; + unsigned int contextSize; + } z; +}; + +class AlgaChoice; +typedef int (*INIT_ALGA) + (THIS_ALGA_CHOICE *algaChoice, POINTER keyInfo, + struct B_ALGORITHM_METHOD *algorithmMethod, + A_SURRENDER_CTX *surrenderContext); + +class AlgaChoice { +public: + AlgaChoice (INIT_ALGA InitAlga) : _InitAlga (InitAlga) {} + ~AlgaChoice () {} + int choose + (int encryptFlag, B_Key *key, B_ALGORITHM_CHOOSER chooser, + A_SURRENDER_CTX *surrenderContext); + int makeNewContext (unsigned int contextSize) { + context.makeNewContext (contextSize); } + POINTER alga () {return _alga;} + POINTER algorithmInfo () {return _algorithmInfo;} + POINTER context () {return context.context ();} + void setAlgorithmInfoType (B_AlgorithmInfoType *algorithmInfoType) { + _algorithmInfoType = algorithmInfoType; + } + void setAlgorithmInfo (POINTER algorithmInfo) { + _algorithmInfo = algorithmInfo; + } + +private: + POINTER _alga; + B_AlgorithmInfoType *_algorithmInfoType; + POINTER _algorithmInfo; + INIT_ALGA _InitAlga; + + ResizeContext context; +}; + */ +struct B_AlgorithmInfoType; + +typedef struct ResizeContext { + struct { + POINTER context; + unsigned int contextSize; + } z; /* zeriozed by constructor */ +} ResizeContext; + +typedef int (*INIT_ALGA) PROTO_LIST + ((THIS_ALGA_CHOICE *, POINTER, struct B_ALGORITHM_METHOD *, + A_SURRENDER_CTX *)); + +typedef struct AlgaChoice { + POINTER _alga; + struct B_AlgorithmInfoType *_algorithmInfoType; + POINTER _algorithmInfo; + INIT_ALGA _InitAlga; + + ResizeContext context; +} AlgaChoice; + +void ResizeContextConstructor PROTO_LIST ((ResizeContext *)); +void ResizeContextDestructor PROTO_LIST ((ResizeContext *)); +int ResizeContextMakeNewContext PROTO_LIST ((ResizeContext *, unsigned int)); + +#define ALGA_CHOICE_Constructor(algaChoice, InitAlga)\ + (ResizeContextConstructor (&(algaChoice)->context), \ + (algaChoice)->_InitAlga = (InitAlga)) +#define ALGA_CHOICE_Destructor(algaChoice)\ + (ResizeContextDestructor (&(algaChoice)->context)) + +int AlgaChoiceChoose PROTO_LIST + ((AlgaChoice *, int, B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); + +int ConvertAlgaeError PROTO_LIST ((int)); + +#endif diff --git a/lib/bind/dnssafe/algobj.c b/lib/bind/dnssafe/algobj.c new file mode 100644 index 0000000000..78e9d7e6bf --- /dev/null +++ b/lib/bind/dnssafe/algobj.c @@ -0,0 +1,123 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ainfotyp.h" +#include "keyobj.h" +#include "algobj.h" +#include "port_after.h" + +static char ALGORITHM_TYPE_TAG = 0; + +int B_CreateAlgorithmObject (algorithmObject) +B_ALGORITHM_OBJ *algorithmObject; +{ + AlgorithmWrap *algorithmWrap; + + if ((*algorithmObject = T_malloc (sizeof (*algorithmWrap))) == NULL_PTR) + return (BE_ALLOC); + + algorithmWrap = (AlgorithmWrap *)*algorithmObject; + + /* First construct base class */ + B_AlgorithmConstructor (&algorithmWrap->algorithm); + + algorithmWrap->typeTag = &ALGORITHM_TYPE_TAG; + algorithmWrap->selfCheck = algorithmWrap; + return (0); +} + +void B_DestroyAlgorithmObject (algorithmObject) +B_ALGORITHM_OBJ *algorithmObject; +{ + AlgorithmWrap *algorithmWrap = (AlgorithmWrap *)*algorithmObject; + + if (AlgorithmWrapCheck (algorithmWrap) == 0) { + /* zeroize self check to invalidate memory. */ + algorithmWrap->selfCheck = (AlgorithmWrap *)NULL_PTR; + + /* Call base class descructor */ + B_AlgorithmDestructor (&algorithmWrap->algorithm); + + T_free ((POINTER)algorithmWrap); + } + + *algorithmObject = NULL_PTR; +} + +int B_SetAlgorithmInfo (algorithmObject, infoType, info) +B_ALGORITHM_OBJ algorithmObject; +B_INFO_TYPE infoType; +POINTER info; +{ + B_AlgorithmInfoType *algorithmInfoType; + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + + /* Get the AlgorithmInfoType from the B_INFO_TYPE, which returns + zero for an AlgorithmInfoType, non-zero for KeyInfoType + */ + if ((*infoType) ((POINTER *)&algorithmInfoType) != 0) + return (BE_KEY_OPERATION_UNKNOWN); + + return (B_AlgorithmSetInfo + (&THE_ALG_WRAP->algorithm, algorithmInfoType, info)); +} + +int B_GetAlgorithmInfo (info, algorithmObject, infoType) +POINTER *info; +B_ALGORITHM_OBJ algorithmObject; +B_INFO_TYPE infoType; +{ + B_AlgorithmInfoType *algorithmInfoType; + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + + /* Get the AlgorithmInfoType from the B_INFO_TYPE, which returns + zero for an AlgorithmInfoType, non-zero for KeyInfoType + */ + if ((*infoType) ((POINTER *)&algorithmInfoType) != 0) + return (BE_KEY_OPERATION_UNKNOWN); + + return (B_AlgorithmGetInfo + (&THE_ALG_WRAP->algorithm, info, algorithmInfoType)); +} + +/* Return 0 if this is a valid AlgorithmWrap object. Return BE_ALGORITHM_OBJ if + algorithmWrap is NULL_PTR or invalid. + */ +int AlgorithmWrapCheck (algorithmWrap) +AlgorithmWrap *algorithmWrap; +{ + return ((algorithmWrap != (AlgorithmWrap *)NULL_PTR && + algorithmWrap->selfCheck == algorithmWrap && + algorithmWrap->typeTag == &ALGORITHM_TYPE_TAG) ? + 0 : BE_ALGORITHM_OBJ); +} + +/* Like AlgorithmWrapCheck except returns BE_RANDOM_OBJ for error. + Also, return OK status if randomAlgorithm is NULL_PTR. + */ +int RandomAlgorithmCheck (randomAlgorithm) +B_ALGORITHM_OBJ randomAlgorithm; +{ + if (randomAlgorithm == NULL_PTR) + return (0); + + return (AlgorithmWrapCheck ((AlgorithmWrap *)randomAlgorithm) ? + BE_RANDOM_OBJ : 0); +} + diff --git a/lib/bind/dnssafe/algobj.h b/lib/bind/dnssafe/algobj.h new file mode 100644 index 0000000000..7f87cfae74 --- /dev/null +++ b/lib/bind/dnssafe/algobj.h @@ -0,0 +1,19 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#define THE_ALG_WRAP ((AlgorithmWrap *)algorithmObject) + +typedef struct AlgorithmWrap { + B_Algorithm algorithm; + char *typeTag; + struct AlgorithmWrap *selfCheck; +} AlgorithmWrap; + +int AlgorithmWrapCheck PROTO_LIST ((AlgorithmWrap *)); +int RandomAlgorithmCheck PROTO_LIST ((B_ALGORITHM_OBJ)); + diff --git a/lib/bind/dnssafe/amcrte.c b/lib/bind/dnssafe/amcrte.c new file mode 100644 index 0000000000..ed771ea8d2 --- /dev/null +++ b/lib/bind/dnssafe/amcrte.c @@ -0,0 +1,119 @@ +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bsafe2.h" +#include "balgmeth.h" +#include "crt2.h" +#include "amencdec.h" +#include "port_after.h" + +static int RSA_CRT2Query PROTO_LIST ((unsigned int *, POINTER, POINTER)); +static int RSA_CRT2Init PROTO_LIST + ((POINTER, POINTER, POINTER, A_SURRENDER_CTX *)); +static int RSA_CRT2Update PROTO_LIST + ((POINTER, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, unsigned int, A_SURRENDER_CTX *)); +static int RSA_CRT2Final PROTO_LIST + ((POINTER, unsigned char *, unsigned int *, unsigned int, + A_SURRENDER_CTX *)); +static int RSA_CRT2GetMaxOutputLen PROTO_LIST + ((POINTER, unsigned int *, unsigned int)); +static int RSA_CRT2GetBlockLen PROTO_LIST ((POINTER, unsigned int *)); + +extern struct B_AlgorithmInfoType AIT_RSAPrivate; +extern struct B_KeyInfoType KIT_RSA_CRT; + +static A_ENCRYPT_DECRYPT_ALGA A_RSA_CRT2_CRYPT = { + RSA_CRT2Query, RSA_CRT2Init, RSA_CRT2Update, RSA_CRT2Final, + RSA_CRT2GetMaxOutputLen, RSA_CRT2GetBlockLen +}; + +B_ALGORITHM_METHOD AM_RSA_CRT_DECRYPT = + {&AIT_RSAPrivate, 0, &KIT_RSA_CRT, (POINTER)&A_RSA_CRT2_CRYPT}; +B_ALGORITHM_METHOD AM_RSA_CRT_ENCRYPT = + {&AIT_RSAPrivate, 1, &KIT_RSA_CRT, (POINTER)&A_RSA_CRT2_CRYPT}; + +static int RSA_CRT2Query (contextLen, key, params) +unsigned int *contextLen; +POINTER key; +POINTER params; +{ +UNUSED_ARG (params) + + if (A_IntegerBits + (((A_RSA_CRT_KEY *)key)->modulus.data, + ((A_RSA_CRT_KEY *)key)->modulus.len) > MAX_RSA_MODULUS_BITS) + /* Key size is too big to handle. */ + return (AE_MODULUS_LEN); + + *contextLen = sizeof (A_RSA_CRT2_CTX); + return (0); +} + +static int RSA_CRT2Init (context, key, params, surrenderContext) +POINTER context; +POINTER key; +POINTER params; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (params) +UNUSED_ARG (surrenderContext) + + return (A_RSA_CRT2Init ((A_RSA_CRT2_CTX *)context, (A_RSA_CRT_KEY *)key)); +} + +static int RSA_CRT2Update + (context, output, outputLen, maxOutputLen, input, inputLen, surrenderContext) +POINTER context; +unsigned char *output; +unsigned int *outputLen; +unsigned int maxOutputLen; +const unsigned char *input; +unsigned int inputLen; +A_SURRENDER_CTX *surrenderContext; +{ + return (A_RSA_CRT2Update + ((A_RSA_CRT2_CTX *)context, output, outputLen, maxOutputLen, input, + inputLen, surrenderContext)); +} + +static int RSA_CRT2Final + (context, output, outputLen, maxOutputLen, surrenderContext) +POINTER context; +unsigned char *output; +unsigned int *outputLen; +unsigned int maxOutputLen; +A_SURRENDER_CTX * surrenderContext; +{ +UNUSED_ARG (output) +UNUSED_ARG (maxOutputLen) +UNUSED_ARG (surrenderContext) + + *outputLen = 0; + return (A_RSA_CRT2Final ((A_RSA_CRT2_CTX *)context)); +} + +static int RSA_CRT2GetMaxOutputLen (context, outputLen, inputLen) +POINTER context; +unsigned int *outputLen; +unsigned int inputLen; +{ + *outputLen = A_RSA_CRT2_MAX_OUTPUT_LEN ((A_RSA_CRT2_CTX *)context, inputLen); + return (0); +} + +static int RSA_CRT2GetBlockLen (context, blockLen) +POINTER context; +unsigned int *blockLen; +{ + *blockLen = A_RSA_CRT2_BLOCK_LEN ((A_RSA_CRT2_CTX *)context); + return(0); +} diff --git a/lib/bind/dnssafe/amdigest.h b/lib/bind/dnssafe/amdigest.h new file mode 100644 index 0000000000..ec176ebb99 --- /dev/null +++ b/lib/bind/dnssafe/amdigest.h @@ -0,0 +1,19 @@ +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +typedef struct { + int (*Query) PROTO_LIST ((unsigned int *, POINTER)); + int (*Init) PROTO_LIST ((POINTER, POINTER, A_SURRENDER_CTX *)); + int (*Update) PROTO_LIST + ((POINTER, const unsigned char *, unsigned int, A_SURRENDER_CTX *)); + int (*Final) PROTO_LIST + ((POINTER, unsigned char *, unsigned int *, unsigned int, + A_SURRENDER_CTX *)); + int (*GetMaxOutputLen) PROTO_LIST ((POINTER, unsigned int *)); +} A_DIGEST_ALGA; + diff --git a/lib/bind/dnssafe/amencdec.h b/lib/bind/dnssafe/amencdec.h new file mode 100644 index 0000000000..21ab2c8698 --- /dev/null +++ b/lib/bind/dnssafe/amencdec.h @@ -0,0 +1,21 @@ +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +typedef struct { + int (*Query) PROTO_LIST ((unsigned int *, POINTER, POINTER)); + int (*Init) PROTO_LIST ((POINTER, POINTER, POINTER, A_SURRENDER_CTX *)); + int (*Update) PROTO_LIST + ((POINTER, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, unsigned int, A_SURRENDER_CTX *)); + int (*Final) PROTO_LIST + ((POINTER, unsigned char *, unsigned int *, unsigned int, + A_SURRENDER_CTX *)); + int (*GetMaxOutputLen) PROTO_LIST ((POINTER, unsigned int *, unsigned int)); + int (*GetBlockLen) PROTO_LIST ((POINTER, unsigned int *)); +} A_ENCRYPT_DECRYPT_ALGA; + diff --git a/lib/bind/dnssafe/amgen.h b/lib/bind/dnssafe/amgen.h new file mode 100644 index 0000000000..ffdf45765c --- /dev/null +++ b/lib/bind/dnssafe/amgen.h @@ -0,0 +1,19 @@ +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +struct B_KeyInfoType; + +typedef struct { + int (*Query) PROTO_LIST + ((unsigned int *, unsigned int *, unsigned int *, struct B_KeyInfoType **, + POINTER)); + int (*Init) PROTO_LIST ((POINTER, POINTER, POINTER, A_SURRENDER_CTX *)); + int (*Generate) PROTO_LIST + ((POINTER, POINTER *, unsigned char *, A_SURRENDER_CTX *)); +} A_GENERATE_ALGA; + diff --git a/lib/bind/dnssafe/ammd5.c b/lib/bind/dnssafe/ammd5.c new file mode 100644 index 0000000000..cea0aa4af7 --- /dev/null +++ b/lib/bind/dnssafe/ammd5.c @@ -0,0 +1,102 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bsafe2.h" +#include "balgmeth.h" +#include "md5.h" +#include "amdigest.h" +#include "port_after.h" + +static int MD5Query PROTO_LIST ((unsigned int *, POINTER)); +static int MD5Init PROTO_LIST ((POINTER, POINTER, A_SURRENDER_CTX*)); +static int MD5Update PROTO_LIST + ((POINTER, const unsigned char *, unsigned int, A_SURRENDER_CTX*)); +static int MD5Final PROTO_LIST + ((POINTER, unsigned char *, unsigned int *, unsigned int, A_SURRENDER_CTX*)); +static int MD5GetMaxOutputLen PROTO_LIST ((POINTER, unsigned int *)); + +static A_DIGEST_ALGA A_MD5_DIGEST = { + MD5Query, MD5Init, MD5Update, MD5Final, MD5GetMaxOutputLen +}; + +extern struct B_AlgorithmInfoType AIT_MD5; + +B_ALGORITHM_METHOD AM_MD5 = + {&AIT_MD5, 0, (struct B_KeyInfoType *)NULL_PTR, (POINTER)&A_MD5_DIGEST}; + +/* Returns 0. + */ +static int MD5Query (contextLen, params) +unsigned int *contextLen; +POINTER params; +{ +UNUSED_ARG (params) + + *contextLen = sizeof (A_MD5_CTX); + return (0); +} + +/* Returns 0. + */ +static int MD5Init (context, params, surrenderContext) +POINTER context; +POINTER params; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (params) +UNUSED_ARG (surrenderContext) + + A_MD5Init ((A_MD5_CTX *)context); + return (0); +} + +/* Returns 0. + */ +static int MD5Update (context, input, inputLen, surrenderContext) +POINTER context; +const unsigned char *input; +unsigned int inputLen; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (surrenderContext) + + A_MD5Update ((A_MD5_CTX *)context, input, inputLen); + return (0); +} + +/* Returns 0, AE_OUTPUT_LEN if maxDigestLen is too small. + */ +static int MD5Final + (context, digest, digestLen, maxDigestLen, surrenderContext) +POINTER context; +unsigned char *digest; +unsigned int *digestLen; +unsigned int maxDigestLen; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (surrenderContext) + + if ((*digestLen = A_MD5_DIGEST_LEN) > maxDigestLen) + return (AE_OUTPUT_LEN); + + A_MD5Final ((A_MD5_CTX *)context, digest); + return (0); +} + +static int MD5GetMaxOutputLen (context, outputLen) +POINTER context; +unsigned int *outputLen; +{ +UNUSED_ARG (context) + + *outputLen = A_MD5_DIGEST_LEN; + return(0); +} diff --git a/lib/bind/dnssafe/ammd5r.c b/lib/bind/dnssafe/ammd5r.c new file mode 100644 index 0000000000..900a872ac6 --- /dev/null +++ b/lib/bind/dnssafe/ammd5r.c @@ -0,0 +1,79 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bsafe2.h" +#include "balgmeth.h" +#include "md5rand.h" +#include "amrandom.h" +#include "port_after.h" + +static int MD5RandomQuery PROTO_LIST ((unsigned int *, POINTER)); +static int MD5RandomInit PROTO_LIST ((POINTER, POINTER, A_SURRENDER_CTX *)); +static int MD5RandomUpdate PROTO_LIST + ((POINTER, unsigned char *, unsigned int, A_SURRENDER_CTX *)); +static int MD5RandomGenerateBytes PROTO_LIST + ((POINTER, unsigned char *, unsigned int, A_SURRENDER_CTX *)); + +extern struct B_AlgorithmInfoType AIT_MD5Random; + +static A_RANDOM_ALGA A_MD5_RANDOM = + {MD5RandomQuery, MD5RandomInit, MD5RandomUpdate, MD5RandomGenerateBytes}; + +B_ALGORITHM_METHOD AM_MD5_RANDOM = + {&AIT_MD5Random, 0, (struct B_KeyInfoType *)NULL_PTR, + (POINTER)&A_MD5_RANDOM}; + +static int MD5RandomQuery (contextLen, params) +unsigned int *contextLen; +POINTER params; +{ +UNUSED_ARG (params) + + *contextLen = sizeof (A_MD5_RANDOM_CTX); + return (0); +} + +static int MD5RandomInit (context, params, surrenderContext) +POINTER context; +POINTER params; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (params) +UNUSED_ARG (surrenderContext) + + A_MD5RandomInit ((A_MD5_RANDOM_CTX *)context); + return (0); +} + +static int MD5RandomUpdate (context, input, inputLen, surrenderContext) +POINTER context; +unsigned char *input; +unsigned int inputLen; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (surrenderContext) + + A_MD5RandomUpdate ((A_MD5_RANDOM_CTX *)context, input, inputLen); + return (0); +} + +static int MD5RandomGenerateBytes + (context, output, outputLen, surrenderContext) +POINTER context; +unsigned char *output; +unsigned int outputLen; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (surrenderContext) + + A_MD5RandomGenerateBytes ((A_MD5_RANDOM_CTX *)context, output, outputLen); + return (0); +} diff --git a/lib/bind/dnssafe/amrandom.h b/lib/bind/dnssafe/amrandom.h new file mode 100644 index 0000000000..3b9539a049 --- /dev/null +++ b/lib/bind/dnssafe/amrandom.h @@ -0,0 +1,17 @@ +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +typedef struct { + int (*Query) PROTO_LIST ((unsigned int *, POINTER)); + int (*Init) PROTO_LIST ((POINTER, POINTER, A_SURRENDER_CTX *)); + int (*Update) PROTO_LIST + ((POINTER, unsigned char *, unsigned int, A_SURRENDER_CTX *)); + int (*Generate) PROTO_LIST + ((POINTER, unsigned char *, unsigned int, A_SURRENDER_CTX *)); +} A_RANDOM_ALGA; + diff --git a/lib/bind/dnssafe/amrkg.c b/lib/bind/dnssafe/amrkg.c new file mode 100644 index 0000000000..d5a19fb465 --- /dev/null +++ b/lib/bind/dnssafe/amrkg.c @@ -0,0 +1,83 @@ +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "algae.h" +#include "rsakeygn.h" +#include "balgmeth.h" +#include "amgen.h" +#include "port_after.h" + +#define THE_GEN_PARAMS ((A_RSA_KEY_GEN_PARAMS *)params) + +extern struct B_AlgorithmInfoType AIT_RSAKeyGen; +extern struct B_KeyInfoType KIT_PKCS_RSAPrivate; + +static int RSAKeyGenQuery PROTO_LIST + ((unsigned int *, unsigned int *, unsigned int *, struct B_KeyInfoType **, + POINTER)); +static int RSAKeyGenInit PROTO_LIST + ((POINTER, POINTER, POINTER, A_SURRENDER_CTX *)); +static int RSAKeyGen PROTO_LIST + ((POINTER, POINTER *, unsigned char *, A_SURRENDER_CTX *)); + +static A_GENERATE_ALGA A_RSA_KEY_GEN = + {RSAKeyGenQuery, RSAKeyGenInit, RSAKeyGen}; + +B_ALGORITHM_METHOD AM_RSA_KEY_GEN = + {&AIT_RSAKeyGen, 0, (struct B_KeyInfoType *)NULL_PTR, + (POINTER)&A_RSA_KEY_GEN}; + +static int RSAKeyGenQuery + (contextLen, secondContextLen, randomBlockLen, resultInfoType, params) +unsigned int *contextLen; +unsigned int *secondContextLen; +unsigned int *randomBlockLen; +struct B_KeyInfoType **resultInfoType; +POINTER params; +{ + if ((THE_GEN_PARAMS->modulusBits > MAX_RSA_MODULUS_BITS) || + (THE_GEN_PARAMS->modulusBits < MIN_RSA_MODULUS_BITS)) + /* Can't support a keypair of this size. */ + return (AE_MODULUS_LEN); + + *contextLen = sizeof (A_RSA_KEY_GEN_CTX); + *secondContextLen = 0; + *randomBlockLen = + A_RSA_KEY_GEN_RANDOM_BLOCK_LEN (THE_GEN_PARAMS->modulusBits); + *resultInfoType = &KIT_PKCS_RSAPrivate; + + return (0); +} + +static int RSAKeyGenInit (context, secondContext, params, surrenderContext) +POINTER context; +POINTER secondContext; +POINTER params; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (secondContext) +UNUSED_ARG (surrenderContext) + + return (A_RSAKeyGenInit + ((A_RSA_KEY_GEN_CTX *)context, (A_RSA_KEY_GEN_PARAMS *)params)); +} + +static int RSAKeyGen (context, result, randomBlock, surrenderContext) +POINTER context; +POINTER *result; +unsigned char *randomBlock; +A_SURRENDER_CTX *surrenderContext; +{ + return (A_RSAKeyGen + ((A_RSA_KEY_GEN_CTX *)context, (A_PKCS_RSA_PRIVATE_KEY **)result, + randomBlock, surrenderContext)); +} + diff --git a/lib/bind/dnssafe/amrsae.c b/lib/bind/dnssafe/amrsae.c new file mode 100644 index 0000000000..f4d067039c --- /dev/null +++ b/lib/bind/dnssafe/amrsae.c @@ -0,0 +1,117 @@ +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bsafe2.h" +#include "balgmeth.h" +#include "rsa.h" +#include "amencdec.h" +#include "port_after.h" + +static int RSAQuery PROTO_LIST ((unsigned int *, POINTER, POINTER)); +static int RSAInit PROTO_LIST ((POINTER, POINTER, POINTER, A_SURRENDER_CTX *)); +static int RSAUpdate PROTO_LIST + ((POINTER, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, unsigned int, A_SURRENDER_CTX *)); +static int RSAFinal PROTO_LIST + ((POINTER, unsigned char *, unsigned int *, unsigned int, + A_SURRENDER_CTX *)); +static int RSAGetMaxOutputLen PROTO_LIST + ((POINTER, unsigned int *, unsigned int)); +static int RSAGetBlockLen PROTO_LIST ((POINTER, unsigned int *)); + +extern struct B_AlgorithmInfoType AIT_RSAPublic; +extern struct B_KeyInfoType KIT_RSAPublic; + +static A_ENCRYPT_DECRYPT_ALGA A_RSA_CRYPT = { + RSAQuery, RSAInit, RSAUpdate, RSAFinal, RSAGetMaxOutputLen, RSAGetBlockLen +}; + +B_ALGORITHM_METHOD AM_RSA_DECRYPT = + {&AIT_RSAPublic, 0, &KIT_RSAPublic, (POINTER)&A_RSA_CRYPT}; +B_ALGORITHM_METHOD AM_RSA_ENCRYPT = + {&AIT_RSAPublic, 1, &KIT_RSAPublic, (POINTER)&A_RSA_CRYPT}; + +static int RSAQuery (contextLen, key, params) +unsigned int *contextLen; +POINTER key; +POINTER params; +{ +UNUSED_ARG (params) + + if (A_IntegerBits + (((A_RSA_KEY *)key)->modulus.data, ((A_RSA_KEY *)key)->modulus.len) + > MAX_RSA_MODULUS_BITS) + /* Key size is too big to handle. */ + return (AE_MODULUS_LEN); + + *contextLen = sizeof (A_RSA_CTX); + return (0); +} + +static int RSAInit (context, key, params, surrenderContext) +POINTER context; +POINTER key; +POINTER params; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (params) +UNUSED_ARG (surrenderContext) + + return (A_RSAInit ((A_RSA_CTX *)context, (A_RSA_KEY *)key)); +} + +static int RSAUpdate + (context, output, outputLen, maxOutputLen, input, inputLen, surrenderContext) +POINTER context; +unsigned char *output; +unsigned int *outputLen; +unsigned int maxOutputLen; +const unsigned char *input; +unsigned int inputLen; +A_SURRENDER_CTX *surrenderContext; +{ + return (A_RSAUpdate + ((A_RSA_CTX *)context, output, outputLen, maxOutputLen, input, + inputLen, surrenderContext)); +} + +static int RSAFinal + (context, output, outputLen, maxOutputLen, surrenderContext) +POINTER context; +unsigned char *output; +unsigned int *outputLen; +unsigned int maxOutputLen; +A_SURRENDER_CTX * surrenderContext; +{ +UNUSED_ARG (output) +UNUSED_ARG (maxOutputLen) +UNUSED_ARG (surrenderContext) + + *outputLen = 0; + return (A_RSAFinal ((A_RSA_CTX *)context)); +} + +static int RSAGetMaxOutputLen (context, outputLen, inputLen) +POINTER context; +unsigned int *outputLen; +unsigned int inputLen; +{ + *outputLen = A_RSA_MAX_OUTPUT_LEN ((A_RSA_CTX *)context, inputLen); + return (0); +} + +static int RSAGetBlockLen (context, blockLen) +POINTER context; +unsigned int *blockLen; +{ + *blockLen = A_RSA_BLOCK_LEN ((A_RSA_CTX *)context); + return(0); +} diff --git a/lib/bind/dnssafe/atypes.h b/lib/bind/dnssafe/atypes.h new file mode 100644 index 0000000000..e1af4eac3e --- /dev/null +++ b/lib/bind/dnssafe/atypes.h @@ -0,0 +1,60 @@ +/* Copyright (C) RSA Data Security, Inc. created 1992, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _ATYPES_H_ +#define _ATYPES_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ITEM_ +#define _ITEM_ 1 +typedef struct { + unsigned char *data; + unsigned int len; +} ITEM; +#endif + +typedef struct { + int (T_CALL *Surrender) PROTO_LIST ((POINTER)); + POINTER handle; + POINTER reserved; +} A_SURRENDER_CTX; + +typedef struct { + ITEM modulus; + ITEM publicExponent; + ITEM privateExponent; + ITEM prime[2]; /* prime factors */ + ITEM primeExponent[2]; /* exponents for prime factors */ + ITEM coefficient; /* CRT coefficient */ +} A_PKCS_RSA_PRIVATE_KEY; + +typedef struct { + ITEM modulus; + ITEM prime[2]; /* prime factors */ + ITEM primeExponent[2]; /* exponents for prime factors */ + ITEM coefficient; /* CRT coefficient */ +} A_RSA_CRT_KEY; + +typedef struct { + ITEM modulus; /* modulus */ + ITEM exponent; /* exponent */ +} A_RSA_KEY; + +typedef struct { + unsigned int modulusBits; + ITEM publicExponent; +} A_RSA_KEY_GEN_PARAMS; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/bind/dnssafe/balg.c b/lib/bind/dnssafe/balg.c new file mode 100644 index 0000000000..48af15a3da --- /dev/null +++ b/lib/bind/dnssafe/balg.c @@ -0,0 +1,117 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "btypechk.h" +#include "ainfotyp.h" +#include "port_after.h" + +void B_AlgorithmConstructor (algorithm) +B_Algorithm *algorithm; +{ + /* Construct immediate base class. */ + B_InfoCacheConstructor (&algorithm->infoCache); + + T_memset ((POINTER)&algorithm->z, 0, sizeof (algorithm->z)); +} + +void B_AlgorithmDestructor (algorithm) +B_Algorithm *algorithm; +{ + if (algorithm->z.handler != (B_TypeCheck *)NULL_PTR) { + B_TYPE_CHECK_Destructor (algorithm->z.handler); + T_free ((POINTER)algorithm->z.handler); + } + + /* Destroy base class */ + B_INFO_CACHE_Destructor (&algorithm->infoCache); +} + +int B_AlgorithmCheckType (algorithm, Destructor) +B_Algorithm *algorithm; +B_TYPE_CHECK_DESTRUCTOR Destructor; +{ + if (algorithm->z.handler == (B_TypeCheck *)NULL_PTR) + return (BE_ALGORITHM_NOT_SET); + + if (algorithm->z.handler->_Destructor != Destructor) + return (BE_ALG_OPERATION_UNKNOWN); + + return (0); +} + +int B_AlgorithmCheckTypeAndInitFlag (algorithm, Destructor) +B_Algorithm *algorithm; +B_TYPE_CHECK_DESTRUCTOR Destructor; +{ + int status; + + /* Check the type first. */ + if ((status = B_AlgorithmCheckType (algorithm, Destructor)) != 0) + return (status); + + if (!algorithm->z.initFlag) + return (BE_ALGORITHM_NOT_INITIALIZED); + + return (0); +} + +int B_AlgorithmSetInfo (algorithm, algorithmInfoType, info) +B_Algorithm *algorithm; +B_AlgorithmInfoType *algorithmInfoType; +POINTER info; +{ + int status; + + if (algorithm->infoCache.z.infoCount > 0) + return (BE_ALGORITHM_ALREADY_SET); + + /* This will cache the encoding. */ + if ((status = (*algorithmInfoType->vTable->AddInfo) + (algorithmInfoType, algorithm, info)) != 0) + return (status); + + /* Allocate the algorithm handler. NewHandler returns NULL_PTR for error. + */ + if ((algorithm->z.handler = (*algorithmInfoType->vTable->NewHandler) + (algorithmInfoType, algorithm)) == (B_TypeCheck *)NULL_PTR) + return (BE_ALLOC); + + return (0); +} + +int B_AlgorithmGetInfo (algorithm, info, algorithmInfoType) +B_Algorithm *algorithm; +POINTER *info; +B_AlgorithmInfoType *algorithmInfoType; +{ + int status; + + if (algorithm->infoCache.z.infoCount == 0) + return (BE_ALGORITHM_NOT_SET); + + /* First check if the encoding is already in the encoding cache. + */ + if (B_InfoCacheFindInfo + (&algorithm->infoCache, info, (POINTER)algorithmInfoType) == 0) + return (0); + + /* Info is not in the cache, go ahead and encode. + */ + if ((status = (*algorithmInfoType->vTable->MakeInfo) + (algorithmInfoType, info, algorithm)) != 0) + return (status); + + return (B_InfoCacheAddInfo + (&algorithm->infoCache, (POINTER)algorithmInfoType, *info)); +} + diff --git a/lib/bind/dnssafe/balg.h b/lib/bind/dnssafe/balg.h new file mode 100644 index 0000000000..517a69c021 --- /dev/null +++ b/lib/bind/dnssafe/balg.h @@ -0,0 +1,116 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _BALG_H_ +#define _BALG_H_ 1 + +#include "binfocsh.h" +#include "btypechk.h" + +typedef struct { + B_InfoCache infoCache; /* inherited */ + + struct { + B_TypeCheck *handler; + int initFlag; + /* POINTER reserved; */ + } z; +} B_Algorithm; + +void B_AlgorithmConstructor PROTO_LIST ((B_Algorithm *)); +void B_AlgorithmDestructor PROTO_LIST ((B_Algorithm *)); + +int B_AlgorithmCheckType PROTO_LIST ((B_Algorithm *, B_TYPE_CHECK_DESTRUCTOR)); +int B_AlgorithmCheckTypeAndInitFlag PROTO_LIST + ((B_Algorithm *, B_TYPE_CHECK_DESTRUCTOR)); + +struct B_AlgorithmInfoType; +int B_AlgorithmSetInfo PROTO_LIST + ((B_Algorithm *, struct B_AlgorithmInfoType *, POINTER)); +int B_AlgorithmGetInfo PROTO_LIST + ((B_Algorithm *, POINTER *, struct B_AlgorithmInfoType *)); + +int B_AlgorithmRandomInit PROTO_LIST + ((B_Algorithm *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int B_AlgorithmRandomUpdate PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int B_AlgorithmGenerateRandomBytes PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int, A_SURRENDER_CTX *)); + +int B_AlgorithmDigestInit PROTO_LIST + ((B_Algorithm *, B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int B_AlgorithmDigestUpdate PROTO_LIST + ((B_Algorithm *, const unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int B_AlgorithmDigestFinal PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + A_SURRENDER_CTX *)); + +int B_AlgorithmEncryptInit PROTO_LIST + ((B_Algorithm *, B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int B_AlgorithmDecryptInit PROTO_LIST + ((B_Algorithm *, B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int B_AlgorithmEncryptUpdate PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + unsigned char *, unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); +int B_AlgorithmDecryptUpdate PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); +int B_AlgorithmEncryptFinal PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + B_Algorithm *, A_SURRENDER_CTX *)); +int B_AlgorithmDecryptFinal PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + B_Algorithm *, A_SURRENDER_CTX *)); + +int B_AlgorithmEncodeInit PROTO_LIST ((B_Algorithm *)); +int B_AlgorithmDecodeInit PROTO_LIST ((B_Algorithm *)); +int B_AlgorithmEncodeUpdate PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + unsigned char *, unsigned int)); +int B_AlgorithmDecodeUpdate PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + unsigned char *, unsigned int)); +int B_AlgorithmEncodeFinal PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int)); +int B_AlgorithmDecodeFinal PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int)); + +int B_AlgorithmSignInit PROTO_LIST + ((B_Algorithm *, B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int B_AlgorithmSignUpdate PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int B_AlgorithmSignFinal PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + B_Algorithm *, A_SURRENDER_CTX *)); + +int B_AlgorithmVerifyInit PROTO_LIST + ((B_Algorithm *, B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int B_AlgorithmVerifyUpdate PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int B_AlgorithmVerifyFinal PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int, B_Algorithm *, + A_SURRENDER_CTX *)); + +int B_AlgorithmKeyAgreeInit PROTO_LIST + ((B_Algorithm *, B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int B_AlgorithmKeyAgreePhase1 PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + B_Algorithm *, A_SURRENDER_CTX *)); +int B_AlgorithmKeyAgreePhase2 PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + unsigned char *, unsigned int, A_SURRENDER_CTX *)); + +int B_AlgorithmGenerateInit PROTO_LIST + ((B_Algorithm *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int B_AlgorithmGenerateKeypair PROTO_LIST + ((B_Algorithm *, B_Key *, B_Key *, B_Algorithm *, + A_SURRENDER_CTX *)); +int B_AlgorithmGenerateParameters PROTO_LIST + ((B_Algorithm *, B_Algorithm *, B_Algorithm *, A_SURRENDER_CTX *)); + +#endif diff --git a/lib/bind/dnssafe/balgmeth.h b/lib/bind/dnssafe/balgmeth.h new file mode 100644 index 0000000000..c73e3ad42e --- /dev/null +++ b/lib/bind/dnssafe/balgmeth.h @@ -0,0 +1,18 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +struct B_AlgorithmInfoType; +struct B_KeyInfoType; + +struct B_ALGORITHM_METHOD { + struct B_AlgorithmInfoType *algorithmInfoType; + int encryptFlag; + struct B_KeyInfoType *keyInfoType; + POINTER alga; +}; + diff --git a/lib/bind/dnssafe/bgclrbit.c b/lib/bind/dnssafe/bgclrbit.c new file mode 100644 index 0000000000..0516928acf --- /dev/null +++ b/lib/bind/dnssafe/bgclrbit.c @@ -0,0 +1,30 @@ +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigClrbit (a, v) -- clears v-th bit of a, where v is nonnegative. + */ +void BigClrbit (a, v) +UINT2 *a; +unsigned int v; +{ + a[v/16] &= ~ (1 << (v % 16)); +} + +/* BigSetbit (a, v) -- sets v-th bit of a, where v is nonnegative. + */ +void BigSetbit (a, v) +UINT2 *a; +unsigned int v; +{ + a[v/16] |= (1 << (v % 16)); +} diff --git a/lib/bind/dnssafe/bgmdmpyx.c b/lib/bind/dnssafe/bgmdmpyx.c new file mode 100644 index 0000000000..53b191f554 --- /dev/null +++ b/lib/bind/dnssafe/bgmdmpyx.c @@ -0,0 +1,28 @@ +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigModMpyx (a, b, c, d, dInv, n) -- a = (b * c) mod d !! EXPRESS. + -- assumes a, b, c, d of length n, dInv of length n+2. + -- assumes dInv previously computed by BigInv. + */ +void BigModMpyx (a, b, c, d, dInv, n) +UINT2 *a, *b, *c, *d, *dInv; +unsigned int n; +{ + UINT2 prod[2 * MAX_RSA_MODULUS_WORDS]; + + BigPmpy (prod, b, c, n); + BigModx (a, prod, d, dInv, n); + + T_memset ((POINTER)prod, 0, sizeof (prod)); +} diff --git a/lib/bind/dnssafe/bgmdsqx.c b/lib/bind/dnssafe/bgmdsqx.c new file mode 100644 index 0000000000..95be98be73 --- /dev/null +++ b/lib/bind/dnssafe/bgmdsqx.c @@ -0,0 +1,26 @@ +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigModSqx (a, b, d, dInv, n) -- a = (b * b) mod d !! EXPRESS. + */ +void BigModSqx (a, b, d, dInv, n) +UINT2 *a, *b, *d, *dInv; +unsigned int n; +{ + UINT2 prod[2 * MAX_RSA_MODULUS_WORDS]; + + BigPsq (prod, b, n); + BigModx (a, prod, d, dInv, n); + + T_memset ((POINTER)prod, 0, sizeof (prod)); +} diff --git a/lib/bind/dnssafe/bgmodexp.c b/lib/bind/dnssafe/bgmodexp.c new file mode 100644 index 0000000000..d548d68c08 --- /dev/null +++ b/lib/bind/dnssafe/bgmodexp.c @@ -0,0 +1,134 @@ +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "surrendr.h" +#include "port_after.h" + +/* BigModExp (a, b, c, d, n): a = b**c (mod d) + Assumes a, b, c, d of length n. + Returns 0, AE_CANCEL. + */ +int BigModExp (a, b, c, d, n, surrenderContext) +UINT2 *a, *b, *c, *d; +unsigned int n; +A_SURRENDER_CTX *surrenderContext; +{ + struct BigModExpFrame { + UINT2 dInv[MAX_RSA_MODULUS_WORDS + 2], result[MAX_RSA_MODULUS_WORDS], + tab[16][MAX_RSA_MODULUS_WORDS]; + } *frame = (struct BigModExpFrame *)NULL_PTR; +#if !USE_ALLOCED_FRAME + struct BigModExpFrame stackFrame; +#endif + int i, didAMultiply, status; + unsigned int cLen, w, setup[64], power, mask; + + /* Initialize. + */ + do { +#if USE_ALLOCED_FRAME + if ((frame = (struct BigModExpFrame *)T_malloc (sizeof (*frame))) + == (struct BigModExpFrame *)NULL_PTR) { + status = AE_ALLOC; + break; + } +#else + /* Just use the buffers allocated on the stack. */ + frame = &stackFrame; +#endif + + /* precompute inverse of d to enable express mod-outs */ + BigInv (frame->dInv, d, n); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + + /* precompute small (size 2**w) table of powers of b */ + cLen = BigLen (c, n); + if (cLen < 4) + w = 1; + else if (cLen < 16) + w = 2; + else if (cLen < 64) + w = 3; + else + w = 4; + + /* zeroth power is one */ + BigConst (frame->tab[0], 1, n); + + /* first power is b */ + BigCopy (frame->tab[1], b, n); + setup[0] = 1; + setup[1] = 1; + for (i = 2; i < 64; i++) + setup[i] = 0; + + /* Loop over elements of exponent c in appropriate radix. + */ + power = 0; + didAMultiply = 0; + mask = 1 << ((cLen) % 16); + for (i = cLen; i >= 0; i--) { + if (didAMultiply) { + BigModSqx (frame->result, frame->result, d, frame->dInv, n); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + } + + power = power << 1; + if (setup[power] == 0) { + BigModSqx (frame->tab[power], frame->tab[power/2], d, frame->dInv, n); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + setup[power] = 1; + } + if (c[i/16] & mask) + power = power + 1; + if (mask == 1) + mask = 0x8000; + else + mask = (mask >> 1) & 0x7FFF; + if (setup[power] == 0) { + BigModMpyx + (frame->tab[power], frame->tab[power-1], b, d, frame->dInv, n); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + setup[power] = 1; + } + if ((i == 0) || (power >= (unsigned int)(1 << (w-1)))) { + if (didAMultiply) { + BigModMpyx + (frame->result, frame->result, frame->tab[power], d, frame->dInv, + n); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + } + else + BigCopy (frame->result, frame->tab[power], n); + + power = 0; + didAMultiply = 1; + } + } + if (status) + break; + + BigCopy (a, frame->result, n); + } while (0); + + if (frame != (struct BigModExpFrame *)NULL_PTR) { + T_memset ((POINTER)frame, 0, sizeof (*frame)); +#if USE_ALLOCED_FRAME + T_free ((POINTER)frame); +#endif + } + return (status); +} diff --git a/lib/bind/dnssafe/bgpegcd.c b/lib/bind/dnssafe/bgpegcd.c new file mode 100644 index 0000000000..eedfe79cd3 --- /dev/null +++ b/lib/bind/dnssafe/bgpegcd.c @@ -0,0 +1,80 @@ +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigPegcd + input + u, v bignums + k int size of u, v regs + restriction u, v positive + output + u3=GCD (u, v) (pos) + u1=inv (u)modv (pos) + u2=inv (v)modu (pos) + if GCD (u, v)!=1 then u1, u2 st + u3=u * u1mod (v) & u3=v * u2mod (u) + (see KNUTH vol 2) + */ +void BigPegcd (u3, u1, u2, u, v, k) +UINT2 *u3, *u2, *u1, *u, *v; +unsigned int k; +{ + UINT2 v1[2 * MAX_RSA_PRIME_WORDS], v2[2 * MAX_RSA_PRIME_WORDS], + v3[2 * MAX_RSA_PRIME_WORDS], q[2 * MAX_RSA_PRIME_WORDS], + r[2 * MAX_RSA_PRIME_WORDS], t1[2 * MAX_RSA_PRIME_WORDS], + t2[2 * MAX_RSA_PRIME_WORDS], t3[2 * MAX_RSA_PRIME_WORDS]; + + BigConst (u1, 1, k); + BigConst (u2, 0, k); + BigCopy (u3, u, k); + BigConst (v1, 0, k); + BigConst (v2, 1, k); + BigCopy (v3, v, k); + + /* Begin calc. + */ + while (1) { + if (BigSign (v3, k) == 0) + break; + BigPdiv (q, r, u3, v3, k, k); + BigPmpyl (t1, v1, q, k); + BigPmpyl (t2, v2, q, k); + BigPmpyl (t3, v3, q, k); + BigSub (t1, u1, t1, k); + BigSub (t2, u2, t2, k); + BigSub (t3, u3, t3, k); + + BigCopy (u1, v1, k); + BigCopy (u2, v2, k); + BigCopy (u3, v3, k); + BigCopy (v1, t1, k); + BigCopy (v2, t2, k); + BigCopy (v3, t3, k); + } + + if (BigSign (u1, k) == -1) + /* make positive */ + BigAdd (u1, u1, v, k); + + if (BigSign (u2, k) == -1) + /* make positive */ + BigAdd (u2, u2, u, k); + + T_memset ((POINTER)v1, 0, sizeof (v1)); + T_memset ((POINTER)v2, 0, sizeof (v2)); + T_memset ((POINTER)v3, 0, sizeof (v3)); + T_memset ((POINTER)q, 0, sizeof (q)); + T_memset ((POINTER)r, 0, sizeof (r)); + T_memset ((POINTER)t1, 0, sizeof (t1)); + T_memset ((POINTER)t2, 0, sizeof (t2)); + T_memset ((POINTER)t3, 0, sizeof (t3)); +} diff --git a/lib/bind/dnssafe/big2exp.c b/lib/bind/dnssafe/big2exp.c new file mode 100644 index 0000000000..c0793e23bf --- /dev/null +++ b/lib/bind/dnssafe/big2exp.c @@ -0,0 +1,27 @@ +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* Big2Exp (a, v, n) -- a = 2**v, where v is nonnegative int. + Sets a to be 2**v. + */ +void Big2Exp (a, v, n) +UINT2 *a; +unsigned v; +unsigned int n; +{ + register unsigned int i; + + for (i = 0; i < n; i++) + a[i] = 0; + a[v/16] = 1 << (v % 16); +} diff --git a/lib/bind/dnssafe/bigabs.c b/lib/bind/dnssafe/bigabs.c new file mode 100644 index 0000000000..0024cbf24f --- /dev/null +++ b/lib/bind/dnssafe/bigabs.c @@ -0,0 +1,24 @@ +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigAbs (a, b, n) -- a = ABS (b). + */ +void BigAbs (a, b, n) +UINT2 *a, *b; +unsigned int n; +{ + if (BigSign (b, n) >= 0) + BigCopy (a, b, n); + else + BigNeg (a, b, n); +} diff --git a/lib/bind/dnssafe/bigacc.c b/lib/bind/dnssafe/bigacc.c new file mode 100644 index 0000000000..3f84836451 --- /dev/null +++ b/lib/bind/dnssafe/bigacc.c @@ -0,0 +1,36 @@ +/* Copyright (C) RSA Data Security, Inc. created 1987, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* Returns carry: vector a = b * vector c. + */ +UINT2 BigAcc (a, b, c, n) +UINT2 *a; +unsigned int b; +UINT2 *c; +unsigned int n; +{ + UINT4 bTemp, result = (UINT4)0; + register unsigned int i; + + if (!b) + return (0); + + bTemp = b; + for (i = 0; i < n; i++) { + result += bTemp * ((UINT4) c[i]); + result += ((UINT4) a[i]); + a[i] = (UINT2) result; + result >>= 16; + } + return ((UINT2)result); +} diff --git a/lib/bind/dnssafe/bigarith.c b/lib/bind/dnssafe/bigarith.c new file mode 100644 index 0000000000..04fbe7c690 --- /dev/null +++ b/lib/bind/dnssafe/bigarith.c @@ -0,0 +1,140 @@ +/* Copyright (C) RSA Data Security, Inc. created 1987, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +void BigZero (a, n) +UINT2 *a; +unsigned int n; +{ + register unsigned int i; + + for (i = 0; i < n; i++) + a[i] = 0; +} + +void BigAdd (a, b, c, n) +UINT2 *a, *b, *c; +unsigned int n; +{ + UINT4 result = (UINT4)0; + register unsigned int i; + + for (i = 0; i < n; i++) { + result += (UINT4) b[i]; + result += (UINT4) c[i]; + a[i] = (UINT2) result; + result >>= 16; + } +} + +void BigSub (a, b, c, n) +UINT2 *a, *b, *c; +unsigned int n; +{ + UINT4 result = (UINT4)1; /* carry bit for negation of c */ + register unsigned int i; + + for (i = 0; i < n; i++) { + result += (UINT4) b[i]; + result += (((UINT4) ~c[i]) & 0x0000FFFFL); + a[i] = (UINT2)result; + result >>= 16; + } +} + +void BigNeg (a, b, n) +UINT2 *a, *b; +unsigned int n; +{ + register unsigned int i; + unsigned int carry = 1; + + for (i = 0; i < n-1; i++) { + a[i] = ~b[i] + carry; + if (a[i]) + carry = 0; + } + + a[i] = ~b[i] + carry; +} + +void BigInc (a, n) +UINT2 *a; +unsigned int n; +{ + register unsigned int i; + unsigned int carry = 1; /* carry to start */ + + for (i = 0; i < n-1 && carry; i++) { + a[i]++; + if (a[i]) + carry = 0; + } + + if (carry) + a[i]++; +} + +void BigDec (a, n) +UINT2 *a; +unsigned int n; +{ + register unsigned int i; + unsigned int borrow = 1; /* borrow to start */ + + for (i = 0; i < n-1 && borrow; i++) { + a[i]--; + if (a[i] != 0xFFFF) + borrow = 0; + } + + if (borrow) + a[i]--; +} + +int BigSign (a, n) +UINT2 *a; +unsigned int n; +{ + register int i; + + if (a[n-1] & 0x8000) + return (-1); + for (i = n-1; i >= 0; i--) + if (a[i]) + return (1); + return (0); +} + +void BigCopy (a, b, n) +UINT2 *a, *b; +unsigned int n; +{ + register unsigned int i; + + for (i = 0; i < n; i++) + a[i] = b[i]; +} + +/* Assumes a is nonnegative. + */ +unsigned int BigLenw (a, n) +UINT2 *a; +unsigned int n; +{ + register int i; + + for (i = n-1; i >= 0; i--) + if (a[i]) + return (i+1); + return (0); +} diff --git a/lib/bind/dnssafe/bigcmp.c b/lib/bind/dnssafe/bigcmp.c new file mode 100644 index 0000000000..514e2b92c6 --- /dev/null +++ b/lib/bind/dnssafe/bigcmp.c @@ -0,0 +1,36 @@ +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* Comparison operator. + BigCmp (a, b, n) -- returns sign of a-b. + */ +int BigCmp (a, b, n) +UINT2 *a, *b; +unsigned int n; +{ + register int i; + int aSign = BigSign (a, n), bSign = BigSign (b, n); + + if (aSign > bSign) + return (1); + if (aSign < bSign) + return (-1); + + for (i = n-1; i >= 0 && a[i] == b[i]; i--); + + if (i == -1) + return (0); + if (a[i] > b[i]) + return (1); + return (-1); +} diff --git a/lib/bind/dnssafe/bigconst.c b/lib/bind/dnssafe/bigconst.c new file mode 100644 index 0000000000..85a6870cee --- /dev/null +++ b/lib/bind/dnssafe/bigconst.c @@ -0,0 +1,28 @@ +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigConst (a, v, n) -- a = v, where v is an int. Initialize bignum a to + value v. + */ +void BigConst (a, v, n) +UINT2 *a; +unsigned int v; +unsigned int n; +{ + UINT2 signWord = (((UINT2)v & 0x8000) ? ~0 : 0); + register unsigned int i; + + a[0] = (UINT2)v; + for (i = 1; i < n; i++) + a[i] = signWord; +} diff --git a/lib/bind/dnssafe/biginv.c b/lib/bind/dnssafe/biginv.c new file mode 100644 index 0000000000..047902e0a2 --- /dev/null +++ b/lib/bind/dnssafe/biginv.c @@ -0,0 +1,105 @@ +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +static unsigned int Log2 PROTO_LIST ((unsigned int)); + +/* BigInv (a, b, n) -- compute a as an "inverse" to b, suitable for + modding out integers which are < b**2. + -- assumes a has n+2 words, b has n words. + -- assumes b is a positive integer. + */ +void BigInv (a, b, n) +UINT2 *a, *b; +unsigned int n; +{ + UINT2 p[2 * (MAX_RSA_MODULUS_WORDS + 2)], + q[2 * (MAX_RSA_MODULUS_WORDS + 3)], t1[MAX_RSA_MODULUS_WORDS + 3]; + register int i; + unsigned int bl, u, uw, sw; + + /* Do initializations. + */ + /* 2** (bl-1) <= b < 2 ** bl */ + bl = BigLen (b, n); + u = BigU (2 * bl); + + /* uw and sw are in words */ + uw = u/16; + sw = (bl - 2) / 16; + + /* since a = floor ((2**u)/b), 2**(u-bl) < a <= 2**(u-bl+1) */ + + /* Initialize a to 1+2**(u-bl) -- we will converge from below. + */ + Big2Exp (a, u - bl, n + 2); + BigInc (a, n + 2); + + /* Copy b to local register. + */ + BigZero (t1, n + 3); + BigCopy (t1, b, n); + + /* Convergence is quadratic, so iterate log (len (a)) times. + */ + for (i = 1 + Log2 (u - bl + 1); i > 0; i--) { + /* use fast squaring routine to compute p = a**2 + 2**(2 * (u-bl)) < p <= 2**(2 * (u-bl+1)) */ + BigPsq (p, a, n + 2); + + /* compute q = b * floor (p/ (2**s)) + 2**(2 * (u-bl)-s+bl-1) <= q <= 2**(2 * (u-bl+1)-s+bl + 2**(2 * u-bl-s-1) <= q <= 2**(2 * u-bl-s+2) */ + BigPmpy (q, t1, &p[sw], n + 3); + + /* double a + 2**(u-bl+1) < a <= 2**(u-bl+2) */ + BigAdd (a, a, a, n + 2); + /* a = a - floor (q/(2**(u-s))) + 2**(u-bl) < a <= 2**(u-bl+1) + epsilon */ + BigSub (a, a, &q[uw-sw], n + 2); + } + + /* now we are guaranteed that a is not too small */ + BigInc (a, n + 2); + + while (1) { + BigPmpy (p, a, t1, n + 2); + /* makes comparison to 2**u easier */ + BigDec (p, 2 * (n + 2)); + + /* a is desired result */ + if (BigLen (p, 2 * (n + 2)) <= u) + break; + + /* a was too big, reduce and try again */ + BigDec (a, n + 2); + } + + T_memset ((POINTER)p, 0, sizeof (p)); + T_memset ((POINTER)q, 0, sizeof (q)); + T_memset ((POINTER)t1, 0, sizeof (t1)); +} + +/* Log2 (x) -- ceiling of log base 2 of x > 0. Auxiliary function. + */ +static unsigned int Log2 (x) +unsigned int x; +{ + unsigned int i; + + x = x - 1; + /* now Log2 is equal to len in bits of x */ + for (i = 0; x > 0; i++, x >>= 1); + + return (i); +} diff --git a/lib/bind/dnssafe/biglen.c b/lib/bind/dnssafe/biglen.c new file mode 100644 index 0000000000..8a9eacb520 --- /dev/null +++ b/lib/bind/dnssafe/biglen.c @@ -0,0 +1,30 @@ +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +unsigned int BigLen (a, n) +UINT2 *a; +unsigned int n; +{ + UINT2 signWord = ((a[n-1] & 0x8000) ? ~0 : 0); + int i, j; + unsigned int k; + + for (i = n-1; i >= 0 && a[i] == signWord; i--); + if (i == -1) + return (1); /* len of 0 or -1 */ + + for (j = 16, k = 0x8000; + j >= 0 && 0 == (k & (signWord ^ a[i])); + j--, k >>= 1); + return (16 * i + j); +} diff --git a/lib/bind/dnssafe/bigmath.h b/lib/bind/dnssafe/bigmath.h new file mode 100644 index 0000000000..0cb5b4bebc --- /dev/null +++ b/lib/bind/dnssafe/bigmath.h @@ -0,0 +1,71 @@ +/* Copyright (C) RSA Data Security, Inc. created 1992, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _BIGMATH_H_ +#define _BIGMATH_H_ 1 + +#include "algae.h" +#include "bigmaxes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void Big2Exp PROTO_LIST ((UINT2 *, unsigned int, unsigned int)); +void BigAbs PROTO_LIST ((UINT2 *, UINT2 *, unsigned int)); +UINT2 BigAcc PROTO_LIST ((UINT2 *, unsigned int, UINT2 *, unsigned int)); +void BigZero PROTO_LIST ((UINT2 *, unsigned int)); +void BigAdd PROTO_LIST ((UINT2 *, UINT2 *, UINT2 *, unsigned int)); +void BigSub PROTO_LIST ((UINT2 *, UINT2 *, UINT2 *, unsigned int)); +void BigNeg PROTO_LIST ((UINT2 *, UINT2 *, unsigned int)); +void BigInc PROTO_LIST ((UINT2 *, unsigned int)); +void BigDec PROTO_LIST ((UINT2 *, unsigned int)); +int BigSign PROTO_LIST ((UINT2 *, unsigned int)); +void BigCopy PROTO_LIST ((UINT2 *, UINT2 *, unsigned int)); +unsigned int BigLenw PROTO_LIST ((UINT2 *, unsigned int)); +void BigClrbit PROTO_LIST ((UINT2 *, unsigned int)); +void BigSetbit PROTO_LIST ((UINT2 *, unsigned int)); +int BigCmp PROTO_LIST ((UINT2 *, UINT2 *, unsigned int)); +void BigConst PROTO_LIST ((UINT2 *, unsigned int, unsigned int)); +void BigInv PROTO_LIST ((UINT2 *, UINT2 *, unsigned int)); +unsigned int BigLen PROTO_LIST ((UINT2 *, unsigned int)); +void BigModMpyx PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, unsigned int)); +void BigModSqx PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, UINT2 *, unsigned int)); +int BigModExp PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, UINT2 *, unsigned int, A_SURRENDER_CTX *)); +void BigModx PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, UINT2 *, unsigned int)); +void BigMpy PROTO_LIST ((UINT2 *, UINT2 *, UINT2 *, unsigned int)); +void BigPdiv PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, UINT2 *, unsigned int , unsigned int)); +void BigPegcd PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, unsigned int)); +void BigPmpy PROTO_LIST ((UINT2 *, UINT2 *, UINT2 *, unsigned int)); +void BigPmpyh PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, unsigned int, unsigned int)); +void BigPmpyl PROTO_LIST ((UINT2 *, UINT2 *, UINT2 *, unsigned int)); +void BigPsq PROTO_LIST ((UINT2 *, UINT2 *, unsigned int)); +void BigQrx PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, unsigned int)); +UINT2 BigSmod PROTO_LIST ((UINT2 *, unsigned int, unsigned int)); +int BigToCanonical PROTO_LIST + ((unsigned char *, unsigned int, UINT2 *, unsigned int)); +unsigned int BigU PROTO_LIST ((unsigned int)); +int BigUnexp PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, + unsigned int, A_SURRENDER_CTX *)); +int CanonicalToBig PROTO_LIST + ((UINT2 *, unsigned int, const unsigned char *, unsigned int)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/bind/dnssafe/bigmaxes.h b/lib/bind/dnssafe/bigmaxes.h new file mode 100644 index 0000000000..17182cb78d --- /dev/null +++ b/lib/bind/dnssafe/bigmaxes.h @@ -0,0 +1,47 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _BIGMAXES_H_ +#define _BIGMAXES_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_RSA_MODULUS_BITS 4096 + +#define BITS_TO_LEN(modulusBits) (((modulusBits) + 7) / 8) +#define RSA_PRIME_BITS(modulusBits) (((modulusBits) + 1) / 2) +#define RSA_PRIME_LEN(modulusBits) ((RSA_PRIME_BITS (modulusBits) + 7) / 8) +#define BITS_TO_WORDS(bits) ((bits >> 4) + 1) +#define LEN_TO_WORDS(len) ((len >> 1) + 1) + +/* MAX_RSA_PRIME_BITS -- length in bits of the maximum allowed RSA prime + MAX_RSA_MODULUS_LEN -- length in bytes of the maximum allowed RSA modulus, + in canonical format (no sign bit) + MAX_RSA_PRIME_LEN -- length in bytes of the maximum allowed RSA prime, in + canonical format (no sign bit) + */ +#define MAX_RSA_PRIME_BITS RSA_PRIME_BITS (MAX_RSA_MODULUS_BITS) +#define MAX_RSA_PRIME_LEN RSA_PRIME_LEN (MAX_RSA_MODULUS_BITS) +#define MAX_RSA_MODULUS_LEN BITS_TO_LEN (MAX_RSA_MODULUS_BITS) + +/* MAX_RSA_MODULUS_WORDS -- length in 16-bit words of the maximum allowed RSA + modulus, in bignum format (including sign bit) + MAX_RSA_PRIME_WORDS -- length in 16-bit words of the maximum allowed RSA + prime, in bignum format (including sign bit) + */ + +#define MAX_RSA_MODULUS_WORDS BITS_TO_WORDS (MAX_RSA_MODULUS_BITS) +#define MAX_RSA_PRIME_WORDS BITS_TO_WORDS (MAX_RSA_PRIME_BITS) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/bind/dnssafe/bigmodx.c b/lib/bind/dnssafe/bigmodx.c new file mode 100644 index 0000000000..af25041790 --- /dev/null +++ b/lib/bind/dnssafe/bigmodx.c @@ -0,0 +1,27 @@ +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigModx (a, b, c, cInv, n) -- compute a as (b mod c). + -- assumes a and c of length n, cInv of length n + 2, b of length 2n. + -- assumes cInv computed with BigInv, and that b < c**2. + */ +void BigModx (a, b, c, cInv, n) +UINT2 *a, *b, *c, *cInv; +unsigned int n; +{ + UINT2 q[MAX_RSA_MODULUS_WORDS]; + + BigQrx (q, a, b, c, cInv, n); + + T_memset ((POINTER)q, 0, sizeof (q)); +} diff --git a/lib/bind/dnssafe/bigmpy.c b/lib/bind/dnssafe/bigmpy.c new file mode 100644 index 0000000000..3bea934e33 --- /dev/null +++ b/lib/bind/dnssafe/bigmpy.c @@ -0,0 +1,38 @@ +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigMpy (a, b, c, n) -- a = b * c + -- assumes b and c have n words, a has 2*n words + -- inputs may be positive or negative. + */ +void BigMpy (a, b, c, n) +UINT2 *a, *b, *c; +unsigned int n; +{ + UINT2 prod[2 * MAX_RSA_PRIME_WORDS], absb[MAX_RSA_PRIME_WORDS], + absc[MAX_RSA_PRIME_WORDS]; + int bSign = BigSign (b, n), cSign = BigSign (c, n); + + BigAbs (absb, b, n); + BigAbs (absc, c, n); + BigPmpy (prod, absb, absc, n); + + if (bSign * cSign >= 0) + BigCopy (a, prod, 2 * n); + else + BigNeg (a, prod, 2 * n); + + T_memset ((POINTER)prod, 0, sizeof (prod)); + T_memset ((POINTER)absb, 0, sizeof (absb)); + T_memset ((POINTER)absc, 0, sizeof (absc)); +} diff --git a/lib/bind/dnssafe/bigpdiv.c b/lib/bind/dnssafe/bigpdiv.c new file mode 100644 index 0000000000..92aa189bbf --- /dev/null +++ b/lib/bind/dnssafe/bigpdiv.c @@ -0,0 +1,161 @@ +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigPdiv POSITIVE DIVIDE + uu=vv * qi+ri + uu in reg of ll cells + vv in reg of kk cells + qi assumed to be ll cells + ri assumed to be kk cells + restriction uu>=0, vv>0 + + input uu in reg of ll cells + input vv in reg of kk cells + output qi assumed to be ll cells + output ri assumed to be kk cells + restriction uu>=0, vv>0 + uu=vv * qi+ri + */ +#define UJN (u[(j+n)/2] & mk[(j+n)%2]) +#define VN (v[n/2] & mk[n%2]) +#define UT (u[t/2] & mk[t%2]) +void BigPdiv (qi, ri, uu, vv, ll, kk) +UINT2 *qi, *ri, *uu, *vv; +unsigned int ll, kk; +{ + UINT2 u[2 * MAX_RSA_PRIME_WORDS + 2], us[2 * MAX_RSA_PRIME_WORDS + 2], + v[2 * MAX_RSA_PRIME_WORDS + 2], vs[2 * MAX_RSA_PRIME_WORDS + 2], + q[2 * MAX_RSA_PRIME_WORDS + 2], r[2 * MAX_RSA_PRIME_WORDS + 2], + t1[2 * MAX_RSA_PRIME_WORDS + 2], t2[2 * MAX_RSA_PRIME_WORDS + 2], + t3[2 * MAX_RSA_PRIME_WORDS + 2], mk[2]; + int j, l, n, m, t, x; + unsigned int a, b, c, d, e, vh, qq; + + if (ll >= kk) + l = ll + 2; + else + l = kk + 2; + + mk[0] = 0x00FF; + mk[1] = 0xFF00; + b = 0x0100; + + BigConst (u, 0, l); + BigConst (v, 0, l); + BigCopy (u, uu, ll); + BigCopy (us, u, l); + BigCopy (v, vv, kk); + BigCopy (vs, v, l); + + /* zero q */ + BigConst (q, 0, l); + + /* Calculate len of v=n. + */ + for (n = (2 * l) - 1; n >= 0; n--) { + if (VN == 0) + continue; + break; + } + + /* Normalize. + */ + a = VN; + if (n % 2 == 1) + a = a >> 8; + d = b / (a+1); + BigConst (t1, d, l); + BigPmpyl (t2, t1, v, l); + BigCopy (v, t2, l); + + /* vh=high order digit of normalized v */ + vh = VN; + if (n % 2 == 1) + vh = vh >> 8; + BigPmpyl (t2, t1, u, l); + BigCopy (u, t2, l); + + /* Calculate len of u=t. + */ + for (t = (2 * l)-1; t >= 0; t--) { + if (UT == 0) + continue; + break; + } + + /* calc t = n + m */ + m = t - n; + + /* Divide u by v. + */ + for (j = m + 1 + n; j > n; j--) { + if (j % 2 == 1) + c = u[j / 2]; + else { + a = u[j/2]; + a = a << 8; + e = u[(j - 1) / 2]; + e = e >> 8; + c = a + e; + } + a = c >> 8; + if (vh == a) + qq = b - 1; + else + qq = c / vh; + + BigConst (t1, qq, l); + BigPmpyl (t2, v, t1, l); + Big2Exp (t3, (j - 1 - n) * 8, l); + BigPmpyl (t1, t3, t2, l); + BigSub (t2, u, t1, l); + + /* Adjust q. + */ + for (x = 0; ; qq --, x ++) { + if (BigSign (t2, l) != -1) + break; + BigPmpyl (t1, t3, v, l); + BigAdd (t2, t2, t1, l); + } + + BigCopy (u, t2, l); + BigConst (t3, qq, l); + Big2Exp (t2, 8, l); + BigPmpyl (t1, q, t2, l); + BigAdd (q, t3, t1, l); + } + + /* Check result. + */ + + BigPmpyl (t1, vs, q, l); + /* t2 has remainder */ + BigSub (t2, us, t1, l); + + BigSub (t3, vs, t2, l); + + /* transfer results to input registers */ + BigCopy (qi, q, ll); + BigCopy (ri, t2, kk); + + T_memset ((POINTER)u, 0, sizeof (u)); + T_memset ((POINTER)us, 0, sizeof (us)); + T_memset ((POINTER)v, 0, sizeof (v)); + T_memset ((POINTER)vs, 0, sizeof (vs)); + T_memset ((POINTER)q, 0, sizeof (q)); + T_memset ((POINTER)r, 0, sizeof (r)); + T_memset ((POINTER)t1, 0, sizeof (t1)); + T_memset ((POINTER)t2, 0, sizeof (t2)); + T_memset ((POINTER)t3, 0, sizeof (t3)); +} diff --git a/lib/bind/dnssafe/bigpmpy.c b/lib/bind/dnssafe/bigpmpy.c new file mode 100644 index 0000000000..ff5b441d94 --- /dev/null +++ b/lib/bind/dnssafe/bigpmpy.c @@ -0,0 +1,27 @@ +/* Copyright (C) RSA Data Security, Inc. created 1987, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* a = b * c. + */ +void BigPmpy (a, b, c, n) +UINT2 *a, *b, *c; +unsigned int n; +{ + register unsigned int i; + unsigned int cLen; + + BigZero (a, 2*n); + cLen = BigLenw (c, n); + for (i = 0; i < n; i++) + a[cLen+i] = BigAcc (&a[i], (unsigned int)b[i], c, cLen); +} diff --git a/lib/bind/dnssafe/bigpmpyh.c b/lib/bind/dnssafe/bigpmpyh.c new file mode 100644 index 0000000000..94fcc25457 --- /dev/null +++ b/lib/bind/dnssafe/bigpmpyh.c @@ -0,0 +1,32 @@ +/* Copyright (C) RSA Data Security, Inc. created 1987, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* Returns high order t bytes of result. + */ +void BigPmpyh (a, b, c, t, n) +UINT2 *a, *b, *c; +unsigned int t, n; +{ + register unsigned int i; + unsigned int iStart, cLen, j; + + BigZero (a, 2*n); + cLen = BigLenw (c, n); + iStart = (t >= n-1) ? t - (n-1) : 0; + + for (i = iStart; i < n; i++) { + j = (t >= i) ? t - i : 0; + a[cLen+i] = BigAcc + (&a[i+j], (unsigned int)b[i], &c[j], (cLen >= j) ? cLen-j : 0); + } +} diff --git a/lib/bind/dnssafe/bigpmpyl.c b/lib/bind/dnssafe/bigpmpyl.c new file mode 100644 index 0000000000..dffd70d0a8 --- /dev/null +++ b/lib/bind/dnssafe/bigpmpyl.c @@ -0,0 +1,32 @@ +/* Copyright (C) RSA Data Security, Inc. created 1987, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* Single precision multiply, a is same len as b and c. + Returns low order n bytes of result. + */ +void BigPmpyl (a, b, c, n) +UINT2 *a, *b, *c; +unsigned int n; +{ + register unsigned int i; + unsigned int cLen; + + BigZero (a, n); + cLen = BigLenw (c, n); + for (i = 0; i < n; i++) { + if (cLen < n-i) + a[cLen+i] = BigAcc (&a[i], (unsigned int)b[i], c, cLen); + else + BigAcc (&a[i], (unsigned int)b[i], c, n-i); + } +} diff --git a/lib/bind/dnssafe/bigpsq.c b/lib/bind/dnssafe/bigpsq.c new file mode 100644 index 0000000000..97f0366f35 --- /dev/null +++ b/lib/bind/dnssafe/bigpsq.c @@ -0,0 +1,44 @@ +/* Copyright (C) RSA Data Security, Inc. created 1987, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* Similar to BigPmpy (a, b, b, n) but faster. + */ +void BigPsq (a, b, n) +UINT2 *a, *b; +unsigned int n; +{ + UINT4 result = (UINT4)0; + register unsigned int i; + unsigned int bLen; + + BigZero (a, 2*n); + bLen = BigLenw (b, n); + if (!bLen) + return; + + for (i = 0; i < bLen-1; i++) + a[bLen+i] = BigAcc (&a[2*i+1], (unsigned int)b[i], &b[i+1], bLen-i-1); + BigAdd (a, a, a, 2*n); + + /* add in trace b[i] * b[i] */ + for (i = 0; i < bLen; i++) { + result += ((UINT4)b[i]) * ((UINT4)b[i]); + result += (UINT4)a[2*i]; + a[2*i] = (UINT2)result; + result >>= 16; + result += (UINT4)a[2*i+1]; + a[2*i+1] = (UINT2)result; + result >>= 16; + } + a[2*i] = (UINT2)result; +} diff --git a/lib/bind/dnssafe/bigqrx.c b/lib/bind/dnssafe/bigqrx.c new file mode 100644 index 0000000000..2e27ee2eda --- /dev/null +++ b/lib/bind/dnssafe/bigqrx.c @@ -0,0 +1,87 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + + +/* BigQrx (q, r, b, c, cInv, n) -- compute quotient and remainder fast. + -- computes q and r s.t. b = q * c + r with 0 <= r < c. + -- assumes b and c are positive integers. + -- assumes q, r, c have n words, cInv has n+2 words, b has 2*n words. + -- assumes cInv previously computed with BigInv. + */ +void BigQrx (q, r, b, c, cInv, n) +UINT2 *q, *r, *b, *c, *cInv; +unsigned int n; +{ + UINT2 qc[2 * (MAX_RSA_MODULUS_WORDS + 2)], /* current product of q and c */ + qsc[2 * (MAX_RSA_MODULUS_WORDS + 2)], /* temporary q scaled by 2**(u-s) */ + t1[2 * MAX_RSA_MODULUS_WORDS + 2]; + int uwsw3; + register unsigned int i; + unsigned int u, uw, cl, sw; + + /* 2**(cl-1) <= c < 2**cl + 2**(u-cl) <= cInv <= 2**(u-cl+1) */ + cl = BigLen (c, n); + + /* u is in bits, uw is in words */ + u = BigU (2 * cl); + uw = u/16; + + /* sw is in words, s is is bits */ + sw = (cl - 2) / 16; + + uwsw3 = uw - sw - 3; + + if (uwsw3 < 0) + uwsw3 = 0; + + /* Copy b to local register. + */ + BigZero (t1, 2 * n + 2); + BigCopy (t1, b, 2 * n); + + /* Compute qsc = cInv * floor (b/ (2**s)). + qsc an approximation to (b/c) * (2**(u-s)) + 2**((u-cl)+ (bl-1-s)) <= qsc 2**((u-cl+1)+ (bl-s)) + 2**(u-cl+bl-s-1) <= qsc <= 2 ** (u-cl+bl-s+1) + (Actually, we only compute a "high-order" approximation + to qsc, by using BigPmpyh.) + */ + BigPmpyh (qsc, cInv, &t1[sw], uwsw3, n + 2); + + /* Divide by 2**(u-s) to get initial estimate for quotient q + 2**(bl-cl-1) <= q <= 2**(bl-cl+1) (unless q = 0). + */ + for (i = 0; i < n; i++) + q[i] = qsc[i+ (uw - sw)]; + + /* compute qc = low-order part of q * c + 2 ** (bl - 2) <= qc <= 2 ** (bl + 1) */ + BigPmpyl (qc, q, c, n); + + /* subtract qc from b to get initial estimate for remainder r */ + BigSub (r, b, qc, n); + + /* Adjust to be exactly right by repeated subtraction. + */ + while (BigCmp (r, c, n) >= 0) { + BigSub (r, r, c, n); + BigInc (q, n); + } + + T_memset ((POINTER)qc, 0, sizeof (qc)); + T_memset ((POINTER)qsc, 0, sizeof (qsc)); + T_memset ((POINTER)t1, 0, sizeof (t1)); +} + + diff --git a/lib/bind/dnssafe/bigsmod.c b/lib/bind/dnssafe/bigsmod.c new file mode 100644 index 0000000000..7e54ff9e39 --- /dev/null +++ b/lib/bind/dnssafe/bigsmod.c @@ -0,0 +1,30 @@ +/* Copyright (C) RSA Data Security, Inc. created 1987, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +UINT2 BigSmod (a, v, n) +UINT2 *a; +unsigned int v; +unsigned int n; +{ + UINT4 r = (UINT4)0; + register int i; + unsigned int scale; + + scale = (unsigned int)((UINT4)65536 % (UINT4)v); + + for (i = n-1; i >= 0; i--) { + r = (r*scale) + (UINT4)a[i]; + r = r % (UINT4)v; + } + return ((UINT2)r); +} diff --git a/lib/bind/dnssafe/bigtocan.c b/lib/bind/dnssafe/bigtocan.c new file mode 100644 index 0000000000..2ab03a713a --- /dev/null +++ b/lib/bind/dnssafe/bigtocan.c @@ -0,0 +1,62 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bigmath.h" +#include "port_after.h" + + +/* BigToCanonical () copies a word vector to a byte vector while REVERSING the + order of significance. The word vector is input LSWord first and the + byte vector is written out MSByte first. It also removes a leading zero + sign bit. (The byte vector must represent a nonnegative number.) + Returns 0, AE_DATA. + */ +int BigToCanonical (bytePointer, numBytes, wordPointer, wordCount) +unsigned char *bytePointer; +unsigned int numBytes; +UINT2 *wordPointer; +unsigned int wordCount; +{ + unsigned int copyCount; + + if (BigSign (wordPointer, wordCount) < 0 || + (BigLen (wordPointer, wordCount) + 7) / 8 > numBytes) + return (AE_DATA); + + /* start at end of byte vector */ + bytePointer += numBytes-1; + + /* copy as much as possible */ + copyCount = (wordCount < numBytes / 2) ? wordCount : numBytes / 2; + wordCount -= copyCount; + numBytes -= 2 * copyCount; + while (copyCount--) { + /* Copy two bytes.*/ + *bytePointer-- = (unsigned char)*wordPointer; + *bytePointer-- = (unsigned char)(*wordPointer >> 8); + wordPointer++; + } + + if (wordCount && numBytes & 1) { + /* The number of output bytes was odd. Copy one last byte */ + *bytePointer-- = (unsigned char)*wordPointer++; + wordCount--; + numBytes--; + } + + /* zero fill remainder of byte vector */ + while (numBytes--) + *bytePointer-- = 0; + + return (0); +} + + diff --git a/lib/bind/dnssafe/bigu.c b/lib/bind/dnssafe/bigu.c new file mode 100644 index 0000000000..9c51e26df7 --- /dev/null +++ b/lib/bind/dnssafe/bigu.c @@ -0,0 +1,23 @@ +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigU (t) -- returns length u where floor (2**u/b) is used as scaled version + of (1/b) when modding out modulo b, and where (positive) integers to be + reduced are < 2**t; i.e. they are at most t bits in length. + Result is (t+1) rounded up if necessary to next multiple of 16. +*/ +unsigned int BigU (t) +unsigned int t; +{ + return (16 * (((t+1) + 15)/16)); +} diff --git a/lib/bind/dnssafe/bigunexp.c b/lib/bind/dnssafe/bigunexp.c new file mode 100644 index 0000000000..9db983420a --- /dev/null +++ b/lib/bind/dnssafe/bigunexp.c @@ -0,0 +1,100 @@ +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "surrendr.h" +#include "port_after.h" + +/* BigUnexp - decrypt ciphertext c into message m using Chinese remainder. + Assumes m, c of length 2*pSize, pp, qq, dp, dq and cr of length pSize. + Returns 0, AE_CANCEL. + */ +int BigUnexp (m, c, pp, qq, dp, dq, cr, pSize, surrenderContext) +UINT2 *m; /* output message size 2*pSize words */ +UINT2 *c; /* input `ciphertext' size 2*pSize */ +UINT2 *pp; /* first prime size pSize */ +UINT2 *qq; /* second prime; size pSize */ +UINT2 *dp; /* decryption exponent mod p size pSize */ +UINT2 *dq; /* decryption exponent mod q size pSize */ +UINT2 *cr; /* CRT coef (inverse of q mod p) cr has len pSize */ +unsigned int pSize; /* length of p in words */ +A_SURRENDER_CTX *surrenderContext; +{ + struct BigUnexpFrame { + UINT2 t1[2 * MAX_RSA_PRIME_WORDS], t2[2 * MAX_RSA_PRIME_WORDS], + t3[2 * MAX_RSA_PRIME_WORDS], u1[2 * MAX_RSA_PRIME_WORDS], + u2[2 * MAX_RSA_PRIME_WORDS], u3[2 * MAX_RSA_PRIME_WORDS]; + } *frame = (struct BigUnexpFrame *)NULL_PTR; +#if !USE_ALLOCED_FRAME + struct BigUnexpFrame stackFrame; +#endif + int status; + + do { +#if USE_ALLOCED_FRAME + if ((frame = (struct BigUnexpFrame *)T_malloc (sizeof (*frame))) + == (struct BigUnexpFrame *)NULL_PTR) { + status = AE_ALLOC; + break; + } +#else + /* Just use the buffers allocated on the stack. */ + frame = &stackFrame; +#endif + + BigConst (frame->t1, 0, 2 * pSize); + BigConst (frame->t2, 0, 2 * pSize); + + /* u2=c mod p */ + BigPdiv (frame->u1, frame->u2, c, pp, 2 * pSize, pSize); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + + /* t1=c**dp modP */ + if ((status = BigModExp + (frame->t1, frame->u2, dp, pp, pSize, surrenderContext)) != 0) + break; + + /* u3=CmodQ */ + BigPdiv (frame->u2, frame->u3, c, qq, 2 * pSize, pSize); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + + /* t2=c**DQmodQ */ + if ((status = BigModExp + (frame->t2, frame->u3, dq, qq, pSize, surrenderContext)) != 0) + break; + + /* CRT. + */ + BigSub (frame->u1, frame->t1, frame->t2, pSize); + + while (-1 == BigSign (frame->u1, pSize)) + BigAdd (frame->u1, frame->u1, pp, pSize); + + BigMpy (frame->u2, frame->u1, cr, pSize); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + BigPdiv (frame->u3, frame->u1, frame->u2, pp, 2 * pSize, pSize); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + BigMpy (m, frame->u1, qq, pSize); + + BigAdd (m, m, frame->t2, 2 * pSize); + } while (0); + + if (frame != (struct BigUnexpFrame *)NULL_PTR) { + T_memset ((POINTER)frame, 0, sizeof (*frame)); +#if USE_ALLOCED_FRAME + T_free ((POINTER)frame); +#endif + } + return (status); +} diff --git a/lib/bind/dnssafe/binfocsh.c b/lib/bind/dnssafe/binfocsh.c new file mode 100644 index 0000000000..bde32ea096 --- /dev/null +++ b/lib/bind/dnssafe/binfocsh.c @@ -0,0 +1,65 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "binfocsh.h" +#include "port_after.h" + +void B_InfoCacheConstructor (infoCache) +B_InfoCache *infoCache; +{ + /* Construct immediate base class. */ + B_MemoryPoolConstructor (&infoCache->memoryPool); + + T_memset ((POINTER)&infoCache->z, 0, sizeof (infoCache->z)); +} + +/* Returns 0, BE_ALLOC. + */ +int B_InfoCacheAddInfo (infoCache, infoType, info) +B_InfoCache *infoCache; +POINTER infoType; +POINTER info; +{ + int status; + + if ((status = B_MemoryPoolRealloc + (&infoCache->memoryPool, (POINTER *)&infoCache->z.infos, + (infoCache->z.infoCount + 1) * sizeof (infoCache->z.infos[0]))) != 0) + return (status); + + infoCache->z.infos[infoCache->z.infoCount].infoType = infoType; + infoCache->z.infos[infoCache->z.infoCount].info = info; + infoCache->z.infoCount++; + + return (0); +} + +/* Set info to the entry in the cache for the given infoType. + Returns 0, or BE_NOT_SUPPORTED if infoType is not in the cache. + */ +int B_InfoCacheFindInfo (infoCache, info, infoType) +B_InfoCache *infoCache; +POINTER *info; +POINTER infoType; +{ + unsigned int i; + + for (i = 0; i < infoCache->z.infoCount; ++i) { + if (infoCache->z.infos[i].infoType == infoType) { + /* The info has already been constructed. */ + *info = infoCache->z.infos[i].info; + return (0); + } + } + + return (BE_NOT_SUPPORTED); +} + diff --git a/lib/bind/dnssafe/binfocsh.h b/lib/bind/dnssafe/binfocsh.h new file mode 100644 index 0000000000..32778765db --- /dev/null +++ b/lib/bind/dnssafe/binfocsh.h @@ -0,0 +1,33 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _BINFOCSH_H_ +#define _BINFOCSH_H_ 1 + +#include "bmempool.h" + +typedef struct B_InfoCache { + B_MemoryPool memoryPool; /* inherited */ + struct { + unsigned int infoCount; + struct { + POINTER infoType; + POINTER info; + } *infos; + /* POINTER reserved; */ + } z; /* z gives the members that are zeroized by the constructor */ +} B_InfoCache; + +void B_InfoCacheConstructor PROTO_LIST ((B_InfoCache *)); +#define B_INFO_CACHE_Destructor(infoCache) \ + B_MemoryPoolDestructor (&(infoCache)->memoryPool) + +int B_InfoCacheAddInfo PROTO_LIST ((B_InfoCache *, POINTER, POINTER)); +int B_InfoCacheFindInfo PROTO_LIST ((B_InfoCache *, POINTER *, POINTER)); + +#endif diff --git a/lib/bind/dnssafe/bkey.c b/lib/bind/dnssafe/bkey.c new file mode 100644 index 0000000000..a4e348dcf7 --- /dev/null +++ b/lib/bind/dnssafe/bkey.c @@ -0,0 +1,103 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "kinfotyp.h" +#include "kiitem.h" +#include "port_after.h" + +int B_KeySetInfo (key, keyInfoType, info) +B_Key *key; +B_KeyInfoType *keyInfoType; +POINTER info; +{ + if (key == (B_Key *)NULL_PTR) + return (BE_KEY_OBJ); + + if (key->infoCache.z.infoCount > 0) + return (BE_KEY_ALREADY_SET); + + /* This will cache the encoding. */ + return ((*keyInfoType->AddInfo) (key, info)); +} + +int B_KeyGetInfo (key, info, keyInfoType) +B_Key *key; +POINTER *info; +B_KeyInfoType *keyInfoType; +{ + int status; + + if (key == (B_Key *)NULL_PTR) + return (BE_KEY_OBJ); + + if (key->infoCache.z.infoCount == 0) + return (BE_KEY_NOT_SET); + + /* First check if the encoding is already in the encoding cache. + */ + if (B_InfoCacheFindInfo (&key->infoCache, info, (POINTER)keyInfoType) == 0) + return (0); + + /* Info is not in the cache, go ahead and encode. + */ + if ((status = (*keyInfoType->MakeInfo) (info, key)) != 0) + return (status); + + return (B_InfoCacheAddInfo (&key->infoCache, (POINTER)keyInfoType, *info)); +} + +/* Create an ITEM out of the data and len and cache it as KITItem. + The data is already alloced in the info cache. + Returns 0, BE_ALLOC. + */ +int B_KeyAddItemInfo (key, data, len) +B_Key *key; +unsigned char *data; +unsigned int len; +{ + ITEM *newInfo; + int status; + + if ((status = B_MemoryPoolAlloc + (&key->infoCache.memoryPool, (POINTER *)&newInfo, sizeof (*newInfo))) + != 0) + return (status); + + newInfo->data = data; + newInfo->len = len; + + return (B_InfoCacheAddInfo + (&key->infoCache, (POINTER)&KITItem, (POINTER)newInfo)); +} + +/* Return the number of bits in the canonical, positive integer. + B_IntegerBits (0) = 0. + */ +unsigned int B_IntegerBits (integer, integerLen) +unsigned char *integer; +unsigned int integerLen; +{ + unsigned char mask, byte; + unsigned int bytes, bits; + + for (bytes = 0; bytes < integerLen && integer[bytes] == 0; bytes++); + if (bytes == integerLen) + return (0); + + /* Get byte to test and increment byte count for final calculation */ + byte = integer[bytes++]; + + /* Get number of bits in most significant byte */ + for (bits = 8, mask = 0x80; (byte & mask) == 0; bits--, mask >>= 1); + return (8 * (integerLen - bytes) + bits); +} + diff --git a/lib/bind/dnssafe/bkey.h b/lib/bind/dnssafe/bkey.h new file mode 100644 index 0000000000..bfcaca7ac4 --- /dev/null +++ b/lib/bind/dnssafe/bkey.h @@ -0,0 +1,32 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _BKEY_H_ +#define _BKEY_H_ 1 + +#include "binfocsh.h" + +typedef struct { + B_InfoCache infoCache; /* inherited */ + + /* For now we don't need to worry about a reserved field. + struct { + POINTER reserved; + } z; + */ +} B_Key; + +#define B_KEY_Constructor(key) (B_InfoCacheConstructor (&(key)->infoCache)) +#define B_KEY_Destructor(key) (B_INFO_CACHE_Destructor (&(key)->infoCache)) + +struct B_KeyInfoType; +int B_KeySetInfo PROTO_LIST ((B_Key *, struct B_KeyInfoType *, POINTER)); +int B_KeyGetInfo PROTO_LIST ((B_Key *, POINTER *, struct B_KeyInfoType *)); +int B_KeyAddItemInfo PROTO_LIST ((B_Key *, unsigned char *, unsigned int)); + +#endif diff --git a/lib/bind/dnssafe/bmempool.c b/lib/bind/dnssafe/bmempool.c new file mode 100644 index 0000000000..b353f395ca --- /dev/null +++ b/lib/bind/dnssafe/bmempool.c @@ -0,0 +1,273 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bmempool.h" +#include "port_after.h" + +#define ALLOCED_LIST_SLACK 10 + +void B_MemoryPoolConstructor (memoryPool) +B_MemoryPool *memoryPool; +{ + T_memset ((POINTER)&memoryPool->z, 0, sizeof (memoryPool->z)); +} + +void B_MemoryPoolDestructor (memoryPool) +B_MemoryPool *memoryPool; +{ + B_MemoryPoolReset (memoryPool); + T_free ((POINTER)memoryPool->z.allocedList); +} + +/* For each item on the alloced list, call the DeleteFuncion if + there is one, otherwise zerioze and free. + Leave the list itself allocated with all NULL entries. + */ +void B_MemoryPoolReset (memoryPool) +B_MemoryPool *memoryPool; +{ + B_ALLOCED_DATA *allocedData; + unsigned int i; + + for (i = memoryPool->z.allocedCount, + allocedData = memoryPool->z.allocedList; + i-- > 0; + ++allocedData) { + /* Only process this entry if the data is not NULL_PTR. + */ + if (allocedData->object != NULL_PTR) { + if (allocedData->DeleteFunction != NULL) + /* There is a destroy function, so call. */ + (*allocedData->DeleteFunction) (allocedData->object); + else { + T_memset (allocedData->object, 0, allocedData->size); + T_free (allocedData->object); + } + allocedData->object = NULL_PTR; + } + } + + memoryPool->z.allocedCount = 0; + /* Note that maxAllocedCount still indicates the size of the alloced list. */ +} + +/* On any error return, NULL_PTR is returned for the data. + Returns 0 if successful, or BE_ALLOC if cannot alloc the memory. + */ +int B_MemoryPoolAlloc (memoryPool, data, size) +B_MemoryPool *memoryPool; +POINTER *data; +unsigned int size; +{ + if ((*data = T_malloc (size)) == NULL_PTR) + return (BE_ALLOC); + return (B_MemoryPoolAdoptData (memoryPool, data, size)); +} + +/* Use alloc to allocate the newData of length size and T_memcpy data into it. + On any error return, NULL_PTR is returned for the newData. + Returns 0 if successful or BE_ALLOC if cannot alloc the memory. + */ +int B_MemoryPoolAllocAndCopy (memoryPool, newData, data, size) +B_MemoryPool *memoryPool; +POINTER *newData; +POINTER data; +unsigned int size; +{ + int status; + + if ((status = B_MemoryPoolAlloc (memoryPool, newData, size)) != 0) + return (status); + + T_memcpy (*newData, data, size); + return (0); +} + +/* Put the given data on the memory pool's alloced list. + The size of the alloced data buffer must be passed in so that it can + be zeroized when the object is reset (Pass in a size of zero if + the buffer does not need to be zeroized.) + The data is passed by reference, so that if there is an error, + the data is zeroized and freed, and the pointer to the data is set + to NULL_PTR. + This routine should be used with caution - it is meant be called + immediately after an alloc. + No check is made as to whether the data is already on the memory pool's + alloced list (which would be a problem since it will get freed twice). + Returns 0 if successful or BE_ALLOC if cannot expand the alloced list. + */ +int B_MemoryPoolAdoptData (memoryPool, data, size) +B_MemoryPool *memoryPool; +POINTER *data; +unsigned int size; +{ + int status; + + if ((status = B_MemoryPoolAdoptHelper(memoryPool, *data, size, NULL)) != 0) { + T_memset (*data, 0, size); + T_free (*data); + *data = NULL_PTR; + return (status); + } + + return (0); +} + +/* Put the given object on the memory pool's alloced list. + The size of the alloced object must be passed in so that it can + be zeroized when the object is reset (Pass in a size of zero if + the buffer does not need to be zeroized, especially if it + is an object and not a data buffer.) + The object is not passed by reference. If there is an error, + the calling routine should clean up the object, such as zeroizing + and freeing. + No check is made as to whether the object is already on the memory pool's + alloced list (which would be a problem since it will get freed twice). + Returns 0 if successful or BE_ALLOC if cannot expand the alloced list. + */ +int B_MemoryPoolAdoptHelper (memoryPool, object, size, DeleteFunction) +B_MemoryPool *memoryPool; +POINTER object; +unsigned int size; +B_MEMORY_POOL_DELETE_FUNCTION DeleteFunction; +{ + POINTER newList; + unsigned int newMaxCount; + + if (memoryPool->z.allocedCount + 1 > memoryPool->z.maxAllocedCount) { + /* Make extra room on the alloced list. + */ + newMaxCount = memoryPool->z.allocedCount + ALLOCED_LIST_SLACK; + if ((newList = T_malloc (newMaxCount * sizeof (B_ALLOCED_DATA))) + == NULL_PTR) + /* alloc errorm so caller should clean up the object it passed. */ + return (BE_ALLOC); + + /* move in new list and free old list */ + T_memcpy + (newList, (POINTER)memoryPool->z.allocedList, + memoryPool->z.allocedCount * sizeof (B_ALLOCED_DATA)); + T_free ((POINTER)memoryPool->z.allocedList); + memoryPool->z.allocedList = (B_ALLOCED_DATA *)newList; + memoryPool->z.maxAllocedCount = newMaxCount; + } + + /* Put object on alloced list and increment count. + */ + memoryPool->z.allocedList[memoryPool->z.allocedCount].object = object; + memoryPool->z.allocedList[memoryPool->z.allocedCount].size = size; + memoryPool->z.allocedList[memoryPool->z.allocedCount++].DeleteFunction = + DeleteFunction; + return (0); +} + +/* 'data' points to the pointer to realloc and also is used to + return the realloced memory. + If data points to NULL_PTR, behaves like B_MemoryPoolAlloc. + Find 'data' on the allocedList and realloc it to the given size, + replacing the entry on the alloced list with the new memory. + If it is not on the allocedList, the adopt the reallocated memory. + If the buffer must be moved during the realloc, the old buffer is not + zeroized (unless T_realloc does the zeroizing). + This assumes that the (POINTER *)data is not (POINTER *)NULL_PTR. + This assumes there is no DesroyFunction for this entry. That is, + you should not try to resize an object. + On any error return, NULL_PTR is returned for the data. + Returns 0 if successful or BE_ALLOC if cannot alloc the memory. + */ +int B_MemoryPoolRealloc (memoryPool, data, size) +B_MemoryPool *memoryPool; +POINTER *data; +unsigned int size; +{ + B_ALLOCED_DATA *allocedData; + + allocedData = B_MemoryPoolFindAllocedObject (memoryPool, *data); + + if ((*data = T_realloc (*data, size)) == NULL_PTR) { + if (allocedData != (B_ALLOCED_DATA *)NULL_PTR) + /* Could not reallocate, so nullify this entry. */ + allocedData->object = NULL_PTR; + + return (BE_ALLOC); + } + + /* Realloc was successful. + */ + if (allocedData == (B_ALLOCED_DATA *)NULL_PTR) + /* The data was not in the memory pool to start with, so adopt it. + Note that this also happens when the data is initially NULL_PTR. */ + return (B_MemoryPoolAdoptData (memoryPool, data, size)); + + /* Replace the entry on the alloced list with the new memory. + */ + allocedData->object = *data; + allocedData->size = size; + return (0); +} + +/* Find the object in the alloced list, call the DeleteFunction if + there is one, zeroize it and free it, nullifying that alloced list entry. + The object to be freed is passed by pointer and is set to NULL_PTR to + enforce the fact that the address no longer points to valid memory. + This assumes that the (POINTER *)data is not (POINTER *)NULL_PTR. + If the address is not found on the alloced list, only set the address + to NULL_PTR. + */ +void B_MemoryPoolFree (memoryPool, object) +B_MemoryPool *memoryPool; +POINTER *object; +{ + B_ALLOCED_DATA *allocedData; + + if ((allocedData = B_MemoryPoolFindAllocedObject (memoryPool, *object)) + != (B_ALLOCED_DATA *)NULL_PTR) { + if (allocedData->DeleteFunction != NULL) + /* There is a destroy function, so call. */ + (*allocedData->DeleteFunction) (allocedData->object); + else { + T_memset (*object, 0, allocedData->size); + T_free (*object); + } + + /* Set this entry to NULL_PTR so that reset will not process it. */ + allocedData->object = NULL_PTR; + } + + *object = NULL_PTR; +} + +/* Return a pointer to the alloced object entry in the memoryPool. + Return (ALLOCED_DATA *)NULL_PTR if object is NULL_PTR or object is not + in the memoryPool. + */ +B_ALLOCED_DATA *B_MemoryPoolFindAllocedObject (memoryPool, object) +B_MemoryPool *memoryPool; +POINTER object; +{ + B_ALLOCED_DATA *allocedData; + unsigned int i; + + if (object == NULL_PTR) + return ((B_ALLOCED_DATA *)NULL_PTR); + + for (i = memoryPool->z.allocedCount, + allocedData = memoryPool->z.allocedList; + i-- > 0; + ++allocedData) { + if (allocedData->object == object) + return (allocedData); + } + + /* data not found. */ + return ((B_ALLOCED_DATA *)NULL_PTR); +} + diff --git a/lib/bind/dnssafe/bmempool.h b/lib/bind/dnssafe/bmempool.h new file mode 100644 index 0000000000..b5216dd2f2 --- /dev/null +++ b/lib/bind/dnssafe/bmempool.h @@ -0,0 +1,53 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _BMEMPOOL_H_ +#define _BMEMPOOL_H_ 1 + +typedef void (*B_MEMORY_POOL_DELETE_FUNCTION) PROTO_LIST ((POINTER)); + +typedef struct { + POINTER object; + unsigned int size; + B_MEMORY_POOL_DELETE_FUNCTION DeleteFunction; +} B_ALLOCED_DATA; + +typedef struct { + struct { + unsigned int allocedCount; + unsigned int maxAllocedCount; /* Size of the actuall allocated list */ + B_ALLOCED_DATA *allocedList; + /* POINTER reserved; */ + } z; /* z gives the members that are zeroized by the constructor */ +} B_MemoryPool; + +void B_MemoryPoolConstructor PROTO_LIST ((B_MemoryPool *)); +void B_MemoryPoolDestructor PROTO_LIST ((B_MemoryPool *)); + +void B_MemoryPoolReset PROTO_LIST ((B_MemoryPool *)); +int B_MemoryPoolAlloc PROTO_LIST ((B_MemoryPool *, POINTER *, unsigned int)); +int B_MemoryPoolAllocAndCopy PROTO_LIST + ((B_MemoryPool *, POINTER *, POINTER, unsigned int)); +int B_MemoryPoolAdoptData PROTO_LIST + ((B_MemoryPool *, POINTER *, unsigned int)); +int B_MemoryPoolAdoptObject PROTO_LIST + ((B_MemoryPool *, POINTER *, B_MEMORY_POOL_DELETE_FUNCTION)); +int B_MemoryPoolRealloc PROTO_LIST ((B_MemoryPool *, POINTER *, unsigned int)); +int B_MemoryPoolSafeRealloc PROTO_LIST + ((B_MemoryPool *, POINTER *, unsigned int)); +void B_MemoryPoolFree PROTO_LIST ((B_MemoryPool *, POINTER *)); +void B_MemoryPoolResetExceptObject PROTO_LIST ((B_MemoryPool *, POINTER)); + +/* These are "private member functions ". + */ +B_ALLOCED_DATA *B_MemoryPoolFindAllocedObject PROTO_LIST + ((B_MemoryPool *, POINTER)); +int B_MemoryPoolAdoptHelper PROTO_LIST + ((B_MemoryPool *, POINTER, unsigned int, B_MEMORY_POOL_DELETE_FUNCTION)); + +#endif diff --git a/lib/bind/dnssafe/bsafe2.h b/lib/bind/dnssafe/bsafe2.h new file mode 100644 index 0000000000..6dfbbf307e --- /dev/null +++ b/lib/bind/dnssafe/bsafe2.h @@ -0,0 +1,194 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _BSAFE_H_ +#define _BSAFE_H_ 1 + +#ifndef T_CALL +#define T_CALL +#endif + +#include "atypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BE_ALGORITHM_ALREADY_SET 0x0200 +#define BE_ALGORITHM_INFO 0x0201 +#define BE_ALGORITHM_NOT_INITIALIZED 0x0202 +#define BE_ALGORITHM_NOT_SET 0x0203 +#define BE_ALGORITHM_OBJ 0x0204 +#define BE_ALG_OPERATION_UNKNOWN 0x0205 +#define BE_ALLOC 0x0206 +#define BE_CANCEL 0x0207 +#define BE_DATA 0x0208 +#define BE_EXPONENT_EVEN 0x0209 +#define BE_EXPONENT_LEN 0x020a +#define BE_HARDWARE 0x020b +#define BE_INPUT_DATA 0x020c +#define BE_INPUT_LEN 0x020d +#define BE_KEY_ALREADY_SET 0x020e +#define BE_KEY_INFO 0x020f +#define BE_KEY_LEN 0x0210 +#define BE_KEY_NOT_SET 0x0211 +#define BE_KEY_OBJ 0x0212 +#define BE_KEY_OPERATION_UNKNOWN 0x0213 +#define BE_MEMORY_OBJ 0x0214 +#define BE_MODULUS_LEN 0x0215 +#define BE_NOT_INITIALIZED 0x0216 +#define BE_NOT_SUPPORTED 0x0217 +#define BE_OUTPUT_LEN 0x0218 +#define BE_OVER_32K 0x0219 +#define BE_RANDOM_NOT_INITIALIZED 0x021a +#define BE_RANDOM_OBJ 0x021b +#define BE_SIGNATURE 0x021c +#define BE_WRONG_ALGORITHM_INFO 0x021d +#define BE_WRONG_KEY_INFO 0x021e +#define BE_INPUT_COUNT 0x021f +#define BE_OUTPUT_COUNT 0x0220 +#define BE_METHOD_NOT_IN_CHOOSER 0x221 + +typedef POINTER B_KEY_OBJ; +typedef POINTER B_ALGORITHM_OBJ; + +typedef int (T_CALL *B_INFO_TYPE) PROTO_LIST ((POINTER *)); + +typedef struct B_ALGORITHM_METHOD B_ALGORITHM_METHOD; +typedef B_ALGORITHM_METHOD **B_ALGORITHM_CHOOSER; + +/* Routines supplied by the implementor. + */ +void T_CALL T_memset PROTO_LIST ((POINTER, int, unsigned int)); +void T_CALL T_memcpy PROTO_LIST ((POINTER, CPOINTER, unsigned int)); +void T_CALL T_memmove PROTO_LIST ((POINTER, POINTER, unsigned int)); +int T_CALL T_memcmp PROTO_LIST ((CPOINTER, CPOINTER, unsigned int)); +POINTER T_CALL T_malloc PROTO_LIST ((unsigned int)); +POINTER T_CALL T_realloc PROTO_LIST ((POINTER, unsigned int)); +void T_CALL T_free PROTO_LIST ((POINTER)); + +/* The key object. + */ +int T_CALL B_CreateKeyObject PROTO_LIST ((B_KEY_OBJ *)); +void T_CALL B_DestroyKeyObject PROTO_LIST ((B_KEY_OBJ *)); +int T_CALL B_SetKeyInfo PROTO_LIST ((B_KEY_OBJ, B_INFO_TYPE, POINTER)); +int T_CALL B_GetKeyInfo PROTO_LIST ((POINTER *, B_KEY_OBJ, B_INFO_TYPE)); + +/* The algorithm object. + */ +int T_CALL B_CreateAlgorithmObject PROTO_LIST ((B_ALGORITHM_OBJ *)); +void T_CALL B_DestroyAlgorithmObject PROTO_LIST ((B_ALGORITHM_OBJ *)); +int T_CALL B_SetAlgorithmInfo PROTO_LIST + ((B_ALGORITHM_OBJ, B_INFO_TYPE, POINTER)); +int T_CALL B_GetAlgorithmInfo PROTO_LIST + ((POINTER *, B_ALGORITHM_OBJ, B_INFO_TYPE)); + +unsigned int B_IntegerBits PROTO_LIST ((unsigned char *, unsigned int)); + +/* Algorithm operations. + */ +int T_CALL B_RandomInit PROTO_LIST + ((B_ALGORITHM_OBJ, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int T_CALL B_RandomUpdate PROTO_LIST + ((B_ALGORITHM_OBJ, unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int T_CALL B_GenerateRandomBytes PROTO_LIST + ((B_ALGORITHM_OBJ, unsigned char *, unsigned int, A_SURRENDER_CTX *)); + +int T_CALL B_DigestInit PROTO_LIST + ((B_ALGORITHM_OBJ, B_KEY_OBJ, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int T_CALL B_DigestUpdate PROTO_LIST + ((B_ALGORITHM_OBJ, const unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int T_CALL B_DigestFinal PROTO_LIST + ((B_ALGORITHM_OBJ, unsigned char *, unsigned int *, unsigned int, + A_SURRENDER_CTX *)); + +int T_CALL B_EncryptInit PROTO_LIST + ((B_ALGORITHM_OBJ, B_KEY_OBJ, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int T_CALL B_EncryptUpdate PROTO_LIST + ((B_ALGORITHM_OBJ, unsigned char *, unsigned int *, unsigned int, + unsigned char *, unsigned int, B_ALGORITHM_OBJ, A_SURRENDER_CTX *)); +int T_CALL B_EncryptFinal PROTO_LIST + ((B_ALGORITHM_OBJ, unsigned char *, unsigned int *, unsigned int, + B_ALGORITHM_OBJ, A_SURRENDER_CTX *)); + +int T_CALL B_DecryptInit PROTO_LIST + ((B_ALGORITHM_OBJ, B_KEY_OBJ, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int T_CALL B_DecryptUpdate PROTO_LIST + ((B_ALGORITHM_OBJ, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, unsigned int, B_ALGORITHM_OBJ, A_SURRENDER_CTX *)); +int T_CALL B_DecryptFinal PROTO_LIST + ((B_ALGORITHM_OBJ, unsigned char *, unsigned int *, unsigned int, + B_ALGORITHM_OBJ, A_SURRENDER_CTX *)); + + + +int T_CALL B_GenerateInit PROTO_LIST + ((B_ALGORITHM_OBJ, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int T_CALL B_GenerateKeypair PROTO_LIST + ((B_ALGORITHM_OBJ, B_KEY_OBJ, B_KEY_OBJ, B_ALGORITHM_OBJ, + A_SURRENDER_CTX *)); +int T_CALL B_GenerateParameters PROTO_LIST + ((B_ALGORITHM_OBJ, B_ALGORITHM_OBJ, B_ALGORITHM_OBJ, A_SURRENDER_CTX *)); + + +/* Information for password-based encryption (PBE) algorithms. + */ +typedef struct { + unsigned char *salt; /* salt value */ + unsigned int iterationCount; /* iteration count */ +} B_PBE_PARAMS; + +/* Information for MAC algorithm. + */ +typedef struct { + unsigned int macLen; /* length of MAC value */ +} B_MAC_PARAMS; + + +/* Information for BSAFE 1.x compatible encryption algorithms. + */ + + +typedef struct { + unsigned int threshold; /* share threshold */ +} B_SECRET_SHARING_PARAMS; + +/* Key Info Types. + */ +int T_CALL KI_8Byte PROTO_LIST ((POINTER *)); +int T_CALL KI_Item PROTO_LIST ((POINTER *)); +int T_CALL KI_PKCS_RSAPrivate PROTO_LIST ((POINTER *)); +int T_CALL KI_RSAPublic PROTO_LIST ((POINTER *)); +int T_CALL KI_RSA_CRT PROTO_LIST ((POINTER *)); + +/* Algorithm Info Types. + */ +int T_CALL AI_MD5 PROTO_LIST ((POINTER *)); +int T_CALL AI_MD5Random PROTO_LIST ((POINTER *)); +int T_CALL AI_PKCS_RSAPrivate PROTO_LIST ((POINTER *)); +int T_CALL AI_PKCS_RSAPublic PROTO_LIST ((POINTER *)); +int T_CALL AI_RSAKeyGen PROTO_LIST ((POINTER *)); +int T_CALL AI_RSAPrivate PROTO_LIST ((POINTER *)); +int T_CALL AI_RSAPublic PROTO_LIST ((POINTER *)); + + +/* Algorithm methods for use int the algorithm chooser. + */ +extern B_ALGORITHM_METHOD T_CALL AM_MD5; +extern B_ALGORITHM_METHOD T_CALL AM_MD5_RANDOM; +extern B_ALGORITHM_METHOD T_CALL AM_RSA_CRT_DECRYPT; +extern B_ALGORITHM_METHOD T_CALL AM_RSA_CRT_ENCRYPT; +extern B_ALGORITHM_METHOD T_CALL AM_RSA_DECRYPT; +extern B_ALGORITHM_METHOD T_CALL AM_RSA_ENCRYPT; +extern B_ALGORITHM_METHOD T_CALL AM_RSA_KEY_GEN; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/bind/dnssafe/btypechk.h b/lib/bind/dnssafe/btypechk.h new file mode 100644 index 0000000000..93f5a97bac --- /dev/null +++ b/lib/bind/dnssafe/btypechk.h @@ -0,0 +1,25 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _BTYPECHK_H_ +#define _BTYPECHK_H_ 1 + +struct B_TypeCheck; + +typedef void (*B_TYPE_CHECK_DESTRUCTOR) PROTO_LIST ((struct B_TypeCheck *)); + +typedef struct B_TypeCheck { + B_TYPE_CHECK_DESTRUCTOR _Destructor; +} B_TypeCheck; + +#define B_TYPE_CHECK_Constructor(typeCheck, Destructor)\ + (typeCheck)->_Destructor = (Destructor) +#define B_TYPE_CHECK_Destructor(typeCheck)\ + (*(typeCheck)->_Destructor) (typeCheck) + +#endif diff --git a/lib/bind/dnssafe/cantobig.c b/lib/bind/dnssafe/cantobig.c new file mode 100644 index 0000000000..674b51eb5b --- /dev/null +++ b/lib/bind/dnssafe/cantobig.c @@ -0,0 +1,59 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bigmath.h" +#include "port_after.h" + +/* CanonicalToBig () copies a byte vector into a word vector while REVERSING + the order of significance. The byte vector is input MSByte first while + the word vector is written out LSWord first. It also adds a leading zero + sign bit if necessary. + Returns 0, AE_DATA. + */ +int CanonicalToBig (wordPointer, wordCount, bytePointer, numBytes) +UINT2 *wordPointer; +unsigned int wordCount; +const unsigned char *bytePointer; +unsigned int numBytes; +{ + unsigned int copyCount; + + if (A_IntegerBits (bytePointer, numBytes) / 16 + 1 > wordCount) + return (AE_DATA); + + /* start at end of byte vector */ + bytePointer += numBytes-1; + + /* copy as much as possible */ + copyCount = (wordCount < numBytes / 2) ? wordCount : numBytes / 2; + wordCount -= copyCount; + numBytes -= 2 * copyCount; + while (copyCount--) { + /* Copy two bytes.*/ + *wordPointer++ = (UINT2)*bytePointer + (*(bytePointer - 1) << 8); + bytePointer -= 2; + } + + if (wordCount && numBytes & 1) { + /* If the number of input bytes was odd. Copy one last byte.*/ + *wordPointer++ = (UINT2)*bytePointer--; + wordCount--; + numBytes--; + } + + /* zero fill remainder of word vector */ + while (wordCount--) + *wordPointer++ = 0; + + return (0); +} + + diff --git a/lib/bind/dnssafe/crt2.c b/lib/bind/dnssafe/crt2.c new file mode 100644 index 0000000000..b1307ac39e --- /dev/null +++ b/lib/bind/dnssafe/crt2.c @@ -0,0 +1,230 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "crt2.h" +#include "bigmath.h" +#include "port_after.h" + +/* RSA encryption/decryption with Chinese Remainder Theorem. + */ + +#define GENERATE_BREAK(type) { \ + status = type; \ + break; \ + } + +static int RSA_CRT2 PROTO_LIST + ((A_RSA_CRT2_CTX *, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, A_SURRENDER_CTX *)); + +int A_RSA_CRT2Init (context, key) +A_RSA_CRT2_CTX *context; +A_RSA_CRT_KEY *key; +{ + if (A_IntegerBits (key->modulus.data, key->modulus.len) + > MAX_RSA_MODULUS_BITS) + /* Key len is too big to handle. */ + return (AE_MODULUS_LEN); + + /* Set the block update blockLen to be big enough to hold the modulus. + */ + context->blockLen = + BITS_TO_LEN (A_IntegerBits (key->modulus.data, key->modulus.len)); + + context->inputLen = 0; + + /* convert first prime to bignum format */ + if (CanonicalToBig + (context->primeP, MAX_RSA_PRIME_WORDS, key->prime[0].data, + key->prime[0].len)) + return (AE_KEY_INFO); + + /* compute significant length of first prime */ + context->primeWords = BITS_TO_WORDS + (BigLen (context->primeP, MAX_RSA_PRIME_WORDS)); + + /* convert other private key parameters to bignum format */ + if (CanonicalToBig + (context->primeQ, context->primeWords, key->prime[1].data, + key->prime[1].len) || + CanonicalToBig + (context->exponentP, context->primeWords, + key->primeExponent[0].data, key->primeExponent[0].len) || + CanonicalToBig + (context->exponentQ, context->primeWords, + key->primeExponent[1].data, key->primeExponent[1].len) || + CanonicalToBig + (context->coefficient, context->primeWords, + key->coefficient.data, key->coefficient.len)) + return (AE_KEY_INFO); + + /* convert modulus to bignum format */ + if (CanonicalToBig + (context->modulus, 2 * context->primeWords, + key->modulus.data, key->modulus.len)) + return (AE_KEY_INFO); + + return (0); +} + +int A_RSA_CRT2Update + (context, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + surrenderContext) +A_RSA_CRT2_CTX *context; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +const unsigned char *partIn; +unsigned int partInLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned int partialLen, localPartOutLen; + + /* Initialize partOutLen to zero. */ + *partOutLen = 0; + + if (context->inputLen + partInLen < context->blockLen) { + /* Not enough to encrypt - just accumulate. + */ + T_memcpy + ((POINTER)(context->input + context->inputLen), (CPOINTER)partIn, + partInLen); + context->inputLen += partInLen; + return (0); + } + + if (context->inputLen > 0) { + /* Need to accumulate the rest of the block bytes into the input and + encrypt from there (otherwise it's OK to encrypt straight from + the partIn). + */ + partialLen = context->blockLen - context->inputLen; + T_memcpy + ((POINTER)(context->input + context->inputLen), (CPOINTER)partIn, + partialLen); + partIn += partialLen; + partInLen -= partialLen; + + if ((status = RSA_CRT2 + (context, partOut, &localPartOutLen, maxPartOutLen, context->input, + surrenderContext)) != 0) + return (status); + (*partOutLen) += localPartOutLen; + partOut += localPartOutLen; + maxPartOutLen -= localPartOutLen; + } + + /* Encrypt as many blocks of input as provided. + */ + while (partInLen >= context->blockLen) { + if ((status = RSA_CRT2 + (context, partOut, &localPartOutLen, maxPartOutLen, partIn, + surrenderContext)) != 0) + return (status); + + partIn += context->blockLen; + partInLen -= context->blockLen; + (*partOutLen) += localPartOutLen; + partOut += localPartOutLen; + maxPartOutLen -= localPartOutLen; + } + + /* Copy remaining input bytes to the context's input buffer. + */ + T_memcpy + ((POINTER)context->input, partIn, partInLen); + context->inputLen = partInLen; + return (0); +} + +int A_RSA_CRT2Final (context) +A_RSA_CRT2_CTX *context; +{ + if (context->inputLen != 0) + return (AE_INPUT_LEN); + + /* Restart context to accumulate a new block. + */ + context->inputLen = 0; + return (0); +} + +/* Assume input length is context->blockLen. + */ +static int RSA_CRT2 + (context, output, outputLen, maxOutputLen, input, surrenderContext) +A_RSA_CRT2_CTX *context; +unsigned char *output; +unsigned int *outputLen; +unsigned int maxOutputLen; +const unsigned char *input; +A_SURRENDER_CTX *surrenderContext; +{ + struct ModExpCRTFrame { + UINT2 bigInBuf[2 * MAX_RSA_PRIME_WORDS], + bigOutBuf[2 * MAX_RSA_PRIME_WORDS]; + } *frame = (struct ModExpCRTFrame *)NULL_PTR; +#if !USE_ALLOCED_FRAME + struct ModExpCRTFrame stackFrame; +#endif + int status; + + status = 0; + do { + if ((*outputLen = context->blockLen) > maxOutputLen) + return (AE_OUTPUT_LEN); + +#if USE_ALLOCED_FRAME + if ((frame = (struct ModExpCRTFrame *)T_malloc (sizeof (*frame))) + == (struct ModExpCRTFrame *)NULL_PTR) { + status = AE_ALLOC; + break; + } +#else + /* Just use the buffers allocated on the stack. */ + frame = &stackFrame; +#endif + + /* Convert input to bignum representation. + This won't return AE_DATA since input length was checked at Update. + */ + CanonicalToBig + (frame->bigInBuf, 2 * context->primeWords, input, context->blockLen); + + /* Check for overflow. */ + if (BigCmp + (frame->bigInBuf, context->modulus, 2 * context->primeWords) >= 0) + GENERATE_BREAK (AE_INPUT_DATA); + + /* Chinese remainder exponentiation. */ + if ((status = BigUnexp + (frame->bigOutBuf, frame->bigInBuf, context->primeP, context->primeQ, + context->exponentP, context->exponentQ, context->coefficient, + context->primeWords, surrenderContext)) != 0) + break; + + /* Convert output to canonical representation. + This won't return AE_DATA since outputLen was set above. + */ + BigToCanonical + (output, *outputLen, frame->bigOutBuf, 2 * context->primeWords); + } while (0); + + if (frame != (struct ModExpCRTFrame *)NULL_PTR) { + T_memset ((POINTER)frame, 0, sizeof (*frame)); +#if USE_ALLOCED_FRAME + T_free ((POINTER)frame); +#endif + } + return (status); +} + diff --git a/lib/bind/dnssafe/crt2.h b/lib/bind/dnssafe/crt2.h new file mode 100644 index 0000000000..c51b4a88dd --- /dev/null +++ b/lib/bind/dnssafe/crt2.h @@ -0,0 +1,50 @@ +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _RSA_H_ +#define _RSA_H_ 1 + +#include "bigmaxes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Note, these are only valid after a call to A_RSA_CRT2Init. + */ +#define A_RSA_CRT2_BLOCK_LEN(context) ((context)->blockLen) +#define A_RSA_CRT2_MAX_OUTPUT_LEN(context, inputLen)\ + (inputLen) + (((inputLen) % (context)->blockLen) ?\ + (context)->blockLen - ((inputLen) % (context)->blockLen) : 0) + +typedef struct { + unsigned int blockLen; /* total size of the block to be computed */ + unsigned char input[MAX_RSA_MODULUS_LEN]; + unsigned int inputLen; + unsigned int primeWords; + UINT2 modulus[2 * MAX_RSA_PRIME_WORDS]; + UINT2 primeP[MAX_RSA_PRIME_WORDS]; + UINT2 primeQ[MAX_RSA_PRIME_WORDS]; + UINT2 exponentP[MAX_RSA_PRIME_WORDS]; + UINT2 exponentQ[MAX_RSA_PRIME_WORDS]; + UINT2 coefficient[MAX_RSA_PRIME_WORDS]; +} A_RSA_CRT2_CTX; + +int A_RSA_CRT2Init PROTO_LIST ((A_RSA_CRT2_CTX *, A_RSA_CRT_KEY *)); +int A_RSA_CRT2Update PROTO_LIST + ((A_RSA_CRT2_CTX *, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int A_RSA_CRT2Final PROTO_LIST ((A_RSA_CRT2_CTX *)); +void A_RSA_CRT2GetMaxOutputLen PROTO_LIST + ((A_RSA_CRT2_CTX *, unsigned int *, unsigned int)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/bind/dnssafe/digest.c b/lib/bind/dnssafe/digest.c new file mode 100644 index 0000000000..0995b5d6a1 --- /dev/null +++ b/lib/bind/dnssafe/digest.c @@ -0,0 +1,69 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "keyobj.h" +#include "algobj.h" +#include "port_after.h" + +int B_DigestInit + (algorithmObject, keyObject, algorithmChooser, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +B_KEY_OBJ keyObject; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + if ((status = KeyWrapCheck ((KeyWrap *)keyObject)) != 0) + return (status); + + return (B_AlgorithmDigestInit + (&THE_ALG_WRAP->algorithm, &((KeyWrap *)keyObject)->key, + algorithmChooser, surrenderContext)); +} + +int B_DigestUpdate (algorithmObject, partIn, partInLen, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +const unsigned char *partIn; +unsigned int partInLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + + return (B_AlgorithmDigestUpdate + (&THE_ALG_WRAP->algorithm, partIn, partInLen, surrenderContext)); +} + +int B_DigestFinal + (algorithmObject, digest, digestLen, maxDigestLen, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +unsigned char *digest; +unsigned int *digestLen; +unsigned int maxDigestLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + + return (B_AlgorithmDigestFinal + (&THE_ALG_WRAP->algorithm, digest, digestLen, maxDigestLen, + surrenderContext)); +} + diff --git a/lib/bind/dnssafe/digrand.c b/lib/bind/dnssafe/digrand.c new file mode 100644 index 0000000000..2abf028d59 --- /dev/null +++ b/lib/bind/dnssafe/digrand.c @@ -0,0 +1,90 @@ +/* Copyright (C) RSA Data Security, Inc. created 1992, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "digrand.h" +#include "port_after.h" + +/* Calling routine must initialize the digest algorithm and set + digestRandom->vTable. + digestLen is the length of the output of the digest algorithm (i.e. 16). + state must point to an unsigned char * array of 3 * digestLen. + */ +void A_DigestRandomInit (digestRandom, digestLen, state) +A_DigestRandom *digestRandom; +unsigned int digestLen; +unsigned char *state; +{ + digestRandom->_state = state; + digestRandom->_output = state + digestLen; + digestRandom->_digest = digestRandom->_output + digestLen; + + digestRandom->_outputAvailable = 0; + digestRandom->_digestLen = digestLen; + + T_memset ((POINTER)digestRandom->_state, 0, digestLen); +} + +void A_DigestRandomUpdate (digestRandom, input, inputLen) +A_DigestRandom *digestRandom; +unsigned char *input; +unsigned int inputLen; +{ + unsigned int i, j, x; + + (*digestRandom->vTable->DigestUpdate) (digestRandom, input, inputLen); + (*digestRandom->vTable->DigestFinal) (digestRandom, digestRandom->_digest); + + /* add digest to state */ + x = 0; + for (i = 0; i < digestRandom->_digestLen; i++) { + j = digestRandom->_digestLen-1-i; + x += digestRandom->_state[j] + digestRandom->_digest[j]; + digestRandom->_state[j] = (unsigned char)x; + x >>= 8; + } +} + +void A_DigestRandomGenerateBytes (digestRandom, output, outputLen) +A_DigestRandom *digestRandom; +unsigned char *output; +unsigned int outputLen; +{ + unsigned int available, i; + + available = digestRandom->_outputAvailable; + + while (outputLen > available) { + T_memcpy + ((POINTER)output, + (POINTER)&digestRandom->_output[digestRandom->_digestLen-available], + available); + output += available; + outputLen -= available; + + /* generate new output */ + (*digestRandom->vTable->DigestUpdate) + (digestRandom, digestRandom->_state, digestRandom->_digestLen); + (*digestRandom->vTable->DigestFinal) (digestRandom, digestRandom->_output); + available = digestRandom->_digestLen; + + /* increment state */ + for (i = 0; i < digestRandom->_digestLen; i++) + if (digestRandom->_state[digestRandom->_digestLen-1-i]++) + break; + } + + T_memcpy + ((POINTER)output, + (POINTER)&digestRandom->_output[digestRandom->_digestLen-available], + outputLen); + digestRandom->_outputAvailable = available - outputLen; +} + diff --git a/lib/bind/dnssafe/digrand.h b/lib/bind/dnssafe/digrand.h new file mode 100644 index 0000000000..6753c9cfab --- /dev/null +++ b/lib/bind/dnssafe/digrand.h @@ -0,0 +1,53 @@ +/* Copyright (C) RSA Data Security, Inc. created 1992, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _DIGRAND_H_ +#define _DIGRAND_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Use the THIS_DIGEST_RANDOM macro to define the type of object in the + virtual function prototype. It defaults to the most base class, but + derived modules may define the macro to a more derived class before + including this header file. + */ +#ifndef THIS_DIGEST_RANDOM +#define THIS_DIGEST_RANDOM struct A_DigestRandom +#endif + +struct A_DigestRandom; + +typedef struct { + void (*DigestUpdate) PROTO_LIST + ((THIS_DIGEST_RANDOM *, unsigned char *, unsigned int)); + void (*DigestFinal) PROTO_LIST ((THIS_DIGEST_RANDOM *, unsigned char *)); +} A_DigestRandomVTable; + +typedef struct A_DigestRandom { + unsigned char *_state; /* input to digest */ + unsigned char *_output; /* current output of digest */ + unsigned int _outputAvailable; + unsigned char *_digest; + unsigned int _digestLen; + A_DigestRandomVTable *vTable; +} A_DigestRandom; + +void A_DigestRandomInit PROTO_LIST + ((A_DigestRandom *, unsigned int, unsigned char *)); +void A_DigestRandomUpdate PROTO_LIST + ((A_DigestRandom *, unsigned char *, unsigned int)); +void A_DigestRandomGenerateBytes PROTO_LIST + ((A_DigestRandom *, unsigned char *, unsigned int)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/bind/dnssafe/encrypt.c b/lib/bind/dnssafe/encrypt.c new file mode 100644 index 0000000000..37b02bdd33 --- /dev/null +++ b/lib/bind/dnssafe/encrypt.c @@ -0,0 +1,149 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "keyobj.h" +#include "algobj.h" +#include "port_after.h" + +int B_EncryptInit + (algorithmObject, keyObject, algorithmChooser, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +B_KEY_OBJ keyObject; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + if ((status = KeyWrapCheck ((KeyWrap *)keyObject)) != 0) + return (status); + + return (B_AlgorithmEncryptInit + (&THE_ALG_WRAP->algorithm, &((KeyWrap *)keyObject)->key, + algorithmChooser, surrenderContext)); +} + +int B_EncryptUpdate + (algorithmObject, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + randomAlgorithm, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +unsigned char *partIn; +unsigned int partInLen; +B_ALGORITHM_OBJ randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + if ((status = RandomAlgorithmCheck (randomAlgorithm)) != 0) + return (status); + + return (B_AlgorithmEncryptUpdate + (&THE_ALG_WRAP->algorithm, partOut, partOutLen, maxPartOutLen, + partIn, partInLen, + &((AlgorithmWrap *)randomAlgorithm)->algorithm, surrenderContext)); +} + +int B_EncryptFinal + (algorithmObject, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_ALGORITHM_OBJ randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + if ((status = RandomAlgorithmCheck (randomAlgorithm)) != 0) + return (status); + + return (B_AlgorithmEncryptFinal + (&THE_ALG_WRAP->algorithm, partOut, partOutLen, maxPartOutLen, + &((AlgorithmWrap *)randomAlgorithm)->algorithm, surrenderContext)); +} + +int B_DecryptInit + (algorithmObject, keyObject, algorithmChooser, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +B_KEY_OBJ keyObject; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + if ((status = KeyWrapCheck ((KeyWrap *)keyObject)) != 0) + return (status); + + return (B_AlgorithmDecryptInit + (&THE_ALG_WRAP->algorithm, &((KeyWrap *)keyObject)->key, + algorithmChooser, surrenderContext)); +} + +int B_DecryptUpdate + (algorithmObject, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + randomAlgorithm, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +const unsigned char *partIn; +unsigned int partInLen; +B_ALGORITHM_OBJ randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + if ((status = RandomAlgorithmCheck (randomAlgorithm)) != 0) + return (status); + + return (B_AlgorithmDecryptUpdate + (&THE_ALG_WRAP->algorithm, partOut, partOutLen, maxPartOutLen, + partIn, partInLen, + &((AlgorithmWrap *)randomAlgorithm)->algorithm, surrenderContext)); +} + +int B_DecryptFinal + (algorithmObject, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_ALGORITHM_OBJ randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + if ((status = RandomAlgorithmCheck (randomAlgorithm)) != 0) + return (status); + + return (B_AlgorithmDecryptFinal + (&THE_ALG_WRAP->algorithm, partOut, partOutLen, maxPartOutLen, + &((AlgorithmWrap *)randomAlgorithm)->algorithm, surrenderContext)); +} + diff --git a/lib/bind/dnssafe/generate.c b/lib/bind/dnssafe/generate.c new file mode 100644 index 0000000000..9ffbe790bf --- /dev/null +++ b/lib/bind/dnssafe/generate.c @@ -0,0 +1,80 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ainfotyp.h" +#include "keyobj.h" +#include "algobj.h" +#include "port_after.h" + +int B_GenerateInit (algorithmObject, algorithmChooser, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + + return (B_AlgorithmGenerateInit + (&THE_ALG_WRAP->algorithm, algorithmChooser, surrenderContext)); +} + +int B_GenerateKeypair + (algorithmObject, publicKey, privateKey, randomAlgorithm, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +B_KEY_OBJ publicKey; +B_KEY_OBJ privateKey; +B_ALGORITHM_OBJ randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + if ((status = KeyWrapCheck ((KeyWrap *)publicKey)) != 0) + return (status); + if ((status = KeyWrapCheck ((KeyWrap *)privateKey)) != 0) + return (status); + if ((status = RandomAlgorithmCheck (randomAlgorithm)) != 0) + return (status); + + return (B_AlgorithmGenerateKeypair + (&THE_ALG_WRAP->algorithm, &((KeyWrap *)publicKey)->key, + &((KeyWrap *)privateKey)->key, + &((AlgorithmWrap *)randomAlgorithm)->algorithm, surrenderContext)); +} + +int B_GenerateParameters + (algorithmObject, resultAlgorithmObject, randomAlgorithm, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +B_ALGORITHM_OBJ resultAlgorithmObject; +B_ALGORITHM_OBJ randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + if ((status = AlgorithmWrapCheck ((AlgorithmWrap *)resultAlgorithmObject)) + != 0) + return (status); + if ((status = RandomAlgorithmCheck (randomAlgorithm)) != 0) + return (status); + + return (B_AlgorithmGenerateParameters + (&THE_ALG_WRAP->algorithm, + &((AlgorithmWrap *)resultAlgorithmObject)->algorithm, + &((AlgorithmWrap *)randomAlgorithm)->algorithm, surrenderContext)); +} + diff --git a/lib/bind/dnssafe/global.h b/lib/bind/dnssafe/global.h new file mode 100644 index 0000000000..8cd672354a --- /dev/null +++ b/lib/bind/dnssafe/global.h @@ -0,0 +1,63 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _GLOBAL_H_ +#define _GLOBAL_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* PROTOTYPES should be set to one if and only if the compiler supports + function argument prototyping. + The following makes PROTOTYPES default to 1 if it has not already been + defined as 0 with C compiler flags. + */ +#ifndef PROTOTYPES +#define PROTOTYPES 1 +#endif + +#include +#include +#if (!defined(BSD)) || (BSD < 199306) +# include +#endif + +/* POINTER defines a generic pointer type */ +typedef unsigned char *POINTER; +typedef const unsigned char *CPOINTER; + +/* UINT2 defines a two byte word */ +typedef u_int16_t UINT2; + +/* UINT4 defines a four byte word */ +typedef u_int32_t UINT4; + +#ifndef NULL_PTR +#define NULL_PTR ((POINTER)0) +#endif + +#ifndef UNUSED_ARG +#define UNUSED_ARG(x) x = *(&x); +#endif + +/* PROTO_LIST is defined depending on how PROTOTYPES is defined above. + If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it + returns an empty list. + */ +#if PROTOTYPES +#define PROTO_LIST(list) list +#else +#define PROTO_LIST(list) () +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end _GLOBAL_H_ */ diff --git a/lib/bind/dnssafe/intbits.c b/lib/bind/dnssafe/intbits.c new file mode 100644 index 0000000000..7b35c6abeb --- /dev/null +++ b/lib/bind/dnssafe/intbits.c @@ -0,0 +1,34 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "port_after.h" + +/* Return the number of bits in the canonical, positive integer. + IntgerBits (0) = 0. + */ +unsigned int A_IntegerBits (integer, integerLen) +const unsigned char *integer; +unsigned int integerLen; +{ + unsigned char mask, byte; + unsigned int bytes, bits; + + for (bytes = 0; bytes < integerLen && integer[bytes] == 0; bytes++); + if (bytes == integerLen) + return (0); + + /* Get byte to test and increment byte count for final calculation */ + byte = integer[bytes++]; + + /* Get number of bits in most significant byte */ + for (bits = 8, mask = 0x80; (byte & mask) == 0; bits--, mask >>= 1); + return (8 * (integerLen - bytes) + bits); +} diff --git a/lib/bind/dnssafe/intitem.c b/lib/bind/dnssafe/intitem.c new file mode 100644 index 0000000000..272681c3f2 --- /dev/null +++ b/lib/bind/dnssafe/intitem.c @@ -0,0 +1,56 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bmempool.h" +#include "intitem.h" +#include "port_after.h" + +/* Copy itemCount ITEMs from source to destination, allocating new + memory in the memoryPool. + Each ITEM is a canonical integer, and is stripped of leading zeros. + Use the list of staticItems as a template. Each of the staticItems + points to the ITEM within the staticStruct, which is a structure + of the same format as destination and source. + Returns 0, BE_ALLOC. + */ +int AllocAndCopyIntegerItems + (destination, source, staticStruct, staticItems, itemCount, memoryPool) +POINTER destination; +POINTER source; +POINTER staticStruct; +ITEM **staticItems; +unsigned int itemCount; +B_MemoryPool *memoryPool; +{ + ITEM sourceItem, *destinationItem; + int status; + unsigned int i, offset; + + for (i = 0; i < itemCount; i++) { + offset = (unsigned int)((char *)staticItems[i] - (char *)staticStruct); + sourceItem = *(ITEM *)((char *)source + offset); + destinationItem = (ITEM *)((char *)destination + offset); + + while (sourceItem.len > 0 && *sourceItem.data == 0) { + sourceItem.len--; + sourceItem.data++; + } + + if ((status = B_MemoryPoolAllocAndCopy + (memoryPool, (POINTER *)&destinationItem->data, + (POINTER)sourceItem.data, destinationItem->len = sourceItem.len)) + != 0) + return (status); + } + + return (0); +} + diff --git a/lib/bind/dnssafe/intitem.h b/lib/bind/dnssafe/intitem.h new file mode 100644 index 0000000000..05cb2fc14a --- /dev/null +++ b/lib/bind/dnssafe/intitem.h @@ -0,0 +1,11 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +int AllocAndCopyIntegerItems PROTO_LIST + ((POINTER, POINTER, POINTER, ITEM **, unsigned int, B_MemoryPool *)); + diff --git a/lib/bind/dnssafe/keyobj.c b/lib/bind/dnssafe/keyobj.c new file mode 100644 index 0000000000..7ba2d5bec8 --- /dev/null +++ b/lib/bind/dnssafe/keyobj.c @@ -0,0 +1,115 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "kinfotyp.h" +#include "keyobj.h" +#include "port_after.h" + +#define THE_KEY_WRAP ((KeyWrap *)keyObject) + +static char KEY_TYPE_TAG = 0; + +int B_CreateKeyObject (keyObject) +B_KEY_OBJ *keyObject; +{ + KeyWrap *keyWrap; + + if ((*keyObject = T_malloc (sizeof (*keyWrap))) == NULL_PTR) + return (BE_ALLOC); + + keyWrap = (KeyWrap *)*keyObject; + + /* First construct base class */ + B_KEY_Constructor (&keyWrap->key); + + keyWrap->typeTag = &KEY_TYPE_TAG; + keyWrap->selfCheck = keyWrap; + return (0); +} + +void B_DestroyKeyObject (keyObject) +B_KEY_OBJ *keyObject; +{ + KeyWrap *keyWrap = (KeyWrap *)*keyObject; + + /* Need to explicitly check for NULL_PTR since KeyWrapCheck does not. + */ + if (*keyObject == NULL_PTR) + return; + + if (KeyWrapCheck (keyWrap) == 0) { + /* zeroize self check to invalidate memory. */ + keyWrap->selfCheck = (KeyWrap *)NULL_PTR; + + /* Call base class descructor */ + B_KEY_Destructor (&keyWrap->key); + + T_free ((POINTER)keyWrap); + } + + *keyObject = NULL_PTR; +} + +int B_SetKeyInfo (keyObject, infoType, info) +B_KEY_OBJ keyObject; +B_INFO_TYPE infoType; +POINTER info; +{ + B_KeyInfoType *keyInfoType; + int status; + + if ((status = KeyWrapCheck (THE_KEY_WRAP)) != 0) + return (status); + + /* Get the KeyInfoType from the B_INFO_TYPE, which returns + zero for an AlgorithmInfoType, non-zero for KeyInfoType + */ + if ((*infoType) ((POINTER *)&keyInfoType) == 0) + return (BE_ALG_OPERATION_UNKNOWN); + + return (B_KeySetInfo (&THE_KEY_WRAP->key, keyInfoType, info)); +} + +int B_GetKeyInfo (info, keyObject, infoType) +POINTER *info; +B_KEY_OBJ keyObject; +B_INFO_TYPE infoType; +{ + B_KeyInfoType *keyInfoType; + int status; + + if ((status = KeyWrapCheck (THE_KEY_WRAP)) != 0) + return (status); + + /* Get the KeyInfoType from the B_INFO_TYPE, which returns + zero for an AlgorithmInfoType, non-zero for KeyInfoType + */ + if ((*infoType) ((POINTER *)&keyInfoType) == 0) + return (BE_ALG_OPERATION_UNKNOWN); + + return (B_KeyGetInfo (&THE_KEY_WRAP->key, info, keyInfoType)); +} + +/* Return 0 if this is a valid KeyWrap object, else BE_KEY_OBJ. + If keyWrap is NULL_PTR, return 0 and expect the lower routines + to check for NULL. + */ +int KeyWrapCheck (keyWrap) +KeyWrap *keyWrap; +{ + if (keyWrap == (KeyWrap *)NULL_PTR) + return (0); + + return ((keyWrap->selfCheck == keyWrap && keyWrap->typeTag == &KEY_TYPE_TAG) + ? 0 : BE_KEY_OBJ); +} + diff --git a/lib/bind/dnssafe/keyobj.h b/lib/bind/dnssafe/keyobj.h new file mode 100644 index 0000000000..b7f582f8da --- /dev/null +++ b/lib/bind/dnssafe/keyobj.h @@ -0,0 +1,16 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +typedef struct KeyWrap { + B_Key key; + char *typeTag; + struct KeyWrap *selfCheck; +} KeyWrap; + +int KeyWrapCheck PROTO_LIST ((KeyWrap *)); + diff --git a/lib/bind/dnssafe/ki8byte.c b/lib/bind/dnssafe/ki8byte.c new file mode 100644 index 0000000000..6c43a9c43f --- /dev/null +++ b/lib/bind/dnssafe/ki8byte.c @@ -0,0 +1,72 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "kinfotyp.h" +#include "kiitem.h" +#include "ki8byte.h" +#include "port_after.h" + +int KIT_8ByteAddInfo PROTO_LIST ((B_Key *, POINTER)); +int KIT_8ByteMakeInfo PROTO_LIST ((POINTER *, B_Key *)); + +B_KeyInfoType KIT_8Byte = {KIT_8ByteAddInfo, KIT_8ByteMakeInfo}; + +int KI_8Byte (keyInfoType) +POINTER *keyInfoType; +{ + *keyInfoType = (POINTER)&KIT_8Byte; + + /* Return 1 to indicate a KeyInfoType, not an AlgorithmInfoType */ + return (1); +} + +/* info points to 8 byte key. + Cache as a KITItem and a KIT_8Byte. + */ +int KIT_8ByteAddInfo (key, info) +B_Key *key; +POINTER info; +{ + POINTER newData; + int status; + + /* Copy the 8 byte key. */ + if ((status = B_MemoryPoolAllocAndCopy + (&key->infoCache.memoryPool, &newData, info, 8)) != 0) + return (status); + + /* Cache as a KITItem as well as KIT_8Byte. + */ + if ((status = B_KeyAddItemInfo (key, (unsigned char *)newData, 8)) != 0) + return (status); + return (B_InfoCacheAddInfo (&key->infoCache, (POINTER)&KIT_8Byte, newData)); +} + +int KIT_8ByteMakeInfo (info, key) +POINTER *info; +B_Key *key; +{ + ITEM *item; + int status; + + /* Try to make one from a KI_Item. Since KI_Item doesn't + call KI_8Byte, this should not cause an endless loop. + */ + if ((status = B_KeyGetInfo (key, (POINTER *)&item, &KITItem)) != 0) + return (status); + if (item->len != 8) + return (BE_WRONG_KEY_INFO); + + *(unsigned char **)info = item->data; + return (0); +} + diff --git a/lib/bind/dnssafe/ki8byte.h b/lib/bind/dnssafe/ki8byte.h new file mode 100644 index 0000000000..1c78bb12d4 --- /dev/null +++ b/lib/bind/dnssafe/ki8byte.h @@ -0,0 +1,9 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +extern B_KeyInfoType KIT_8Byte; diff --git a/lib/bind/dnssafe/kifulprv.c b/lib/bind/dnssafe/kifulprv.c new file mode 100644 index 0000000000..ef1f299b21 --- /dev/null +++ b/lib/bind/dnssafe/kifulprv.c @@ -0,0 +1,153 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "kinfotyp.h" +#include "kifulprv.h" +#include "port_after.h" + +typedef struct { + ITEM modulus; /* modulus */ + ITEM publicExponent; /* exponent for the public key */ + ITEM privateExponent; /* exponent for the private key */ + ITEM prime[2]; /* prime factors */ + ITEM primeExponent[2]; /* exponents for prime factors */ + ITEM coefficient; /* CRT coefficient */ +} FULL_PRIVATE_KEY; + +static int KITFullPrivateKeyAddInfo PROTO_LIST ((B_Key *, POINTER)); + +static B_KeyInfoType KITFullPrivate = + {KITFullPrivateKeyAddInfo, B_KeyInfoTypeMakeError}; + +/* Create a FULL_PRIVATE_KEY value and only copy inthe entries + that are not (ITEM *)NULL_PTR. + primes and primeExponents point to a 2 entry ITEM array. + */ +int CacheFullPrivateKey + (key, modulus, publicExponent, privateExponent, primes, + primeExponents, coefficient) +B_Key *key; +ITEM *modulus; +ITEM *publicExponent; +ITEM *privateExponent; +ITEM *primes; +ITEM *primeExponents; +ITEM *coefficient; +{ + FULL_PRIVATE_KEY *fullKey; + int status; + + /* Allocate memory for FULL_PRIVATE_KEY value. + */ + if ((status = B_MemoryPoolAlloc + (&key->infoCache.memoryPool, (POINTER *)&fullKey, + sizeof (FULL_PRIVATE_KEY))) != 0) + return (status); + + /* Pre-zeroize and only copy in values that are not NULL. + */ + T_memset ((POINTER)fullKey, 0, sizeof (*fullKey)); + if (modulus != (ITEM *)NULL_PTR) + fullKey->modulus = *modulus; + if (publicExponent != (ITEM *)NULL_PTR) + fullKey->publicExponent = *publicExponent; + if (privateExponent != (ITEM *)NULL_PTR) + fullKey->privateExponent = *privateExponent; + if (primes != (ITEM *)NULL_PTR) { + fullKey->prime[0] = primes[0]; + fullKey->prime[1] = primes[1]; + } + if (primeExponents != (ITEM *)NULL_PTR) { + fullKey->primeExponent[0] = primeExponents[0]; + fullKey->primeExponent[1] = primeExponents[1]; + } + if (coefficient != (ITEM *)NULL_PTR) + fullKey->coefficient = *coefficient; + + return (B_InfoCacheAddInfo + (&key->infoCache, (POINTER)&KITFullPrivate, (POINTER)fullKey)); +} + +/* Select the key object's full private key and set all of the supplied + fields which are not (ITEM *)NULL_PTR. + primes and primeExponents point to a 2 entry ITEM array. + If one of the fields is not (ITEM *)NULL_PTR, but the full key's + field is null, return BE_WRONG_KEY_INFO. + */ +int GetFullPrivateKeyInfo + (modulus, publicExponent, privateExponent, primes, primeExponents, + coefficient, key) +ITEM *modulus; +ITEM *publicExponent; +ITEM *privateExponent; +ITEM *primes; +ITEM *primeExponents; +ITEM *coefficient; +B_Key *key; +{ + FULL_PRIVATE_KEY *fullKey; + int status; + + if ((status = B_KeyGetInfo + (key, (POINTER *)&fullKey, &KITFullPrivate)) != 0) + return (status); + + if (modulus != (ITEM *)NULL_PTR) { + if (fullKey->modulus.data == (unsigned char *)NULL_PTR) + return (BE_WRONG_KEY_INFO); + *modulus = fullKey->modulus; + } + if (publicExponent != (ITEM *)NULL_PTR) { + if (fullKey->publicExponent.data == (unsigned char *)NULL_PTR) + return (BE_WRONG_KEY_INFO); + *publicExponent = fullKey->publicExponent; + } + if (privateExponent != (ITEM *)NULL_PTR) { + if (fullKey->privateExponent.data == (unsigned char *)NULL_PTR) + return (BE_WRONG_KEY_INFO); + *privateExponent = fullKey->privateExponent; + } + if (primes != (ITEM *)NULL_PTR) { + if (fullKey->prime[0].data == (unsigned char *)NULL_PTR || + fullKey->prime[1].data == (unsigned char *)NULL_PTR) + return (BE_WRONG_KEY_INFO); + primes[0] = fullKey->prime[0]; + primes[1] = fullKey->prime[1]; + } + if (primeExponents != (ITEM *)NULL_PTR) { + if (fullKey->primeExponent[0].data == (unsigned char *)NULL_PTR || + fullKey->primeExponent[1].data == (unsigned char *)NULL_PTR) + return (BE_WRONG_KEY_INFO); + primeExponents[0] = fullKey->primeExponent[0]; + primeExponents[1] = fullKey->primeExponent[1]; + } + if (coefficient != (ITEM *)NULL_PTR) { + if (fullKey->coefficient.data == (unsigned char *)NULL_PTR) + return (BE_WRONG_KEY_INFO); + *coefficient = fullKey->coefficient; + } + + return (0); +} + +/* This is not intended to be called from B_SetKeyInfo. + Get returns BE_WRONG_KEY_INFO. + */ +static int KITFullPrivateKeyAddInfo (key, info) +B_Key *key; +POINTER info; +{ +UNUSED_ARG (key) +UNUSED_ARG (info) + return (BE_ALG_OPERATION_UNKNOWN); +} + diff --git a/lib/bind/dnssafe/kifulprv.h b/lib/bind/dnssafe/kifulprv.h new file mode 100644 index 0000000000..8e469ce9f3 --- /dev/null +++ b/lib/bind/dnssafe/kifulprv.h @@ -0,0 +1,12 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +int CacheFullPrivateKey PROTO_LIST + ((B_Key *, ITEM *, ITEM *, ITEM *, ITEM *, ITEM *, ITEM *)); +int GetFullPrivateKeyInfo PROTO_LIST + ((ITEM *, ITEM *, ITEM *, ITEM *, ITEM *, ITEM *, B_Key *)); diff --git a/lib/bind/dnssafe/kiitem.c b/lib/bind/dnssafe/kiitem.c new file mode 100644 index 0000000000..846f6dc94a --- /dev/null +++ b/lib/bind/dnssafe/kiitem.c @@ -0,0 +1,46 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "kinfotyp.h" +#include "kiitem.h" +#include "port_after.h" + +int KITItemAddInfo PROTO_LIST ((B_Key *, POINTER)); + +B_KeyInfoType KITItem = {KITItemAddInfo, B_KeyInfoTypeMakeError}; + +int KI_Item (keyInfoType) +POINTER *keyInfoType; +{ + *keyInfoType = (POINTER)&KITItem; + + /* Return 1 to indicate a KeyInfoType, not an AlgorithmInfoType */ + return (1); +} + +/* info is an ITEM. The ITEM's data is copied into the object. + */ +int KITItemAddInfo (key, info) +B_Key *key; +POINTER info; +{ + unsigned char *newData; + int status; + + if ((status = B_MemoryPoolAllocAndCopy + (&key->infoCache.memoryPool, (POINTER *)&newData, + (POINTER)((ITEM *)info)->data, ((ITEM *)info)->len)) != 0) + return (status); + + return (B_KeyAddItemInfo (key, newData, ((ITEM *)info)->len)); +} + diff --git a/lib/bind/dnssafe/kiitem.h b/lib/bind/dnssafe/kiitem.h new file mode 100644 index 0000000000..ab80ceee63 --- /dev/null +++ b/lib/bind/dnssafe/kiitem.h @@ -0,0 +1,9 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +extern B_KeyInfoType KITItem; diff --git a/lib/bind/dnssafe/kinfotyp.c b/lib/bind/dnssafe/kinfotyp.c new file mode 100644 index 0000000000..a374c914cf --- /dev/null +++ b/lib/bind/dnssafe/kinfotyp.c @@ -0,0 +1,28 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "kinfotyp.h" +#include "port_after.h" + +/* This is the default routine which key info types can point MakeInfo to. + */ +int B_KeyInfoTypeMakeError (info, key) +POINTER *info; +B_Key *key; +{ +UNUSED_ARG (info) +UNUSED_ARG (key) + + /* Should already have been found in the cache. */ + return (BE_WRONG_KEY_INFO); +} + diff --git a/lib/bind/dnssafe/kinfotyp.h b/lib/bind/dnssafe/kinfotyp.h new file mode 100644 index 0000000000..3f6ce7c152 --- /dev/null +++ b/lib/bind/dnssafe/kinfotyp.h @@ -0,0 +1,57 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +typedef int (*KIT_ADD_INFO) PROTO_LIST ((B_Key *, POINTER)); +typedef int (*KIT_MAKE_INFO) PROTO_LIST ((POINTER *, B_Key *)); + +/* The definition in C++ is: + class B_KeyInfoType { + public: + B_KeyInfoType (KIT_ADD_INFO AddInfo) { + _AddInfo = AddInfo; + _MakeInfo = KeyInfoType::makeError;} + B_KeyInfoType (KIT_ADD_INFO AddInfo, KIT_MAKE_INFO MakeInfo) { + _AddInfo = AddInfo; + _MakeInfo = MakeInfo;} + + int addInfo (B_Key *key, POINTER info) {return (*_AddInfo) (key, info);} + int makeInfo (POINTER *info, B_Key *key) {return (*_MakeInfo) (info, key);} + + static int makeError (POINTER *info, B_Key *key); + + private: + KIT_ADD_INFO _AddInfo; + KIT_MAKE_INFO _MakeInfo; + }; + + Note that a derived class simply calls one of the B_KeyInfoType constructors + which set the addInfo or both the addInfo and makeInfo callbacks. + There is no need for an extra level involving virtual functions because + each key class only has one instance, making a V table a waste of space. + An example of a derived class is: + + class KITItem : public B_KeyInfoType { + public: + // Set addInfo and leave makeInfo as B_KeyInfoType::makeError + KITItem () : B_KeyInfoType (KITItem::addInfo) {}; + + static int addInfo (B_Key *key, POINTER info); + }; + + + There is one global instance which is used by B_Key::setInfo, etc.: + + KITItem KITItem; + */ + +typedef struct B_KeyInfoType { + KIT_ADD_INFO AddInfo; + KIT_MAKE_INFO MakeInfo; +} B_KeyInfoType; + +int B_KeyInfoTypeMakeError PROTO_LIST ((POINTER *, B_Key *)); diff --git a/lib/bind/dnssafe/kipkcrpr.c b/lib/bind/dnssafe/kipkcrpr.c new file mode 100644 index 0000000000..10177fe6c2 --- /dev/null +++ b/lib/bind/dnssafe/kipkcrpr.c @@ -0,0 +1,102 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "kinfotyp.h" +#include "intitem.h" +#include "kifulprv.h" +#include "kipkcrpr.h" +#include "port_after.h" + +B_KeyInfoType KIT_PKCS_RSAPrivate = + {KIT_PKCS_RSAPrivateAddInfo, KIT_PKCS_RSAPrivateMakeInfo}; + +static A_PKCS_RSA_PRIVATE_KEY STATIC_PKCS_RSA_PRIVATE_KEY; +static ITEM *PKCS_RSA_PRIVATE_KEY_ITEMS[] = { + &STATIC_PKCS_RSA_PRIVATE_KEY.modulus, + &STATIC_PKCS_RSA_PRIVATE_KEY.publicExponent, + &STATIC_PKCS_RSA_PRIVATE_KEY.privateExponent, + &STATIC_PKCS_RSA_PRIVATE_KEY.prime[0], + &STATIC_PKCS_RSA_PRIVATE_KEY.prime[1], + &STATIC_PKCS_RSA_PRIVATE_KEY.primeExponent[0], + &STATIC_PKCS_RSA_PRIVATE_KEY.primeExponent[1], + &STATIC_PKCS_RSA_PRIVATE_KEY.coefficient +}; + +int KI_PKCS_RSAPrivate (keyInfoType) +POINTER *keyInfoType; +{ + *keyInfoType = (POINTER)&KIT_PKCS_RSAPrivate; + + /* Return 1 to indicate a KeyInfoType, not an AlgorithmInfoType */ + return (1); +} + +int KIT_PKCS_RSAPrivateAddInfo (key, info) +B_Key *key; +POINTER info; +{ + A_PKCS_RSA_PRIVATE_KEY *newValue; + int status; + + /* Allocate memory for A_PKCS_RSA_PRIVATE_KEY struct and copy integers + from supplied value. + */ + if ((status = B_MemoryPoolAlloc + (&key->infoCache.memoryPool, (POINTER *)&newValue, + sizeof (A_PKCS_RSA_PRIVATE_KEY))) != 0) + return (status); + if ((status = AllocAndCopyIntegerItems + ((POINTER)newValue, info, (POINTER)&STATIC_PKCS_RSA_PRIVATE_KEY, + PKCS_RSA_PRIVATE_KEY_ITEMS, sizeof (PKCS_RSA_PRIVATE_KEY_ITEMS) / + sizeof (PKCS_RSA_PRIVATE_KEY_ITEMS[0]), &key->infoCache.memoryPool)) + != 0) + return (status); + + /* Cache the full private key info. + */ + if ((status = CacheFullPrivateKey + (key, &newValue->modulus, &newValue->publicExponent, + &newValue->privateExponent, newValue->prime, newValue->primeExponent, + &newValue->coefficient)) != 0) + return (status); + return (B_InfoCacheAddInfo + (&key->infoCache, (POINTER)&KIT_PKCS_RSAPrivate, (POINTER)newValue)); +} + +int KIT_PKCS_RSAPrivateMakeInfo (info, key) +POINTER *info; +B_Key *key; +{ + A_PKCS_RSA_PRIVATE_KEY keyValue; + int status; + + /* If not already found in the cache, try to get values from + a full private key info. + */ + if ((status = GetFullPrivateKeyInfo + (&keyValue.modulus, &keyValue.publicExponent, + &keyValue.privateExponent, keyValue.prime, keyValue.primeExponent, + &keyValue.coefficient, key)) != 0) + return (status); + + /* Got all the needed fields, so allocate memory for a new + A_PKCS_RSA_PRIVATE_KEY struct and copy the key value. + */ + if ((status = B_MemoryPoolAlloc + (&key->infoCache.memoryPool, info, sizeof (A_PKCS_RSA_PRIVATE_KEY))) + != 0) + return (status); + + **(A_PKCS_RSA_PRIVATE_KEY **)info = keyValue; + return (0); +} + diff --git a/lib/bind/dnssafe/kipkcrpr.h b/lib/bind/dnssafe/kipkcrpr.h new file mode 100644 index 0000000000..9bcfc02d4c --- /dev/null +++ b/lib/bind/dnssafe/kipkcrpr.h @@ -0,0 +1,13 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +extern B_KeyInfoType KIT_PKCS_RSAPrivate; + +int KIT_PKCS_RSAPrivateAddInfo PROTO_LIST ((B_Key *, POINTER)); +int KIT_PKCS_RSAPrivateMakeInfo PROTO_LIST ((POINTER *, B_Key *)); + diff --git a/lib/bind/dnssafe/kirsacrt.c b/lib/bind/dnssafe/kirsacrt.c new file mode 100644 index 0000000000..ad086d7a7b --- /dev/null +++ b/lib/bind/dnssafe/kirsacrt.c @@ -0,0 +1,103 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "kinfotyp.h" +#include "intitem.h" +#include "kifulprv.h" +#include "port_after.h" + +#define NULL_UCHAR_PTR ((unsigned char *)NULL_PTR) + +int KIT_RSA_CRTAddInfo PROTO_LIST ((B_Key *, POINTER)); +int KIT_RSA_CRTMakeInfo PROTO_LIST ((POINTER *, B_Key *)); + +B_KeyInfoType KIT_RSA_CRT = {KIT_RSA_CRTAddInfo, KIT_RSA_CRTMakeInfo}; + +static A_RSA_CRT_KEY STATIC_RSA_CRT_KEY; +static ITEM *RSA_CRT_KEY_ITEMS[] = { + &STATIC_RSA_CRT_KEY.modulus, &STATIC_RSA_CRT_KEY.prime[0], + &STATIC_RSA_CRT_KEY.prime[1], + &STATIC_RSA_CRT_KEY.primeExponent[0], + &STATIC_RSA_CRT_KEY.primeExponent[1], + &STATIC_RSA_CRT_KEY.coefficient +}; + +/* args points to A_RSA_CRT_KEY. + */ +int KI_RSA_CRT (keyInfoType) +POINTER *keyInfoType; +{ + *keyInfoType = (POINTER)&KIT_RSA_CRT; + + /* Return 1 to indicate a KeyInfoType, not an AlgorithmInfoType */ + return (1); +} + +int KIT_RSA_CRTAddInfo (key, info) +B_Key *key; +POINTER info; +{ + A_RSA_CRT_KEY *newValue; + int status; + + /* Allocate memory for A_RSA_CRT_KEY struct and copy integers + from supplied value. + */ + if ((status = B_MemoryPoolAlloc + (&key->infoCache.memoryPool, (POINTER *)&newValue, + sizeof (A_RSA_CRT_KEY))) != 0) + return (status); + if ((status = AllocAndCopyIntegerItems + ((POINTER)newValue, info, (POINTER)&STATIC_RSA_CRT_KEY, + RSA_CRT_KEY_ITEMS, + sizeof (RSA_CRT_KEY_ITEMS) / sizeof (RSA_CRT_KEY_ITEMS[0]), + &key->infoCache.memoryPool)) != 0) + return (status); + + /* Cache the full private key info, setting unused fields to NULL. + */ + if ((status = CacheFullPrivateKey + (key, &newValue->modulus, (ITEM *)NULL_PTR, (ITEM *)NULL_PTR, + newValue->prime, newValue->primeExponent, &newValue->coefficient)) + != 0) + return (status); + return (B_InfoCacheAddInfo + (&key->infoCache, (POINTER)&KIT_RSA_CRT, (POINTER)newValue)); +} + +int KIT_RSA_CRTMakeInfo (info, key) +POINTER *info; +B_Key *key; +{ + A_RSA_CRT_KEY keyValue; + int status; + + /* If not already found in the cache, try to get values from + a full private key info, setting unneeded entries to NULL. + */ + if ((status = GetFullPrivateKeyInfo + (&keyValue.modulus, (ITEM *)NULL_PTR, (ITEM *)NULL_PTR, + keyValue.prime, keyValue.primeExponent, &keyValue.coefficient, + key)) != 0) + return (status); + + /* Got all the needed fields, so allocate memory for a new + A_RSA_CRT_KEY struct and copy the key value. + */ + if ((status = B_MemoryPoolAlloc + (&key->infoCache.memoryPool, info, sizeof (A_RSA_CRT_KEY))) != 0) + return (status); + + **(A_RSA_CRT_KEY **)info = keyValue; + return (0); +} + diff --git a/lib/bind/dnssafe/kirsapub.c b/lib/bind/dnssafe/kirsapub.c new file mode 100644 index 0000000000..bb55c31fd5 --- /dev/null +++ b/lib/bind/dnssafe/kirsapub.c @@ -0,0 +1,82 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "kinfotyp.h" +#include "intitem.h" +#include "kifulprv.h" +#include "kirsapub.h" +#include "port_after.h" + +B_KeyInfoType KIT_RSAPublic = + {KIT_RSAPublicAddInfo, KIT_RSAPublicMakeInfo}; + +static A_RSA_KEY STATIC_RSA_KEY; +static ITEM *RSA_KEY_ITEMS[] = + {&STATIC_RSA_KEY.modulus, &STATIC_RSA_KEY.exponent}; + +int KI_RSAPublic (keyInfoType) +POINTER *keyInfoType; +{ + *keyInfoType = (POINTER)&KIT_RSAPublic; + + /* Return 1 to indicate a KeyInfoType, not an AlgorithmInfoType */ + return (1); +} + +int KIT_RSAPublicAddInfo (key, info) +B_Key *key; +POINTER info; +{ + POINTER newValue; + int status; + + /* Allocate memory for A_RSA_KEY struct and copy integers + from supplied value. + */ + if ((status = B_MemoryPoolAlloc + (&key->infoCache.memoryPool, &newValue, sizeof (A_RSA_KEY))) != 0) + return (status); + if ((status = AllocAndCopyIntegerItems + (newValue, info, (POINTER)&STATIC_RSA_KEY, RSA_KEY_ITEMS, + sizeof (RSA_KEY_ITEMS) / sizeof (RSA_KEY_ITEMS[0]), + &key->infoCache.memoryPool)) != 0) + return (status); + + return (B_InfoCacheAddInfo + (&key->infoCache, (POINTER)&KIT_RSAPublic, newValue)); +} + +int KIT_RSAPublicMakeInfo (info, key) +POINTER *info; +B_Key *key; +{ + A_RSA_KEY keyValue; + int status; + + /* If not already found in the cache, try to get values from + a full private key info, setting unneeded entries to NULL. + */ + if ((status = GetFullPrivateKeyInfo + (&keyValue.modulus, &keyValue.exponent, (ITEM *)NULL_PTR, + (ITEM *)NULL_PTR, (ITEM *)NULL_PTR, (ITEM *)NULL_PTR, key)) != 0) + return (status); + + /* Got all the needed fields, so allocate memory for a new + A_RSA_KEY struct and copy the key value. + */ + if ((status = B_MemoryPoolAlloc + (&key->infoCache.memoryPool, info, sizeof (A_RSA_KEY))) != 0) + return (status); + + **(A_RSA_KEY **)info = keyValue; + return (0); +} diff --git a/lib/bind/dnssafe/kirsapub.h b/lib/bind/dnssafe/kirsapub.h new file mode 100644 index 0000000000..485fd79a77 --- /dev/null +++ b/lib/bind/dnssafe/kirsapub.h @@ -0,0 +1,13 @@ +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +extern B_KeyInfoType KIT_RSAPublic; + +int KIT_RSAPublicAddInfo PROTO_LIST ((B_Key *, POINTER)); +int KIT_RSAPublicMakeInfo PROTO_LIST ((POINTER *, B_Key *)); + diff --git a/lib/bind/dnssafe/md5.c b/lib/bind/dnssafe/md5.c new file mode 100644 index 0000000000..ed452422f0 --- /dev/null +++ b/lib/bind/dnssafe/md5.c @@ -0,0 +1,283 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "md5.h" +#include "port_after.h" + +/* Constants for MD5Transform routine. + */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +static void MD5Transform PROTO_LIST ((UINT4 [4], const unsigned char [64])); +static void Encode PROTO_LIST ((unsigned char *, UINT4 *, unsigned int)); +static void Decode PROTO_LIST ((UINT4 *, const unsigned char *, unsigned int)); + +/* F, G, H and I are basic MD5 functions. + */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. + */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. + Rotation is separate from addition to prevent recomputation. + */ +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +/* MD5 initialization. Begins an MD5 operation, writing a new context. + */ +void A_MD5Init (context) +A_MD5_CTX *context; +{ + context->count[0] = context->count[1] = 0; + + /* Load magic initialization constants. + */ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* MD5 block update operation. Continues an MD5 message-digest + operation, processing another message block, and updating the + context. + */ +void A_MD5Update (context, input, inputLen) +A_MD5_CTX *context; +const unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +{ + unsigned int i, index, partLen; + + /* Compute number of bytes mod 64 */ + index = (unsigned int)((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3)) + context->count[1]++; + context->count[1] += ((UINT4)inputLen >> 29); + + partLen = 64 - index; + + /* Transform as many times as possible. + */ + if (inputLen >= partLen) { + T_memcpy ((POINTER)&context->buffer[index], (CPOINTER)input, partLen); + MD5Transform (context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform (context->state, &input[i]); + + index = 0; + } + else + i = 0; + + /* Buffer remaining input */ + T_memcpy ((POINTER)&context->buffer[index], (CPOINTER)&input[i], inputLen-i); +} + +/* MD5 finalization. Ends an MD5 message-digest operation, writing the + the message digest and zeroizing the context. + Assume digest buffer is at least A_MD5_DIGEST_LEN. + */ +void A_MD5Final (context, digest) +A_MD5_CTX *context; +unsigned char *digest; +{ + unsigned char bits[8], pad[64]; + unsigned int index, padLen; + + /* Save number of bits */ + Encode (bits, context->count, 8); + + /* Pad out to 56 mod 64. + */ + index = (unsigned int)((context->count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + T_memset ((POINTER)pad, 0, padLen); + pad[0] = 0x80; + A_MD5Update (context, pad, padLen); + + /* Append length (before padding) */ + A_MD5Update (context, bits, 8); + + /* Store state in digest */ + Encode (digest, context->state, 16); + + /* Restart the context. */ + A_MD5Init (context); +} + +/* MD5 basic transformation. Transforms state based on block. + */ +static void MD5Transform (state, block) +UINT4 state[4]; +const unsigned char block[64]; +{ + UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode (x, block, 64); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. + */ + T_memset ((POINTER)x, 0, sizeof (x)); +} + +/* Encodes input (UINT4) into output (unsigned char). Assumes len is + a multiple of 4. + */ +static void Encode (output, input, len) +unsigned char *output; +UINT4 *input; +unsigned int len; +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (unsigned char)(input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); + } +} + +/* Decodes input (unsigned char) into output (UINT4). Assumes len is + a multiple of 4. + */ +static void Decode (output, input, len) +UINT4 *output; +const unsigned char *input; +unsigned int len; +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | + (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); +} + diff --git a/lib/bind/dnssafe/md5.h b/lib/bind/dnssafe/md5.h new file mode 100644 index 0000000000..ebfaed7d2e --- /dev/null +++ b/lib/bind/dnssafe/md5.h @@ -0,0 +1,32 @@ +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _MD5_H_ +#define _MD5_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#define A_MD5_DIGEST_LEN 16 + +typedef struct { + UINT4 state[4]; /* state (ABCD) */ + UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +} A_MD5_CTX; + +void A_MD5Init PROTO_LIST ((A_MD5_CTX *)); +void A_MD5Update PROTO_LIST ((A_MD5_CTX *, const unsigned char *, unsigned int)); +void A_MD5Final PROTO_LIST ((A_MD5_CTX *, unsigned char *)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/bind/dnssafe/md5rand.c b/lib/bind/dnssafe/md5rand.c new file mode 100644 index 0000000000..ca393111f6 --- /dev/null +++ b/lib/bind/dnssafe/md5rand.c @@ -0,0 +1,71 @@ +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +/* Define this so that the type of the 'this' pointer in the + virtual functions will be correct for this derived class. + */ +struct A_MD5_RANDOM_CTX; +#define THIS_DIGEST_RANDOM struct A_MD5_RANDOM_CTX + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "md5rand.h" +#include "port_after.h" + +static void A_MD5RandomDigestUpdate PROTO_LIST + ((A_MD5_RANDOM_CTX *, unsigned char *, unsigned int)); +static void A_MD5RandomDigestFinal PROTO_LIST + ((A_MD5_RANDOM_CTX *, unsigned char *)); + +static A_DigestRandomVTable V_TABLE = + {A_MD5RandomDigestUpdate, A_MD5RandomDigestFinal}; + +void A_MD5RandomInit (context) +A_MD5_RANDOM_CTX *context; +{ + /* Initialize "base class" */ + A_DigestRandomInit + (&context->digestRandom, A_MD5_DIGEST_LEN, context->state); + + /* Initialize digest algorithm and set vTable. + */ + A_MD5Init (&context->md5Context); + context->digestRandom.vTable = &V_TABLE; +} + +void A_MD5RandomUpdate (context, input, inputLen) +A_MD5_RANDOM_CTX *context; +unsigned char *input; +unsigned int inputLen; +{ + A_DigestRandomUpdate (&context->digestRandom, input, inputLen); +} + +void A_MD5RandomGenerateBytes (context, output, outputLen) +A_MD5_RANDOM_CTX *context; +unsigned char *output; +unsigned int outputLen; +{ + A_DigestRandomGenerateBytes (&context->digestRandom, output, outputLen); +} + +static void A_MD5RandomDigestUpdate (context, input, inputLen) +A_MD5_RANDOM_CTX *context; +unsigned char *input; +unsigned int inputLen; +{ + A_MD5Update (&context->md5Context, input, inputLen); +} + +static void A_MD5RandomDigestFinal (context, digest) +A_MD5_RANDOM_CTX *context; +unsigned char *digest; +{ + A_MD5Final (&context->md5Context, digest); +} diff --git a/lib/bind/dnssafe/md5rand.h b/lib/bind/dnssafe/md5rand.h new file mode 100644 index 0000000000..f197410695 --- /dev/null +++ b/lib/bind/dnssafe/md5rand.h @@ -0,0 +1,36 @@ +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _MD5RAND_H_ +#define _MD5RAND_H_ 1 + +#include "digrand.h" +#include "md5.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct A_MD5_RANDOM_CTX { + A_DigestRandom digestRandom; /* "base class" */ + + unsigned char state[3 * A_MD5_DIGEST_LEN]; + A_MD5_CTX md5Context; +} A_MD5_RANDOM_CTX; + +void A_MD5RandomInit PROTO_LIST ((A_MD5_RANDOM_CTX *)); +void A_MD5RandomUpdate PROTO_LIST + ((A_MD5_RANDOM_CTX *, unsigned char *, unsigned int)); +void A_MD5RandomGenerateBytes PROTO_LIST + ((A_MD5_RANDOM_CTX *, unsigned char *, unsigned int)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/bind/dnssafe/prime.c b/lib/bind/dnssafe/prime.c new file mode 100644 index 0000000000..14bab25ef3 --- /dev/null +++ b/lib/bind/dnssafe/prime.c @@ -0,0 +1,166 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bigmath.h" +#include "prime.h" +#include "port_after.h" + +static unsigned char SMALL_PRIME[]= {3, 5, 7, 11, 13, 17, 19, 23, 29, 31}; + +/* Prime finding routine. + Returns 0, AE_CANCEL, AE_NEED_RANDOM. + */ +int PrimeFind + (prime, primeSizeBits, primeWords, ee, modulusWords, randomBlock, + surrenderContext) +UINT2 *prime; +unsigned int primeSizeBits; +unsigned int primeWords; +UINT2 *ee; +unsigned int modulusWords; +unsigned char *randomBlock; +A_SURRENDER_CTX *surrenderContext; +{ + UINT2 t1[MAX_RSA_MODULUS_WORDS], u1[MAX_RSA_MODULUS_WORDS], + u2[MAX_RSA_MODULUS_WORDS], u3[MAX_RSA_MODULUS_WORDS], + u4[MAX_RSA_MODULUS_WORDS]; + char sieve[1000]; + int status = 0; + unsigned int i, r, s, testResult; + + do { + /* Create a starting point for the prime from the random block */ + for (i = 0; i < primeWords; i++) { + prime[i] = (UINT2)((UINT2)randomBlock[0] << 8) + randomBlock[1]; + randomBlock += 2; + } + + /* set high order two bits */ + BigSetbit (prime, primeSizeBits-2); + BigSetbit (prime, primeSizeBits-1); + for (i = primeSizeBits; i < (unsigned int)(16 * primeWords); i++) + BigClrbit (prime, i); + + /* force p to be even */ + BigClrbit (prime, 0); + + /* clear sieve and mark even positions */ + for (i = 0; i < 1000; i += 2) { + sieve[i] = 1; + sieve[i+1] = 0; + } + + /* sieve by all odd numbers (don't bother with primality checking) */ + for (s = 3; s < 9000; s += 2) { + /* increase likelihood that s is prime */ + for (i = 0; i < 5; i++) + if (s > SMALL_PRIME[i] && !(s % SMALL_PRIME[i])) + continue; + + /* sieve based on s */ + r = BigSmod (prime, s, primeWords); + + /* returns prime modulo s */ + if (r == 0) + r = s; + + for (i = s - r; i < 1000; i += s) + sieve[i] = 1; + } + + /* t1 = 1 */ + BigConst (t1, 1, modulusWords); + + /* now check for primality of values with unmarked sieve */ + testResult = 0; + for (i = 0; i < 1000; i++, BigInc (prime, primeWords)) { + if (sieve[i]) + continue; + + /* copy prime into big variable */ + BigZero (u4, modulusWords); + BigCopy (u4, prime, primeWords); + + /* set u4 = p - 1 */ + BigDec (u4, modulusWords); + BigPegcd (u1, u2, u3, ee, u4, modulusWords); + + /* Now u1 = gcd (E, t1). + Test (E, t1)==1 */ + if (BigCmp (t1, u1, modulusWords)) + continue; + + /* check for pseudo primality */ + if ((status = PseudoPrime + (&testResult, prime, primeWords, surrenderContext)) != 0) + break; + if (testResult) + /* testResult is set and will cause a break out of while (1) loop */ + break; + } + if (status) + break; + + if (!testResult) + /* Couldn't find a prime with the supplied random block, so ask + caller to generate another random block and try again. */ + status = AE_NEED_RANDOM; + } while (0); + + T_memset ((POINTER)u1, 0, sizeof (u1)); + T_memset ((POINTER)u2, 0, sizeof (u2)); + T_memset ((POINTER)u3, 0, sizeof (u3)); + T_memset ((POINTER)u4, 0, sizeof (u4)); + return (status); +} + +/* Pseudo-primality test. + If pseudo prime, *testResult = 1, else *testResult = 0. + Returns 0, AE_CANCEL. + */ +int PseudoPrime (testResult, prime, primeWords, surrenderContext) +unsigned int *testResult; +UINT2 *prime; +unsigned int primeWords; +A_SURRENDER_CTX *surrenderContext; +{ + UINT2 base[MAX_RSA_MODULUS_WORDS], remainder[MAX_RSA_MODULUS_WORDS]; + int status; + unsigned int i; + + /* Default testResult to false. */ + *testResult = 0; + + /* Prepare for setting base vector to the small prime. */ + T_memset ((POINTER)base, 0, sizeof (base)); + + for (i = 0; i < 4; i++) { + /* check to see if target is multiple of SMALL_PRIME */ + if (BigSmod (prime, (unsigned int)SMALL_PRIME[i], primeWords) == 0) + /* fail... */ + return (0); + + /* Fermat test. Compute remainder = base ^ prime mod prime + and compare the base to the remainder. + */ + base[0] = (UINT2)SMALL_PRIME[i]; + if ((status = BigModExp + (remainder, base, prime, prime, primeWords, surrenderContext)) != 0) + return (status); + if (BigCmp (remainder, base, primeWords) != 0) + /* fail... */ + return (0); + } + + *testResult = 1; + return (0); +} + diff --git a/lib/bind/dnssafe/prime.h b/lib/bind/dnssafe/prime.h new file mode 100644 index 0000000000..e922f36abd --- /dev/null +++ b/lib/bind/dnssafe/prime.h @@ -0,0 +1,26 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _PRIME_H_ +#define _PRIME_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +int PrimeFind PROTO_LIST + ((UINT2 *, unsigned int, unsigned int, UINT2 *, unsigned int, + unsigned char *, A_SURRENDER_CTX *)); +int PseudoPrime PROTO_LIST + ((unsigned int *, UINT2 *, unsigned int, A_SURRENDER_CTX *)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/bind/dnssafe/random.c b/lib/bind/dnssafe/random.c new file mode 100644 index 0000000000..1ddb188513 --- /dev/null +++ b/lib/bind/dnssafe/random.c @@ -0,0 +1,60 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ainfotyp.h" +#include "algobj.h" +#include "port_after.h" + +int B_RandomInit + (algorithmObject, algorithmChooser, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + if (AlgorithmWrapCheck (THE_ALG_WRAP) != 0) + /* Assume error is B_ALGORITHM_OBJ */ + return (BE_RANDOM_OBJ); + + return (B_AlgorithmRandomInit + (&THE_ALG_WRAP->algorithm, algorithmChooser, surrenderContext)); +} + +int B_RandomUpdate (algorithmObject, input, inputLen, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +unsigned char *input; +unsigned int inputLen; +A_SURRENDER_CTX *surrenderContext; +{ + if (AlgorithmWrapCheck (THE_ALG_WRAP) != 0) + /* Assume error is B_ALGORITHM_OBJ */ + return (BE_RANDOM_OBJ); + + return (B_AlgorithmRandomUpdate + (&THE_ALG_WRAP->algorithm, input, inputLen, surrenderContext)); +} + +int B_GenerateRandomBytes + (algorithmObject, output, outputLen, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +unsigned char *output; +unsigned int outputLen; +A_SURRENDER_CTX *surrenderContext; +{ + if (AlgorithmWrapCheck (THE_ALG_WRAP) != 0) + /* Assume error is B_ALGORITHM_OBJ */ + return (BE_RANDOM_OBJ); + + return (B_AlgorithmGenerateRandomBytes + (&THE_ALG_WRAP->algorithm, output, outputLen, surrenderContext)); +} + diff --git a/lib/bind/dnssafe/rsa.c b/lib/bind/dnssafe/rsa.c new file mode 100644 index 0000000000..64bc5e6ec8 --- /dev/null +++ b/lib/bind/dnssafe/rsa.c @@ -0,0 +1,211 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "rsa.h" +#include "bigmath.h" +#include "port_after.h" + +/* RSA encryption/decryption with full exponent. + */ + +#define GENERATE_BREAK(type) { \ + status = type; \ + break; \ + } + +static int RSA PROTO_LIST + ((A_RSA_CTX *, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, A_SURRENDER_CTX *)); + +/* Returns 0, AE_MODULUS_LEN, AE_KEY_INFO. + */ +int A_RSAInit (context, key) +A_RSA_CTX *context; +A_RSA_KEY *key; +{ + if (A_IntegerBits (key->modulus.data, key->modulus.len) + > MAX_RSA_MODULUS_BITS) + /* Key size is too big to handle. */ + return (AE_MODULUS_LEN); + + /* Set the block update blockLen to be big enough to hold the modulus. */ + context->blockLen = + (A_IntegerBits (key->modulus.data, key->modulus.len) + 7) / 8; + + context->inputLen = 0; + + /* convert modulus to bignum representation */ + if (CanonicalToBig + (context->modulus, MAX_RSA_MODULUS_WORDS, key->modulus.data, + key->modulus.len)) + return (AE_KEY_INFO); + + /* compute significant length of modulus */ + context->modulusWords = BigLen + (context->modulus, MAX_RSA_MODULUS_WORDS) / 16 + 1; + + /* convert exponent to bignum representation */ + if (CanonicalToBig + (context->exponent, context->modulusWords, + key->exponent.data, key->exponent.len)) + return (AE_KEY_INFO); + + return (0); +} + +int A_RSAUpdate + (context, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + surrenderContext) +A_RSA_CTX *context; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +const unsigned char *partIn; +unsigned int partInLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned int partialLen, localPartOutLen; + + /* Initialize partOutLen to zero. */ + *partOutLen = 0; + + if (context->inputLen + partInLen < context->blockLen) { + /* Not enough to encrypt - just accumulate. + */ + T_memcpy + ((POINTER)(context->input + context->inputLen), (CPOINTER)partIn, + partInLen); + context->inputLen += partInLen; + return (0); + } + + if (context->inputLen > 0) { + /* Need to accumulate the rest of the block bytes into the input and + encrypt from there (otherwise it's OK to encrypt straight from + the partIn). + */ + partialLen = context->blockLen - context->inputLen; + T_memcpy + ((POINTER)(context->input + context->inputLen), (CPOINTER)partIn, + partialLen); + partIn += partialLen; + partInLen -= partialLen; + + if ((status = RSA + (context, partOut, &localPartOutLen, maxPartOutLen, context->input, + surrenderContext)) != 0) + return (status); + (*partOutLen) += localPartOutLen; + partOut += localPartOutLen; + maxPartOutLen -= localPartOutLen; + } + + /* Encrypt as many blocks of input as provided. + */ + while (partInLen >= context->blockLen) { + if ((status = RSA + (context, partOut, &localPartOutLen, maxPartOutLen, partIn, + surrenderContext)) != 0) + return (status); + + partIn += context->blockLen; + partInLen -= context->blockLen; + (*partOutLen) += localPartOutLen; + partOut += localPartOutLen; + maxPartOutLen -= localPartOutLen; + } + + /* Copy remaining input bytes to the context's input buffer. + */ + T_memcpy + ((POINTER)context->input, partIn, context->inputLen = partInLen); + return (0); +} + +int A_RSAFinal (context) +A_RSA_CTX *context; +{ + if (context->inputLen != 0) + return (AE_INPUT_LEN); + + /* Restart context to accumulate a new block. */ + context->inputLen = 0; + return (0); +} + +/* Assume input length is context->blockLen. + */ +static int RSA + (context, output, outputLen, maxOutputLen, input, surrenderContext) +A_RSA_CTX *context; +unsigned char *output; +unsigned int *outputLen; +unsigned int maxOutputLen; +const unsigned char *input; +A_SURRENDER_CTX *surrenderContext; +{ + struct ModExpFrame { + UINT2 bigInBuf[MAX_RSA_MODULUS_WORDS], bigOutBuf[MAX_RSA_MODULUS_WORDS]; + } *frame = (struct ModExpFrame *)NULL_PTR; +#if !USE_ALLOCED_FRAME + struct ModExpFrame stackFrame; +#endif + int status; + + status = 0; + do { + if ((*outputLen = context->blockLen) > maxOutputLen) + return (AE_OUTPUT_LEN); + +#if USE_ALLOCED_FRAME + if ((frame = (struct ModExpFrame *)T_malloc (sizeof (*frame))) + == (struct ModExpFrame *)NULL_PTR) { + status = AE_ALLOC; + break; + } +#else + /* Just use the buffers allocated on the stack. */ + frame = &stackFrame; +#endif + + /* Convert input to bignum representation. + This won't return AE_DATA since input length was checked at Update. + */ + CanonicalToBig + (frame->bigInBuf, context->modulusWords, input, context->blockLen); + + /* Check for overflow. */ + if (BigCmp (frame->bigInBuf, context->modulus, context->modulusWords) >= 0) + GENERATE_BREAK (AE_INPUT_DATA); + + /* Exponentiate. */ + if ((status = BigModExp + (frame->bigOutBuf, frame->bigInBuf, context->exponent, + context->modulus, context->modulusWords, surrenderContext)) != 0) + break; + + /* Convert output to canonical representation. + This won't return AE_DATA since outputLen was set above. + */ + BigToCanonical + (output, *outputLen, frame->bigOutBuf, context->modulusWords); + } while (0); + + if (frame != (struct ModExpFrame *)NULL_PTR) { + T_memset ((POINTER)frame, 0, sizeof (*frame)); +#if USE_ALLOCED_FRAME + T_free ((POINTER)frame); +#endif + } + + return (status); +} diff --git a/lib/bind/dnssafe/rsa.h b/lib/bind/dnssafe/rsa.h new file mode 100644 index 0000000000..153263f677 --- /dev/null +++ b/lib/bind/dnssafe/rsa.h @@ -0,0 +1,44 @@ +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _RSA_H_ +#define _RSA_H_ 1 + +#include "bigmaxes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Note, these are only valid after a call to A_RSAInit. + */ +#define A_RSA_BLOCK_LEN(context) ((context)->blockLen) +#define A_RSA_MAX_OUTPUT_LEN(context, inputLen)\ + (inputLen) + (((inputLen) % (context)->blockLen) ?\ + (context)->blockLen - ((inputLen) % (context)->blockLen) : 0) + +typedef struct { + unsigned int blockLen; /* total size for the block to be computed */ + unsigned char input[MAX_RSA_MODULUS_LEN]; + unsigned int inputLen; + unsigned int modulusWords; + UINT2 modulus[MAX_RSA_MODULUS_WORDS]; + UINT2 exponent[MAX_RSA_MODULUS_WORDS]; +} A_RSA_CTX; + +int A_RSAInit PROTO_LIST ((A_RSA_CTX *, A_RSA_KEY *)); +int A_RSAUpdate PROTO_LIST + ((A_RSA_CTX *, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int A_RSAFinal PROTO_LIST ((A_RSA_CTX *)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/bind/dnssafe/rsakeygn.c b/lib/bind/dnssafe/rsakeygn.c new file mode 100644 index 0000000000..bad9e8c290 --- /dev/null +++ b/lib/bind/dnssafe/rsakeygn.c @@ -0,0 +1,244 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bigmath.h" +#include "surrendr.h" +#include "prime.h" +#include "rsakeygn.h" +#include "port_after.h" + +#define GENERATE_BREAK(type) { \ + status = type; \ + break; \ + } + +static int RSAParameters PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, + unsigned int, unsigned int, A_SURRENDER_CTX *)); +static void SetRSAKeyGenResult PROTO_LIST + ((A_PKCS_RSA_PRIVATE_KEY *, A_RSA_KEY_GEN_CTX *, UINT2 *, UINT2 *)); + +int A_RSAKeyGenInit (context, params) +A_RSA_KEY_GEN_CTX *context; +A_RSA_KEY_GEN_PARAMS *params; +{ + context->modulusBits = params->modulusBits; + + /* Prezeroize big public exponent vector. */ + T_memset + ((POINTER)context->bigPublicExponent, 0, + sizeof (context->bigPublicExponent)); + + /* Copy public exponent into big vector */ + if (CanonicalToBig + (context->bigPublicExponent, MAX_RSA_MODULUS_WORDS, + params->publicExponent.data, params->publicExponent.len) != 0) + /* could not copy exponent into MAX_RSA_MODULUS_WORDS */ + return (AE_EXPONENT_LEN); + + /* Check that public exponent is in bounds and odd. + */ + if (BigLen (context->bigPublicExponent, MAX_RSA_MODULUS_WORDS) >= + context->modulusBits) + return (AE_EXPONENT_LEN); + if (!(context->bigPublicExponent[0] & 1)) + return (AE_EXPONENT_EVEN); + + return (0); +} + +/* This generates an RSA keypair of size modulusBits with the fixed + publicExponent, pointing result to the resulting integers. The + resulting integer data is in the context, so that the values must be + copied before the context is zeroized. + All integers are unsigned canonical bytes arrays with the most significant + byte first. + The randomBlock is of length randomBlockLen returned by RSAKeyGenQuery. + This assumes that the modulusBits size was checked by RSAKeyGenQuery. + */ +int A_RSAKeyGen (context, result, randomBlock, surrenderContext) +A_RSA_KEY_GEN_CTX *context; +A_PKCS_RSA_PRIVATE_KEY **result; +unsigned char *randomBlock; +A_SURRENDER_CTX *surrenderContext; +{ + UINT2 *bigPrimeP, *bigPrimeQ; + int status; + unsigned int modulusWords, primeSizeBits, primeWords; + + /* Prezeroize all big word vectors. */ + T_memset ((POINTER)context->bigModulus, 0, sizeof (context->bigModulus)); + T_memset + ((POINTER)context->bigPrivateExponent, 0, + sizeof (context->bigPrivateExponent)); + T_memset ((POINTER)context->bigPrime1, 0, sizeof (context->bigPrime1)); + T_memset ((POINTER)context->bigPrime2, 0, sizeof (context->bigPrime2)); + T_memset ((POINTER)context->bigExponentP, 0, sizeof (context->bigExponentP)); + T_memset ((POINTER)context->bigExponentQ, 0, sizeof (context->bigExponentQ)); + T_memset + ((POINTER)context->bigCoefficient, 0, sizeof (context->bigCoefficient)); + + /* prime size is half modulus size */ + modulusWords = BITS_TO_WORDS (context->modulusBits); + primeSizeBits = RSA_PRIME_BITS (context->modulusBits); + primeWords = BITS_TO_WORDS (RSA_PRIME_BITS (context->modulusBits)); + + /* Fish for bigPrime1 and bigPrime2 that are compatible with supplied + publicExponent. + The randomBlock holds random bytes for two primes. + */ + if ((status = PrimeFind + (context->bigPrime1, primeSizeBits, primeWords, + context->bigPublicExponent, modulusWords, randomBlock, + surrenderContext)) != 0) + return (status); + if ((status = PrimeFind + (context->bigPrime2, context->modulusBits - primeSizeBits, + primeWords, context->bigPublicExponent, modulusWords, + randomBlock + (2 * primeWords), surrenderContext)) != 0) + return (status); + + /* Set bigPrimeP to the larger of bigPrime1 and bigPrime2 and set + bigPrimeQ to the smaller. + */ + if (BigCmp (context->bigPrime1, context->bigPrime2, primeWords) == 1) { + bigPrimeP = context->bigPrime1; + bigPrimeQ = context->bigPrime2; + } + else { + bigPrimeP = context->bigPrime2; + bigPrimeQ = context->bigPrime1; + } + + /* Calculate the rest of the key components */ + if ((status = RSAParameters + (context->bigModulus, context->bigCoefficient, + context->bigExponentP, context->bigExponentQ, + context->bigPrivateExponent, context->bigPublicExponent, + bigPrimeP, bigPrimeQ, primeWords, modulusWords, surrenderContext)) != 0) + return (status); + + /* Copy key components into canonical buffers which are at the + end of the context. */ + *result = &context->result; + SetRSAKeyGenResult (*result, context, bigPrimeP, bigPrimeQ); + + return (0); +} + +/* Assumes ee, pp, qq are given, calculates other parameters. + Returns 0, AE_CANCEL. + */ +static int RSAParameters + (nn, cr, dp, dq, dd, ee, pp, qq, primeWords, modulusWords, surrenderContext) +UINT2 *nn, *cr, *dp, *dq, *dd, *ee, *pp, *qq; +unsigned int primeWords, modulusWords; +A_SURRENDER_CTX *surrenderContext; +{ + UINT2 t1[2 * MAX_RSA_PRIME_WORDS], t2[MAX_RSA_PRIME_WORDS], + t3[MAX_RSA_MODULUS_WORDS], u1[MAX_RSA_MODULUS_WORDS], + u3[MAX_RSA_MODULUS_WORDS], pm1[MAX_RSA_PRIME_WORDS], + qm1[MAX_RSA_PRIME_WORDS]; + int status; + + do { + /* N=P*Q */ + BigMpy (t1, pp, qq, primeWords); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + BigCopy (nn, t1, modulusWords); + + /* qm1=q-1 & pm1=p-1 */ + BigConst (t1, 1, primeWords); + BigSub (qm1, qq, t1, primeWords); + BigSub (pm1, pp, t1, primeWords); + + /* t3=1 */ + BigConst (t3, 1, modulusWords); + + /*t1=phi (N) */ + BigMpy (t1, pm1, qm1, primeWords); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + + /* compute decryption exponent */ + BigPegcd (u1, dd, u3, ee, t1, modulusWords); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + + /* calc DP=inv (E)[mod (P-1)] & DQ=inv (e)[mod (Q-1)] */ + BigPdiv (t1, dp, dd, pm1, modulusWords, primeWords); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + BigPdiv (t1, dq, dd, qm1, modulusWords, primeWords); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + + /* calc CR = (inv (Q)[modP]) */ + BigPegcd (t1, t2, cr, pp, qq, primeWords); + } while (0); + + T_memset ((POINTER)t1, 0, sizeof (t1)); + T_memset ((POINTER)t2, 0, sizeof (t2)); + T_memset ((POINTER)t3, 0, sizeof (t3)); + T_memset ((POINTER)u1, 0, sizeof (u1)); + T_memset ((POINTER)u3, 0, sizeof (u3)); + T_memset ((POINTER)pm1, 0, sizeof (pm1)); + T_memset ((POINTER)qm1, 0, sizeof (qm1)); + return (status); +} + +static void SetRSAKeyGenResult (result, context, bigPrimeP, bigPrimeQ) +A_PKCS_RSA_PRIVATE_KEY *result; +A_RSA_KEY_GEN_CTX *context; +UINT2 *bigPrimeP; +UINT2 *bigPrimeQ; +{ + unsigned int primeLen, modulusLen; + + modulusLen = result->modulus.len = result->publicExponent.len = + result->privateExponent.len = BITS_TO_LEN (context->modulusBits); + primeLen = result->prime[0].len = result->prime[1].len = + result->primeExponent[0].len = result->primeExponent[1].len = + result->coefficient.len = RSA_PRIME_LEN (context->modulusBits); + + result->modulus.data = context->resultBuffer; + result->publicExponent.data = result->modulus.data + modulusLen; + result->privateExponent.data = result->publicExponent.data + modulusLen; + result->prime[0].data = result->privateExponent.data + modulusLen; + result->prime[1].data = result->prime[0].data + primeLen; + result->primeExponent[0].data = result->prime[1].data + primeLen; + result->primeExponent[1].data = result->primeExponent[0].data + primeLen; + result->coefficient.data = result->primeExponent[1].data + primeLen; + + BigToCanonical + (result->modulus.data, modulusLen, context->bigModulus, + MAX_RSA_MODULUS_WORDS); + BigToCanonical + (result->publicExponent.data, modulusLen, + context->bigPublicExponent, MAX_RSA_MODULUS_WORDS); + BigToCanonical + (result->privateExponent.data, modulusLen, + context->bigPrivateExponent, MAX_RSA_MODULUS_WORDS); + BigToCanonical + (result->prime[0].data, primeLen, bigPrimeP, MAX_RSA_PRIME_WORDS); + BigToCanonical + (result->prime[1].data, primeLen, bigPrimeQ, MAX_RSA_PRIME_WORDS); + BigToCanonical + (result->primeExponent[0].data, primeLen, context->bigExponentP, + MAX_RSA_PRIME_WORDS); + BigToCanonical + (result->primeExponent[1].data, primeLen, context->bigExponentQ, + MAX_RSA_PRIME_WORDS); + BigToCanonical + (result->coefficient.data, primeLen, context->bigCoefficient, + MAX_RSA_PRIME_WORDS); +} diff --git a/lib/bind/dnssafe/rsakeygn.h b/lib/bind/dnssafe/rsakeygn.h new file mode 100644 index 0000000000..ba40b86486 --- /dev/null +++ b/lib/bind/dnssafe/rsakeygn.h @@ -0,0 +1,54 @@ +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _RSAKEYGN_H_ +#define _RSAKEYGN_H_ 1 + +#include "bigmaxes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MIN_RSA_MODULUS_BITS 256 + +/* Need randomBlock to hold bytes for two UINT2 prime number arrays each, + of length primeWords = BITS_TO_WORDS (RSA_PRIME_BITS (modulusBits)). */ +#define A_RSA_KEY_GEN_RANDOM_BLOCK_LEN(modulusBits) \ + (4 * BITS_TO_WORDS (RSA_PRIME_BITS (modulusBits))) + +/* Note that the scratch area for the output integers is allocated + in the context after the RSA_KEY_GEN_CTX. + */ +typedef struct { + unsigned int modulusBits; + UINT2 bigModulus[MAX_RSA_MODULUS_WORDS]; + UINT2 bigPublicExponent[MAX_RSA_MODULUS_WORDS]; + UINT2 bigPrivateExponent[MAX_RSA_MODULUS_WORDS]; + UINT2 bigPrime1[MAX_RSA_PRIME_WORDS]; + UINT2 bigPrime2[MAX_RSA_PRIME_WORDS]; + UINT2 bigExponentP[MAX_RSA_PRIME_WORDS]; + UINT2 bigExponentQ[MAX_RSA_PRIME_WORDS]; + UINT2 bigCoefficient[MAX_RSA_PRIME_WORDS]; + A_PKCS_RSA_PRIVATE_KEY result; + unsigned char resultBuffer + [3 * BITS_TO_LEN (MAX_RSA_MODULUS_BITS) + + 5 * RSA_PRIME_LEN (MAX_RSA_MODULUS_BITS)]; +} A_RSA_KEY_GEN_CTX; + +int A_RSAKeyGenInit PROTO_LIST ((A_RSA_KEY_GEN_CTX *, A_RSA_KEY_GEN_PARAMS *)); +int A_RSAKeyGen PROTO_LIST + ((A_RSA_KEY_GEN_CTX *, A_PKCS_RSA_PRIVATE_KEY **, unsigned char *, + A_SURRENDER_CTX *)); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/lib/bind/dnssafe/seccbcd.c b/lib/bind/dnssafe/seccbcd.c new file mode 100644 index 0000000000..bff839d91f --- /dev/null +++ b/lib/bind/dnssafe/seccbcd.c @@ -0,0 +1,148 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "secrcbc.h" +#include "port_after.h" + +static void SecretCBCDecryptBlock PROTO_LIST + ((POINTER, unsigned char *, SECRET_CRYPT, unsigned char *, + unsigned char *)); + +/* On first call, it is assumed that *remainderLen is zero. + This assumes remainder buffer is at least 16 bytes is size. + Returns AE_OUTPUT_LEN, 0. + */ +int SecretCBCDecryptUpdate + (context, xorBlock, remainder, remainderLen, SecretDecrypt, output, + outputLen, maxOutputLen, input, inputLen) +POINTER context; +unsigned char *xorBlock; +unsigned char *remainder; +unsigned int *remainderLen; +SECRET_CRYPT SecretDecrypt; +unsigned char *output; +unsigned int *outputLen; +unsigned int maxOutputLen; +unsigned char *input; +unsigned int inputLen; +{ + unsigned int partialLen; + + if (*remainderLen + inputLen <= 16) { + /* Not enough to decrypt, just accumulate into remainder. + */ + *outputLen = 0; + T_memcpy ((POINTER)remainder + *remainderLen, (POINTER)input, inputLen); + *remainderLen += inputLen; + return (0); + } + + /* Fill up the rest of the remainder with bytes from input. + */ + T_memcpy + ((POINTER)remainder + *remainderLen, (POINTER)input, + partialLen = 16 - *remainderLen); + input += partialLen; + inputLen -= partialLen; + + /* remainder is full and inputLen is at least 1. Compute outputLen + as the size needed to keep remainder as full as possible. + */ + if ((*outputLen = 8 * ((inputLen + 7) / 8)) > maxOutputLen) + return (AE_OUTPUT_LEN); + + SecretCBCDecryptBlock + (context, xorBlock, SecretDecrypt, output, remainder); + output += 8; + + if (inputLen <= 8) { + /* Shift remaining input bytes into remainder */ + T_memmove ((POINTER)remainder, (POINTER)(remainder + 8), 8); + T_memcpy ((POINTER)(remainder + 8), (POINTER)input, inputLen); + *remainderLen = 8 + inputLen; + return (0); + } + + /* Decrypt the rest of the remainder. + */ + SecretCBCDecryptBlock + (context, xorBlock, SecretDecrypt, output, remainder + 8); + output += 8; + + /* Now decrypt the bulk of the input. + */ + while (inputLen > 16) { + SecretCBCDecryptBlock (context, xorBlock, SecretDecrypt, output, input); + output += 8; + input += 8; + inputLen -= 8; + } + + /* inputLen is now <= 16, so copy input to remainder. + */ + T_memcpy ((POINTER)remainder, (POINTER)input, inputLen); + *remainderLen = inputLen; + return (0); +} + +/* The caller must restart the context (setting remainderLen to zero). + Returns AE_INPUT_LEN, AE_OUTPUT_LEN, 0. + */ +int SecretCBCDecryptFinal + (context, xorBlock, remainder, remainderLen, SecretDecrypt, output, + outputLen, maxOutputLen) +POINTER context; +unsigned char *xorBlock; +unsigned char *remainder; +unsigned int remainderLen; +SECRET_CRYPT SecretDecrypt; +unsigned char *output; +unsigned int *outputLen; +unsigned int maxOutputLen; +{ + if ((*outputLen = remainderLen) == 0) + /* There was never any data. */ + return (0); + + if (remainderLen != 8 && remainderLen != 16) + return (AE_INPUT_LEN); + + if (*outputLen > maxOutputLen) + return (AE_OUTPUT_LEN); + + SecretCBCDecryptBlock + (context, xorBlock, SecretDecrypt, output, remainder); + output += 8; + if (remainderLen == 16) + SecretCBCDecryptBlock + (context, xorBlock, SecretDecrypt, output, remainder + 8); + return (0); +} + +static void SecretCBCDecryptBlock (context, xorBlock, SecretDecrypt, out, in) +POINTER context; +unsigned char *xorBlock; +SECRET_CRYPT SecretDecrypt; +unsigned char *out; +unsigned char *in; +{ + unsigned char tempBuffer[8]; + unsigned int i; + + /* Save input to be copied to the xor block. */ + T_memcpy ((POINTER)tempBuffer, (POINTER)in, 8); + (*SecretDecrypt) (context, out, in); + for (i = 0; i < 8; i++) + out[i] ^= xorBlock[i]; + T_memcpy ((POINTER)xorBlock, (POINTER)tempBuffer, 8); + + T_memset ((POINTER)tempBuffer, 0, sizeof (tempBuffer)); +} diff --git a/lib/bind/dnssafe/seccbce.c b/lib/bind/dnssafe/seccbce.c new file mode 100644 index 0000000000..3a9a291239 --- /dev/null +++ b/lib/bind/dnssafe/seccbce.c @@ -0,0 +1,99 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "secrcbc.h" +#include "port_after.h" + +/* On first call, it is assumed that *remainderLen is zero. + Returns AE_OUTPUT_LEN, 0. + */ +int SecretCBCEncryptUpdate + (context, xorBlock, remainder, remainderLen, SecretEncrypt, output, + outputLen, maxOutputLen, input, inputLen) +POINTER context; +unsigned char *xorBlock; +unsigned char *remainder; +unsigned int *remainderLen; +SECRET_CRYPT SecretEncrypt; +unsigned char *output; +unsigned int *outputLen; +unsigned int maxOutputLen; +unsigned char *input; +unsigned int inputLen; +{ + unsigned int partialLen, totalLen, i; + + totalLen = *remainderLen + inputLen; + + /* Output length will be all available 8-byte blocks. + */ + if ((*outputLen = 8 * (totalLen / 8)) > maxOutputLen) + return (AE_OUTPUT_LEN); + + if (totalLen < 8) { + /* Not enough to encrypt, just accumulate into remainder. + */ + T_memcpy + ((POINTER)remainder + *remainderLen, (POINTER)input, inputLen); + *remainderLen = totalLen; + + return (0); + } + + /* Accumulate enough bytes from input into remainder to encrypt the + remainder. + */ + T_memcpy + ((POINTER)remainder + *remainderLen, (POINTER)input, + partialLen = 8 - *remainderLen); + + for (i = 0; i < 8; i++) + output[i] = remainder[i] ^ xorBlock[i]; + /* Encrypt in place */ + (*SecretEncrypt) (context, output, output); + + T_memcpy ((POINTER)xorBlock, (POINTER)output, 8); + input += partialLen; + inputLen -= partialLen; + output += 8; + + /* Now encrypt the bulk of the input. + */ + while (inputLen >= 8) { + for (i = 0; i < 8; i++) + output[i] = *(input++) ^ xorBlock[i]; + /* Encrypt in place */ + (*SecretEncrypt) (context, output, output); + T_memcpy ((POINTER)xorBlock, (POINTER)output, 8); + output += 8; + inputLen -= 8; + } + + /* inputLen is now < 8, so copy input to remainder. + */ + T_memcpy ((POINTER)remainder, (POINTER)input, inputLen); + *remainderLen = inputLen; + + return (0); +} + +/* This just ensures that *remainderLen is zero. + The caller must restart the context (setting remainderLen to zero). + Returns AE_INPUT_LEN, 0. + */ +int SecretCBCEncryptFinal (remainderLen) +unsigned int remainderLen; +{ + if (remainderLen != 0) + return (AE_INPUT_LEN); + + return (0); +} diff --git a/lib/bind/dnssafe/secrcbc.h b/lib/bind/dnssafe/secrcbc.h new file mode 100644 index 0000000000..122f83f5b8 --- /dev/null +++ b/lib/bind/dnssafe/secrcbc.h @@ -0,0 +1,36 @@ +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _SECRCBC_H_ +#define _SECRCBC_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*SECRET_CRYPT) PROTO_LIST + ((POINTER, unsigned char *, unsigned char *)); + +int SecretCBCEncryptUpdate PROTO_LIST + ((POINTER, unsigned char *, unsigned char *, unsigned int *, SECRET_CRYPT, + unsigned char *, unsigned int *, unsigned int, unsigned char *, + unsigned int)); +int SecretCBCEncryptFinal PROTO_LIST ((unsigned int)); +int SecretCBCDecryptUpdate PROTO_LIST + ((POINTER, unsigned char *, unsigned char *, unsigned int *, SECRET_CRYPT, + unsigned char *, unsigned int *, unsigned int, unsigned char *, + unsigned int)); +int SecretCBCDecryptFinal PROTO_LIST + ((POINTER, unsigned char *, unsigned char *, unsigned int, SECRET_CRYPT, + unsigned char *, unsigned int *, unsigned int)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/bind/dnssafe/surrendr.c b/lib/bind/dnssafe/surrendr.c new file mode 100644 index 0000000000..05a81a5053 --- /dev/null +++ b/lib/bind/dnssafe/surrendr.c @@ -0,0 +1,26 @@ +/* Copyright (C) RSA Data Security, Inc. created 1992, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "surrendr.h" +#include "port_after.h" + +/* Returns 0, AE_CANCEL. + */ +int CheckSurrender (surrenderContext) +A_SURRENDER_CTX *surrenderContext; +{ + if (surrenderContext == (A_SURRENDER_CTX *)NULL_PTR) + return (0); + + if ((*surrenderContext->Surrender) (surrenderContext->handle)) + return (AE_CANCEL); + return (0); +} diff --git a/lib/bind/dnssafe/surrendr.h b/lib/bind/dnssafe/surrendr.h new file mode 100644 index 0000000000..dc929046aa --- /dev/null +++ b/lib/bind/dnssafe/surrendr.h @@ -0,0 +1,22 @@ +/* Copyright (C) RSA Data Security, Inc. created 1992, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _SURRENDR_H_ +#define _SURRENDR_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +int CheckSurrender PROTO_LIST ((A_SURRENDER_CTX *)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/bind/dst/Makefile.in b/lib/bind/dst/Makefile.in new file mode 100644 index 0000000000..66b7b893eb --- /dev/null +++ b/lib/bind/dst/Makefile.in @@ -0,0 +1,16 @@ +OBJS= bsafe_link.@O@ cylink_link.@O@ dst_api.@O@ eay_dss_link.@O@ \ + hmac_link.@O@ md5_dgst.@O@ prandom.@O@ rsaref_link.@O@ support.@O@ + +SRCS= bsafe_link.c cylink_link.c dst_api.c eay_dss_link.c \ + hmac_link.c md5_dgst.c prandom.c rsaref_link.c support.c + +TARGETS= ${OBJS} + +CRYPTINCL= -I../cylink -I../dnssafe +CRYPTFLAGS= -DCYLINK_DSS -DHMAC_MD5 -DUSE_MD5 -DDNSSAFE + +CINCLUDES= -I.. -I../include ${CRYPTINCL} +CWARNINGS= -Werror +CDEFINES= ${CRYPTFLAGS} + +@BIND9_MAKE_RULES@ diff --git a/lib/bind/dst/bsafe_link.c b/lib/bind/dst/bsafe_link.c new file mode 100644 index 0000000000..b8d30b7f18 --- /dev/null +++ b/lib/bind/dst/bsafe_link.c @@ -0,0 +1,1129 @@ +#if defined(BSAFE) || defined(DNSSAFE) +static const char rcsid[] = "$Header: /u0/home/explorer/proj/ISC/git-conversion/cvsroot/bind9/lib/bind/dst/Attic/bsafe_link.c,v 1.1 2001/03/29 06:31:31 marka Exp $"; + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + */ +/* + * This file contains two components + * 1. Interface to the BSAFE library to allow compilation of Bind + * with TIS/DNSSEC when BSAFE is not available + * all calls to BSAFE are contained inside this file. + * 2. The glue to connvert RSA KEYS to and from external formats + */ +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dst_internal.h" + +# ifdef __STDC__ +# define PROTOTYPES 1 +# else +# define PROTOTYPES 0 +# endif + +# ifdef BSAFE +# include +# include +# else +# include +# include +# include +# endif + +#include "port_after.h" + +typedef struct bsafekey { + char *rk_signer; + B_KEY_OBJ rk_Private_Key; + B_KEY_OBJ rk_Public_Key; +} RSA_Key; + +#ifndef MAX_RSA_MODULUS_BITS +#define MAX_RSA_MODULUS_BITS 4096 +#define MAX_RSA_MODULUS_LEN (MAX_RSA_MODULUS_BITS/8) +#define MAX_RSA_PRIME_LEN (MAX_RSA_MODULUS_LEN/2) +#endif + +#define NULL_SURRENDER (A_SURRENDER_CTX *)NULL_PTR +#define NULL_RANDOM (B_ALGORITHM_OBJ)NULL_PTR + +B_ALGORITHM_METHOD *CHOOSER[] = +{ + &AM_MD5, + &AM_MD5_RANDOM, + &AM_RSA_KEY_GEN, + &AM_RSA_ENCRYPT, + &AM_RSA_DECRYPT, + &AM_RSA_CRT_ENCRYPT, + &AM_RSA_CRT_DECRYPT, + (B_ALGORITHM_METHOD *) NULL_PTR +}; + +static u_char pkcs1[] = +{ + 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, + 0x04, 0x10 +}; + +static int dst_bsafe_md5digest(const int mode, B_ALGORITHM_OBJ *digest_obj, + const u_char *data, const int len, + u_char *digest, const int digest_len); + +static int dst_bsafe_key_size(RSA_Key *r_key); + +static int dst_bsafe_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len); +static int dst_bsafe_verify(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len); +static int dst_bsafe_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len); +static int dst_bsafe_from_dns_key(DST_KEY *s_key, const u_char *key, + const int len); +static int dst_bsafe_key_to_file_format(const DST_KEY *key, char *buff, + const int buff_len); +static int dst_bsafe_key_from_file_format(DST_KEY *d_key, + const char *buff, + const int buff_len); +static int dst_bsafe_generate_keypair(DST_KEY *key, int exp); +static int dst_bsafe_compare_keys(const DST_KEY *key1, const DST_KEY *key2); +static void *dst_bsafe_free_key_structure(void *key); + +/* + * dst_bsafe_init() Function to answer set up function pointers for + * BSAFE/DNSSAFE related functions + */ +int +dst_bsafe_init(void) +{ + 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, + (const 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 (n != 0) + return (-1); + + if (pub->exponent.len < 256) { /* key exponent is <= 2040 bits */ + if ((unsigned int)out_len < pub->exponent.len + 1) + return (-1); + *op++ = (u_int8_t) pub->exponent.len; + } else { /* key exponent is > 2040 bits */ + u_int16_t e = (u_int16_t) pub->exponent.len; + if ((unsigned int)out_len < pub->exponent.len + 3) + return (-1); + *op++ = 0; /* 3 byte length field */ + dst_s_put_int16(op, e); + op += sizeof(e); + n = 2; + } + n++; + memcpy(op, pub->exponent.data, pub->exponent.len); + op += pub->exponent.len; + n += pub->exponent.len; + + if ((unsigned int)(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, 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(CPOINTER firstBlock, CPOINTER secondBlock, unsigned int len) +{ + return (memcmp(firstBlock, secondBlock, len)); +} + +void +T_memcpy(POINTER output, CPOINTER 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/lib/bind/dst/cylink_link.c b/lib/bind/dst/cylink_link.c new file mode 100644 index 0000000000..27d657ec75 --- /dev/null +++ b/lib/bind/dst/cylink_link.c @@ -0,0 +1,678 @@ +#ifdef CYLINK_DSS +static const char rcsid[] = "$Header: /u0/home/explorer/proj/ISC/git-conversion/cvsroot/bind9/lib/bind/dst/Attic/cylink_link.c,v 1.1 2001/03/29 06:31:31 marka Exp $"; + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + */ +/* + * This file contains two components + * 1. Interface to the CYLINK library to allow compilation of Bind + * with TIS/DNSSEC when CYLINK is not available + * all calls to CYLINK are contained inside this file. + * 2. The glue to connvert DSA KEYS to and from external formats + */ +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dst_internal.h" +#include + +#include "port_after.h" + +typedef struct cylinkkey { + char *dk_signer; + uchar *dk_p; + uchar *dk_q; + uchar *dk_g; + uchar *dk_x; + uchar *dk_y; + ushort dk_p_bytes; +} DSA_Key; + +#define NULL_PRIV_KEY(k)(k == NULL || k->dk_p == NULL || k->dk_q == NULL || \ + k->dk_g == NULL || k->dk_x == NULL) +#define NULL_PUB_KEY(k)(k == NULL || k->dk_p == NULL || k->dk_q == NULL || \ + k->dk_g == NULL || k->dk_y == NULL) + +static int dst_cylink_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len); + +static int dst_cylink_verify(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len); + +static int dst_cylink_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len); +static int dst_cylink_from_dns_key(DST_KEY *s_key, const u_char *key, + const int len); +static int dst_cylink_key_to_file_format(const DST_KEY *key, char *buff, + const int buff_len); +static int dst_cylink_key_from_file_format(DST_KEY *d_key, + const char *buff, + const int buff_len); +static void *dst_cylink_free_key_structure(void *key); + +static int dst_cylink_generate_keypair(DST_KEY *key, int exp); +static int dst_cylink_compare_keys(const DST_KEY *key1, const DST_KEY *key2); + +static void *memcpyend(void *dest, const void *src, size_t n, size_t size); + +/* + * dst_cylink_init() Function to answer set up function pointers for + * CYLINK related functions + */ +int +dst_cylink_init() +{ + if (dst_t_func[KEY_DSA] != NULL) + return (1); + dst_t_func[KEY_DSA] = malloc(sizeof(struct dst_func)); + if (dst_t_func[KEY_DSA] == NULL) + return (0); + memset(dst_t_func[KEY_DSA], 0, sizeof(struct dst_func)); + dst_t_func[KEY_DSA]->sign = dst_cylink_sign; + dst_t_func[KEY_DSA]->verify = dst_cylink_verify; + dst_t_func[KEY_DSA]->compare = dst_cylink_compare_keys; + dst_t_func[KEY_DSA]->generate = dst_cylink_generate_keypair; + dst_t_func[KEY_DSA]->destroy = dst_cylink_free_key_structure; + dst_t_func[KEY_DSA]->from_dns_key = dst_cylink_from_dns_key; + dst_t_func[KEY_DSA]->to_dns_key = dst_cylink_to_dns_key; + dst_t_func[KEY_DSA]->from_file_fmt = dst_cylink_key_from_file_format; + dst_t_func[KEY_DSA]->to_file_fmt = dst_cylink_key_to_file_format; + SetDataOrder(1); + return (1); +} + +/* + * dst_cylink_sign + * Call CYLINK signing functions to sign a block of data. + * There are three steps to signing, INIT (initialize structures), + * UPDATE (hash (more) data), FINAL (generate a signature). This + * routine performs one or more of these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * algobj structure holds context for a sign done in multiple calls. + * context the context to use for this computation + * data data to be signed. + * len length in bytes of data. + * priv_key key to use for signing. + * signature location to store signature. + * sig_len size in bytes of signature field. + * returns + * N Success on SIG_MODE_FINAL = returns signature length in bytes + * N is 41 for DNS + * 0 Success on SIG_MODE_INIT and UPDATE + * <0 Failure + */ + +static int +dst_cylink_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len) +{ + int sign_len = 0; + int status; + SHA_context *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = (SHA_context *) malloc(sizeof(SHA_context)); + else if (context) + ctx = (SHA_context *) *context; + if (ctx == NULL) + return (-1); + + if (mode & SIG_MODE_INIT) + SHAInit(ctx); + + if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) { + status = SHAUpdate(ctx, 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, 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]; + + UNUSED(nothing); + + 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/lib/bind/dst/dst_api.c b/lib/bind/dst/dst_api.c new file mode 100644 index 0000000000..954f8c5f76 --- /dev/null +++ b/lib/bind/dst/dst_api.c @@ -0,0 +1,1069 @@ +#ifndef LINT +static const char rcsid[] = "$Header: /u0/home/explorer/proj/ISC/git-conversion/cvsroot/bind9/lib/bind/dst/Attic/dst_api.c,v 1.1 2001/03/29 06:31:31 marka Exp $"; +#endif + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + */ +/* + * This file contains the interface between the DST API and the crypto API. + * This is the only file that needs to be changed if the crypto system is + * changed. Exported functions are: + * void dst_init() Initialize the toolkit + * int dst_check_algorithm() Function to determines if alg is suppored. + * int dst_compare_keys() Function to compare two keys for equality. + * int dst_sign_data() Incremental signing routine. + * int dst_verify_data() Incremental verify routine. + * int dst_generate_key() Function to generate new KEY + * DST_KEY *dst_read_key() Function to retrieve private/public KEY. + * void dst_write_key() Function to write out a key. + * DST_KEY *dst_dnskey_to_key() Function to convert DNS KEY RR to a DST + * KEY structure. + * int dst_key_to_dnskey() Function to return a public key in DNS + * format binary + * DST_KEY *dst_buffer_to_key() Converst a data in buffer to KEY + * int *dst_key_to_buffer() Writes out DST_KEY key matterial in buffer + * void dst_free_key() Releases all memory referenced by key structure + */ + +#include "port_before.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dst_internal.h" +#include "port_after.h" + +/* static variables */ +static int done_init = 0; +dst_func *dst_t_func[DST_MAX_ALGS]; +const char *key_file_fmt_str = "Private-key-format: v%s\nAlgorithm: %d (%s)\n"; +const 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 { + char *tmp; + tmp = (char *) malloc(len + 2); + memcpy(tmp, s, len + 1); + if (tmp[strlen(tmp) - 1] != '/') { + tmp[strlen(tmp) + 1] = 0; + tmp[strlen(tmp)] = '/'; + } + dst_path = tmp; + } + } + memset(dst_t_func, 0, sizeof(dst_t_func)); + /* first one is selected */ + dst_bsafe_init(); + dst_rsaref_init(); + dst_hmac_md5_init(); + dst_eay_dss_init(); + dst_cylink_init(); +} + +/* + * dst_check_algorithm + * This function determines if the crypto system for the specified + * algorithm is present. + * Parameters + * alg 1 KEY_RSA + * 3 KEY_DSA + * 157 KEY_HMAC_MD5 + * future algorithms TBD and registered with IANA. + * Returns + * 1 - The algorithm is available. + * 0 - The algorithm is not available. + */ +int +dst_check_algorithm(const int alg) +{ + return (dst_t_func[alg] != NULL); +} + +/* + * dst_s_get_key_struct + * This function allocates key structure and fills in some of the + * fields of the structure. + * Parameters: + * name: the name of the key + * alg: the algorithm number + * flags: the dns flags of the key + * protocol: the dns protocol of the key + * bits: the size of the key + * Returns: + * NULL if error + * valid pointer otherwise + */ +static DST_KEY * +dst_s_get_key_struct(const char *name, const int alg, const int flags, + const int protocol, const int bits) +{ + DST_KEY *new_key = NULL; + + if (dst_check_algorithm(alg)) /* make sure alg is available */ + new_key = (DST_KEY *) malloc(sizeof(*new_key)); + if (new_key == NULL) + return (NULL); + + memset(new_key, 0, sizeof(*new_key)); + new_key->dk_key_name = strdup(name); + new_key->dk_alg = alg; + new_key->dk_flags = flags; + new_key->dk_proto = protocol; + new_key->dk_KEY_struct = NULL; + new_key->dk_key_size = bits; + new_key->dk_func = dst_t_func[alg]; + return (new_key); +} + +/* + * dst_compare_keys + * Compares two keys for equality. + * Parameters + * key1, key2 Two keys to be compared. + * Returns + * 0 The keys are equal. + * non-zero The keys are not equal. + */ + +int +dst_compare_keys(const DST_KEY *key1, const DST_KEY *key2) +{ + if (key1 == key2) + return (0); + if (key1 == NULL || key2 == NULL) + return (4); + if (key1->dk_alg != key2->dk_alg) + return (1); + if (key1->dk_key_size != key2->dk_key_size) + return (2); + if (key1->dk_id != key2->dk_id) + return (3); + return (key1->dk_func->compare(key1, key2)); +} + + +/* + * dst_sign_data + * An incremental signing function. Data is signed in steps. + * First the context must be initialized (SIG_MODE_INIT). + * Then data is hashed (SIG_MODE_UPDATE). Finally the signature + * itself is created (SIG_MODE_FINAL). This function can be called + * once with INIT, UPDATE and FINAL modes all set, or it can be + + * called separately with a different mode set for each step. The + * UPDATE step can be repeated. + * Parameters + * mode A bit mask used to specify operation(s) to be performed. + * SIG_MODE_INIT 1 Initialize digest + * SIG_MODE_UPDATE 2 Add data to digest + * SIG_MODE_FINAL 4 Generate signature + * from signature + * SIG_MODE_ALL (SIG_MODE_INIT,SIG_MODE_UPDATE,SIG_MODE_FINAL + * data Data to be signed. + * len The length in bytes of data to be signed. + * in_key Contains a private key to sign with. + * KEY structures should be handled (created, converted, + * compared, stored, freed) by the DST. + * signature + * The location to which the signature will be written. + * sig_len Length of the signature field in bytes. + * Return + * 0 Successfull INIT or Update operation + * >0 success FINAL (sign) operation + * <0 failure + */ + +int +dst_sign_data(const int mode, DST_KEY *in_key, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len) +{ + DUMP(data, mode, len, "dst_sign_data()"); + + if (mode & SIG_MODE_FINAL && + (in_key->dk_KEY_struct == NULL || signature == NULL)) + return (MISSING_KEY_OR_SIGNATURE); + + if (in_key->dk_func && in_key->dk_func->sign) + return (in_key->dk_func->sign(mode, in_key, context, data, len, + signature, sig_len)); + return (UNKNOWN_KEYALG); +} + + +/* + * dst_verify_data + * An incremental verify function. Data is verified in steps. + * First the context must be initialized (SIG_MODE_INIT). + * Then data is hashed (SIG_MODE_UPDATE). Finally the signature + * is verified (SIG_MODE_FINAL). This function can be called + * once with INIT, UPDATE and FINAL modes all set, or it can be + * called separately with a different mode set for each step. The + * UPDATE step can be repeated. + * Parameters + * mode Operations to perform this time. + * SIG_MODE_INIT 1 Initialize digest + * SIG_MODE_UPDATE 2 add data to digest + * SIG_MODE_FINAL 4 verify signature + * SIG_MODE_ALL + * (SIG_MODE_INIT,SIG_MODE_UPDATE,SIG_MODE_FINAL) + * data Data to pass through the hash function. + * len Length of the data in bytes. + * in_key Key for verification. + * signature Location of signature. + * sig_len Length of the signature in bytes. + * Returns + * 0 Verify success + * Non-Zero Verify Failure + */ + +int +dst_verify_data(const int mode, DST_KEY *in_key, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len) +{ + DUMP(data, mode, len, "dst_verify_data()"); + if (mode & SIG_MODE_FINAL && + (in_key->dk_KEY_struct == NULL || signature == NULL)) + return (MISSING_KEY_OR_SIGNATURE); + + if (in_key->dk_func == NULL || in_key->dk_func->verify == NULL) + return (UNSUPPORTED_KEYALG); + return (in_key->dk_func->verify(mode, in_key, context, data, len, + signature, sig_len)); +} + + +/* + * dst_read_private_key + * Access a private key. First the list of private keys that have + * already been read in is searched, then the key accessed on disk. + * If the private key can be found, it is returned. If the key cannot + * be found, a null pointer is returned. The options specify required + * key characteristics. If the private key requested does not have + * these characteristics, it will not be read. + * Parameters + * in_keyname The private key name. + * in_id The id of the private key. + * options DST_FORCE_READ Read from disk - don't use a previously + * read key. + * DST_CAN_SIGN The key must be useable for signing. + * DST_NO_AUTHEN The key must be useable for authentication. + * DST_STANDARD Return any key + * Returns + * NULL If there is no key found in the current directory or + * this key has not been loaded before. + * !NULL Success - KEY structure returned. + */ + +DST_KEY * +dst_read_key(const char *in_keyname, const u_int16_t in_id, + const int in_alg, const int type) +{ + char keyname[PATH_MAX]; + DST_KEY *dg_key = NULL, *pubkey = NULL; + + if (!dst_check_algorithm(in_alg)) { /* make sure alg is available */ + EREPORT(("dst_read_private_key(): Algorithm %d not suppored\n", + in_alg)); + return (NULL); + } + if ((type & (DST_PUBLIC | DST_PRIVATE)) == 0) + return (NULL); + if (in_keyname == NULL) { + EREPORT(("dst_read_private_key(): Null key name passed in\n")); + return (NULL); + } else + strcpy(keyname, in_keyname); + + /* before I read in the public key, check if it is allowed to sign */ + if ((pubkey = dst_s_read_public_key(keyname, in_id, in_alg)) == NULL) + return (NULL); + + if (type == DST_PUBLIC) + return pubkey; + + if (!(dg_key = dst_s_get_key_struct(keyname, pubkey->dk_alg, + pubkey->dk_flags, pubkey->dk_proto, + 0))) + return (dg_key); + /* Fill in private key and some fields in the general key structure */ + if (dst_s_read_private_key_file(keyname, dg_key, pubkey->dk_id, + pubkey->dk_alg) == 0) + dg_key = dst_free_key(dg_key); + + pubkey = dst_free_key(pubkey); + return (dg_key); +} + +int +dst_write_key(const DST_KEY *key, const int type) +{ + int pub = 0, priv = 0; + + if (key == NULL) + return (0); + if (!dst_check_algorithm(key->dk_alg)) { /* make sure alg is available */ + EREPORT(("dst_write_key(): Algorithm %d not suppored\n", + key->dk_alg)); + return (UNSUPPORTED_KEYALG); + } + if ((type & (DST_PRIVATE|DST_PUBLIC)) == 0) + return (0); + + if (type & DST_PUBLIC) + if ((pub = dst_s_write_public_key(key)) < 0) + return (pub); + if (type & DST_PRIVATE) + if ((priv = dst_s_write_private_key(key)) < 0) + return (priv); + return (priv+pub); +} + +/* + * dst_write_private_key + * Write a private key to disk. The filename will be of the form: + * Kdk_name>+dk_alg>+dk_id>.. + * If there is already a file with this name, an error is returned. + * + * Parameters + * key A DST managed key structure that contains + * all information needed about a key. + * Return + * >= 0 Correct behavior. Returns length of encoded key value + * written to disk. + * < 0 error. + */ + +static int +dst_s_write_private_key(const DST_KEY *key) +{ + u_char encoded_block[RAW_KEY_SIZE]; + char file[PATH_MAX]; + int len; + FILE *fp; + + /* First encode the key into the portable key format */ + if (key == NULL) + return (-1); + if (key->dk_KEY_struct == NULL) + return (0); /* null key has no private key */ + + if (key->dk_func == NULL || key->dk_func->to_file_fmt == NULL) { + EREPORT(("dst_write_private_key(): Unsupported operation %d\n", + key->dk_alg)); + return (-5); + } else if ((len = key->dk_func->to_file_fmt(key, (char *)encoded_block, + sizeof(encoded_block))) <= 0) { + EREPORT(("dst_write_private_key(): Failed encoding private RSA bsafe key %d\n", len)); + return (-8); + } + /* Now I can create the file I want to use */ + dst_s_build_filename(file, key->dk_key_name, key->dk_id, key->dk_alg, + PRIVATE_KEY, PATH_MAX); + + /* Do not overwrite an existing file */ + if ((fp = dst_s_fopen(file, "w", 0600)) != NULL) { + int nn; + if ((nn = fwrite(encoded_block, 1, len, fp)) != len) { + EREPORT(("dst_write_private_key(): Write failure on %s %d != %d errno=%d\n", + file, out_len, nn, errno)); + return (-5); + } + fclose(fp); + } else { + EREPORT(("dst_write_private_key(): Can not create file %s\n" + ,file)); + return (-6); + } + memset(encoded_block, 0, len); + return (len); +} + +/* +* + * dst_read_public_key + * Read a public key from disk and store in a DST key structure. + * Parameters + * in_name K. is the + * filename of the key file to be read. + * Returns + * NULL If the key does not exist or no name is supplied. + * NON-NULL Initalized key structure if the key exists. + */ + +static DST_KEY * +dst_s_read_public_key(const char *in_name, const u_int16_t in_id, int in_alg) +{ + int flags, proto, alg, len, dlen; + int c; + char name[PATH_MAX], enckey[RAW_KEY_SIZE], *notspace; + u_char deckey[RAW_KEY_SIZE]; + FILE *fp; + + if (in_name == NULL) { + EREPORT(("dst_read_public_key(): No key name given\n")); + return (NULL); + } + if (dst_s_build_filename(name, in_name, in_id, in_alg, PUBLIC_KEY, + PATH_MAX) == -1) { + EREPORT(("dst_read_public_key(): Cannot make filename from %s, %d, and %s\n", + in_name, in_id, PUBLIC_KEY)); + return (NULL); + } + /* + * Open the file and read it's formatted contents up to key + * File format: + * domain.name [ttl] [IN] KEY + * flags, proto, alg stored as decimal (or hex numbers FIXME). + * (FIXME: handle parentheses for line continuation.) + */ + if ((fp = dst_s_fopen(name, "r", 0)) == NULL) { + EREPORT(("dst_read_public_key(): Public Key not found %s\n", + name)); + return (NULL); + } + /* Skip domain name, which ends at first blank */ + while ((c = getc(fp)) != EOF) + if (isspace(c)) + break; + /* Skip blank to get to next field */ + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + + /* Skip optional TTL -- if initial digit, skip whole word. */ + if (isdigit(c)) { + while ((c = getc(fp)) != EOF) + if (isspace(c)) + break; + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + } + /* Skip optional "IN" */ + if (c == 'I' || c == 'i') { + while ((c = getc(fp)) != EOF) + if (isspace(c)) + break; + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + } + /* Locate and skip "KEY" */ + if (c != 'K' && c != 'k') { + EREPORT(("\"KEY\" doesn't appear in file: %s", name)); + return NULL; + } + while ((c = getc(fp)) != EOF) + if (isspace(c)) + break; + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + ungetc(c, fp); /* return the charcter to the input field */ + /* Handle hex!! FIXME. */ + + if (fscanf(fp, "%d %d %d", &flags, &proto, &alg) != 3) { + EREPORT(("dst_read_public_key(): Can not read flag/proto/alg field from %s\n" + ,name)); + return (NULL); + } + /* read in the key string */ + fgets(enckey, sizeof(enckey), fp); + + /* If we aren't at end-of-file, something is wrong. */ + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + if (!feof(fp)) { + EREPORT(("Key too long in file: %s", name)); + return NULL; + } + fclose(fp); + + if ((len = strlen(enckey)) <= 0) + return (NULL); + + /* discard \n */ + enckey[--len] = '\0'; + + /* remove leading spaces */ + for (notspace = (char *) enckey; isspace(*notspace); len--) + notspace++; + + dlen = b64_pton(notspace, deckey, sizeof(deckey)); + if (dlen < 0) { + EREPORT(("dst_read_public_key: bad return from b64_pton = %d", + dlen)); + return (NULL); + } + /* store key and info in a key structure that is returned */ +/* return dst_store_public_key(in_name, alg, proto, 666, flags, deckey, + dlen);*/ + return dst_buffer_to_key(in_name, alg, flags, proto, deckey, dlen); +} + + +/* + * dst_write_public_key + * Write a key to disk in DNS format. + * Parameters + * key Pointer to a DST key structure. + * Returns + * 0 Failure + * 1 Success + */ + +static int +dst_s_write_public_key(const DST_KEY *key) +{ + FILE *fp; + char filename[PATH_MAX]; + u_char out_key[RAW_KEY_SIZE]; + char enc_key[RAW_KEY_SIZE]; + int len = 0; + + memset(out_key, 0, sizeof(out_key)); + if (key == NULL) { + EREPORT(("dst_write_public_key(): No key specified \n")); + return (0); + } else if ((len = dst_key_to_dnskey(key, out_key, sizeof(out_key)))< 0) + return (0); + + /* Make the filename */ + if (dst_s_build_filename(filename, key->dk_key_name, key->dk_id, + key->dk_alg, PUBLIC_KEY, PATH_MAX) == -1) { + EREPORT(("dst_write_public_key(): Cannot make filename from %s, %d, and %s\n", + key->dk_key_name, key->dk_id, PUBLIC_KEY)); + return (0); + } + /* create public key file */ + if ((fp = dst_s_fopen(filename, "w+", 0644)) == NULL) { + EREPORT(("DST_write_public_key: open of file:%s failed (errno=%d)\n", + filename, errno)); + return (0); + } + /*write out key first base64 the key data */ + if (key->dk_flags & DST_EXTEND_FLAG) + b64_ntop(&out_key[6], len - 6, enc_key, sizeof(enc_key)); + else + b64_ntop(&out_key[4], len - 4, enc_key, sizeof(enc_key)); + fprintf(fp, "%s IN KEY %d %d %d %s\n", + key->dk_key_name, + key->dk_flags, key->dk_proto, key->dk_alg, enc_key); + fclose(fp); + return (1); +} + + +/* + * dst_dnskey_to_public_key + * This function converts the contents of a DNS KEY RR into a DST + * key structure. + * Paramters + * len Length of the RDATA of the KEY RR RDATA + * rdata A pointer to the the KEY RR RDATA. + * in_name Key name to be stored in key structure. + * Returns + * NULL Failure + * NON-NULL Success. Pointer to key structure. + * Caller's responsibility to free() it. + */ + +DST_KEY * +dst_dnskey_to_key(const char *in_name, const u_char *rdata, const int len) +{ + DST_KEY *key_st; + int alg ; + int start = DST_KEY_START; + + if (rdata == NULL || len <= DST_KEY_ALG) /* no data */ + return (NULL); + alg = (u_int8_t) rdata[DST_KEY_ALG]; + if (!dst_check_algorithm(alg)) { /* make sure alg is available */ + EREPORT(("dst_dnskey_to_key(): Algorithm %d not suppored\n", + alg)); + return (NULL); + } + if ((key_st = dst_s_get_key_struct(in_name, alg, 0, 0, 0)) == NULL) + return (NULL); + + if (in_name == NULL) + return (NULL); + key_st->dk_flags = dst_s_get_int16(rdata); + key_st->dk_proto = (u_int16_t) rdata[DST_KEY_PROT]; + if (key_st->dk_flags & DST_EXTEND_FLAG) { + u_int32_t ext_flags; + ext_flags = (u_int32_t) dst_s_get_int16(&rdata[DST_EXT_FLAG]); + key_st->dk_flags = key_st->dk_flags | (ext_flags << 16); + start += 2; + } + /* + * now point to the begining of the data representing the encoding + * of the key + */ + if (key_st->dk_func && key_st->dk_func->from_dns_key) { + if (key_st->dk_func->from_dns_key(key_st, &rdata[start], + len - start) > 0) + return (key_st); + } else + EREPORT(("dst_dnskey_to_public_key(): unsuppored alg %d\n", + alg)); + + SAFE_FREE(key_st); + return (key_st); +} + + +/* + * dst_public_key_to_dnskey + * Function to encode a public key into DNS KEY wire format + * Parameters + * key Key structure to encode. + * out_storage Location to write the encoded key to. + * out_len Size of the output array. + * Returns + * <0 Failure + * >=0 Number of bytes written to out_storage + */ + +int +dst_key_to_dnskey(const DST_KEY *key, u_char *out_storage, + const int out_len) +{ + u_int16_t val; + int loc = 0; + int enc_len = 0; + if (key == NULL) + return (-1); + + if (!dst_check_algorithm(key->dk_alg)) { /* make sure alg is available */ + EREPORT(("dst_key_to_dnskey(): Algorithm %d not suppored\n", + key->dk_alg)); + return (UNSUPPORTED_KEYALG); + } + memset(out_storage, 0, out_len); + val = (u_int16_t)(key->dk_flags & 0xffff); + dst_s_put_int16(out_storage, val); + loc += 2; + + out_storage[loc++] = (u_char) key->dk_proto; + out_storage[loc++] = (u_char) key->dk_alg; + + if (key->dk_flags > 0xffff) { /* Extended flags */ + val = (u_int16_t)((key->dk_flags >> 16) & 0xffff); + dst_s_put_int16(&out_storage[loc], val); + loc += 2; + } + if (key->dk_KEY_struct == NULL) + return (loc); + if (key->dk_func && key->dk_func->to_dns_key) { + enc_len = key->dk_func->to_dns_key(key, + (u_char *) &out_storage[loc], + out_len - loc); + if (enc_len > 0) + return (enc_len + loc); + else + return (-1); + } else + EREPORT(("dst_key_to_dnskey(): Unsupported ALG %d\n", + key->dk_alg)); + return (-1); +} + + +/* + * dst_buffer_to_key + * Function to encode a string of raw data into a DST key + * Parameters + * alg The algorithm (HMAC only) + * key A pointer to the data + * keylen The length of the data + * Returns + * NULL an error occurred + * NON-NULL the DST key + */ +DST_KEY * +dst_buffer_to_key(const char *key_name, /* name of the key */ + const int alg, /* algorithm */ + const int flags, /* dns flags */ + const int protocol, /* dns protocol */ + const u_char *key_buf, /* key in dns wire fmt */ + const int key_len) /* size of key */ +{ + + DST_KEY *dkey = NULL; + + if (!dst_check_algorithm(alg)) { /* make sure alg is available */ + EREPORT(("dst_buffer_to_key(): Algorithm %d not suppored\n", alg)); + return (NULL); + } + + dkey = dst_s_get_key_struct(key_name, alg, flags, + protocol, -1); + + if (dkey == NULL) + return (NULL); + if (dkey->dk_func != NULL && dkey->dk_func->from_dns_key != NULL) { + if (dkey->dk_func->from_dns_key(dkey, key_buf, key_len) < 0) { + EREPORT(("dst_buffer_to_key(): dst_buffer_to_hmac failed\n")); + return (dst_free_key(dkey)); + } + return (dkey); + } + return (NULL); +} + +int +dst_key_to_buffer(DST_KEY *key, u_char *out_buff, int buf_len) +{ + int len; + /* this function will extrac the secret of HMAC into a buffer */ + if (key == NULL) + return (0); + if (key->dk_func != NULL && key->dk_func->to_dns_key != NULL) { + len = key->dk_func->to_dns_key(key, out_buff, buf_len); + if (len < 0) + return (0); + return (len); + } + return (0); +} + + +/* + * dst_s_read_private_key_file + * Function reads in private key from a file. + * Fills out the KEY structure. + * Parameters + * name Name of the key to be read. + * pk_key Structure that the key is returned in. + * in_id Key identifier (tag) + * Return + * 1 if everthing works + * 0 if there is any problem + */ + +static int +dst_s_read_private_key_file(char *name, DST_KEY *pk_key, u_int16_t in_id, + int in_alg) +{ + int cnt, alg, len, major, minor, file_major, file_minor; + int id; + char filename[PATH_MAX]; + u_char in_buff[RAW_KEY_SIZE], *p; + FILE *fp; + + if (name == NULL || pk_key == NULL) { + EREPORT(("dst_read_private_key_file(): No key name given\n")); + return (0); + } + /* Make the filename */ + if (dst_s_build_filename(filename, name, in_id, in_alg, PRIVATE_KEY, + PATH_MAX) == -1) { + EREPORT(("dst_read_private_key(): Cannot make filename from %s, %d, and %s\n", + name, in_id, PRIVATE_KEY)); + return (0); + } + /* first check if we can find the key file */ + if ((fp = dst_s_fopen(filename, "r", 0)) == NULL) { + EREPORT(("dst_s_read_private_key_file: Could not open file %s in directory %s\n", + filename, dst_path[0] ? dst_path : + (char *) getcwd(NULL, PATH_MAX - 1))); + return (0); + } + /* now read the header info from the file */ + if ((cnt = fread(in_buff, 1, sizeof(in_buff), fp)) < 5) { + fclose(fp); + EREPORT(("dst_s_read_private_key_file: error reading file %s (empty file)\n", + filename)); + return (0); + } + /* decrypt key */ + fclose(fp); + if (memcmp(in_buff, "Private-key-format: v", 20) != 0) + goto fail; + len = cnt; + p = in_buff; + + if (!dst_s_verify_str((const char **) &p, "Private-key-format: v")) { + EREPORT(("dst_s_read_private_key_file(): Not a Key file/Decrypt failed %s\n", name)); + goto fail; + } + /* read in file format */ + sscanf((char *)p, "%d.%d", &file_major, &file_minor); + sscanf(KEY_FILE_FORMAT, "%d.%d", &major, &minor); + if (file_major < 1) { + EREPORT(("dst_s_read_private_key_file(): Unknown keyfile %d.%d version for %s\n", + file_major, file_minor, name)); + goto fail; + } else if (file_major > major || file_minor > minor) + EREPORT(( + "dst_s_read_private_key_file(): Keyfile %s version higher than mine %d.%d MAY FAIL\n", + name, file_major, file_minor)); + + while (*p++ != '\n') ; /* skip to end of line */ + + if (!dst_s_verify_str((const char **) &p, "Algorithm: ")) + goto fail; + + if (sscanf((char *)p, "%d", &alg) != 1) + goto fail; + while (*p++ != '\n') ; /* skip to end of line */ + + if (pk_key->dk_key_name && !strcmp(pk_key->dk_key_name, name)) + SAFE_FREE2(pk_key->dk_key_name, strlen(pk_key->dk_key_name)); + pk_key->dk_key_name = (char *) strdup(name); + + /* allocate and fill in key structure */ + if (pk_key->dk_func == NULL || pk_key->dk_func->from_file_fmt == NULL) + goto fail; + + id = pk_key->dk_func->from_file_fmt(pk_key, (char *)p, &in_buff[len] - p); + if (id < 0) + goto fail; + + /* Make sure the actual key tag matches the input tag used in the filename + */ + if (id != in_id) { + EREPORT(("dst_s_read_private_key_file(): actual tag of key read %d != input tag used to build filename %d.\n", id, in_id)); + goto fail; + } + pk_key->dk_id = (u_int16_t) id; + pk_key->dk_alg = alg; + memset(in_buff, 0, cnt); + return (1); + + fail: + memset(in_buff, 0, cnt); + return (0); +} + + +/* + * dst_generate_key + * Generate and store a public/private keypair. + * Keys will be stored in formatted files. + * Parameters + * name Name of the new key. Used to create key files + * K++.public and K++.private. + * bits Size of the new key in bits. + * exp What exponent to use: + * 0 use exponent 3 + * non-zero use Fermant4 + * flags The default value of the DNS Key flags. + * The DNS Key RR Flag field is defined in RFC 2065, + * section 3.3. The field has 16 bits. + * protocol + * Default value of the DNS Key protocol field. + * The DNS Key protocol field is defined in RFC 2065, + * section 3.4. The field has 8 bits. + * alg What algorithm to use. Currently defined: + * KEY_RSA 1 + * KEY_DSA 3 + * KEY_HMAC 157 + * out_id The key tag is returned. + * + * Return + * NULL Failure + * non-NULL the generated key pair + * Caller frees the result, and its dk_name pointer. + */ +DST_KEY * +dst_generate_key(const char *name, const int bits, const int exp, + const int flags, const int protocol, const int alg) +{ + DST_KEY *new_key = NULL; + int res; + if (name == NULL) + return (NULL); + + if (!dst_check_algorithm(alg)) { /* make sure alg is available */ + EREPORT(("dst_generate_key(): Algorithm %d not suppored\n", alg)); + return (NULL); + } + + new_key = dst_s_get_key_struct(name, alg, flags, protocol, bits); + if (new_key == NULL) + return (NULL); + if (bits == 0) /* null key we are done */ + return (new_key); + if (new_key->dk_func == NULL || new_key->dk_func->generate == NULL) { + EREPORT(("dst_generate_key_pair():Unsupported algorithm %d\n", + alg)); + return (dst_free_key(new_key)); + } + if ((res = new_key->dk_func->generate(new_key, exp)) <= 0) { + EREPORT(("dst_generate_key_pair(): Key generation failure %s %d %d %d\n", + new_key->dk_key_name, new_key->dk_alg, + new_key->dk_key_size, exp)); + return (dst_free_key(new_key)); + } + return (new_key); +} + + +/* + * dst_free_key + * Release all data structures pointed to by a key structure. + * Parameters + * f_key Key structure to be freed. + */ + +DST_KEY * +dst_free_key(DST_KEY *f_key) +{ + + if (f_key == NULL) + return (f_key); + if (f_key->dk_func && f_key->dk_func->destroy) + f_key->dk_KEY_struct = + f_key->dk_func->destroy(f_key->dk_KEY_struct); + else { + EREPORT(("dst_free_key(): Unknown key alg %d\n", + f_key->dk_alg)); + free(f_key->dk_KEY_struct); /* SHOULD NOT happen */ + } + if (f_key->dk_KEY_struct) { + free(f_key->dk_KEY_struct); + f_key->dk_KEY_struct = NULL; + } + if (f_key->dk_key_name) + SAFE_FREE(f_key->dk_key_name); + SAFE_FREE(f_key); + return (NULL); +} + +/* + * dst_sig_size + * Return the maximim size of signature from the key specified in bytes + * Parameters + * key + * Returns + * bytes + */ +int +dst_sig_size(DST_KEY *key) { + switch (key->dk_alg) { + case KEY_HMAC_MD5: + return (16); + case KEY_HMAC_SHA1: + return (20); + case KEY_RSA: + return (key->dk_key_size + 7) / 8; + case KEY_DSA: + return (40); + default: + EREPORT(("dst_sig_size(): Unknown key alg %d\n", key->dk_alg)); + return -1; + } +} + +/* + * dst_random + * function that multiplexes number of random number generators + * Parameters + * mode: select the random number generator + * wanted is how many bytes of random data are requested + * outran is a buffer of size at least wanted for the output data + * + * Returns + * number of bytes written to outran + */ +int +dst_random(const int mode, int wanted, u_char *outran) +{ + u_int32_t *buff = NULL, *bp = NULL; + int i; + if (wanted <= 0 || outran == NULL) + return (0); + + switch (mode) { + case DST_RAND_SEMI: + bp = buff = (u_int32_t *) malloc(wanted+sizeof(u_int32_t)); + for (i = 0; i < wanted; i+= sizeof(u_int32_t), bp++) { + *bp = dst_s_quick_random(i); + } + memcpy(outran, buff, wanted); + SAFE_FREE(buff); + return (wanted); + case DST_RAND_STD: + return (dst_s_semi_random(outran, wanted)); + case DST_RAND_KEY: + return (dst_s_random(outran, wanted)); + case DST_RAND_DSS: + default: + /* need error case here XXX OG */ + return (0); + } +} + diff --git a/lib/bind/dst/dst_internal.h b/lib/bind/dst/dst_internal.h new file mode 100644 index 0000000000..0825109f5e --- /dev/null +++ b/lib/bind/dst/dst_internal.h @@ -0,0 +1,168 @@ +#ifndef DST_INTERNAL_H +#define DST_INTERNAL_H + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + */ +#include +#include +#if (!defined(BSD)) || (BSD < 199306) +# include +#else +# include +#endif + +#ifndef PATH_MAX +# ifdef POSIX_PATH_MAX +# define PATH_MAX POSIX_PATH_MAX +# else +# define PATH_MAX 255 /* this is the value of POSIX_PATH_MAX */ +# endif +#endif + +typedef struct dst_key { + char *dk_key_name; /* name of the key */ + int dk_key_size; /* this is the size of the key in bits */ + int dk_proto; /* what protocols this key can be used for */ + int dk_alg; /* algorithm number from key record */ + u_int32_t dk_flags; /* and the flags of the public key */ + u_int16_t dk_id; /* identifier of the key */ + void *dk_KEY_struct; /* pointer to key in crypto pkg fmt */ + struct dst_func *dk_func; /* point to cryptto pgk specific function table */ +} DST_KEY; +#define HAS_DST_KEY + +#include +/* + * define what crypto systems are supported for RSA, + * BSAFE is prefered over RSAREF; only one can be set at any time + */ +#if defined(BSAFE) && defined(RSAREF) +# error "Cannot have both BSAFE and RSAREF defined" +#endif + +/* Declare dst_lib specific constants */ +#define KEY_FILE_FORMAT "1.2" + +/* suffixes for key file names */ +#define PRIVATE_KEY "private" +#define PUBLIC_KEY "key" + +/* error handling */ +#ifdef REPORT_ERRORS +#define EREPORT(str) printf str +#else +#define EREPORT(str) (void)0 +#endif + +/* use our own special macro to FRRE memory */ + +#ifndef SAFE_FREE +#define SAFE_FREE(a) \ +do{if(a != NULL){memset(a,0, sizeof(*a)); free(a); a=NULL;}} while (0) +#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 const char *key_file_fmt_str; +extern const 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(void); + +int dst_rsaref_init(void); + +int dst_hmac_md5_init(void); + +int dst_cylink_init(void); + +int dst_eay_dss_init(void); + +/* 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 +void +dst_s_dump(const int mode, const u_char *data, const int size, + const char *msg); + + + +#endif /* DST_INTERNAL_H */ diff --git a/lib/bind/dst/eay_dss_link.c b/lib/bind/dst/eay_dss_link.c new file mode 100644 index 0000000000..c4d024cd08 --- /dev/null +++ b/lib/bind/dst/eay_dss_link.c @@ -0,0 +1,638 @@ +#ifdef EAY_DSS +static const char rcsid[] = "$Header: /u0/home/explorer/proj/ISC/git-conversion/cvsroot/bind9/lib/bind/dst/Attic/eay_dss_link.c,v 1.1 2001/03/29 06:31:31 marka Exp $"; + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + */ +/* + * This file contains two components + * 1. Interface to the EAY libcrypto library to allow compilation of Bind + * with TIS/DNSSEC when EAY libcrypto is not available + * all calls to libcrypto are contained inside this file. + * 2. The glue to connvert DSA KEYS to and from external formats + */ +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dst_internal.h" + +#include "crypto.h" +#include "bn.h" +#include "dsa.h" +#include "sha.h" + +#include "port_after.h" + + +static int dst_eay_dss_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len); + +static int dst_eay_dss_verify(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len); + +static int dst_eay_dss_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len); +static int dst_eay_dss_from_dns_key(DST_KEY *s_key, const u_char *key, + const int len); +static int dst_eay_dss_key_to_file_format(const DST_KEY *key, u_char *buff, + const int buff_len); +static int dst_eay_dss_key_from_file_format(DST_KEY *d_key, + const u_char *buff, + const int buff_len); +static void *dst_eay_dss_free_key_structure(void *key); + +static int dst_eay_dss_generate_keypair(DST_KEY *key, int exp); +static int dst_eay_dss_compare_keys(const DST_KEY *key1, const DST_KEY *key2); + +/* + * dst_eay_dss_init() Function to answer set up function pointers for + * EAY DSS related functions + */ +int +dst_eay_dss_init(void) +{ + 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 +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dst_internal.h" +#include "port_after.h" +int +dst_eay_dss_init(void) +{ + return (0); +} +#endif /* EAY_DSS */ diff --git a/lib/bind/dst/hmac_link.c b/lib/bind/dst/hmac_link.c new file mode 100644 index 0000000000..dee97e68a1 --- /dev/null +++ b/lib/bind/dst/hmac_link.c @@ -0,0 +1,495 @@ +#ifdef HMAC_MD5 +#ifndef LINT +static const char rcsid[] = "$Header: /u0/home/explorer/proj/ISC/git-conversion/cvsroot/bind9/lib/bind/dst/Attic/hmac_link.c,v 1.1 2001/03/29 06:31:31 marka Exp $"; +#endif +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + */ + +/* + * This file contains an implementation of the HMAC-MD5 algorithm. + */ +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dst_internal.h" +#ifdef USE_MD5 +# include "md5.h" +# ifndef _MD5_H_ +# define _MD5_H_ 1 /* make sure we do not include rsaref md5.h file */ +# endif +#endif + +#include "port_after.h" + + +#define HMAC_LEN 64 +#define HMAC_IPAD 0x36 +#define HMAC_OPAD 0x5c +#define MD5_LEN 16 + + +typedef struct hmackey { + u_char hk_ipad[64], hk_opad[64]; +} HMAC_Key; + + +/************************************************************************** + * dst_hmac_md5_sign + * Call HMAC signing functions to sign a block of data. + * There are three steps to signing, INIT (initialize structures), + * UPDATE (hash (more) data), FINAL (generate a signature). This + * routine performs one or more of these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * priv_key key to use for signing. + * context the context to be used in this digest + * data data to be signed. + * len length in bytes of data. + * signature location to store signature. + * sig_len size of the signature location + * returns + * N Success on SIG_MODE_FINAL = returns signature length in bytes + * 0 Success on SIG_MODE_INIT and UPDATE + * <0 Failure + */ + +static int +dst_hmac_md5_sign(const int mode, DST_KEY *d_key, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len) +{ + HMAC_Key *key; + int sign_len = 0; + MD5_CTX *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = (MD5_CTX *) malloc(sizeof(*ctx)); + else if (context) + ctx = (MD5_CTX *) *context; + if (ctx == NULL) + return (-1); + + if (d_key == NULL || d_key->dk_KEY_struct == NULL) + return (-1); + key = (HMAC_Key *) d_key->dk_KEY_struct; + + if (mode & SIG_MODE_INIT) { + MD5Init(ctx); + MD5Update(ctx, key->hk_ipad, HMAC_LEN); + } + + if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) + MD5Update(ctx, 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, 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, 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; + + i = nothing; + + 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/lib/bind/dst/md5.h b/lib/bind/dst/md5.h new file mode 100644 index 0000000000..c886d17bb0 --- /dev/null +++ b/lib/bind/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, const 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/lib/bind/dst/md5_dgst.c b/lib/bind/dst/md5_dgst.c new file mode 100644 index 0000000000..9bb0228dd0 --- /dev/null +++ b/lib/bind/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 +#ifdef USE_MD5 /* Added by ogud@tis.com 1998/1/26 */ +#include "md5_locl.h" + +const 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 const unsigned char *data; +unsigned long len; + { + register ULONG *p; + int sw,sc; + ULONG l; + + if (len == 0) return; + + l=(c->Nl+(len<<3))&0xffffffffL; + /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to + * Wei Dai for pointing it out. */ + if (l < c->Nl) /* overflow */ + c->Nh++; + c->Nh+=(len>>29); + c->Nl=l; + + if (c->num != 0) + { + p=c->data; + sw=c->num>>2; + sc=c->num&0x03; + + if ((c->num+len) >= MD5_CBLOCK) + { + l= p[sw]; + p_c2l(data,l,sc); + p[sw++]=l; + for (; swnum); + + md5_block(c,p); + c->num=0; + /* drop through and do the rest */ + } + else + { + int ew,ec; + + c->num+=(int)len; + if ((sc+len) < 4) /* ugly, add char's to a word */ + { + l= p[sw]; + p_c2l_p(data,l,sc,len); + p[sw]=l; + } + else + { + ew=(c->num>>2); + ec=(c->num&0x03); + l= p[sw]; + p_c2l(data,l,sc); + p[sw++]=l; + for (; sw < ew; sw++) + { c2l(data,l); p[sw]=l; } + if (ec) + { + c2l_p(data,l,ec); + p[sw]=l; + } + } + return; + } + } + /* we now can process the input data in blocks of MD5_CBLOCK + * chars and save the leftovers to c->data. */ + p=c->data; + while (len >= MD5_CBLOCK) + { +#if defined(L_ENDIAN) || defined(B_ENDIAN) + memcpy(p,data,MD5_CBLOCK); + data+=MD5_CBLOCK; +#ifdef B_ENDIAN + for (sw=(MD5_LBLOCK/4); sw; sw--) + { + Endian_Reverse32(p[0]); + Endian_Reverse32(p[1]); + Endian_Reverse32(p[2]); + Endian_Reverse32(p[3]); + p+=4; + } +#endif +#else + for (sw=(MD5_LBLOCK/4); sw; sw--) + { + c2l(data,l); *(p++)=l; + c2l(data,l); *(p++)=l; + c2l(data,l); *(p++)=l; + c2l(data,l); *(p++)=l; + } +#endif + p=c->data; + md5_block(c,p); + len-=MD5_CBLOCK; + } + sc=(int)len; + c->num=sc; + if (sc) + { + sw=sc>>2; /* words to copy */ +#ifdef L_ENDIAN + p[sw]=0; + memcpy(p,data,sc); +#else + sc&=0x03; + for ( ; sw; sw--) + { c2l(data,l); *(p++)=l; } + c2l_p(data,l,sc); + *p=l; +#endif + } + } + +static void md5_block(c, X) +MD5_CTX *c; +register ULONG *X; + { + register ULONG A,B,C,D; + + A=c->A; + B=c->B; + C=c->C; + D=c->D; + + /* Round 0 */ + R0(A,B,C,D,X[ 0], 7,0xd76aa478L); + R0(D,A,B,C,X[ 1],12,0xe8c7b756L); + R0(C,D,A,B,X[ 2],17,0x242070dbL); + R0(B,C,D,A,X[ 3],22,0xc1bdceeeL); + R0(A,B,C,D,X[ 4], 7,0xf57c0fafL); + R0(D,A,B,C,X[ 5],12,0x4787c62aL); + R0(C,D,A,B,X[ 6],17,0xa8304613L); + R0(B,C,D,A,X[ 7],22,0xfd469501L); + R0(A,B,C,D,X[ 8], 7,0x698098d8L); + R0(D,A,B,C,X[ 9],12,0x8b44f7afL); + R0(C,D,A,B,X[10],17,0xffff5bb1L); + R0(B,C,D,A,X[11],22,0x895cd7beL); + R0(A,B,C,D,X[12], 7,0x6b901122L); + R0(D,A,B,C,X[13],12,0xfd987193L); + R0(C,D,A,B,X[14],17,0xa679438eL); + R0(B,C,D,A,X[15],22,0x49b40821L); + /* Round 1 */ + R1(A,B,C,D,X[ 1], 5,0xf61e2562L); + R1(D,A,B,C,X[ 6], 9,0xc040b340L); + R1(C,D,A,B,X[11],14,0x265e5a51L); + R1(B,C,D,A,X[ 0],20,0xe9b6c7aaL); + R1(A,B,C,D,X[ 5], 5,0xd62f105dL); + R1(D,A,B,C,X[10], 9,0x02441453L); + R1(C,D,A,B,X[15],14,0xd8a1e681L); + R1(B,C,D,A,X[ 4],20,0xe7d3fbc8L); + R1(A,B,C,D,X[ 9], 5,0x21e1cde6L); + R1(D,A,B,C,X[14], 9,0xc33707d6L); + R1(C,D,A,B,X[ 3],14,0xf4d50d87L); + R1(B,C,D,A,X[ 8],20,0x455a14edL); + R1(A,B,C,D,X[13], 5,0xa9e3e905L); + R1(D,A,B,C,X[ 2], 9,0xfcefa3f8L); + R1(C,D,A,B,X[ 7],14,0x676f02d9L); + R1(B,C,D,A,X[12],20,0x8d2a4c8aL); + /* Round 2 */ + R2(A,B,C,D,X[ 5], 4,0xfffa3942L); + R2(D,A,B,C,X[ 8],11,0x8771f681L); + R2(C,D,A,B,X[11],16,0x6d9d6122L); + R2(B,C,D,A,X[14],23,0xfde5380cL); + R2(A,B,C,D,X[ 1], 4,0xa4beea44L); + R2(D,A,B,C,X[ 4],11,0x4bdecfa9L); + R2(C,D,A,B,X[ 7],16,0xf6bb4b60L); + R2(B,C,D,A,X[10],23,0xbebfbc70L); + R2(A,B,C,D,X[13], 4,0x289b7ec6L); + R2(D,A,B,C,X[ 0],11,0xeaa127faL); + R2(C,D,A,B,X[ 3],16,0xd4ef3085L); + R2(B,C,D,A,X[ 6],23,0x04881d05L); + R2(A,B,C,D,X[ 9], 4,0xd9d4d039L); + R2(D,A,B,C,X[12],11,0xe6db99e5L); + R2(C,D,A,B,X[15],16,0x1fa27cf8L); + R2(B,C,D,A,X[ 2],23,0xc4ac5665L); + /* Round 3 */ + R3(A,B,C,D,X[ 0], 6,0xf4292244L); + R3(D,A,B,C,X[ 7],10,0x432aff97L); + R3(C,D,A,B,X[14],15,0xab9423a7L); + R3(B,C,D,A,X[ 5],21,0xfc93a039L); + R3(A,B,C,D,X[12], 6,0x655b59c3L); + R3(D,A,B,C,X[ 3],10,0x8f0ccc92L); + R3(C,D,A,B,X[10],15,0xffeff47dL); + R3(B,C,D,A,X[ 1],21,0x85845dd1L); + R3(A,B,C,D,X[ 8], 6,0x6fa87e4fL); + R3(D,A,B,C,X[15],10,0xfe2ce6e0L); + R3(C,D,A,B,X[ 6],15,0xa3014314L); + R3(B,C,D,A,X[13],21,0x4e0811a1L); + R3(A,B,C,D,X[ 4], 6,0xf7537e82L); + R3(D,A,B,C,X[11],10,0xbd3af235L); + R3(C,D,A,B,X[ 2],15,0x2ad7d2bbL); + R3(B,C,D,A,X[ 9],21,0xeb86d391L); + + c->A+=A&0xffffffffL; + c->B+=B&0xffffffffL; + c->C+=C&0xffffffffL; + c->D+=D&0xffffffffL; + } + +void MD5_Final(md, c) +unsigned char *md; +MD5_CTX *c; + { + register int i,j; + register ULONG l; + register ULONG *p; + static unsigned char end[4]={0x80,0x00,0x00,0x00}; + unsigned char *cp=end; + + /* c->num should definitly have room for at least one more byte. */ + p=c->data; + j=c->num; + i=j>>2; + + /* purify often complains about the following line as an + * Uninitialized Memory Read. While this can be true, the + * following p_c2l macro will reset l when that case is true. + * This is because j&0x03 contains the number of 'valid' bytes + * already in p[i]. If and only if j&0x03 == 0, the UMR will + * occur but this is also the only time p_c2l will do + * l= *(cp++) instead of l|= *(cp++) + * Many thanks to Alex Tang for pickup this + * 'potential bug' */ +#ifdef PURIFY + if ((j&0x03) == 0) p[i]=0; +#endif + l=p[i]; + p_c2l(cp,l,j&0x03); + p[i]=l; + i++; + /* i is the next 'undefined word' */ + if (c->num >= MD5_LAST_BLOCK) + { + for (; iNl; + p[MD5_LBLOCK-1]=c->Nh; + md5_block(c,p); + cp=md; + l=c->A; l2c(l,cp); + l=c->B; l2c(l,cp); + l=c->C; l2c(l,cp); + l=c->D; l2c(l,cp); + + /* clear stuff, md5_block may be leaving some stuff on the stack + * but I'm not worried :-) */ + c->num=0; +/* memset((char *)&c,0,sizeof(c));*/ + } + +#ifdef undef +int printit(l) +unsigned long *l; + { + int i,ii; + + for (i=0; i<2; i++) + { + for (ii=0; ii<8; ii++) + { + fprintf(stderr,"%08lx ",l[i*8+ii]); + } + fprintf(stderr,"\n"); + } + } +#endif +#endif /* USE_MD5 */ diff --git a/lib/bind/dst/md5_locl.h b/lib/bind/dst/md5_locl.h new file mode 100644 index 0000000000..b2f0028fbd --- /dev/null +++ b/lib/bind/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 +#include +#include "md5.h" + +#define ULONG unsigned long +#define UCHAR unsigned char +#define UINT unsigned int + +#if defined(NOCONST) +#define const +#endif + +#undef c2l +#define c2l(c,l) (l = ((unsigned long)(*((c)++))) , \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<<24)) + +#undef p_c2l +#define p_c2l(c,l,n) { \ + switch (n) { \ + case 0: l =((unsigned long)(*((c)++))); \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + case 3: l|=((unsigned long)(*((c)++)))<<24; \ + } \ + } + +/* NOTE the pointer is not incremented at the end of this */ +#undef c2l_p +#define c2l_p(c,l,n) { \ + l=0; \ + (c)+=n; \ + switch (n) { \ + case 3: l =((unsigned long)(*(--(c))))<<16; \ + case 2: l|=((unsigned long)(*(--(c))))<< 8; \ + case 1: l|=((unsigned long)(*(--(c)))) ; \ + } \ + } + +#undef p_c2l_p +#define p_c2l_p(c,l,sc,len) { \ + switch (sc) \ + { \ + case 0: l =((unsigned long)(*((c)++))); \ + if (--len == 0) break; \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + if (--len == 0) break; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + } \ + } + +#undef l2c +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff)) + +/* NOTE - c is not incremented as per l2c */ +#undef l2cn +#define l2cn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ + } \ + } + +/* A nice byte order reversal from Wei Dai */ +#if defined(WIN32) +/* 5 instructions with rotate instruction, else 9 */ +#define Endian_Reverse32(a) \ + { \ + unsigned long l=(a); \ + (a)=((ROTATE(l,8)&0x00FF00FF)|(ROTATE(l,24)&0xFF00FF00)); \ + } +#else +/* 6 instructions with rotate instruction, else 8 */ +#define Endian_Reverse32(a) \ + { \ + unsigned long l=(a); \ + l=(((l&0xFF00FF00)>>8L)|((l&0x00FF00FF)<<8L)); \ + (a)=ROTATE(l,16L); \ + } +#endif +/* +#define F(x,y,z) (((x) & (y)) | ((~(x)) & (z))) +#define G(x,y,z) (((x) & (z)) | ((y) & (~(z)))) +*/ + +/* As pointed out by Wei Dai , the above can be + * simplified to the code below. Wei attributes these optimisations + * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel. + */ +#define F(x,y,z) ((((y) ^ (z)) & (x)) ^ (z)) +#define G(x,y,z) ((((x) ^ (y)) & (z)) ^ (y)) +#define H(x,y,z) ((x) ^ (y) ^ (z)) +#define I(x,y,z) (((x) | (~(z))) ^ (y)) + +#undef ROTATE +#if defined(WIN32) +#define ROTATE(a,n) _lrotl(a,n) +#else +#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) +#endif + + +#define R0(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+F((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; };\ + +#define R1(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+G((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; }; + +#define R2(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+H((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; }; + +#define R3(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+I((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; }; diff --git a/lib/bind/dst/prandom.c b/lib/bind/dst/prandom.c new file mode 100644 index 0000000000..0c13c0c5a3 --- /dev/null +++ b/lib/bind/dst/prandom.c @@ -0,0 +1,855 @@ +#ifndef LINT +static const char rcsid[] = "$Header: /u0/home/explorer/proj/ISC/git-conversion/cvsroot/bind9/lib/bind/dst/Attic/prandom.c,v 1.1 2001/03/29 06:31:33 marka Exp $"; +#endif +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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, const u_char *input, + int size); +static int my_digest(dst_work *tmp, const 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 < (time_t)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) + (void)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 < (time_t)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, (const 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, const u_char *input, int size) +{ + const u_char *tmp = input; + u_char *save = NULL, *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; + tmp = tp = save = 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_size > 0) + SAFE_FREE2(save, tmp_size); + return (1); + } + } + if (tmp_size > 0) + SAFE_FREE2(save, 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, const u_char *input, int size) +{ + + int i, full = 0; + static unsigned counter; + + counter += size; + /* first do each one of the hashes */ + for (i = 0; i < DST_NUM_HASHES && full == 0; i++) + full = do_hash(work, work->hash[i], input, size) + + do_hash(work, work->hash[i], (u_char *) &counter, + sizeof(counter)); +/* + * if enough data has be generated do final operation on all hashes + * that have enough date for that + */ + for (i = 0; full && (i < DST_NUM_HASHES); i++) + force_hash(work, work->hash[i]); + + return (full); +} + +/* + * this function gets some semi random data and sets that as an HMAC key + * If we get a valid key this function returns that key initalized + * otherwise it returns NULL; + */ +static prand_hash * +get_hmac_key(int step, int block) +{ + + u_char *buff; + int temp = 0, n = 0, size = 70; + DST_KEY *new_key = NULL; + prand_hash *new = NULL; + + /* use key that is larger than digest algorithms (64) for key size */ + buff = malloc(size); + if (buff == NULL) + return (NULL); + /* do not memset the allocated memory to get random bytes there */ + /* time of day is somewhat random expecialy in the last bytes */ + gettimeofday((struct timeval *) &buff[n], NULL); + n += sizeof(struct timeval); + +/* get some semi random stuff in here stir it with micro seconds */ + if (n < size) { + temp = dst_s_quick_random((int) buff[n - 1]); + memcpy(&buff[n], &temp, sizeof(temp)); + n += sizeof(temp); + } +/* get the pid of this process and its parent */ + if (n < size) { + temp = (int) getpid(); + memcpy(&buff[n], &temp, sizeof(temp)); + n += sizeof(temp); + } + if (n < size) { + temp = (int) getppid(); + memcpy(&buff[n], &temp, sizeof(temp)); + n += sizeof(temp); + } +/* get the user ID */ + if (n < size) { + temp = (int) getuid(); + memcpy(&buff[n], &temp, sizeof(temp)); + n += sizeof(temp); + } +#ifndef GET_HOST_ID_MISSING + if (n < size) { + temp = (int) gethostid(); + memcpy(&buff[n], &temp, sizeof(temp)); + n += sizeof(temp); + } +#endif +/* get some more random data */ + if (n < size) { + temp = dst_s_quick_random((int) buff[n - 1]); + memcpy(&buff[n], &temp, sizeof(temp)); + n += sizeof(temp); + } +/* covert this into a HMAC key */ + new_key = dst_buffer_to_key("", KEY_HMAC_MD5, 0, 0, buff, size); + SAFE_FREE(buff); + +/* get the control structure */ + if ((new = malloc(sizeof(prand_hash))) == NULL) + return (NULL); + new->digested = new->curr = 0; + new->step = step; + new->block = block; + new->key = new_key; + if (dst_sign_data(SIG_MODE_INIT, new_key, &new->ctx, NULL, 0, NULL, 0)) + return (NULL); + + return (new); +} + +/* + * own_random() + * This function goes out and from various sources tries to generate enough + * semi random data that a hash function can generate a random data. + * This function will iterate between the two main random source sources, + * information from programs and directores in random order. + * This function return the number of bytes added to the random output buffer. + */ +static int +own_random(dst_work *work) +{ + int dir = 0, b; + int bytes, n, cmd = 0, dig = 0; + int start =0; +/* + * now get the initial seed to put into the quick random function from + * the address of the work structure + */ + bytes = (int) getpid(); +/* + * proceed while needed + */ + while (work->filled < work->needed) { + EREPORT(("own_random r %08x b %6d t %6d f %6d\n", + ran_val, bytes, work->in_temp, work->filled)); +/* pick a random number in the range of 0..7 based on that random number + * perform some operations that yield random data + */ + start = work->filled; + n = (dst_s_quick_random(bytes) >> DST_SHIFT) & 0x07; + switch (n) { + case 0: + case 3: + if (sizeof(cmds) > 2 *sizeof(*cmds)) { + b = unix_cmd(work); + cmd += b; + } + break; + + case 1: + case 7: + if (sizeof(dirs) > 2 *sizeof(*dirs)) { + b = do_ls(work); + dir += b; + } + break; + + case 4: + case 5: + /* retry getting data from /dev/random */ + b = get_dev_random(&work->output[work->filled], + work->needed - work->filled); + if (b > 0) + work->filled += b; + break; + + case 6: + if (sizeof(files) > 2 * sizeof(*files)) { + b = digest_file(work); + dig += b; + } + break; + + case 2: + default: /* to make sure we make some progress */ + work->output[work->filled++] = 0xff & + dst_s_quick_random(bytes); + b = 1; + break; + } + if (b > 0) + bytes += b; + } + return (work->filled); +} + + +/* + * dst_s_random() This function will return the requested number of bytes + * of randomness to the caller it will use the best available sources of + * randomness. + * The current order is to use /dev/random, precalculated randomness, and + * finaly use some system calls and programs to generate semi random data that + * is then digested to generate randomness. + * This function is thread safe as each thread uses its own context, but + * concurrent treads will affect each other as they update shared state + * information. + * It is strongly recommended that this function be called requesting a size + * that is not a multiple of the output of the hash function used. + * + * If /dev/random is not available this function is not suitable to generate + * large ammounts of data, rather it is suitable to seed a pseudo-random + * generator + * Returns the number of bytes put in the output buffer + */ +int +dst_s_random(u_char *output, int size) +{ + int n = 0, s, i; + static u_char old_unused[DST_HASH_SIZE * DST_NUM_HASHES]; + static int unused = 0; + + if (size <= 0 || output == NULL) + return (0); + + if (size >= 2048) + return (-1); + /* + * Read from /dev/random + */ + n = get_dev_random(output, size); + /* + * If old data is available and needed use it + */ + if (n < size && unused > 0) { + int need = size - n; + if (unused <= need) { + memcpy(output, old_unused, unused); + n += unused; + unused = 0; + } else { + memcpy(output, old_unused, need); + n += need; + unused -= need; + memcpy(old_unused, &old_unused[need], unused); + } + } + /* + * If we need more use the simulated randomness here. + */ + if (n < size) { + dst_work *my_work = (dst_work *) malloc(sizeof(dst_work)); + if (my_work == NULL) + return (n); + my_work->needed = size - n; + my_work->filled = 0; + my_work->output = (u_char *) malloc(my_work->needed + + DST_HASH_SIZE * + DST_NUM_HASHES); + my_work->file_digest = NULL; + if (my_work->output == NULL) + return (n); + memset(my_work->output, 0x0, my_work->needed); +/* allocate upto 4 different HMAC hash functions out of order */ +#if DST_NUM_HASHES >= 3 + my_work->hash[2] = get_hmac_key(3, DST_RANDOM_BLOCK_SIZE / 2); +#endif +#if DST_NUM_HASHES >= 2 + my_work->hash[1] = get_hmac_key(7, DST_RANDOM_BLOCK_SIZE / 6); +#endif +#if DST_NUM_HASHES >= 4 + my_work->hash[3] = get_hmac_key(5, DST_RANDOM_BLOCK_SIZE / 4); +#endif + my_work->hash[0] = get_hmac_key(1, DST_RANDOM_BLOCK_SIZE); + if (my_work->hash[0] == NULL) /* if failure bail out */ + return (n); + s = own_random(my_work); +/* if more generated than needed store it for future use */ + if (s >= my_work->needed) { + EREPORT(("dst_s_random(): More than needed %d >= %d\n", + s, my_work->needed)); + memcpy(&output[n], my_work->output, my_work->needed); + n += my_work->needed; + /* saving unused data for next time */ + unused = s - my_work->needed; + memcpy(old_unused, &my_work->output[my_work->needed], + unused); + } else { + /* XXXX This should not happen */ + EREPORT(("Not enough %d >= %d\n", s, my_work->needed)); + memcpy(&output[n], my_work->output, s); + n += my_work->needed; + } + +/* delete the allocated work area */ + for (i = 0; i < DST_NUM_HASHES; i++) { + dst_free_key(my_work->hash[i]->key); + SAFE_FREE(my_work->hash[i]); + } + SAFE_FREE(my_work->output); + SAFE_FREE(my_work); + } + return (n); +} + +/* + * A random number generator that is fast and strong + * this random number generator is based on HASHing data, + * the input to the digest function is a collection of + * counters that is incremented between digest operations + * each increment operation amortizes to 2 bits changed in that value + * for 5 counters thus the input will amortize to have 10 bits changed + * The counters are initaly set using the strong random function above + * the HMAC key is selected by the same methold as the HMAC keys for the + * strong random function. + * Each set of counters is used for 2^25 operations + * + * returns the number of bytes written to the output buffer + * or negative number in case of error + */ +int +dst_s_semi_random(u_char *output, int size) +{ + static u_int32_t counter[DST_NUMBER_OF_COUNTERS]; + static u_char semi_old[DST_HASH_SIZE]; + static int semi_loc = 0, cnt = 0, hb_size = 0; + static DST_KEY *my_key = NULL; + prand_hash *hash; + int out = 0, i, n; + + if (output == NULL || size <= 0) + return (-2); + +/* check if we need a new key */ + if (my_key == NULL || cnt > (1 << 25)) { /* get HMAC KEY */ + if (my_key) + my_key->dk_func->destroy(my_key); + if ((hash = get_hmac_key(1, DST_RANDOM_BLOCK_SIZE)) == NULL) + return (0); + my_key = hash->key; +/* check if the key works stir the new key using some old random data */ + hb_size = dst_sign_data(SIG_MODE_ALL, my_key, NULL, + (u_char *) counter, sizeof(counter), + semi_old, sizeof(semi_old)); + if (hb_size <= 0) { + EREPORT(("dst_s_semi_random() Sign of alg %d failed %d\n", + my_key->dk_alg, hb_size)); + return (-1); + } +/* new set the counters to random values */ + dst_s_random((u_char *) counter, sizeof(counter)); + cnt = 0; + } +/* if old data around use it first */ + if (semi_loc < hb_size) { + if (size <= hb_size - semi_loc) { /* need less */ + memcpy(output, &semi_old[semi_loc], size); + semi_loc += size; + return (size); /* DONE */ + } else { + out = hb_size - semi_loc; + memcpy(output, &semi_old[semi_loc], out); + semi_loc += out; + } + } +/* generate more randome stuff */ + while (out < size) { + /* + * modify at least one bit by incrementing at least one counter + * based on the last bit of the last counter updated update + * the next one. + * minimaly this operation will modify at least 1 bit, + * amortized 2 bits + */ + for (n = 0; n < DST_NUMBER_OF_COUNTERS; n++) + i = (int) counter[n]++; + + i = dst_sign_data(SIG_MODE_ALL, my_key, NULL, + (u_char *) counter, hb_size, + semi_old, sizeof(semi_old)); +#ifdef REPORT_ERRORS + if (i != hb_size) + EREPORT(("HMAC SIGNATURE FAILURE %d\n", i)); +#endif + 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/lib/bind/dst/rsaref_link.c b/lib/bind/dst/rsaref_link.c new file mode 100644 index 0000000000..a552104872 --- /dev/null +++ b/lib/bind/dst/rsaref_link.c @@ -0,0 +1,767 @@ +#ifdef RSAREF +static const char rcsid[] = "$Header: /u0/home/explorer/proj/ISC/git-conversion/cvsroot/bind9/lib/bind/dst/Attic/rsaref_link.c,v 1.1 2001/03/29 06:31:33 marka Exp $"; + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + */ + +/* + * This file contains two components + * 1. Interface to the rsaref library to allow compilation when RSAREF is + * not available all calls to RSAREF are contained inside this file. + * 2. The glue to connvert RSA{REF} KEYS to and from external formats + */ +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dst_internal.h" + +# ifdef __STDC__ +# define PROTOTYPES 1 +# else +# define PROTOTYPES 0 +# endif + +# include +# include + +#include "port_after.h" + + +typedef struct rsakey { + char *rk_signer; + R_RSA_PRIVATE_KEY *rk_Private_Key; + R_RSA_PUBLIC_KEY *rk_Public_Key; +} RSA_Key; + + +static int dst_rsaref_sign(const int mode, DST_KEY *key, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len); +static int dst_rsaref_verify(const int mode, DST_KEY *key, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len); + +static int dst_rsaref_to_dns_key(const DST_KEY *public, u_char *out_str, + const int out_len); +static int dst_rsaref_from_dns_key(DST_KEY *s_key, const u_char *key, + const int len); + +static int dst_rsaref_key_to_file_format(const DST_KEY *dkey, + u_char *buff, + const int buff_len); +static int dst_rsaref_key_from_file_format(DST_KEY *dkey, + const u_char *buff, + const int buff_len); + +static int dst_rsaref_compare_keys(const DST_KEY *rkey1, + const DST_KEY *rkey2); +static void *dst_rsaref_free_key_structure(void *d_key); + +static int dst_rsaref_generate_keypair(DST_KEY *key, const int exp); + +static void dst_rsaref_init_random_struct(R_RANDOM_STRUCT * randomstruct); + +/* + * dst_rsaref_init() Function to answer set up function pointers for RSAREF + * related functions + */ +int +dst_rsaref_init() +{ + if (dst_t_func[KEY_RSA] != NULL) + return (1); + dst_t_func[KEY_RSA] = malloc(sizeof(struct dst_func)); + if (dst_t_func[KEY_RSA] == NULL) + return (0); + memset(dst_t_func[KEY_RSA], 0, sizeof(struct dst_func)); + dst_t_func[KEY_RSA]->sign = dst_rsaref_sign; + dst_t_func[KEY_RSA]->verify = dst_rsaref_verify; + dst_t_func[KEY_RSA]->compare = dst_rsaref_compare_keys; + dst_t_func[KEY_RSA]->generate = dst_rsaref_generate_keypair; + dst_t_func[KEY_RSA]->destroy = dst_rsaref_free_key_structure; + dst_t_func[KEY_RSA]->to_dns_key = dst_rsaref_to_dns_key; + dst_t_func[KEY_RSA]->from_dns_key = dst_rsaref_from_dns_key; + dst_t_func[KEY_RSA]->to_file_fmt = dst_rsaref_key_to_file_format; + dst_t_func[KEY_RSA]->from_file_fmt = dst_rsaref_key_from_file_format; + return (1); +} + +/* + * dst_rsa_sign + * Call RSAREF signing functions to sign a block of data. + * There are three steps to signing, INIT (initialize structures), + * UPDATE (hash (more) data), FINAL (generate a signature). This + * routine performs one or more of these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * key pointer to a RSA key structure that points to public key + * and context to use. + * data data to be signed. + * len length in bytes of data. + * signature location to store signature. + * sig_len size of the signature storage area + * returns + * N Success on SIG_MODE_FINAL = returns signature length in bytes + * 0 Success on SIG_MODE_INIT and UPDATE + * <0 Failure + */ + + +static int +dst_rsaref_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len) +{ + int sign_len = 0; + R_SIGNATURE_CTX *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = malloc(sizeof(*ctx)); + else if (context) + ctx = (R_SIGNATURE_CTX *) *context; + if (ctx == NULL) + return (-1); + + if ((mode & SIG_MODE_INIT) && R_SignInit(ctx, DA_MD5)) + return (SIGN_INIT_FAILURE); + + /* equivalent of SIG_MODE_UPDATE */ + if ((mode & SIG_MODE_UPDATE) && (data && len > 0) && + R_SignUpdate(ctx, (u_char *) data, len)) + return (SIGN_UPDATE_FAILURE); + + if (mode & SIG_MODE_FINAL) { + RSA_Key *key = (RSA_Key *) dkey->dk_KEY_struct; + if (signature == NULL || + sig_len < (int)(key->rk_Public_Key->bits + 7) / 8) + return (SIGN_FINAL_FAILURE); + if(key == NULL || key->rk_Private_Key == NULL) + return (-1); + if (R_SignFinal(ctx, signature, &sign_len, + key->rk_Private_Key)) + return (SIGN_FINAL_FAILURE); + SAFE_FREE(ctx); + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + return (sign_len); +} + + +/* + * dst_rsaref_verify() + * Calls RSAREF verification routines. There are three steps to + * verification, INIT (initialize structures), UPDATE (hash (more) data), + * FINAL (generate a signature). This routine performs one or more of + * these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * key pointer to a RSA key structure that points to public key + * and context to use. + * data data signed. + * len length in bytes of data. + * signature signature. + * sig_len length in bytes of signature. + * returns + * 0 Success + * <0 Failure + */ + +static int +dst_rsaref_verify(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len) +{ + R_SIGNATURE_CTX *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = malloc(sizeof(*ctx)); + else if (context) + ctx = (R_SIGNATURE_CTX *) *context; + if (ctx == NULL) + return (-1); + + if ((mode & SIG_MODE_INIT) && R_VerifyInit(ctx, DA_MD5)) + return (VERIFY_INIT_FAILURE); + + if ((mode & SIG_MODE_UPDATE) && (data && len > 0) && + R_VerifyUpdate(ctx, (u_char *) data, len)) + return (VERIFY_UPDATE_FAILURE); + + if ((mode & SIG_MODE_FINAL)) { + RSA_Key *key = (RSA_Key *) dkey->dk_KEY_struct; + + if (key == NULL || key->rk_Public_Key == NULL) + return (-1); + if (signature == NULL || sig_len <= 0) + return (VERIFY_FINAL_FAILURE); + if (R_VerifyFinal(ctx, (u_char *) signature, sig_len, + key->rk_Public_Key)) + return (VERIFY_FINAL_FAILURE); + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + + return (0); +} + + +/* + * dst_rsaref_to_dns_key + * Converts key in RSAREF to DNS distribution format + * This function gets in a pointer to the public key and a work area + * to write the key into. + * Parameters + * public KEY structure + * out_str buffer to write encoded key into + * out_len size of out_str + * Return + * N >= 0 length of encoded key + * n < 0 error + */ + +static int +dst_rsaref_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len) +{ + int n, loc; + R_RSA_PUBLIC_KEY *public; + u_char *op = (u_char *) out_str; + + if (in_key == NULL || in_key->dk_KEY_struct == NULL || + out_len <= 0 || out_str == NULL) + return (-1); + public = (R_RSA_PUBLIC_KEY *) + ((RSA_Key *) in_key->dk_KEY_struct)->rk_Public_Key; + if (public == NULL) + return (-1); + + memset(op, 0, out_len); + + /* find first non zero */ + for (n = 0; public->exponent[n] == 0x0; n++) ; + + n = (MAX_RSA_MODULUS_LEN - n); /* find lenght of exponent */ + *op++ = (u_int8_t) n; + + if (n > (out_len - (op-out_str))) + return (-1); + memcpy(op, &public->exponent[MAX_RSA_MODULUS_LEN - n], n); + op += n; + n++; /* include the lenght field in this count */ + + /* find first non zero */ + for (loc = 0; public->modulus[loc] == 0x0; loc++) ; + + /*copy exponent */ + if ((MAX_RSA_MODULUS_LEN - loc) > (out_len - (op-out_str))) + return (-1); + memcpy(op, &public->modulus[loc], MAX_RSA_MODULUS_LEN - loc); + n += (MAX_RSA_MODULUS_LEN - loc); + return (n); +} + + +/* + * dst_rsaref_from_dns_key + * Converts from a DNS KEY RR format to an RSA KEY. + * Parameters + * len Length in bytes of DNS key + * key DNS key + * name Key name + * s_key DST structure that will point to the RSA key this routine + * will build. + * Return + * -1 The input key has fields that are larger than this package supports + * 0 The input key, s_key or name was null. + * 1 Success + */ +static int +dst_rsaref_from_dns_key(DST_KEY *s_key, const u_char *key, const int len) +{ + int bytes; + u_char *key_ptr; + RSA_Key *r_key; + + if (key == NULL || s_key == NULL || len < 0) + return (0); + + if (s_key->dk_KEY_struct) { /* do not reuse */ + dst_rsaref_free_key_structure(s_key->dk_KEY_struct); + s_key->dk_KEY_struct = NULL; + } + if (len == 0) /* null key no conversion needed */ + return (1); + + if ((r_key = (RSA_Key *) malloc(sizeof(RSA_Key))) == NULL) { + EREPORT(("dst_rsaref_from_dns_key(): Memory allocation error 1\n")); + return (0); + } + memset(r_key, 0, sizeof(RSA_Key)); + s_key->dk_KEY_struct = (void *) r_key; + r_key->rk_signer = strdup(s_key->dk_key_name); + r_key->rk_Public_Key = (R_RSA_PUBLIC_KEY *) + malloc(sizeof(R_RSA_PUBLIC_KEY)); + if (r_key->rk_Public_Key == NULL) { + EREPORT(("dst_rsaref_from_dns_key(): Memory allocation error 3\n")); + return (0); + } + memset(r_key->rk_Public_Key, 0, sizeof(R_RSA_PUBLIC_KEY)); + key_ptr = (u_char *) key; + bytes = (int) *key_ptr++; /* length of exponent in bytes */ + if (bytes == 0) { /* special case for long exponents */ + bytes = (int) dst_s_get_int16(key_ptr); + key_ptr += sizeof(u_int16_t); + } + if (bytes > MAX_RSA_MODULUS_LEN) { + dst_rsaref_free_key_structure(r_key); + return (-1); + } + memcpy(&r_key->rk_Public_Key->exponent[MAX_RSA_MODULUS_LEN - bytes], + key_ptr, bytes); + + key_ptr += bytes; /* beginning of modulus */ + bytes = len - bytes - 1; /* length of modulus */ + if (bytes > MAX_RSA_MODULUS_LEN) { + dst_rsaref_free_key_structure(r_key); + return (-1); + } + memcpy(&r_key->rk_Public_Key->modulus[MAX_RSA_MODULUS_LEN - bytes], + key_ptr, bytes); + r_key->rk_Public_Key->bits = bytes * 8; + s_key->dk_id = (u_int16_t) dst_s_get_int16((u_char *) + &r_key->rk_Public_Key->modulus[MAX_RSA_MODULUS_LEN - 3]); + s_key->dk_key_size = r_key->rk_Public_Key->bits; + + return (1); +} + + +/* + * dst_rsaref_key_to_file_format + * Encodes an RSA Key into the portable file format. + * Parameters + * rkey RSA KEY structure + * buff output buffer + * buff_len size of output buffer + * Return + * 0 Failure - null input rkey + * -1 Failure - not enough space in output area + * N Success - Length of data returned in buff + */ + +static int +dst_rsaref_key_to_file_format(const DST_KEY *in_key, u_char *buff, + const int buff_len) +{ + u_char *bp; + int len, b_len; + R_RSA_PRIVATE_KEY *rkey; + + if (in_key == NULL || in_key->dk_KEY_struct == NULL) + return (-1); + rkey = (R_RSA_PRIVATE_KEY *) + ((RSA_Key *) in_key->dk_KEY_struct)->rk_Private_Key; + if (rkey == NULL) /* no output */ + return (0); + if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str)) + return (-1); /* no OR not enough space in output area */ + + memset(buff, 0, buff_len); /* just in case */ + /* write file header */ + sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_RSA, "RSA"); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Modulus: ", + rkey->modulus, + MAX_RSA_MODULUS_LEN)) <= 0) + return (-1); + + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "PublicExponent: ", + rkey->publicExponent, + MAX_RSA_MODULUS_LEN)) <= 0) + return (-2); + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "PrivateExponent: ", + rkey->exponent, + MAX_RSA_MODULUS_LEN)) <= 0) + return (-3); + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime1: ", + rkey->prime[0], + MAX_RSA_PRIME_LEN)) < 0) + return (-4); + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime2: ", + rkey->prime[1], + MAX_RSA_PRIME_LEN)) < 0) + return (-5); + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Exponent1: ", + rkey->primeExponent[0], + MAX_RSA_PRIME_LEN)) < 0) + return (-6); + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Exponent2: ", + rkey->primeExponent[1], + MAX_RSA_PRIME_LEN)) < 0) + return (-7); + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Coefficient: ", + rkey->coefficient, + MAX_RSA_PRIME_LEN)) < 0) + return (-8); + bp += len; + b_len -= len; + return (buff_len - b_len); +} + + +/* + * dst_rsaref_key_from_file_format + * Converts contents of a private key file into a private RSA key. + * Parameters + * r_key structure to put key into + * buff buffer containing the encoded key + * buff_len the length of the buffer + * Return + * n >= 0 Foot print of the key converted + * n < 0 Error in conversion + */ + +static int +dst_rsaref_key_from_file_format(DST_KEY *d_key, const u_char *buff, + const int buff_len) +{ + const char *p = (char *) buff; + R_RSA_PRIVATE_KEY key; + int foot = -1; + RSA_Key *r_key; + + if (d_key == NULL || buff == NULL || buff_len < 0) + return (-1); + + memset(&key, 0, sizeof(key)); + + if (!dst_s_verify_str(&p, "Modulus: ")) + return (-3); + + if (!dst_s_conv_bignum_b64_to_u8(&p, key.modulus, MAX_RSA_MODULUS_LEN)) + return (-4); + + key.bits = dst_s_calculate_bits(key.modulus, MAX_RSA_MODULUS_BITS); + + while (*++p && p < (char *) &buff[buff_len]) { + if (dst_s_verify_str(&p, "PublicExponent: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, + key.publicExponent, + MAX_RSA_MODULUS_LEN)) + return (-5); + } else if (dst_s_verify_str(&p, "PrivateExponent: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, key.exponent, + MAX_RSA_MODULUS_LEN)) + return (-6); + } else if (dst_s_verify_str(&p, "Prime1: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, key.prime[0], + MAX_RSA_PRIME_LEN)) + return (-7); + } else if (dst_s_verify_str(&p, "Prime2: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, key.prime[1], + MAX_RSA_PRIME_LEN)) + return (-8); + } else if (dst_s_verify_str(&p, "Exponent1: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, + key.primeExponent[0], + MAX_RSA_PRIME_LEN)) + return (-9); + } else if (dst_s_verify_str(&p, "Exponent2: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, + key.primeExponent[1], + MAX_RSA_PRIME_LEN)) + return (-10); + } else if (dst_s_verify_str(&p, "Coefficient: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, key.coefficient, + MAX_RSA_PRIME_LEN)) + return (-11); + } else { + EREPORT(("dst_rsaref_key_from_file_format: Bad keyword %s\n", p)); + return (-12); + } + } /* while p */ + + r_key = (RSA_Key *) malloc(sizeof(RSA_Key)); + if (r_key == NULL) { + return (-2); + } + memset(r_key, 0, sizeof(*r_key)); + + r_key->rk_Private_Key = + (R_RSA_PRIVATE_KEY *) malloc(sizeof(R_RSA_PRIVATE_KEY)); + if (r_key->rk_Private_Key == NULL) { + EREPORT(("dst_rsaref_key_from_file_format: Memory allocation error\n")); + return (-13); + } + r_key->rk_Public_Key = (R_RSA_PUBLIC_KEY *) r_key->rk_Private_Key; + memcpy(r_key->rk_Private_Key, &key, sizeof(R_RSA_PRIVATE_KEY)); + + r_key->rk_signer = strdup(d_key->dk_key_name); + d_key->dk_KEY_struct = (void *) r_key; + d_key->dk_key_size = r_key->rk_Private_Key->bits; + d_key->dk_id = (u_int16_t) dst_s_get_int16((u_char *) + &r_key->rk_Public_Key->modulus[MAX_RSA_MODULUS_LEN - 3]); + foot = (int) d_key->dk_id; + return (foot); +} + + + +/* + * dst_rsaref_compare_keys + * Compare two keys for equality. + * Return + * 0 The keys are equal + * NON-ZERO The keys are not equal + */ + +static int +dst_rsaref_compare_keys(const DST_KEY *dkey1, const DST_KEY *dkey2) +{ + RSA_Key *rkey1 = (RSA_Key *) dkey1->dk_KEY_struct; + RSA_Key *rkey2 = (RSA_Key *) dkey2->dk_KEY_struct; + + if (rkey1 == NULL && rkey2 == NULL) + return (0); /* same */ + else if (rkey1 == NULL) + return (1); + else if (rkey2 == NULL) + return (2); + return (memcmp(rkey1->rk_Public_Key, rkey2->rk_Public_Key, + sizeof(R_RSA_PUBLIC_KEY))); +} + +/* + * dst_rsaref_generate_keypair + * Generates unique keys that are hard to predict. + * Parameters + * key generic Key structure + * exp the public exponent + * Return + * 0 Failure + * 1 Success + */ + +static int +dst_rsaref_generate_keypair(DST_KEY *key, const int exp) +{ + R_RSA_PUBLIC_KEY *public; + R_RSA_PRIVATE_KEY *private; + R_RSA_PROTO_KEY proto; + R_RANDOM_STRUCT randomStruct; + RSA_Key *rsa; + int status; + + if (key == NULL || key->dk_alg != KEY_RSA) + return (0); + if (key->dk_key_size < MIN_RSA_MODULUS_BITS || + key->dk_key_size > MAX_RSA_MODULUS_BITS) { + EREPORT(("dst_rsaref_generate_keypair: Invalid key size\n")); + return (0); /* these are the limits on key size in RSAREF */ + } + /* allocate space */ + if ((public = (R_RSA_PUBLIC_KEY *) malloc(sizeof(R_RSA_PUBLIC_KEY))) + == NULL) { + EREPORT(("dst_rsaref_generate_keypair: Memory allocation error 1\n")); + return (0); + } + if ((private = (R_RSA_PRIVATE_KEY *) malloc(sizeof(R_RSA_PRIVATE_KEY))) + == NULL) { + EREPORT(("dst_rsaref_generate_keypair: Memory allocation error 2\n")); + return (0); + } + if ((rsa = (RSA_Key *) malloc(sizeof(RSA_Key))) == NULL) { + EREPORT(("dst_rsaref_generate_keypair: Memory allocation error 3\n")); + return (0); + } + memset(public, 0, sizeof(*public)); + memset(private, 0, sizeof(*private)); + + proto.bits = key->dk_key_size; + proto.useFermat4 = exp ? 0x1 : 0x0; /* 1 for f4=65537, 0 for f0=3 */ + EREPORT(("\ndst_rsaref_generate_keypair: Generating KEY for %s Please wait\n", + key->dk_key_name)); + + /* set up random seed */ + dst_rsaref_init_random_struct(&randomStruct); + + /* generate keys */ + status = R_GeneratePEMKeys(public, private, &proto, &randomStruct); + if (status) { + EREPORT(("dst_rsaref_generate_keypair: No Key Pair generated %d\n", + status)); + SAFE_FREE(public); + SAFE_FREE(private); + SAFE_FREE(rsa); + return (0); + } + memset(rsa, 0, sizeof(*rsa)); + rsa->rk_signer = key->dk_key_name; + rsa->rk_Private_Key = private; + rsa->rk_Public_Key = public; + key->dk_KEY_struct = (void *) rsa; + + key->dk_id = (u_int16_t) dst_s_get_int16((u_char *) + &rsa->rk_Public_Key->modulus[MAX_RSA_MODULUS_LEN - 3]); + return (1); +} + + +/* + * dst_rsaref_free_key_structure + * Frees all dynamicly allocated structures in r_key + */ + +static void * +dst_rsaref_free_key_structure(void *v_key) +{ + RSA_Key *r_key = (RSA_Key *) v_key; + + if (r_key != NULL) { + if ((void *) r_key->rk_Private_Key == (void *) r_key->rk_Public_Key) + r_key->rk_Public_Key = NULL; + SAFE_FREE(r_key->rk_Private_Key); + SAFE_FREE(r_key->rk_Public_Key); + SAFE_FREE(r_key->rk_signer); + SAFE_FREE(r_key); + } + return (NULL); +} + + +/* + * dst_rsaref_init_random_struct + * A random seed value is used in key generation. + * This routine gets a bunch of system values to randomize the + * randomstruct. A number of system calls are used to get somewhat + * unpredicable values, then a special function dst_s_prandom() is called + * that will do some magic depending on the system used. + * If this function is executed on reasonably busy machine then the values + * that prandom uses are hard to + * 1. Predict + * 2. Regenerate + * 3. Hard to spy on as nothing is stored to disk and data is consumed + * as fast as it is generated. + */ + +static void +dst_rsaref_init_random_struct(R_RANDOM_STRUCT * randomstruct) +{ + unsigned bytesNeeded; + struct timeval tv; + u_char *array; + int n; + + R_RandomInit(randomstruct); + + /* The runtime of the script is unpredictable within some range + * thus I'm getting the time of day again as this is an hard to guess + * value and the number of characters of the output from the script is + * hard to guess. + * This must be the FIRST CALL + */ + gettimeofday(&tv, 0); + R_RandomUpdate(randomstruct, (u_char *) &tv, + sizeof(struct timeval)); + + /* + * first find out how many bytes I need + */ + R_GetRandomBytesNeeded(&bytesNeeded, randomstruct); + + /* + * get a storage area for it addjust the area for the possible + * side effects of digest functions writing out in blocks + */ + array = (u_char *) malloc(bytesNeeded); + + /* extract the random data from /dev/random if present, generate + * it if not present + * first fill the buffer with semi random data + * then fill as much as possible with good random data + */ + n = dst_random(DST_RAND_SEMI, bytesNeeded, array); + n += dst_random(DST_RAND_KEY, bytesNeeded, array); + if (n <= bytesNeeded) { + SAFE_FREE(array); + return(0); + } + + /* supply the random data (even if it is larger than requested) */ + R_RandomUpdate(randomstruct, array, bytesNeeded); + + SAFE_FREE(array); + + R_GetRandomBytesNeeded(&bytesNeeded, randomstruct); + if (bytesNeeded) { + EREPORT(("InitRandomStruct() didn't initialize enough randomness\n")); + exit(33); + } +} + + +#else +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dst_internal.h" +#include "port_after.h" +int /* rsaref is not available */ +dst_rsaref_init() +{ + return (0); +} +#endif /* RSAREF */ diff --git a/lib/bind/dst/support.c b/lib/bind/dst/support.c new file mode 100644 index 0000000000..d4db777997 --- /dev/null +++ b/lib/bind/dst/support.c @@ -0,0 +1,463 @@ +static const char rcsid[] = "$Header: /u0/home/explorer/proj/ISC/git-conversion/cvsroot/bind9/lib/bind/dst/Attic/support.c,v 1.1 2001/03/29 06:31:33 marka Exp $"; + + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dst_internal.h" + +#include "port_after.h" +/* + * dst_s_conv_bignum_u8_to_b64 + * This function converts binary data stored as a u_char[] to a + * base-64 string. Leading zeroes are discarded. If a header is + * supplied, it is prefixed to the input prior to encoding. The + * output is \n\0 terminated (the \0 is not included in output length). + * Parameters + * out_buf binary data to convert + * header character string to prefix to the output (label) + * bin_data binary data + * bin_len size of binary data + * Return + * -1 not enough space in output work area + * 0 no output + * >0 number of bytes written to output work area + */ + +int +dst_s_conv_bignum_u8_to_b64(char *out_buf, const int out_len, + const char *header, const u_char *bin_data, + const int bin_len) +{ + const u_char *bp = bin_data; + char *op = out_buf; + int lenh = 0, len64 = 0; + int local_in_len = bin_len; + int local_out_len = out_len; + + if (bin_data == NULL || bin_len <= 0) /* no data no */ + return (0); + + if (out_buf == NULL || out_len <= 0) /* no output_work area */ + return (-1); + + /* suppress leading \0 */ + for (; (*bp == 0x0) && (local_in_len > 0); local_in_len--) + bp++; + + if (header) { /* add header to output string */ + lenh = strlen(header); + if (lenh < out_len) + memcpy(op, header, lenh); + else + return (-1); + local_out_len -= lenh; + op += lenh; + } + len64 = b64_ntop(bp, local_in_len, op, local_out_len - 2); + if (len64 < 0) + return (-1); + op += len64++; + *(op++) = '\n'; /* put CR in the output */ + *op = '\0'; /* make sure output is 0 terminated */ + return (lenh + len64); +} + + +/* + * dst_s_verify_str() + * Validate that the input string(*str) is at the head of the input + * buffer(**buf). If so, move the buffer head pointer (*buf) to + * the first byte of data following the string(*str). + * Parameters + * buf Input buffer. + * str Input string. + * Return + * 0 *str is not the head of **buff + * 1 *str is the head of **buff, *buf is is advanced to + * the tail of **buf. + */ + +int +dst_s_verify_str(const char **buf, const char *str) +{ + int b, s; + if (*buf == NULL) /* error checks */ + return (0); + if (str == NULL || *str == '\0') + return (1); + + b = strlen(*buf); /* get length of strings */ + s = strlen(str); + if (s > b || strncmp(*buf, str, s)) /* check if same */ + return (0); /* not a match */ + (*buf) += s; /* advance pointer */ + return (1); +} + + +/* + * dst_s_conv_bignum_b64_to_u8 + * Read a line of base-64 encoded string from the input buffer, + * convert it to binary, and store it in an output area. The + * input buffer is read until reaching a newline marker or the + * end of the buffer. The binary data is stored in the last X + * number of bytes of the output area where X is the size of the + * binary output. If the operation is successful, the input buffer + * pointer is advanced. This procedure does not do network to host + * byte order conversion. + * Parameters + * buf Pointer to encoded input string. Pointer is updated if + * function is successfull. + * loc Output area. + * loclen Size in bytes of output area. + * Return + * >0 Return = number of bytes of binary data stored in loc. + * 0 Failure. + */ + +int +dst_s_conv_bignum_b64_to_u8(const char **buf, u_char *loc, const int loclen) +{ + int blen; + char *bp; + u_char bstr[RAW_KEY_SIZE]; + + if (buf == NULL || *buf == NULL) { /* error checks */ + EREPORT(("dst_s_conv_bignum_b64_to_u8: null input buffer.\n")); + return (0); + } + bp = strchr(*buf, '\n'); /* find length of input line */ + if (bp != NULL) + *bp = (u_char) NULL; + + blen = b64_pton(*buf, bstr, sizeof(bstr)); + if (blen <= 0) { + EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is null.\n")); + return (0); + } + else if (loclen < blen) { + EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is longer than output buffer.\n")); + return (0); + } + if (bp) + *buf = bp; /* advancing buffer past \n */ + memset(loc, 0, loclen - blen); /* clearing unused output area */ + memcpy(loc + loclen - blen, bstr, blen); /* write last blen bytes */ + return (blen); +} + + +/* + * dst_s_calculate_bits + * Given a binary number represented in a u_char[], determine + * the number of significant bits used. + * Parameters + * str An input character string containing a binary number. + * max_bits The maximum possible significant bits. + * Return + * N The number of significant bits in str. + */ + +int +dst_s_calculate_bits(const u_char *str, const int max_bits) +{ + const u_char *p = str; + u_char i, j = 0x80; + int bits; + for (bits = max_bits; *p == 0x00 && bits > 0; p++) + bits -= 8; + for (i = *p; (i & j) != j; j >>= 1) + bits--; + return (bits); +} + + +/* + * calculates a checksum used in kmt for a id. + * takes an array of bytes and a length. + * returns a 16 bit checksum. + */ +u_int16_t +dst_s_id_calc(const u_char *key, const int keysize) +{ + u_int32_t ac; + const u_char *kp = key; + int size = keysize; + + if (!key || (keysize <= 0)) + return (-1); + + for (ac = 0; size > 1; size -= 2, kp += 2) + ac += ((*kp) << 8) + *(kp + 1); + + if (size > 0) + ac += ((*kp) << 8); + ac += (ac >> 16) & 0xffff; + + return (ac & 0xffff); +} + +/* + * dst_s_dns_key_id() Function to calculated DNSSEC footprint from KEY reocrd + * rdata (all of record) + * Input: + * dns_key_rdata: the raw data in wire format + * rdata_len: the size of the input data + * Output: + * the key footprint/id calcuated from the key data + */ +u_int16_t +dst_s_dns_key_id(const u_char *dns_key_rdata, const int rdata_len) +{ + int key_data = 4; + + if (!dns_key_rdata || (rdata_len < key_data)) + return 0; + + /* check the extended parameters bit in the DNS Key RR flags */ + if (dst_s_get_int16(dns_key_rdata) & DST_EXTEND_FLAG) + key_data += 2; + + /* compute id */ + if (dns_key_rdata[3] == KEY_RSA) /* Algorithm RSA */ + return dst_s_get_int16((const u_char *) + &dns_key_rdata[rdata_len - 3]); + else + /* compute a checksum on the key part of the key rr */ + return dst_s_id_calc(&dns_key_rdata[key_data], + (rdata_len - key_data)); +} + +/* + * dst_s_get_int16 + * This routine extracts a 16 bit integer from a two byte character + * string. The character string is assumed to be in network byte + * order and may be unaligned. The number returned is in host order. + * Parameter + * buf A two byte character string. + * Return + * The converted integer value. + */ + +u_int16_t +dst_s_get_int16(const u_char *buf) +{ + register u_int16_t a = 0; + a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1])); + return (a); +} + + +/* + * dst_s_get_int32 + * This routine extracts a 32 bit integer from a four byte character + * string. The character string is assumed to be in network byte + * order and may be unaligned. The number returned is in host order. + * Parameter + * buf A four byte character string. + * Return + * The converted integer value. + */ + +u_int32_t +dst_s_get_int32(const u_char *buf) +{ + register u_int32_t a = 0; + a = ((u_int32_t)(buf[0] << 24)) | ((u_int32_t)(buf[1] << 16)) | + ((u_int32_t)(buf[2] << 8)) | ((u_int32_t)(buf[3])); + return (a); +} + + +/* + * dst_s_put_int16 + * Take a 16 bit integer and store the value in a two byte + * character string. The integer is assumed to be in network + * order and the string is returned in host order. + * + * Parameters + * buf Storage for a two byte character string. + * val 16 bit integer. + */ + +void +dst_s_put_int16(u_int8_t *buf, const u_int16_t val) +{ + buf[0] = (u_int8_t)(val >> 8); + buf[1] = (u_int8_t)(val); +} + + +/* + * dst_s_put_int32 + * Take a 32 bit integer and store the value in a four byte + * character string. The integer is assumed to be in network + * order and the string is returned in host order. + * + * Parameters + * buf Storage for a four byte character string. + * val 32 bit integer. + */ + +void +dst_s_put_int32(u_int8_t *buf, const u_int32_t val) +{ + buf[0] = (u_int8_t)(val >> 24); + buf[1] = (u_int8_t)(val >> 16); + buf[2] = (u_int8_t)(val >> 8); + buf[3] = (u_int8_t)(val); +} + + +/* + * dst_s_filename_length + * + * This function returns the number of bytes needed to hold the + * filename for a key file. '/', '\' and ':' are not allowed. + * form: K++. + * + * Returns 0 if the filename would contain either '\', '/' or ':' + */ +size_t +dst_s_filename_length(const char *name, const char *suffix) +{ + if (name == NULL) + return (0); + if (strrchr(name, '\\')) + return (0); + if (strrchr(name, '/')) + return (0); + if (strrchr(name, ':')) + return (0); + if (suffix == NULL) + return (0); + if (strrchr(suffix, '\\')) + return (0); + if (strrchr(suffix, '/')) + return (0); + if (strrchr(suffix, ':')) + return (0); + return (1 + strlen(name) + 6 + strlen(suffix)); +} + + +/* + * dst_s_build_filename () + * Builds a key filename from the key name, it's id, and a + * suffix. '\', '/' and ':' are not allowed. fA filename is of the + * form: K. + * form: K++. + * + * Returns -1 if the conversion fails: + * if the filename would be too long for space allotted + * if the filename would contain a '\', '/' or ':' + * Returns 0 on success + */ + +int +dst_s_build_filename(char *filename, const char *name, u_int16_t id, + int alg, const char *suffix, size_t filename_length) +{ + u_int32_t my_id; + if (filename == NULL) + return (-1); + memset(filename, 0, filename_length); + if (name == NULL) + return (-1); + if (suffix == NULL) + return (-1); + if (filename_length < 1 + strlen(name) + 4 + 6 + 1 + strlen(suffix)) + return (-1); + my_id = id; + sprintf(filename, "K%s+%03d+%05d.%s", name, alg, my_id, + (const 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]; + size_t 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) +{ + UNUSED(data); + + 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/lib/bind/include/Makefile.in b/lib/bind/include/Makefile.in new file mode 100644 index 0000000000..f3a030aef4 --- /dev/null +++ b/lib/bind/include/Makefile.in @@ -0,0 +1,2 @@ +all: +@BIND9_MAKE_RULES@ diff --git a/lib/bind/include/arpa/inet.h b/lib/bind/include/arpa/inet.h new file mode 100644 index 0000000000..1a238aa912 --- /dev/null +++ b/lib/bind/include/arpa/inet.h @@ -0,0 +1,110 @@ +/* + * ++Copyright++ 1983, 1993 + * - + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * - + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * - + * --Copyright-- + */ + +/* + * @(#)inet.h 8.1 (Berkeley) 6/2/93 + * $Id: inet.h,v 1.1 2001/03/29 06:31:34 marka Exp $ + */ + +#ifndef _INET_H_ +#define _INET_H_ + +/* External definitions for functions in inet(3) */ + +#include +#if (!defined(BSD)) || (BSD < 199306) +# include +#else +# include +#endif +#include + +#define inet_addr __inet_addr +#define inet_aton __inet_aton +#define inet_lnaof __inet_lnaof +#define inet_makeaddr __inet_makeaddr +#define inet_neta __inet_neta +#define inet_netof __inet_netof +#define inet_network __inet_network +#define inet_net_ntop __inet_net_ntop +#define inet_net_pton __inet_net_pton +#define inet_cidr_ntop __inet_cidr_ntop +#define inet_cidr_pton __inet_cidr_pton +#define inet_ntoa __inet_ntoa +#define inet_pton __inet_pton +#define inet_ntop __inet_ntop +#define inet_nsap_addr __inet_nsap_addr +#define inet_nsap_ntoa __inet_nsap_ntoa + +__BEGIN_DECLS +unsigned long inet_addr __P((const char *)); +int inet_aton __P((const char *, struct in_addr *)); +unsigned long inet_lnaof __P((struct in_addr)); +struct in_addr inet_makeaddr __P((u_long , u_long)); +char * inet_neta __P((u_long, char *, size_t)); +unsigned long inet_netof __P((struct in_addr)); +unsigned long inet_network __P((const char *)); +char *inet_net_ntop __P((int, const void *, int, char *, size_t)); +int inet_net_pton __P((int, const char *, void *, size_t)); +char *inet_cidr_ntop __P((int, const void *, int, char *, size_t)); +int inet_cidr_pton __P((int, const char *, void *, int *)); +/*const*/ char *inet_ntoa __P((struct in_addr)); +int inet_pton __P((int, const char *, void *)); +const char *inet_ntop __P((int, const void *, char *, size_t)); +u_int inet_nsap_addr __P((const char *, u_char *, int)); +char *inet_nsap_ntoa __P((int, const u_char *, char *)); +__END_DECLS + +#endif /* !_INET_H_ */ diff --git a/lib/bind/include/arpa/nameser.h b/lib/bind/include/arpa/nameser.h new file mode 100644 index 0000000000..9934a28d19 --- /dev/null +++ b/lib/bind/include/arpa/nameser.h @@ -0,0 +1,559 @@ +/* + * Copyright (c) 1983, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER 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: nameser.h,v 1.1 2001/03/29 06:31:35 marka Exp $ + */ + +#ifndef _ARPA_NAMESER_H_ +#define _ARPA_NAMESER_H_ + +#define BIND_4_COMPAT + +#include +#if (!defined(BSD)) || (BSD < 199306) +# include +#else +# include +#endif +#include + +/* + * Revision information. This is the release date in YYYYMMDD format. + * It can change every day so the right thing to do with it is use it + * in preprocessor commands such as "#if (__NAMESER > 19931104)". Do not + * compare for equality; rather, use it to determine whether your libbind.a + * contains a new enough lib/nameser/ to support the feature you need. + */ + +#define __NAMESER 19991006 /* New interface version stamp. */ + +/* + * Define constants based on RFC 883, RFC 1034, RFC 1035 + */ +#define NS_PACKETSZ 512 /* maximum packet size */ +#define NS_MAXDNAME 1025 /* maximum domain name */ +#define NS_MAXCDNAME 255 /* maximum compressed domain name */ +#define NS_MAXLABEL 63 /* maximum length of domain label */ +#define NS_HFIXEDSZ 12 /* #/bytes of fixed data in header */ +#define NS_QFIXEDSZ 4 /* #/bytes of fixed data in query */ +#define NS_RRFIXEDSZ 10 /* #/bytes of fixed data in r record */ +#define NS_INT32SZ 4 /* #/bytes of data in a u_int32_t */ +#define NS_INT16SZ 2 /* #/bytes of data in a u_int16_t */ +#define NS_INT8SZ 1 /* #/bytes of data in a u_int8_t */ +#define NS_INADDRSZ 4 /* IPv4 T_A */ +#define NS_IN6ADDRSZ 16 /* IPv6 T_AAAA */ +#define NS_CMPRSFLGS 0xc0 /* Flag bits indicating name compression. */ +#define NS_DEFAULTPORT 53 /* For both TCP and UDP. */ + +/* + * These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord() + * in synch with it. + */ +typedef enum __ns_sect { + ns_s_qd = 0, /* Query: Question. */ + ns_s_zn = 0, /* Update: Zone. */ + ns_s_an = 1, /* Query: Answer. */ + ns_s_pr = 1, /* Update: Prerequisites. */ + ns_s_ns = 2, /* Query: Name servers. */ + ns_s_ud = 2, /* Update: Update. */ + ns_s_ar = 3, /* Query|Update: Additional records. */ + ns_s_max = 4 +} ns_sect; + +/* + * This is a message handle. It is caller allocated and has no dynamic data. + * This structure is intended to be opaque to all but ns_parse.c, thus the + * leading _'s on the member names. Use the accessor functions, not the _'s. + */ +typedef struct __ns_msg { + const u_char *_msg, *_eom; + u_int16_t _id, _flags, _counts[ns_s_max]; + const u_char *_sections[ns_s_max]; + ns_sect _sect; + int _rrnum; + const u_char *_ptr; +} ns_msg; + +/* Private data structure - do not use from outside library. */ +struct _ns_flagdata { int mask, shift; }; +extern struct _ns_flagdata _ns_flagdata[]; + +/* Accessor macros - this is part of the public interface. */ + +#define ns_msg_id(handle) ((handle)._id + 0) +#define ns_msg_base(handle) ((handle)._msg + 0) +#define ns_msg_end(handle) ((handle)._eom + 0) +#define ns_msg_size(handle) ((handle)._eom - (handle)._msg) +#define ns_msg_count(handle, section) ((handle)._counts[section] + 0) + +/* + * This is a parsed record. It is caller allocated and has no dynamic data. + */ +typedef struct __ns_rr { + char name[NS_MAXDNAME]; + u_int16_t type; + u_int16_t rr_class; + u_int32_t ttl; + u_int16_t rdlength; + const u_char * rdata; +} ns_rr; + +/* Accessor macros - this is part of the public interface. */ +#define ns_rr_name(rr) (((rr).name[0] != '\0') ? (rr).name : ".") +#define ns_rr_type(rr) ((ns_type)((rr).type + 0)) +#define ns_rr_class(rr) ((ns_class)((rr).rr_class + 0)) +#define ns_rr_ttl(rr) ((rr).ttl + 0) +#define ns_rr_rdlen(rr) ((rr).rdlength + 0) +#define ns_rr_rdata(rr) ((rr).rdata + 0) + +/* + * These don't have to be in the same order as in the packet flags word, + * and they can even overlap in some cases, but they will need to be kept + * in synch with ns_parse.c:ns_flagdata[]. + */ +typedef enum __ns_flag { + ns_f_qr, /* Question/Response. */ + ns_f_opcode, /* Operation code. */ + ns_f_aa, /* Authoritative Answer. */ + ns_f_tc, /* Truncation occurred. */ + ns_f_rd, /* Recursion Desired. */ + ns_f_ra, /* Recursion Available. */ + ns_f_z, /* MBZ. */ + ns_f_ad, /* Authentic Data (DNSSEC). */ + ns_f_cd, /* Checking Disabled (DNSSEC). */ + ns_f_rcode, /* Response code. */ + ns_f_max +} ns_flag; + +/* + * Currently defined opcodes. + */ +typedef enum __ns_opcode { + ns_o_query = 0, /* Standard query. */ + ns_o_iquery = 1, /* Inverse query (deprecated/unsupported). */ + ns_o_status = 2, /* Name server status query (unsupported). */ + /* Opcode 3 is undefined/reserved. */ + ns_o_notify = 4, /* Zone change notification. */ + ns_o_update = 5, /* Zone update message. */ + ns_o_max = 6 +} ns_opcode; + +/* + * Currently defined response codes. + */ +typedef enum __ns_rcode { + ns_r_noerror = 0, /* No error occurred. */ + ns_r_formerr = 1, /* Format error. */ + ns_r_servfail = 2, /* Server failure. */ + ns_r_nxdomain = 3, /* Name error. */ + ns_r_notimpl = 4, /* Unimplemented. */ + ns_r_refused = 5, /* Operation refused. */ + /* these are for BIND_UPDATE */ + ns_r_yxdomain = 6, /* Name exists */ + ns_r_yxrrset = 7, /* RRset exists */ + ns_r_nxrrset = 8, /* RRset does not exist */ + ns_r_notauth = 9, /* Not authoritative for zone */ + ns_r_notzone = 10, /* Zone of record different from zone section */ + ns_r_max = 11, + /* The following are TSIG extended errors */ + ns_r_badsig = 16, + ns_r_badkey = 17, + ns_r_badtime = 18 +} ns_rcode; + +/* BIND_UPDATE */ +typedef enum __ns_update_operation { + ns_uop_delete = 0, + ns_uop_add = 1, + ns_uop_max = 2 +} ns_update_operation; + +/* + * This structure is used for TSIG authenticated messages + */ +struct ns_tsig_key { + char name[NS_MAXDNAME], alg[NS_MAXDNAME]; + unsigned char *data; + int len; +}; +typedef struct ns_tsig_key ns_tsig_key; + +/* + * This structure is used for TSIG authenticated TCP messages + */ +struct ns_tcp_tsig_state { + int counter; + struct dst_key *key; + void *ctx; + unsigned char sig[NS_PACKETSZ]; + int siglen; +}; +typedef struct ns_tcp_tsig_state ns_tcp_tsig_state; + +#define NS_TSIG_FUDGE 300 +#define NS_TSIG_TCP_COUNT 100 +#define NS_TSIG_ALG_HMAC_MD5 "HMAC-MD5.SIG-ALG.REG.INT" + +#define NS_TSIG_ERROR_NO_TSIG -10 +#define NS_TSIG_ERROR_NO_SPACE -11 +#define NS_TSIG_ERROR_FORMERR -12 + +/* + * Currently defined type values for resources and queries. + */ +typedef enum __ns_type { + ns_t_invalid = 0, /* Cookie. */ + ns_t_a = 1, /* Host address. */ + ns_t_ns = 2, /* Authoritative server. */ + ns_t_md = 3, /* Mail destination. */ + ns_t_mf = 4, /* Mail forwarder. */ + ns_t_cname = 5, /* Canonical name. */ + ns_t_soa = 6, /* Start of authority zone. */ + ns_t_mb = 7, /* Mailbox domain name. */ + ns_t_mg = 8, /* Mail group member. */ + ns_t_mr = 9, /* Mail rename name. */ + ns_t_null = 10, /* Null resource record. */ + ns_t_wks = 11, /* Well known service. */ + ns_t_ptr = 12, /* Domain name pointer. */ + ns_t_hinfo = 13, /* Host information. */ + ns_t_minfo = 14, /* Mailbox information. */ + ns_t_mx = 15, /* Mail routing information. */ + ns_t_txt = 16, /* Text strings. */ + ns_t_rp = 17, /* Responsible person. */ + ns_t_afsdb = 18, /* AFS cell database. */ + ns_t_x25 = 19, /* X_25 calling address. */ + ns_t_isdn = 20, /* ISDN calling address. */ + ns_t_rt = 21, /* Router. */ + ns_t_nsap = 22, /* NSAP address. */ + ns_t_nsap_ptr = 23, /* Reverse NSAP lookup (deprecated). */ + ns_t_sig = 24, /* Security signature. */ + ns_t_key = 25, /* Security key. */ + ns_t_px = 26, /* X.400 mail mapping. */ + ns_t_gpos = 27, /* Geographical position (withdrawn). */ + ns_t_aaaa = 28, /* Ip6 Address. */ + ns_t_loc = 29, /* Location Information. */ + ns_t_nxt = 30, /* Next domain (security). */ + ns_t_eid = 31, /* Endpoint identifier. */ + ns_t_nimloc = 32, /* Nimrod Locator. */ + ns_t_srv = 33, /* Server Selection. */ + ns_t_atma = 34, /* ATM Address */ + ns_t_naptr = 35, /* Naming Authority PoinTeR */ + ns_t_kx = 36, /* Key Exchange */ + ns_t_cert = 37, /* Certification record */ + ns_t_a6 = 38, /* IPv6 address (deprecates AAAA) */ + ns_t_dname = 39, /* Non-terminal DNAME (for IPv6) */ + ns_t_sink = 40, /* Kitchen sink (experimentatl) */ + ns_t_opt = 41, /* EDNS0 option (meta-RR) */ + ns_t_tkey = 249, /* Transaction key */ + ns_t_tsig = 250, /* Transaction signature. */ + ns_t_ixfr = 251, /* Incremental zone transfer. */ + ns_t_axfr = 252, /* Transfer zone of authority. */ + ns_t_mailb = 253, /* Transfer mailbox records. */ + ns_t_maila = 254, /* Transfer mail agent records. */ + ns_t_any = 255, /* Wildcard match. */ + ns_t_zxfr = 256, /* BIND-specific, nonstandard. */ + ns_t_max = 65536 +} ns_type; + +/* Exclusively a QTYPE? (not also an RTYPE) */ +#define ns_t_qt_p(t) (ns_t_xfr_p(t) || (t) == ns_t_any || \ + (t) == ns_t_mailb || (t) == ns_t_maila) +/* Some kind of meta-RR? (not a QTYPE, but also not an RTYPE) */ +#define ns_t_mrr_p(t) ((t) == ns_t_tsig || (t) == ns_t_opt) +/* Exclusively an RTYPE? (not also a QTYPE or a meta-RR) */ +#define ns_t_rr_p(t) (!ns_t_qt_p(t) && !ns_t_mrr_p(t)) +#define ns_t_udp_p(t) ((t) != ns_t_axfr && (t) != ns_t_zxfr) +#define ns_t_xfr_p(t) ((t) == ns_t_axfr || (t) == ns_t_ixfr || \ + (t) == ns_t_zxfr) + +/* + * Values for class field + */ +typedef enum __ns_class { + ns_c_invalid = 0, /* Cookie. */ + ns_c_in = 1, /* Internet. */ + ns_c_2 = 2, /* unallocated/unsupported. */ + ns_c_chaos = 3, /* MIT Chaos-net. */ + ns_c_hs = 4, /* MIT Hesiod. */ + /* Query class values which do not appear in resource records */ + ns_c_none = 254, /* for prereq. sections in update requests */ + ns_c_any = 255, /* Wildcard match. */ + ns_c_max = 65536 +} ns_class; + +/* DNSSEC constants. */ + +typedef enum __ns_key_types { + ns_kt_rsa = 1, /* key type RSA/MD5 */ + ns_kt_dh = 2, /* Diffie Hellman */ + ns_kt_dsa = 3, /* Digital Signature Standard (MANDATORY) */ + ns_kt_private = 254 /* Private key type starts with OID */ +} ns_key_types; + +typedef enum __ns_cert_types { + cert_t_pkix = 1, /* PKIX (X.509v3) */ + cert_t_spki = 2, /* SPKI */ + cert_t_pgp = 3, /* PGP */ + cert_t_url = 253, /* URL private type */ + cert_t_oid = 254 /* OID private type */ +} ns_cert_types; + +/* Flags field of the KEY RR rdata. */ +#define NS_KEY_TYPEMASK 0xC000 /* Mask for "type" bits */ +#define NS_KEY_TYPE_AUTH_CONF 0x0000 /* Key usable for both */ +#define NS_KEY_TYPE_CONF_ONLY 0x8000 /* Key usable for confidentiality */ +#define NS_KEY_TYPE_AUTH_ONLY 0x4000 /* Key usable for authentication */ +#define NS_KEY_TYPE_NO_KEY 0xC000 /* No key usable for either; no key */ +/* The type bits can also be interpreted independently, as single bits: */ +#define NS_KEY_NO_AUTH 0x8000 /* Key unusable for authentication */ +#define NS_KEY_NO_CONF 0x4000 /* Key unusable for confidentiality */ +#define NS_KEY_RESERVED2 0x2000 /* Security is *mandatory* if bit=0 */ +#define NS_KEY_EXTENDED_FLAGS 0x1000 /* reserved - must be zero */ +#define NS_KEY_RESERVED4 0x0800 /* reserved - must be zero */ +#define NS_KEY_RESERVED5 0x0400 /* reserved - must be zero */ +#define NS_KEY_NAME_TYPE 0x0300 /* these bits determine the type */ +#define NS_KEY_NAME_USER 0x0000 /* key is assoc. with user */ +#define NS_KEY_NAME_ENTITY 0x0200 /* key is assoc. with entity eg host */ +#define NS_KEY_NAME_ZONE 0x0100 /* key is zone key */ +#define NS_KEY_NAME_RESERVED 0x0300 /* reserved meaning */ +#define NS_KEY_RESERVED8 0x0080 /* reserved - must be zero */ +#define NS_KEY_RESERVED9 0x0040 /* reserved - must be zero */ +#define NS_KEY_RESERVED10 0x0020 /* reserved - must be zero */ +#define NS_KEY_RESERVED11 0x0010 /* reserved - must be zero */ +#define NS_KEY_SIGNATORYMASK 0x000F /* key can sign RR's of same name */ +#define NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED2 | \ + NS_KEY_RESERVED4 | \ + NS_KEY_RESERVED5 | \ + NS_KEY_RESERVED8 | \ + NS_KEY_RESERVED9 | \ + NS_KEY_RESERVED10 | \ + NS_KEY_RESERVED11 ) +#define NS_KEY_RESERVED_BITMASK2 0xFFFF /* no bits defined here */ + +/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */ +#define NS_ALG_MD5RSA 1 /* MD5 with RSA */ +#define NS_ALG_DH 2 /* Diffie Hellman KEY */ +#define NS_ALG_DSA 3 /* DSA KEY */ +#define NS_ALG_DSS NS_ALG_DSA +#define NS_ALG_EXPIRE_ONLY 253 /* No alg, no security */ +#define NS_ALG_PRIVATE_OID 254 /* Key begins with OID giving alg */ + +/* Protocol values */ +/* value 0 is reserved */ +#define NS_KEY_PROT_TLS 1 +#define NS_KEY_PROT_EMAIL 2 +#define NS_KEY_PROT_DNSSEC 3 +#define NS_KEY_PROT_IPSEC 4 +#define NS_KEY_PROT_ANY 255 + +/* Signatures */ +#define NS_MD5RSA_MIN_BITS 512 /* Size of a mod or exp in bits */ +#define NS_MD5RSA_MAX_BITS 2552 + /* Total of binary mod and exp */ +#define NS_MD5RSA_MAX_BYTES ((NS_MD5RSA_MAX_BITS+7/8)*2+3) + /* Max length of text sig block */ +#define NS_MD5RSA_MAX_BASE64 (((NS_MD5RSA_MAX_BYTES+2)/3)*4) +#define NS_MD5RSA_MIN_SIZE ((NS_MD5RSA_MIN_BITS+7)/8) +#define NS_MD5RSA_MAX_SIZE ((NS_MD5RSA_MAX_BITS+7)/8) + +#define NS_DSA_SIG_SIZE 41 +#define NS_DSA_MIN_SIZE 213 +#define NS_DSA_MAX_BYTES 405 + +/* Offsets into SIG record rdata to find various values */ +#define NS_SIG_TYPE 0 /* Type flags */ +#define NS_SIG_ALG 2 /* Algorithm */ +#define NS_SIG_LABELS 3 /* How many labels in name */ +#define NS_SIG_OTTL 4 /* Original TTL */ +#define NS_SIG_EXPIR 8 /* Expiration time */ +#define NS_SIG_SIGNED 12 /* Signature time */ +#define NS_SIG_FOOT 16 /* Key footprint */ +#define NS_SIG_SIGNER 18 /* Domain name of who signed it */ + +/* How RR types are represented as bit-flags in NXT records */ +#define NS_NXT_BITS 8 +#define NS_NXT_BIT_SET( n,p) (p[(n)/NS_NXT_BITS] |= (0x80>>((n)%NS_NXT_BITS))) +#define NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS))) +#define NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] & (0x80>>((n)%NS_NXT_BITS))) +#define NS_NXT_MAX 127 + +/* + * Inline versions of get/put short/long. Pointer is advanced. + */ +#define NS_GET16(s, cp) do { \ + register const u_char *t_cp = (cp); \ + (s) = ((u_int16_t)t_cp[0] << 8) \ + | ((u_int16_t)t_cp[1]) \ + ; \ + (cp) += NS_INT16SZ; \ +} while (0) + +#define NS_GET32(l, cp) do { \ + register const u_char *t_cp = (cp); \ + (l) = ((u_int32_t)t_cp[0] << 24) \ + | ((u_int32_t)t_cp[1] << 16) \ + | ((u_int32_t)t_cp[2] << 8) \ + | ((u_int32_t)t_cp[3]) \ + ; \ + (cp) += NS_INT32SZ; \ +} while (0) + +#define NS_PUT16(s, cp) do { \ + register u_int16_t t_s = (u_int16_t)(s); \ + register u_char *t_cp = (u_char *)(cp); \ + *t_cp++ = t_s >> 8; \ + *t_cp = t_s; \ + (cp) += NS_INT16SZ; \ +} while (0) + +#define NS_PUT32(l, cp) do { \ + register u_int32_t t_l = (u_int32_t)(l); \ + register u_char *t_cp = (u_char *)(cp); \ + *t_cp++ = t_l >> 24; \ + *t_cp++ = t_l >> 16; \ + *t_cp++ = t_l >> 8; \ + *t_cp = t_l; \ + (cp) += NS_INT32SZ; \ +} while (0) + +/* + * ANSI C identifier hiding for bind's lib/nameser. + */ +#define ns_msg_getflag __ns_msg_getflag +#define ns_get16 __ns_get16 +#define ns_get32 __ns_get32 +#define ns_put16 __ns_put16 +#define ns_put32 __ns_put32 +#define ns_initparse __ns_initparse +#define ns_skiprr __ns_skiprr +#define ns_parserr __ns_parserr +#define ns_sprintrr __ns_sprintrr +#define ns_sprintrrf __ns_sprintrrf +#define ns_format_ttl __ns_format_ttl +#define ns_parse_ttl __ns_parse_ttl +#define ns_datetosecs __ns_datetosecs +#define ns_name_ntol __ns_name_ntol +#define ns_name_ntop __ns_name_ntop +#define ns_name_pton __ns_name_pton +#define ns_name_unpack __ns_name_unpack +#define ns_name_pack __ns_name_pack +#define ns_name_compress __ns_name_compress +#define ns_name_uncompress __ns_name_uncompress +#define ns_name_skip __ns_name_skip +#define ns_name_rollback __ns_name_rollback +#define ns_sign __ns_sign +#define ns_sign_tcp __ns_sign_tcp +#define ns_sign_tcp_init __ns_sign_tcp_init +#define ns_find_tsig __ns_find_tsig +#define ns_verify __ns_verify +#define ns_verify_tcp __ns_verify_tcp +#define ns_verify_tcp_init __ns_verify_tcp_init +#define ns_samedomain __ns_samedomain +#define ns_subdomain __ns_subdomain +#define ns_makecanon __ns_makecanon +#define ns_samename __ns_samename + +__BEGIN_DECLS +int ns_msg_getflag __P((ns_msg, int)); +u_int ns_get16 __P((const u_char *)); +u_long ns_get32 __P((const u_char *)); +void ns_put16 __P((u_int, u_char *)); +void ns_put32 __P((u_long, u_char *)); +int ns_initparse __P((const u_char *, int, ns_msg *)); +int ns_skiprr __P((const u_char *, const u_char *, ns_sect, int)); +int ns_parserr __P((ns_msg *, ns_sect, int, ns_rr *)); +int ns_sprintrr __P((const ns_msg *, const ns_rr *, + const char *, const char *, char *, size_t)); +int ns_sprintrrf __P((const u_char *, size_t, const char *, + ns_class, ns_type, u_long, const u_char *, + size_t, const char *, const char *, + char *, size_t)); +int ns_format_ttl __P((u_long, char *, size_t)); +int ns_parse_ttl __P((const char *, u_long *)); +u_int32_t ns_datetosecs __P((const char *cp, int *errp)); +int ns_name_ntol __P((const u_char *, u_char *, size_t)); +int ns_name_ntop __P((const u_char *, char *, size_t)); +int ns_name_pton __P((const char *, u_char *, size_t)); +int ns_name_unpack __P((const u_char *, const u_char *, + const u_char *, u_char *, size_t)); +int ns_name_pack __P((const u_char *, u_char *, int, + const u_char **, const u_char **)); +int ns_name_uncompress __P((const u_char *, const u_char *, + const u_char *, char *, size_t)); +int ns_name_compress __P((const char *, u_char *, size_t, + const u_char **, const u_char **)); +int ns_name_skip __P((const u_char **, const u_char *)); +void ns_name_rollback __P((const u_char *, const u_char **, + const u_char **)); +int ns_sign __P((u_char *, int *, int, int, void *, + const u_char *, int, u_char *, int *, time_t)); +int ns_sign_tcp __P((u_char *, int *, int, int, + ns_tcp_tsig_state *, int)); +int ns_sign_tcp_init __P((void *, const u_char *, int, + ns_tcp_tsig_state *)); +u_char *ns_find_tsig __P((u_char *, u_char *)); +int ns_verify __P((u_char *, int *, void *, + const u_char *, int, u_char *, int *, + time_t *, int)); +int ns_verify_tcp __P((u_char *, int *, ns_tcp_tsig_state *, int)); +int ns_verify_tcp_init __P((void *, const u_char *, int, + ns_tcp_tsig_state *)); +int ns_samedomain __P((const char *, const char *)); +int ns_subdomain __P((const char *, const char *)); +int ns_makecanon __P((const char *, char *, size_t)); +int ns_samename __P((const char *, const char *)); +__END_DECLS + +#ifdef BIND_4_COMPAT +#include +#endif + +#endif /* !_ARPA_NAMESER_H_ */ diff --git a/lib/bind/include/arpa/nameser_compat.h b/lib/bind/include/arpa/nameser_compat.h new file mode 100644 index 0000000000..335d75b4f7 --- /dev/null +++ b/lib/bind/include/arpa/nameser_compat.h @@ -0,0 +1,230 @@ +/* Copyright (c) 1983, 1989 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * from nameser.h 8.1 (Berkeley) 6/2/93 + * $Id: nameser_compat.h,v 1.1 2001/03/29 06:31:35 marka Exp $ + */ + +#ifndef _ARPA_NAMESER_COMPAT_ +#define _ARPA_NAMESER_COMPAT_ + +#define __BIND 19950621 /* (DEAD) interface version stamp. */ + +#ifndef BYTE_ORDER +#if (BSD >= 199103) +# include +#else +#ifdef linux +# include +#else +#define LITTLE_ENDIAN 1234 /* least-significant byte first (vax, pc) */ +#define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ +#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp)*/ + +#if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \ + defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \ + defined(__alpha__) || defined(__alpha) || \ + (defined(__Lynx__) && defined(__x86__)) +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \ + defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \ + defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\ + defined(apollo) || defined(__convex__) || defined(_CRAY) || \ + defined(__hppa) || defined(__hp9000) || \ + defined(__hp9000s300) || defined(__hp9000s700) || \ + defined (BIT_ZERO_ON_LEFT) || defined(m68k) || \ + (defined(__Lynx__) && \ + (defined(__68k__) || defined(__sparc__) || defined(__powerpc__))) +#define BYTE_ORDER BIG_ENDIAN +#endif +#endif /* linux */ +#endif /* BSD */ +#endif /* BYTE_ORDER */ + +#if !defined(BYTE_ORDER) || \ + (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN && \ + BYTE_ORDER != PDP_ENDIAN) + /* you must determine what the correct bit order is for + * your compiler - the next line is an intentional error + * which will force your compiles to bomb until you fix + * the above macros. + */ + error "Undefined or invalid BYTE_ORDER"; +#endif + +/* + * Structure for query header. The order of the fields is machine- and + * compiler-dependent, depending on the byte/bit order and the layout + * of bit fields. We use bit fields only in int variables, as this + * is all ANSI requires. This requires a somewhat confusing rearrangement. + */ + +typedef struct { + unsigned id :16; /* query identification number */ +#if BYTE_ORDER == BIG_ENDIAN + /* fields in third byte */ + unsigned qr: 1; /* response flag */ + unsigned opcode: 4; /* purpose of message */ + unsigned aa: 1; /* authoritive answer */ + unsigned tc: 1; /* truncated message */ + unsigned rd: 1; /* recursion desired */ + /* fields in fourth byte */ + unsigned ra: 1; /* recursion available */ + unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned ad: 1; /* authentic data from named */ + unsigned cd: 1; /* checking disabled by resolver */ + unsigned rcode :4; /* response code */ +#endif +#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN + /* fields in third byte */ + unsigned rd :1; /* recursion desired */ + unsigned tc :1; /* truncated message */ + unsigned aa :1; /* authoritive answer */ + unsigned opcode :4; /* purpose of message */ + unsigned qr :1; /* response flag */ + /* fields in fourth byte */ + unsigned rcode :4; /* response code */ + unsigned cd: 1; /* checking disabled by resolver */ + unsigned ad: 1; /* authentic data from named */ + unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned ra :1; /* recursion available */ +#endif + /* remaining bytes */ + unsigned qdcount :16; /* number of question entries */ + unsigned ancount :16; /* number of answer entries */ + unsigned nscount :16; /* number of authority entries */ + unsigned arcount :16; /* number of resource entries */ +} HEADER; + +#define PACKETSZ NS_PACKETSZ +#define MAXDNAME NS_MAXDNAME +#define MAXCDNAME NS_MAXCDNAME +#define MAXLABEL NS_MAXLABEL +#define HFIXEDSZ NS_HFIXEDSZ +#define QFIXEDSZ NS_QFIXEDSZ +#define RRFIXEDSZ NS_RRFIXEDSZ +#define INT32SZ NS_INT32SZ +#define INT16SZ NS_INT16SZ +#define INADDRSZ NS_INADDRSZ +#define IN6ADDRSZ NS_IN6ADDRSZ +#define INDIR_MASK NS_CMPRSFLGS +#define NAMESERVER_PORT NS_DEFAULTPORT + +#define S_ZONE ns_s_zn +#define S_PREREQ ns_s_pr +#define S_UPDATE ns_s_ud +#define S_ADDT ns_s_ar + +#define QUERY ns_o_query +#define IQUERY ns_o_iquery +#define STATUS ns_o_status +#define NS_NOTIFY_OP ns_o_notify +#define NS_UPDATE_OP ns_o_update + +#define NOERROR ns_r_noerror +#define FORMERR ns_r_formerr +#define SERVFAIL ns_r_servfail +#define NXDOMAIN ns_r_nxdomain +#define NOTIMP ns_r_notimpl +#define REFUSED ns_r_refused +#define YXDOMAIN ns_r_yxdomain +#define YXRRSET ns_r_yxrrset +#define NXRRSET ns_r_nxrrset +#define NOTAUTH ns_r_notauth +#define NOTZONE ns_r_notzone +/*#define BADSIG ns_r_badsig*/ +/*#define BADKEY ns_r_badkey*/ +/*#define BADTIME ns_r_badtime*/ + + +#define DELETE ns_uop_delete +#define ADD ns_uop_add + +#define T_A ns_t_a +#define T_NS ns_t_ns +#define T_MD ns_t_md +#define T_MF ns_t_mf +#define T_CNAME ns_t_cname +#define T_SOA ns_t_soa +#define T_MB ns_t_mb +#define T_MG ns_t_mg +#define T_MR ns_t_mr +#define T_NULL ns_t_null +#define T_WKS ns_t_wks +#define T_PTR ns_t_ptr +#define T_HINFO ns_t_hinfo +#define T_MINFO ns_t_minfo +#define T_MX ns_t_mx +#define T_TXT ns_t_txt +#define T_RP ns_t_rp +#define T_AFSDB ns_t_afsdb +#define T_X25 ns_t_x25 +#define T_ISDN ns_t_isdn +#define T_RT ns_t_rt +#define T_NSAP ns_t_nsap +#define T_NSAP_PTR ns_t_nsap_ptr +#define T_SIG ns_t_sig +#define T_KEY ns_t_key +#define T_PX ns_t_px +#define T_GPOS ns_t_gpos +#define T_AAAA ns_t_aaaa +#define T_LOC ns_t_loc +#define T_NXT ns_t_nxt +#define T_EID ns_t_eid +#define T_NIMLOC ns_t_nimloc +#define T_SRV ns_t_srv +#define T_ATMA ns_t_atma +#define T_NAPTR ns_t_naptr +#define T_A6 ns_t_a6 +#define T_TSIG ns_t_tsig +#define T_IXFR ns_t_ixfr +#define T_AXFR ns_t_axfr +#define T_MAILB ns_t_mailb +#define T_MAILA ns_t_maila +#define T_ANY ns_t_any + +#define C_IN ns_c_in +#define C_CHAOS ns_c_chaos +#define C_HS ns_c_hs +/* BIND_UPDATE */ +#define C_NONE ns_c_none +#define C_ANY ns_c_any + +#define GETSHORT NS_GET16 +#define GETLONG NS_GET32 +#define PUTSHORT NS_PUT16 +#define PUTLONG NS_PUT32 + +#endif /* _ARPA_NAMESER_COMPAT_ */ diff --git a/lib/bind/include/fd_setsize.h b/lib/bind/include/fd_setsize.h new file mode 100644 index 0000000000..235b1ad1c2 --- /dev/null +++ b/lib/bind/include/fd_setsize.h @@ -0,0 +1,9 @@ +#ifndef _FD_SETSIZE_H +#define _FD_SETSIZE_H + +/* + * If you need a bigger FD_SETSIZE, this is NOT the place to set it. + * This file is a fallback for BIND ports which don't specify their own. + */ + +#endif /* _FD_SETSIZE_H */ diff --git a/lib/bind/include/hesiod.h b/lib/bind/include/hesiod.h new file mode 100644 index 0000000000..b49f5e3de6 --- /dev/null +++ b/lib/bind/include/hesiod.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * This file is primarily maintained by and . + */ + +/* + * $Id: hesiod.h,v 1.1 2001/03/29 06:31:33 marka Exp $ + */ + +#ifndef _HESIOD_H_INCLUDED +#define _HESIOD_H_INCLUDED + +int hesiod_init __P((void **context)); +void hesiod_end __P((void *context)); +char * hesiod_to_bind __P((void *context, const char *name, + const char *type)); +char ** hesiod_resolve __P((void *context, const char *name, + const char *type)); +void hesiod_free_list __P((void *context, char **list)); +struct __res_state * __hesiod_res_get __P((void *context)); +void __hesiod_res_set __P((void *context, struct __res_state *, + void (*)(void *))); + +#endif /*_HESIOD_H_INCLUDED*/ diff --git a/lib/bind/include/irp.h b/lib/bind/include/irp.h new file mode 100644 index 0000000000..e56cfbc688 --- /dev/null +++ b/lib/bind/include/irp.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: irp.h,v 1.1 2001/03/29 06:31:34 marka Exp $ + */ + +#ifndef _IRP_H_INCLUDED +#define _IRP_H_INCLUDED + +#define IRPD_TIMEOUT 30 /* seconds */ +#define IRPD_MAXSESS 50 /* number of simultaneous sessions. */ +#define IRPD_PORT 6660 /* 10 times the number of the beast. */ +#define IRPD_PATH "/var/run/irpd" /* af_unix socket path */ + +/* If sets the environment variable IRPDSERVER to an IP address + (e.g. "192.5.5.1"), then that's the host the client expects irpd to be + running on. */ +#define IRPD_HOST_ENV "IRPDSERVER" + +/* Protocol response codes. */ +#define IRPD_WELCOME_CODE 200 +#define IRPD_NOT_WELCOME_CODE 500 + +#define IRPD_GETHOST_ERROR 510 +#define IRPD_GETHOST_NONE 210 +#define IRPD_GETHOST_OK 211 +#define IRPD_GETHOST_SETOK 212 + +#define IRPD_GETNET_ERROR 520 +#define IRPD_GETNET_NONE 220 +#define IRPD_GETNET_OK 221 +#define IRPD_GETNET_SETOK 222 + +#define IRPD_GETUSER_ERROR 530 +#define IRPD_GETUSER_NONE 230 +#define IRPD_GETUSER_OK 231 +#define IRPD_GETUSER_SETOK 232 + +#define IRPD_GETGROUP_ERROR 540 +#define IRPD_GETGROUP_NONE 240 +#define IRPD_GETGROUP_OK 241 +#define IRPD_GETGROUP_SETOK 242 + +#define IRPD_GETSERVICE_ERROR 550 +#define IRPD_GETSERVICE_NONE 250 +#define IRPD_GETSERVICE_OK 251 +#define IRPD_GETSERVICE_SETOK 252 + +#define IRPD_GETPROTO_ERROR 560 +#define IRPD_GETPROTO_NONE 260 +#define IRPD_GETPROTO_OK 261 +#define IRPD_GETPROTO_SETOK 262 + +#define IRPD_GETNETGR_ERROR 570 +#define IRPD_GETNETGR_NONE 270 +#define IRPD_GETNETGR_OK 271 +#define IRPD_GETNETGR_NOMORE 272 +#define IRPD_GETNETGR_MATCHES 273 +#define IRPD_GETNETGR_NOMATCH 274 +#define IRPD_GETNETGR_SETOK 275 +#define IRPD_GETNETGR_SETERR 276 + +#define irs_irp_read_body __irs_irp_read_body +#define irs_irp_read_response __irs_irp_read_response +#define irs_irp_disconnect __irs_irp_disconnect +#define irs_irp_connect __irs_irp_connect +#define irs_irp_connection_setup __irs_irp_connection_setup +#define irs_irp_send_command __irs_irp_send_command + +struct irp_p; + +char *irs_irp_read_body(struct irp_p *pvt, size_t *size); +int irs_irp_read_response(struct irp_p *pvt, char *text, size_t len); +void irs_irp_disconnect(struct irp_p *pvt); +int irs_irp_connect(struct irp_p *pvt); +int irs_irp_is_connected(struct irp_p *pvt); +int irs_irp_connection_setup(struct irp_p *cxndata, int *warned); +int irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...); +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_read_line(struct irp_p *pvt, char *buffer, int len); + +#endif diff --git a/lib/bind/include/irs.h b/lib/bind/include/irs.h new file mode 100644 index 0000000000..8680469d8f --- /dev/null +++ b/lib/bind/include/irs.h @@ -0,0 +1,330 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: irs.h,v 1.1 2001/03/29 06:31:34 marka Exp $ + */ + +#ifndef _IRS_H_INCLUDED +#define _IRS_H_INCLUDED + +#include + +#include + +#include +#include +#include +#include +#include + +/* + * This is the group map class. + */ +struct irs_gr { + void * private; + void (*close) __P((struct irs_gr *)); + struct group * (*next) __P((struct irs_gr *)); + struct group * (*byname) __P((struct irs_gr *, const char *)); + struct group * (*bygid) __P((struct irs_gr *, gid_t)); + int (*list) __P((struct irs_gr *, const char *, + gid_t, gid_t *, int *)); + void (*rewind) __P((struct irs_gr *)); + void (*minimize) __P((struct irs_gr *)); + struct __res_state * (*res_get) __P((struct irs_gr *)); + void (*res_set) __P((struct irs_gr *, res_state, + void (*)(void *))); +}; + +/* + * This is the password map class. + */ +struct irs_pw { + void * private; + void (*close) __P((struct irs_pw *)); + struct passwd * (*next) __P((struct irs_pw *)); + struct passwd * (*byname) __P((struct irs_pw *, const char *)); + struct passwd * (*byuid) __P((struct irs_pw *, uid_t)); + void (*rewind) __P((struct irs_pw *)); + void (*minimize) __P((struct irs_pw *)); + struct __res_state * (*res_get) __P((struct irs_pw *)); + void (*res_set) __P((struct irs_pw *, res_state, + void (*)(void *))); +}; + +/* + * This is the service map class. + */ +struct irs_sv { + void * private; + void (*close) __P((struct irs_sv *)); + struct servent *(*byname) __P((struct irs_sv *, + const char *, const char *)); + struct servent *(*byport) __P((struct irs_sv *, int, const char *)); + struct servent *(*next) __P((struct irs_sv *)); + void (*rewind) __P((struct irs_sv *)); + void (*minimize) __P((struct irs_sv *)); + struct __res_state * (*res_get) __P((struct irs_sv *)); + void (*res_set) __P((struct irs_sv *, res_state, + void (*)(void *))); +}; + +/* + * This is the protocols map class. + */ +struct irs_pr { + void * private; + void (*close) __P((struct irs_pr *)); + struct protoent *(*byname) __P((struct irs_pr *, const char *)); + struct protoent *(*bynumber) __P((struct irs_pr *, int)); + struct protoent *(*next) __P((struct irs_pr *)); + void (*rewind) __P((struct irs_pr *)); + void (*minimize) __P((struct irs_pr *)); + struct __res_state * (*res_get) __P((struct irs_pr *)); + void (*res_set) __P((struct irs_pr *, res_state, + void (*)(void *))); +}; + +/* + * This is the hosts map class. + */ +struct irs_ho { + void * private; + void (*close) __P((struct irs_ho *)); + struct hostent *(*byname) __P((struct irs_ho *, const char *)); + struct hostent *(*byname2) __P((struct irs_ho *, const char *, int)); + struct hostent *(*byaddr) __P((struct irs_ho *, + const void *, int, int)); + struct hostent *(*next) __P((struct irs_ho *)); + void (*rewind) __P((struct irs_ho *)); + void (*minimize) __P((struct irs_ho *)); + struct __res_state * (*res_get) __P((struct irs_ho *)); + void (*res_set) __P((struct irs_ho *, res_state, + void (*)(void *))); + struct addrinfo *(*addrinfo) __P((struct irs_ho *, const char *, + const struct addrinfo *)); +}; + +/* + * This is the networks map class. + */ +struct irs_nw { + void * private; + void (*close) __P((struct irs_nw *)); + struct nwent * (*byname) __P((struct irs_nw *, const char *, int)); + struct nwent * (*byaddr) __P((struct irs_nw *, void *, int, int)); + struct nwent * (*next) __P((struct irs_nw *)); + void (*rewind) __P((struct irs_nw *)); + void (*minimize) __P((struct irs_nw *)); + struct __res_state * (*res_get) __P((struct irs_nw *)); + void (*res_set) __P((struct irs_nw *, res_state, + void (*)(void *))); +}; + +/* + * This is the netgroups map class. + */ +struct irs_ng { + void * private; + void (*close) __P((struct irs_ng *)); + int (*next) __P((struct irs_ng *, const char **, + const char **, const char **)); + int (*test) __P((struct irs_ng *, const char *, + const char *, const char *, + const char *)); + void (*rewind) __P((struct irs_ng *, const char *)); + void (*minimize) __P((struct irs_ng *)); +}; + +/* + * This is the generic map class, which copies the front of all others. + */ +struct irs_map { + void * private; + void (*close) __P((void *)); +}; + +/* + * This is the accessor class. It contains pointers to all of the + * initializers for the map classes for a particular accessor. + */ +struct irs_acc { + void * private; + void (*close) __P((struct irs_acc *)); + struct irs_gr * (*gr_map) __P((struct irs_acc *)); + struct irs_pw * (*pw_map) __P((struct irs_acc *)); + struct irs_sv * (*sv_map) __P((struct irs_acc *)); + struct irs_pr * (*pr_map) __P((struct irs_acc *)); + struct irs_ho * (*ho_map) __P((struct irs_acc *)); + struct irs_nw * (*nw_map) __P((struct irs_acc *)); + struct irs_ng * (*ng_map) __P((struct irs_acc *)); + struct __res_state * (*res_get) __P((struct irs_acc *)); + void (*res_set) __P((struct irs_acc *, res_state, + void (*)(void *))); +}; + +/* + * This is because the official definition of "struct netent" has no + * concept of CIDR even though it allows variant address families (on + * output but not input). The compatibility stubs convert the structs + * below into "struct netent"'s. + */ +struct nwent { + char *n_name; /* official name of net */ + char **n_aliases; /* alias list */ + int n_addrtype; /* net address type */ + void *n_addr; /* network address */ + int n_length; /* address length, in bits */ +}; + +/* + * Hide external function names from POSIX. + */ +#define irs_gen_acc __irs_gen_acc +#define irs_lcl_acc __irs_lcl_acc +#define irs_dns_acc __irs_dns_acc +#define irs_nis_acc __irs_nis_acc +#define irs_irp_acc __irs_irp_acc + +/* + * Externs. + */ +extern struct irs_acc * irs_gen_acc __P((const char *options, + const char *conf_file)); +extern struct irs_acc * irs_lcl_acc __P((const char *options)); +extern struct irs_acc * irs_dns_acc __P((const char *options)); +extern struct irs_acc * irs_nis_acc __P((const char *options)); +extern struct irs_acc * irs_irp_acc __P((const char *options)); + +extern void irs_destroy(void); + +/* + * These forward declarations are for the semi-private functions in + * the get*.c files. Each of these funcs implements the real get* + * functionality and the standard versions are just wrappers that + * call these. Apart from the wrappers, only irpd is expected to + * call these directly, hence these decls are put here and not in + * the /usr/include replacements. + */ + +struct net_data; /* forward */ + +/* + * net_data_create gets a singleton net_data object. net_data_init + * creates as many net_data objects as times it is called. Clients using + * the default interface will use net_data_create by default. Servers will + * probably want net_data_init (one call per client) + */ +struct net_data *net_data_create(const char *conf_file); +struct net_data *net_data_init(const char *conf_file); +void net_data_destroy(void *p); + +extern struct group *getgrent_p __P((struct net_data *net_data)); +extern struct group *getgrnam_p __P((const char *name, + struct net_data *net_data)); +extern struct group *getgrgid_p __P((gid_t gid, + struct net_data *net_data)); +extern int setgroupent_p __P((int stayopen, + struct net_data *net_data)); +extern void endgrent_p __P((struct net_data *net_data)); +extern int getgrouplist_p __P((const char *name, + gid_t basegid, + gid_t *groups, + int *ngroups, + struct net_data *net_data)); + +#ifdef SETGRENT_VOID +extern void setgrent_p __P((struct net_data *net_data)); +#else +extern int setgrent_p __P((struct net_data *net_data)); +#endif + +extern struct hostent *gethostbyname_p __P((const char *name, + struct net_data *net_data)); +extern struct hostent *gethostbyname2_p __P((const char *name, int af, + struct net_data *net_data)); +extern struct hostent *gethostbyaddr_p __P((const char *addr, int len, + int af, + struct net_data *net_data)); +extern struct hostent *gethostent_p __P((struct net_data *net_data)); +extern void sethostent_p __P((int stayopen, + struct net_data *net_data)); +extern void endhostent_p __P((struct net_data *net_data)); +extern struct hostent *getipnodebyname_p __P((const char *name, int af, + int flags, int *errp, + struct net_data *net_data)); +extern struct hostent *getipnodebyaddr_p __P((const void *addr, size_t len, + int af, int *errp, + struct net_data *net_data)); + +extern struct netent *getnetent_p __P((struct net_data *net_data)); +extern struct netent *getnetbyname_p __P((const char *name, + struct net_data *net_data)); +extern struct netent *getnetbyaddr_p __P((unsigned long net, int type, + struct net_data *net_data)); +extern void setnetent_p __P((int stayopen, + struct net_data *net_data)); +extern void endnetent_p __P((struct net_data *net_data)); + +extern void setnetgrent_p __P((const char *netgroup, + struct net_data *net_data)); +extern void endnetgrent_p __P((struct net_data *net_data)); +extern int innetgr_p __P((const char *netgroup, + const char *host, + const char *user, + const char *domain, + struct net_data *net_data)); +extern int getnetgrent_p __P((const char **host, const char **user, + const char **domain, + struct net_data *net_data)); + +extern struct protoent *getprotoent_p __P((struct net_data *net_data)); +extern struct protoent *getprotobyname_p __P((const char *name, + struct net_data *net_data)); +extern struct protoent *getprotobynumber_p __P((int proto, + struct net_data *net_data)); +extern void setprotoent_p __P((int stayopen, + struct net_data *net_data)); +extern void endprotoent_p __P((struct net_data *net_data)); + + +extern struct passwd *getpwent_p __P((struct net_data *net_data)); +extern struct passwd *getpwnam_p __P((const char *name, + struct net_data *net_data)); +extern struct passwd *getpwuid_p __P((uid_t uid, + struct net_data *net_data)); +extern int setpassent_p __P((int stayopen, + struct net_data *net_data)); +extern void endpwent_p __P((struct net_data *net_data)); + +#ifdef SETPWENT_VOID +extern void setpwent_p __P((struct net_data *net_data)); +#else +extern int setpwent_p __P((struct net_data *net_data)); +#endif + +extern struct servent *getservent_p __P((struct net_data *net_data)); +extern struct servent *getservbyname_p __P((const char *name, + const char *proto, + struct net_data *net_data)); +extern struct servent *getservbyport_p __P((int port, const char *proto, + struct net_data *net_data)); +extern void setservent_p __P((int stayopen, + struct net_data *net_data)); +extern void endservent_p __P((struct net_data *net_data)); + +#endif /*_IRS_H_INCLUDED*/ diff --git a/lib/bind/include/isc/assertions.h b/lib/bind/include/isc/assertions.h new file mode 100644 index 0000000000..bc436a5f14 --- /dev/null +++ b/lib/bind/include/isc/assertions.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 1997-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: assertions.h,v 1.1 2001/03/29 06:31:35 marka Exp $ + */ + +#ifndef ASSERTIONS_H +#define ASSERTIONS_H 1 + +typedef enum { + assert_require, assert_ensure, assert_insist, assert_invariant +} assertion_type; + +typedef void (*assertion_failure_callback)(const char *, int, assertion_type, + const char *, int); + +extern assertion_failure_callback __assertion_failed; +void set_assertion_failure_callback(assertion_failure_callback f); +const char *assertion_type_to_text(assertion_type type); + +#ifdef CHECK_ALL +#define CHECK_REQUIRE 1 +#define CHECK_ENSURE 1 +#define CHECK_INSIST 1 +#define CHECK_INVARIANT 1 +#endif + +#ifdef CHECK_NONE +#define CHECK_REQUIRE 0 +#define CHECK_ENSURE 0 +#define CHECK_INSIST 0 +#define CHECK_INVARIANT 0 +#endif + +#ifndef CHECK_REQUIRE +#define CHECK_REQUIRE 1 +#endif + +#ifndef CHECK_ENSURE +#define CHECK_ENSURE 1 +#endif + +#ifndef CHECK_INSIST +#define CHECK_INSIST 1 +#endif + +#ifndef CHECK_INVARIANT +#define CHECK_INVARIANT 1 +#endif + +#if CHECK_REQUIRE != 0 +#define REQUIRE(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_require, \ + #cond, 0), 0))) +#define REQUIRE_ERR(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_require, \ + #cond, 1), 0))) +#else +#define REQUIRE(cond) ((void) (cond)) +#define REQUIRE_ERR(cond) ((void) (cond)) +#endif /* CHECK_REQUIRE */ + +#if CHECK_ENSURE != 0 +#define ENSURE(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_ensure, \ + #cond, 0), 0))) +#define ENSURE_ERR(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_ensure, \ + #cond, 1), 0))) +#else +#define ENSURE(cond) ((void) (cond)) +#define ENSURE_ERR(cond) ((void) (cond)) +#endif /* CHECK_ENSURE */ + +#if CHECK_INSIST != 0 +#define INSIST(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_insist, \ + #cond, 0), 0))) +#define INSIST_ERR(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_insist, \ + #cond, 1), 0))) +#else +#define INSIST(cond) ((void) (cond)) +#define INSIST_ERR(cond) ((void) (cond)) +#endif /* CHECK_INSIST */ + +#if CHECK_INVARIANT != 0 +#define INVARIANT(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_invariant, \ + #cond, 0), 0))) +#define INVARIANT_ERR(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_invariant, \ + #cond, 1), 0))) +#else +#define INVARIANT(cond) ((void) (cond)) +#define INVARIANT_ERR(cond) ((void) (cond)) +#endif /* CHECK_INVARIANT */ + +#endif /* ASSERTIONS_H */ diff --git a/lib/bind/include/isc/ctl.h b/lib/bind/include/isc/ctl.h new file mode 100644 index 0000000000..4fe786a42d --- /dev/null +++ b/lib/bind/include/isc/ctl.h @@ -0,0 +1,104 @@ +#ifndef ISC_CTL_H +#define ISC_CTL_H + +/* + * Copyright (c) 1998,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: ctl.h,v 1.1 2001/03/29 06:31:35 marka Exp $ + */ + +#include +#include + +#include + +/* Macros. */ + +#define CTL_MORE 0x0001 /* More will be / should be sent. */ +#define CTL_EXIT 0x0002 /* Close connection after this. */ +#define CTL_DATA 0x0004 /* Go into / this is DATA mode. */ + +/* Types. */ + +struct ctl_cctx; +struct ctl_sctx; +struct ctl_sess; +struct ctl_verb; + +enum ctl_severity { ctl_debug, ctl_warning, ctl_error }; + +typedef void (*ctl_logfunc)(enum ctl_severity, const char *fmt, ...); + +typedef void (*ctl_verbfunc)(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, const char *rest, + u_int respflags, const void *respctx, void *uctx); + +typedef void (*ctl_srvrdone)(struct ctl_sctx *, struct ctl_sess *, void *); + +typedef void (*ctl_clntdone)(struct ctl_cctx *, void *, const char *, u_int); + +struct ctl_verb { + const char * name; + ctl_verbfunc func; + const char * help; +}; + +/* General symbols. */ + +#define ctl_logger __ctl_logger + +void ctl_logger(enum ctl_severity, const char *, ...); + +/* Client symbols. */ + +#define ctl_client __ctl_client +#define ctl_endclient __ctl_endclient +#define ctl_command __ctl_command + +struct ctl_cctx * ctl_client(evContext, const struct sockaddr *, size_t, + const struct sockaddr *, size_t, + ctl_clntdone, void *, + u_int, ctl_logfunc); +void ctl_endclient(struct ctl_cctx *); +int ctl_command(struct ctl_cctx *, const char *, size_t, + ctl_clntdone, void *); + +/* Server symbols. */ + +#define ctl_server __ctl_server +#define ctl_endserver __ctl_endserver +#define ctl_response __ctl_response +#define ctl_sendhelp __ctl_sendhelp +#define ctl_getcsctx __ctl_getcsctx +#define ctl_setcsctx __ctl_setcsctx + +struct ctl_sctx * ctl_server(evContext, const struct sockaddr *, size_t, + const struct ctl_verb *, + u_int, u_int, + u_int, int, int, + ctl_logfunc, void *); +void ctl_endserver(struct ctl_sctx *); +void ctl_response(struct ctl_sess *, u_int, + const char *, u_int, const void *, + ctl_srvrdone, void *, + const char *, size_t); +void ctl_sendhelp(struct ctl_sess *, u_int); +void * ctl_getcsctx(struct ctl_sess *); +void * ctl_setcsctx(struct ctl_sess *, void *); + +#endif /*ISC_CTL_H*/ diff --git a/lib/bind/include/isc/dst.h b/lib/bind/include/isc/dst.h new file mode 100644 index 0000000000..9e68a103a7 --- /dev/null +++ b/lib/bind/include/isc/dst.h @@ -0,0 +1,141 @@ +#ifndef DST_H +#define DST_H + +#ifndef HAS_DST_KEY +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 */ +} DST_KEY; +#endif /* HAS_DST_KEY */ + +/* + * DST Crypto API defintions + */ +void dst_init(void); +int dst_check_algorithm(const int); + +int dst_sign_data(const int mode, /* specifies INIT/UPDATE/FINAL/ALL */ + DST_KEY *in_key, /* the key to use */ + void **context, /* pointer to state structure */ + const u_char *data, /* data to be signed */ + const int len, /* length of input data */ + u_char *signature, /* buffer to write signature to */ + const int sig_len); /* size of output buffer */ + +int dst_verify_data(const int mode, /* specifies INIT/UPDATE/FINAL/ALL */ + DST_KEY *in_key, /* the key to use */ + void **context, /* pointer to state structure */ + const u_char *data, /* data to be verified */ + const int len, /* length of input data */ + const u_char *signature,/* buffer containing signature */ + const int sig_len); /* length of signature */ + + +DST_KEY *dst_read_key(const char *in_name, /* name of key */ + const u_int16_t in_id, /* key tag identifier */ + const int in_alg, /* key algorithm */ + const int key_type); /* Private/PublicKey wanted*/ + +int dst_write_key(const DST_KEY *key, /* key to write out */ + const int key_type); /* Public/Private */ + +DST_KEY *dst_dnskey_to_key(const char *in_name, /* KEY record name */ + const u_char *key, /* KEY RDATA */ + const int len); /* size of input buffer*/ + + +int dst_key_to_dnskey(const DST_KEY *key, /* key to translate */ + u_char *out_storage, /* output buffer */ + const int out_len); /* size of out_storage*/ + + +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 */ + + +int dst_key_to_buffer(DST_KEY *key, u_char *out_buff, int buf_len); + +DST_KEY *dst_generate_key(const char *name, /* name of new key */ + const int alg, /* key algorithm to generate */ + const int bits, /* size of new key */ + const int exp, /* alg dependent parameter*/ + const int flags, /* key DNS flags */ + const int protocol); /* key DNS protocol */ + +DST_KEY *dst_free_key(DST_KEY *f_key); +int dst_compare_keys(const DST_KEY *key1, const DST_KEY *key2); + +int dst_sig_size(DST_KEY *key); + +int dst_random(const int mode, int wanted, u_char *outran); + + +/* support for dns key tags/ids */ +u_int16_t dst_s_dns_key_id(const u_char *dns_key_rdata, const int rdata_len); +u_int16_t dst_s_id_calc(const u_char *key_data, const int key_len); + +/* Used by callers as well as by the library. */ +#define RAW_KEY_SIZE 8192 /* large enough to store any key */ + +/* DST_API control flags */ +/* These are used used in functions dst_sign_data and dst_verify_data */ +#define SIG_MODE_INIT 1 /* initalize digest */ +#define SIG_MODE_UPDATE 2 /* add data to digest */ +#define SIG_MODE_FINAL 4 /* generate/verify signature */ +#define SIG_MODE_ALL (SIG_MODE_INIT|SIG_MODE_UPDATE|SIG_MODE_FINAL) + +/* Flags for dst_read_private_key() */ +#define DST_FORCE_READ 0x1000000 +#define DST_CAN_SIGN 0x010F +#define DST_NO_AUTHEN 0x8000 +#define DST_EXTEND_FLAG 0x1000 +#define DST_STANDARD 0 +#define DST_PRIVATE 0x2000000 +#define DST_PUBLIC 0x4000000 +#define DST_RAND_SEMI 1 +#define DST_RAND_STD 2 +#define DST_RAND_KEY 3 +#define DST_RAND_DSS 4 + + +/* DST algorithm codes */ +#define KEY_RSA 1 +#define KEY_DH 2 +#define KEY_DSA 3 +#define KEY_PRIVATE 254 +#define KEY_EXPAND 255 +#define KEY_HMAC_MD5 157 +#define KEY_HMAC_SHA1 158 +#define UNKNOWN_KEYALG 0 +#define DST_MAX_ALGS KEY_HMAC_SHA1 + +/* DST constants to locations in KEY record changes in new KEY record */ +#define DST_FLAGS_SIZE 2 +#define DST_KEY_PROT 2 +#define DST_KEY_ALG 3 +#define DST_EXT_FLAG 4 +#define DST_KEY_START 4 + +#ifndef SIGN_F_NOKEY +#define SIGN_F_NOKEY 0xC000 +#endif + +/* error codes from dst routines */ +#define SIGN_INIT_FAILURE (-23) +#define SIGN_UPDATE_FAILURE (-24) +#define SIGN_FINAL_FAILURE (-25) +#define VERIFY_INIT_FAILURE (-26) +#define VERIFY_UPDATE_FAILURE (-27) +#define VERIFY_FINAL_FAILURE (-28) +#define MISSING_KEY_OR_SIGNATURE (-30) +#define UNSUPPORTED_KEYALG (-31) + +#endif /* DST_H */ diff --git a/lib/bind/include/isc/eventlib.h b/lib/bind/include/isc/eventlib.h new file mode 100644 index 0000000000..4a3dc4b9f8 --- /dev/null +++ b/lib/bind/include/isc/eventlib.h @@ -0,0 +1,196 @@ +/* + * Copyright (c) 1995-1999 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* eventlib.h - exported interfaces for eventlib + * vix 09sep95 [initial] + * + * $Id: eventlib.h,v 1.1 2001/03/29 06:31:36 marka Exp $ + */ + +#ifndef _EVENTLIB_H +#define _EVENTLIB_H + +#include +#include +#include +#include + +#ifndef __P +# define __EVENTLIB_P_DEFINED +# ifdef __STDC__ +# define __P(x) x +# else +# define __P(x) () +# endif +#endif + +/* In the absence of branded types... */ +typedef struct { void *opaque; } evConnID; +typedef struct { void *opaque; } evFileID; +typedef struct { void *opaque; } evStreamID; +typedef struct { void *opaque; } evTimerID; +typedef struct { void *opaque; } evWaitID; +typedef struct { void *opaque; } evContext; +typedef struct { void *opaque; } evEvent; + +#define evInitID(id) ((id)->opaque = NULL) +#define evTestID(id) ((id).opaque != NULL) + +typedef void (*evConnFunc)__P((evContext ctx, void *uap, int fd, + const void *la, int lalen, + const void *ra, int ralen)); +typedef void (*evFileFunc)__P((evContext ctx, void *uap, int fd, int evmask)); +typedef void (*evStreamFunc)__P((evContext ctx, void *uap, int fd, int bytes)); +typedef void (*evTimerFunc)__P((evContext ctx, void *uap, + struct timespec due, struct timespec inter)); +typedef void (*evWaitFunc)__P((evContext ctx, void *uap, const void *tag)); + +typedef struct { unsigned char mask[256/8]; } evByteMask; +#define EV_BYTEMASK_BYTE(b) ((b) / 8) +#define EV_BYTEMASK_MASK(b) (1 << ((b) % 8)) +#define EV_BYTEMASK_SET(bm, b) \ + ((bm).mask[EV_BYTEMASK_BYTE(b)] |= EV_BYTEMASK_MASK(b)) +#define EV_BYTEMASK_CLR(bm, b) \ + ((bm).mask[EV_BYTEMASK_BYTE(b)] &= ~EV_BYTEMASK_MASK(b)) +#define EV_BYTEMASK_TST(bm, b) \ + ((bm).mask[EV_BYTEMASK_BYTE(b)] & EV_BYTEMASK_MASK(b)) + +#define EV_POLL 1 +#define EV_WAIT 2 +#define EV_NULL 4 + +#define EV_READ 1 +#define EV_WRITE 2 +#define EV_EXCEPT 4 + +/* eventlib.c */ +#define evCreate __evCreate +#define evSetDebug __evSetDebug +#define evDestroy __evDestroy +#define evGetNext __evGetNext +#define evDispatch __evDispatch +#define evDrop __evDrop +#define evMainLoop __evMainLoop +#define evHighestFD __evHighestFD + +int evCreate __P((evContext *ctx)); +void evSetDebug __P((evContext ctx, int lev, FILE *out)); +int evDestroy __P((evContext ctx)); +int evGetNext __P((evContext ctx, evEvent *ev, int options)); +int evDispatch __P((evContext ctx, evEvent ev)); +void evDrop __P((evContext ctx, evEvent ev)); +int evMainLoop __P((evContext ctx)); +int evHighestFD __P((evContext ctx)); + +/* ev_connects.c */ +#define evListen __evListen +#define evConnect __evConnect +#define evCancelConn __evCancelConn +#define evHold __evHold +#define evUnhold __evUnhold +#define evTryAccept __evTryAccept + +int evListen __P((evContext ctx, int fd, int maxconn, + evConnFunc func, void *uap, evConnID *id)); +int evConnect __P((evContext ctx, int fd, const void *ra, int ralen, + evConnFunc func, void *uap, evConnID *id)); +int evCancelConn __P((evContext ctx, evConnID id)); +int evHold __P((evContext, evConnID)); +int evUnhold __P((evContext, evConnID)); +int evTryAccept __P((evContext, evConnID, int *)); + +/* ev_files.c */ +#define evSelectFD __evSelectFD +#define evDeselectFD __evDeselectFD + +int evSelectFD __P((evContext ctx, int fd, int eventmask, + evFileFunc func, void *uap, evFileID *id)); +int evDeselectFD __P((evContext ctx, evFileID id)); + +/* ev_streams.c */ +#define evConsIovec __evConsIovec +#define evWrite __evWrite +#define evRead __evRead +#define evTimeRW __evTimeRW +#define evUntimeRW __evUntimeRW +#define evCancelRW __evCancelRW + +struct iovec evConsIovec __P((void *buf, size_t cnt)); +int evWrite __P((evContext ctx, int fd, const struct iovec *iov, int cnt, + evStreamFunc func, void *uap, evStreamID *id)); +int evRead __P((evContext ctx, int fd, const struct iovec *iov, int cnt, + evStreamFunc func, void *uap, evStreamID *id)); +int evTimeRW __P((evContext ctx, evStreamID id, evTimerID timer)); +int evUntimeRW __P((evContext ctx, evStreamID id)); +int evCancelRW __P((evContext ctx, evStreamID id)); + +/* ev_timers.c */ +#define evConsTime __evConsTime +#define evAddTime __evAddTime +#define evSubTime __evSubTime +#define evCmpTime __evCmpTime +#define evTimeSpec __evTimeSpec +#define evTimeVal __evTimeVal + +#define evNowTime __evNowTime +#define evLastEventTime __evLastEventTime +#define evSetTimer __evSetTimer +#define evClearTimer __evClearTimer +#define evResetTimer __evResetTimer +#define evSetIdleTimer __evSetIdleTimer +#define evClearIdleTimer __evClearIdleTimer +#define evResetIdleTimer __evResetIdleTimer +#define evTouchIdleTimer __evTouchIdleTimer + +struct timespec evConsTime __P((time_t sec, long nsec)); +struct timespec evAddTime __P((struct timespec add1, struct timespec add2)); +struct timespec evSubTime __P((struct timespec minu, struct timespec subtra)); +struct timespec evNowTime __P((void)); +struct timespec evLastEventTime __P((evContext)); +struct timespec evTimeSpec __P((struct timeval)); +struct timeval evTimeVal __P((struct timespec)); +int evCmpTime __P((struct timespec a, struct timespec b)); +int evSetTimer __P((evContext ctx, evTimerFunc func, void *uap, + struct timespec due, struct timespec inter, + evTimerID *id)); +int evClearTimer __P((evContext ctx, evTimerID id)); +int evResetTimer __P((evContext, evTimerID, evTimerFunc, void *, + struct timespec, struct timespec)); +int evSetIdleTimer __P((evContext, evTimerFunc, void *, struct timespec, + evTimerID *)); +int evClearIdleTimer __P((evContext, evTimerID)); +int evResetIdleTimer __P((evContext, evTimerID, evTimerFunc, void *, + struct timespec)); +int evTouchIdleTimer __P((evContext, evTimerID)); + +/* ev_waits.c */ +#define evWaitFor __evWaitFor +#define evDo __evDo +#define evUnwait __evUnwait +#define evDefer __evDefer + +int evWaitFor __P((evContext ctx, const void *tag, evWaitFunc func, void *uap, + evWaitID *id)); +int evDo __P((evContext ctx, const void *tag)); +int evUnwait __P((evContext ctx, evWaitID id)); +int evDefer __P((evContext, evWaitFunc, void *)); + +#ifdef __EVENTLIB_P_DEFINED +# undef __P +#endif + +#endif /*_EVENTLIB_H*/ diff --git a/lib/bind/include/isc/heap.h b/lib/bind/include/isc/heap.h new file mode 100644 index 0000000000..45c867c9d1 --- /dev/null +++ b/lib/bind/include/isc/heap.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1997,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +typedef int (*heap_higher_priority_func)(void *, void *); +typedef void (*heap_index_func)(void *, int); +typedef void (*heap_for_each_func)(void *, void *); + +typedef struct heap_context { + int array_size; + int array_size_increment; + int heap_size; + void **heap; + heap_higher_priority_func higher_priority; + heap_index_func index; +} *heap_context; + +#define heap_new __heap_new +#define heap_free __heap_free +#define heap_insert __heap_insert +#define heap_delete __heap_delete +#define heap_increased __heap_increased +#define heap_decreased __heap_decreased +#define heap_element __heap_element +#define heap_for_each __heap_for_each + +heap_context heap_new(heap_higher_priority_func, heap_index_func, int); +int heap_free(heap_context); +int heap_insert(heap_context, void *); +int heap_delete(heap_context, int); +int heap_increased(heap_context, int); +int heap_decreased(heap_context, int); +void * heap_element(heap_context, int); +int heap_for_each(heap_context, heap_for_each_func, void *); diff --git a/lib/bind/include/isc/irpmarshall.h b/lib/bind/include/isc/irpmarshall.h new file mode 100644 index 0000000000..d851ecacd4 --- /dev/null +++ b/lib/bind/include/isc/irpmarshall.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: irpmarshall.h,v 1.1 2001/03/29 06:31:36 marka Exp $ + */ + +#ifndef _IRPMARSHALL_H_INCLUDED +#define _IRPMARSHALL_H_INCLUDED + +/* Hide function names */ +#define irp_marshall_gr __irp_marshall_gr +#define irp_marshall_ho __irp_marshall_ho +#define irp_marshall_ne __irp_marshall_ne +#define irp_marshall_ng __irp_marshall_ng +#define irp_marshall_nw __irp_marshall_nw +#define irp_marshall_pr __irp_marshall_pr +#define irp_marshall_pw __irp_marshall_pw +#define irp_marshall_sv __irp_marshall_sv +#define irp_unmarshall_gr __irp_unmarshall_gr +#define irp_unmarshall_ho __irp_unmarshall_ho +#define irp_unmarshall_ne __irp_unmarshall_ne +#define irp_unmarshall_ng __irp_unmarshall_ng +#define irp_unmarshall_nw __irp_unmarshall_nw +#define irp_unmarshall_pr __irp_unmarshall_pr +#define irp_unmarshall_pw __irp_unmarshall_pw +#define irp_unmarshall_sv __irp_unmarshall_sv + +#define MAXPADDRSIZE (sizeof "255.255.255.255" + 1) +#define ADDR_T_STR(x) (x == AF_INET ? "AF_INET" :\ + (x == AF_INET6 ? "AF_INET6" : "UNKNOWN")) + +/* See comment below on usage */ +int irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len); +int irp_unmarshall_pw(struct passwd *pw, char *buffer); +int irp_marshall_gr(const struct group *gr, char **buffer, size_t *len); +int irp_unmarshall_gr(struct group *gr, char *buffer); +int irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len); +int irp_unmarshall_sv(struct servent *sv, char *buffer); +int irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len); +int irp_unmarshall_pr(struct protoent *pr, char *buffer); +int irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len); +int irp_unmarshall_ho(struct hostent *ho, char *buffer); +int irp_marshall_ng(const char *host, const char *user, const char *domain, + char **buffer, size_t *len); +int irp_unmarshall_ng(const char **host, const char **user, + const char **domain, char *buffer); +int irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len); +int irp_unmarshall_nw(struct nwent *ne, char *buffer); +int irp_marshall_ne(struct netent *ne, char **buffer, size_t *len); +int irp_unmarshall_ne(struct netent *ne, char *buffer); + +/* + * Functions to marshall and unmarshall various system data structures. We + * use a printable ascii format that is as close to various system config + * files as reasonable (e.g. /etc/passwd format). + * + * We are not forgiving with unmarhsalling misformatted buffers. In + * particular whitespace in fields is not ignored. So a formatted password + * entry "brister :1364:100:...." will yield a username of "brister " + * + * We potentially do a lot of mallocs to fill fields that are of type + * (char **) like a hostent h_addr field. Building (for example) the + * h_addr field and its associated addresses all in one buffer is + * certainly possible, but not done here. + * + * The following description is true for all the marshalling functions: + * + */ + +/* int irp_marshall_XX(struct yyyy *XX, char **buffer, size_t *len); + * + * The argument XX (of type struct passwd for example) is marshalled in the + * buffer pointed at by *BUFFER, which is of length *LEN. Returns 0 + * on success and -1 on failure. Failure will occur if *LEN is + * smaller than needed. + * + * If BUFFER is NULL, then *LEN is set to the size of the buffer + * needed to marshall the data and no marshalling is actually done. + * + * If *BUFFER is NULL, then a buffer large enough will be allocated + * with memget() and the size allocated will be stored in *LEN. An extra 2 + * bytes will be allocated for the client to append CRLF if wanted. The + * value of *LEN will include these two bytes. + * + * All the marshalling functions produce a buffer with the fields + * separated by colons (except for the hostent marshalling, which uses '@' + * to separate fields). Fields that have multiple subfields (like the + * gr_mem field in struct group) have their subparts separated by + * commas. + */ + +/* + * int irp_unmarshall_XX(struct YYYYY *XX, char *buffer); + * + * The unmashalling functions break apart the buffer and store the + * values in the struct pointed to by XX. All pointer values inside + * XX are allocated with malloc. All arrays of pointers have a NULL + * as the last element. + */ + +#endif diff --git a/lib/bind/include/isc/list.h b/lib/bind/include/isc/list.h new file mode 100644 index 0000000000..21dd565df5 --- /dev/null +++ b/lib/bind/include/isc/list.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1997,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef LIST_H +#define LIST_H 1 +#include + +#define LIST(type) struct { type *head, *tail; } +#define INIT_LIST(list) \ + do { (list).head = NULL; (list).tail = NULL; } while (0) + +#define LINK(type) struct { type *prev, *next; } +#define INIT_LINK(elt, link) \ + do { \ + (elt)->link.prev = (void *)(-1); \ + (elt)->link.next = (void *)(-1); \ + } while (0) +#define LINKED(elt, link) ((void *)((elt)->link.prev) != (void *)(-1)) + +#define HEAD(list) ((list).head) +#define TAIL(list) ((list).tail) +#define EMPTY(list) ((list).head == NULL) + +#define PREPEND(list, elt, link) \ + do { \ + INSIST(!LINKED(elt, link));\ + if ((list).head != NULL) \ + (list).head->link.prev = (elt); \ + else \ + (list).tail = (elt); \ + (elt)->link.prev = NULL; \ + (elt)->link.next = (list).head; \ + (list).head = (elt); \ + } while (0) + +#define APPEND(list, elt, link) \ + do { \ + INSIST(!LINKED(elt, link));\ + if ((list).tail != NULL) \ + (list).tail->link.next = (elt); \ + else \ + (list).head = (elt); \ + (elt)->link.prev = (list).tail; \ + (elt)->link.next = NULL; \ + (list).tail = (elt); \ + } while (0) + +#define UNLINK(list, elt, link) \ + do { \ + INSIST(LINKED(elt, link));\ + if ((elt)->link.next != NULL) \ + (elt)->link.next->link.prev = (elt)->link.prev; \ + else \ + (list).tail = (elt)->link.prev; \ + if ((elt)->link.prev != NULL) \ + (elt)->link.prev->link.next = (elt)->link.next; \ + else \ + (list).head = (elt)->link.next; \ + INIT_LINK(elt, link); \ + } while (0) + +#define PREV(elt, link) ((elt)->link.prev) +#define NEXT(elt, link) ((elt)->link.next) + +#define INSERT_BEFORE(list, before, elt, link) \ + do { \ + INSIST(!LINKED(elt, link));\ + if ((before)->link.prev == NULL) \ + PREPEND(list, elt, link); \ + else { \ + (elt)->link.prev = (before)->link.prev; \ + (before)->link.prev = (elt); \ + (elt)->link.prev->link.next = (elt); \ + (elt)->link.next = (before); \ + } \ + } while (0) + +#define INSERT_AFTER(list, after, elt, link) \ + do { \ + INSIST(!LINKED(elt, link));\ + if ((after)->link.next == NULL) \ + APPEND(list, elt, link); \ + else { \ + (elt)->link.next = (after)->link.next; \ + (after)->link.next = (elt); \ + (elt)->link.next->link.prev = (elt); \ + (elt)->link.prev = (after); \ + } \ + } while (0) + +#define ENQUEUE(list, elt, link) APPEND(list, elt, link) +#define DEQUEUE(list, elt, link) UNLINK(list, elt, link) + +#endif /* LIST_H */ diff --git a/lib/bind/include/isc/logging.h b/lib/bind/include/isc/logging.h new file mode 100644 index 0000000000..3d3d3132a0 --- /dev/null +++ b/lib/bind/include/isc/logging.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef LOGGING_H +#define LOGGING_H + +#include +#include +#include +#include + +#define log_critical (-5) +#define log_error (-4) +#define log_warning (-3) +#define log_notice (-2) +#define log_info (-1) +#define log_debug(level) (level) + +typedef enum { log_syslog, log_file, log_null } log_channel_type; + +#define LOG_MAX_VERSIONS 99 + +#define LOG_CLOSE_STREAM 0x0001 +#define LOG_TIMESTAMP 0x0002 +#define LOG_TRUNCATE 0x0004 +#define LOG_USE_CONTEXT_LEVEL 0x0008 +#define LOG_PRINT_LEVEL 0x0010 +#define LOG_REQUIRE_DEBUG 0x0020 +#define LOG_CHANNEL_BROKEN 0x0040 +#define LOG_PRINT_CATEGORY 0x0080 +#define LOG_CHANNEL_OFF 0x0100 + +typedef struct log_context *log_context; +typedef struct log_channel *log_channel; + +#define LOG_OPTION_DEBUG 0x01 +#define LOG_OPTION_LEVEL 0x02 + +#define log_open_stream __log_open_stream +#define log_close_stream __log_close_stream +#define log_get_stream __log_get_stream +#define log_get_filename __log_get_filename +#define log_check_channel __log_check_channel +#define log_check __log_check +#define log_vwrite __log_vwrite +#define log_write __log_write +#define log_new_context __log_new_context +#define log_free_context __log_free_context +#define log_add_channel __log_add_channel +#define log_remove_channel __log_remove_channel +#define log_option __log_option +#define log_category_is_active __log_category_is_active +#define log_new_syslog_channel __log_new_syslog_channel +#define log_new_file_channel __log_new_file_channel +#define log_set_file_owner __log_set_file_owner +#define log_new_null_channel __log_new_null_channel +#define log_inc_references __log_inc_references +#define log_dec_references __log_dec_references +#define log_get_channel_type __log_get_channel_type +#define log_free_channel __log_free_channel + +FILE * log_open_stream(log_channel); +int log_close_stream(log_channel); +FILE * log_get_stream(log_channel); +char * log_get_filename(log_channel); +int log_check_channel(log_context, int, log_channel); +int log_check(log_context, int, int); +void log_vwrite(log_context, int, int, const char *, + va_list args); +void log_write(log_context, int, int, const char *, ...); +int log_new_context(int, char **, log_context *); +void log_free_context(log_context); +int log_add_channel(log_context, int, log_channel); +int log_remove_channel(log_context, int, log_channel); +int log_option(log_context, int, int); +int log_category_is_active(log_context, int); +log_channel log_new_syslog_channel(unsigned int, int, int); +log_channel log_new_file_channel(unsigned int, int, char *, + FILE *, unsigned int, + unsigned long); +int log_set_file_owner(log_channel, uid_t, gid_t); +log_channel log_new_null_channel(void); +int log_inc_references(log_channel); +int log_dec_references(log_channel); +log_channel_type log_get_channel_type(log_channel); +int log_free_channel(log_channel); + +#endif /* !LOGGING_H */ diff --git a/lib/bind/include/isc/memcluster.h b/lib/bind/include/isc/memcluster.h new file mode 100644 index 0000000000..b6f4191fd5 --- /dev/null +++ b/lib/bind/include/isc/memcluster.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1997,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef MEMCLUSTER_H +#define MEMCLUSTER_H + +#include + +#define meminit __meminit +#ifdef MEMCLUSTER_DEBUG +#define memget(s) __memget_debug(s, __FILE__, __LINE__) +#define memput(p, s) __memput_debug(p, s, __FILE__, __LINE__) +#else /*MEMCLUSTER_DEBUG*/ +#ifdef MEMCLUSTER_RECORD +#define memget(s) __memget_record(s, __FILE__, __LINE__) +#define memput(p, s) __memput_record(p, s, __FILE__, __LINE__) +#else /*MEMCLUSTER_RECORD*/ +#define memget __memget +#define memput __memput +#endif /*MEMCLUSTER_RECORD*/ +#endif /*MEMCLUSTER_DEBUG*/ +#define memstats __memstats + +int meminit(size_t, size_t); +void * __memget(size_t); +void __memput(void *, size_t); +void * __memget_debug(size_t, const char *, int); +void __memput_debug(void *, size_t, const char *, int); +void * __memget_record(size_t, const char *, int); +void __memput_record(void *, size_t, const char *, int); +void memstats(FILE *); + +#endif /* MEMCLUSTER_H */ diff --git a/lib/bind/include/isc/misc.h b/lib/bind/include/isc/misc.h new file mode 100644 index 0000000000..5799316f12 --- /dev/null +++ b/lib/bind/include/isc/misc.h @@ -0,0 +1,31 @@ +/* + * 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. + */ + +/* + * $Id: misc.h,v 1.1 2001/03/29 06:31:36 marka Exp $ + */ + +#ifndef _ISC_MISC_H +#define _ISC_MISC_H + +#define bitncmp __bitncmp +/*#define isc_movefile __isc_movefile */ + +extern int bitncmp(const void *l, const void *r, int n); +extern int isc_movefile(const char *, const char *); + +#endif /*_ISC_MISC_H*/ diff --git a/lib/bind/include/isc/tree.h b/lib/bind/include/isc/tree.h new file mode 100644 index 0000000000..f383489e17 --- /dev/null +++ b/lib/bind/include/isc/tree.h @@ -0,0 +1,48 @@ +/* tree.h - declare structures used by tree library + * + * vix 22jan93 [revisited; uses RCS, ANSI, POSIX; has bug fixes] + * vix 27jun86 [broken out of tree.c] + * + * $Id: tree.h,v 1.1 2001/03/29 06:31:37 marka Exp $ + */ + + +#ifndef _TREE_H_INCLUDED +#define _TREE_H_INCLUDED + + +#ifndef __P +# if defined(__STDC__) || defined(__GNUC__) +# define __P(x) x +# else +# define __P(x) () +# endif +#endif + +/* + * tree_t is our package-specific anonymous pointer. + */ +#if defined(__STDC__) || defined(__GNUC__) +typedef void *tree_t; +#else +typedef char *tree_t; +#endif + + +typedef struct tree_s { + tree_t data; + struct tree_s *left, *right; + short bal; + } + tree; + + +void tree_init __P((tree **)); +tree_t tree_srch __P((tree **, int (*)(), tree_t)); +tree_t tree_add __P((tree **, int (*)(), tree_t, void (*)())); +int tree_delete __P((tree **, int (*)(), tree_t, void (*)())); +int tree_trav __P((tree **, int (*)())); +void tree_mung __P((tree **, void (*)())); + + +#endif /* _TREE_H_INCLUDED */ diff --git a/lib/bind/include/netdb.h b/lib/bind/include/netdb.h new file mode 100644 index 0000000000..cd7d9a9087 --- /dev/null +++ b/lib/bind/include/netdb.h @@ -0,0 +1,485 @@ +/* + * ++Copyright++ 1980, 1983, 1988, 1993 + * - + * Copyright (c) 1980, 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * - + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * - + * Portions Copyright (C) 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. + * - + * --Copyright-- + */ + +/* + * @(#)netdb.h 8.1 (Berkeley) 6/2/93 + * $Id: netdb.h,v 1.1 2001/03/29 06:31:34 marka Exp $ + */ + +#ifndef _NETDB_H_ +#define _NETDB_H_ + +#include +#if (!defined(BSD)) || (BSD < 199306) +# include +#endif +#include +#include +#include +#include + +#ifndef _PATH_HEQUIV +#define _PATH_HEQUIV "/etc/hosts.equiv" +#endif +#ifndef _PATH_HOSTS +#define _PATH_HOSTS "/etc/hosts" +#endif +#ifndef _PATH_NETWORKS +#define _PATH_NETWORKS "/etc/networks" +#endif +#ifndef _PATH_PROTOCOLS +#define _PATH_PROTOCOLS "/etc/protocols" +#endif +#ifndef _PATH_SERVICES +#define _PATH_SERVICES "/etc/services" +#endif + +#ifdef _REENTRANT +__BEGIN_DECLS +extern int * __h_errno __P((void)); +__END_DECLS +#define h_errno (*__h_errno()) +#else +extern int h_errno; +#endif + +/* + * Structures returned by network data base library. All addresses are + * supplied in host order, and returned in network order (suitable for + * use in system calls). + */ +struct hostent { + char *h_name; /* official name of host */ + char **h_aliases; /* alias list */ + int h_addrtype; /* host address type */ + int h_length; /* length of address */ + char **h_addr_list; /* list of addresses from name server */ +#define h_addr h_addr_list[0] /* address, for backward compatiblity */ +}; + +/* + * Assumption here is that a network number + * fits in an unsigned long -- probably a poor one. + */ +struct netent { + char *n_name; /* official name of net */ + char **n_aliases; /* alias list */ + int n_addrtype; /* net address type */ + unsigned long n_net; /* network # */ +}; + +struct servent { + char *s_name; /* official service name */ + char **s_aliases; /* alias list */ + int s_port; /* port # */ + char *s_proto; /* protocol to use */ +}; + +struct protoent { + char *p_name; /* official protocol name */ + char **p_aliases; /* alias list */ + int p_proto; /* protocol # */ +}; + +struct addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for hostname */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ +}; + +/* + * Error return codes from gethostbyname() and gethostbyaddr() + * (left in extern int h_errno). + */ + +#define NETDB_INTERNAL -1 /* see errno */ +#define NETDB_SUCCESS 0 /* no problem */ +#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */ +#define TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */ +#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ +#define NO_DATA 4 /* Valid name, no data record of requested type */ +#define NO_ADDRESS NO_DATA /* no address, look for MX record */ + +/* + * Error return codes from getaddrinfo() + */ + +#define EAI_ADDRFAMILY 1 /* address family for hostname not supported */ +#define EAI_AGAIN 2 /* temporary failure in name resolution */ +#define EAI_BADFLAGS 3 /* invalid value for ai_flags */ +#define EAI_FAIL 4 /* non-recoverable failure in name resolution */ +#define EAI_FAMILY 5 /* ai_family not supported */ +#define EAI_MEMORY 6 /* memory allocation failure */ +#define EAI_NODATA 7 /* no address associated with hostname */ +#define EAI_NONAME 8 /* hostname nor servname provided, or not known */ +#define EAI_SERVICE 9 /* servname not supported for ai_socktype */ +#define EAI_SOCKTYPE 10 /* ai_socktype not supported */ +#define EAI_SYSTEM 11 /* system error returned in errno */ +#define EAI_BADHINTS 12 +#define EAI_PROTOCOL 13 +#define EAI_MAX 14 + +/* + * Flag values for getaddrinfo() + */ +#define AI_PASSIVE 0x00000001 +#define AI_CANONNAME 0x00000002 +#define AI_NUMERICHOST 0x00000004 +#define AI_MASK 0x00000007 + +/* + * Flag values for getipnodebyname() + */ +#define AI_V4MAPPED 0x00000008 +#define AI_ALL 0x00000010 +#define AI_ADDRCONFIG 0x00000020 +#define AI_DEFAULT (AI_V4MAPPED|AI_ADDRCONFIG) + +/* + * Constants for getnameinfo() + */ +#define NI_MAXHOST 1025 +#define NI_MAXSERV 32 + +/* + * Flag values for getnameinfo() + */ +#define NI_NOFQDN 0x00000001 +#define NI_NUMERICHOST 0x00000002 +#define NI_NAMEREQD 0x00000004 +#define NI_NUMERICSERV 0x00000008 +#define NI_DGRAM 0x00000010 +#define NI_WITHSCOPEID 0x00000020 +#define NI_NUMERICSCOPE 0x00000040 + +/* + * Scope delimit character + */ +#define SCOPE_DELIMITER '%' + + +#ifdef _REENTRANT +#if defined (__hpux) || defined(__osf__) +#define _MAXALIASES 35 +#define _MAXLINELEN 1024 +#define _MAXADDRS 35 +#define _HOSTBUFSIZE (BUFSIZ + 1) + +struct hostent_data { + struct in_addr host_addr; + char *h_addr_ptrs[_MAXADDRS + 1]; + char hostaddr[_MAXADDRS]; + char hostbuf[_HOSTBUFSIZE]; + char *host_aliases[_MAXALIASES]; + char *host_addrs[2]; + FILE *hostf; +#ifdef __osf__ + int svc_gethostflag; + int svc_gethostbind; +#endif +#ifdef __hpux + short _nsw_src; + short _flags; + char *current; + int currentlen; +#endif +}; + +struct netent_data { + FILE *net_fp; +#ifdef __osf__ + char line[_MAXLINELEN]; +#endif +#ifdef __hpux + char line[_MAXLINELEN+1]; +#endif + char *net_aliases[_MAXALIASES]; +#ifdef __osf__ + int _net_stayopen; + int svc_getnetflag; +#endif +#ifdef __hpux + short _nsw_src; + short _flags; + char *current; + int currentlen; +#endif +}; + +struct protoent_data { + FILE *proto_fp; +#ifdef __osf__ + char line[1024]; +#endif +#ifdef __hpux + char line[_MAXLINELEN+1]; +#endif + char *proto_aliases[_MAXALIASES]; +#ifdef __osf__ + int _proto_stayopen; + int svc_getprotoflag; +#endif +#ifdef __hpux + short _nsw_src; + short _flags; + char *current; + int currentlen; +#endif +}; + +struct servent_data { + FILE *serv_fp; +#ifdef __osf__ + char line[_MAXLINELEN]; +#endif +#ifdef __hpux + char line[_MAXLINELEN+1]; +#endif + char *serv_aliases[_MAXALIASES]; +#ifdef __osf__ + int _serv_stayopen; + int svc_getservflag; +#endif +#ifdef __hpux + short _nsw_src; + short _flags; + char *current; + int currentlen; +#endif +}; +#endif +#endif +__BEGIN_DECLS +void endhostent __P((void)); +void endnetent __P((void)); +void endprotoent __P((void)); +void endservent __P((void)); +void freehostent __P((struct hostent *)); +struct hostent *gethostbyaddr __P((const char *, int, int)); +struct hostent *gethostbyname __P((const char *)); +struct hostent *gethostbyname2 __P((const char *, int)); +struct hostent *gethostent __P((void)); +struct hostent *getipnodebyaddr __P((const void *, size_t, int, int *)); +struct hostent *getipnodebyname __P((const char *, int, int, int *)); +struct netent *getnetbyaddr __P((unsigned long, int)); +struct netent *getnetbyname __P((const char *)); +struct netent *getnetent __P((void)); +struct protoent *getprotobyname __P((const char *)); +struct protoent *getprotobynumber __P((int)); +struct protoent *getprotoent __P((void)); +struct servent *getservbyname __P((const char *, const char *)); +struct servent *getservbyport __P((int, const char *)); +struct servent *getservent __P((void)); +void herror __P((const char *)); +const char *hstrerror __P((int)); +void sethostent __P((int)); +/* void sethostfile __P((const char *)); */ +void setnetent __P((int)); +void setprotoent __P((int)); +void setservent __P((int)); +int getaddrinfo __P((const char *, const char *, + const struct addrinfo *, struct addrinfo **)); +int getnameinfo __P((const struct sockaddr *, size_t, char *, + size_t, char *, size_t, int)); +void freeaddrinfo __P((struct addrinfo *)); +const char *gai_strerror __P((int)); +struct hostent *getipnodebyname __P((const char *, int, int, int *)); +struct hostent *getipnodebyaddr __P((const void *, size_t, int, int *)); +void freehostent __P((struct hostent *)); + + +#ifdef _REENTRANT +#if defined(__hpux) || defined(__osf__) +int gethostbyaddr_r __P((const char *, int, int, struct hostent *, + struct hostent_data *)); +int gethostbyname_r __P((const char *, struct hostent *, + struct hostent_data *)); +int gethostent_r __P((struct hostent *, struct hostent_data *)); +int sethostent_r __P((int, struct hostent_data *)); +#if defined(__hpux) +int endhostent_r __P((struct hostent_data *)); +#else +void endhostent_r __P((struct hostent_data *)); +#endif + +#ifdef __hpux +int getnetbyaddr_r __P((int, int, + struct netent *, struct netent_data *)); +#else +int getnetbyaddr_r __P((long, int, + struct netent *, struct netent_data *)); +#endif +int getnetbyname_r __P((const char *, + struct netent *, struct netent_data *)); +int getnetent_r __P((struct netent *, struct netent_data *)); +int setnetent_r __P((int, struct netent_data *)); +#ifdef __hpux +int endnetent_r __P((struct netent_data *buffer)); +#else +void endnetent_r __P((struct netent_data *buffer)); +#endif + +int getprotobyname_r __P((const char *, + struct protoent *, struct protoent_data *)); +int getprotobynumber_r __P((int, + struct protoent *, struct protoent_data *)); +int getprotoent_r __P((struct protoent *, struct protoent_data *)); +int setprotoent_r __P((int, struct protoent_data *)); +#ifdef __hpux +int endprotoent_r __P((struct protoent_data *)); +#else +void endprotoent_r __P((struct protoent_data *)); +#endif + +int getservbyname_r __P((const char *, const char *, + struct servent *, struct servent_data *)); +int getservbyport_r __P((int, const char *, + struct servent *, struct servent_data *)); +int getservent_r __P((struct servent *, struct servent_data *)); +int setservent_r __P((int, struct servent_data *)); +#ifdef __hpux +int endservent_r __P((struct servent_data *)); +#else +void endservent_r __P((struct servent_data *)); +#endif +#else + /* defined(sun) || defined(bsdi) */ +struct hostent *gethostbyaddr_r __P((const char *, int, int, struct hostent *, + char *, int, int *)); +struct hostent *gethostbyname_r __P((const char *, struct hostent *, + char *, int, int *)); +struct hostent *gethostent_r __P((struct hostent *, char *, int, int *)); +void sethostent_r __P((int)); +void endhostent_r __P((void)); + +struct netent *getnetbyname_r __P((const char *, struct netent *, + char *, int)); +struct netent *getnetbyaddr_r __P((long, int, struct netent *, + char *, int)); +struct netent *getnetent_r __P((struct netent *, char *, int)); +void setnetent_r __P((int)); +void endnetent_r __P((void)); + +struct protoent *getprotobyname_r __P((const char *, + struct protoent *, char *, int)); +struct protoent *getprotobynumber_r __P((int, + struct protoent *, char *, int)); +struct protoent *getprotoent_r __P((struct protoent *, char *, int)); +void setprotoent_r __P((int)); +void endprotoent_r __P((void)); + +struct servent *getservbyname_r __P((const char *name, const char *, + struct servent *, char *, int)); +struct servent *getservbyport_r __P((int port, const char *, + struct servent *, char *, int)); +struct servent *getservent_r __P((struct servent *, char *, int)); +void setservent_r __P((int)); +void endservent_r __P((void)); + +#endif +#endif +__END_DECLS + +/* This is nec'y to make this include file properly replace the sun version. */ +#ifdef sun +#ifdef __GNU_LIBRARY__ +#include +#else +struct rpcent { + char *r_name; /* name of server for this rpc program */ + char **r_aliases; /* alias list */ + int r_number; /* rpc program number */ +}; +struct rpcent *getrpcbyname(), *getrpcbynumber(), *getrpcent(); +#endif /* __GNU_LIBRARY__ */ +#endif /* sun */ + +#endif /* !_NETDB_H_ */ diff --git a/lib/bind/include/netgroup.h b/lib/bind/include/netgroup.h new file mode 100644 index 0000000000..30efb94144 --- /dev/null +++ b/lib/bind/include/netgroup.h @@ -0,0 +1,17 @@ +#ifndef netgroup_h +#define netgroup_h + +int getnetgrent(const char **machinep, const char **userp, + const char **domainp); + +int getnetgrent_r(char **machinep, char **userp, char **domainp, + char *buffer, int buflen); + +void setnetgrent(const char *netgroup); + +void endnetgrent(void); + +int innetgr(const char *netgroup, const char *machine, + const char *user, const char *domain); + +#endif diff --git a/lib/bind/include/res_update.h b/lib/bind/include/res_update.h new file mode 100644 index 0000000000..946ad13d4f --- /dev/null +++ b/lib/bind/include/res_update.h @@ -0,0 +1,65 @@ +/* + * 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. + */ + +/* + * $Id: res_update.h,v 1.1 2001/03/29 06:31:34 marka Exp $ + */ + +#ifndef __RES_UPDATE_H +#define __RES_UPDATE_H + +#include +#include +#include +#include + +/* + * This RR-like structure is particular to UPDATE. + */ +struct ns_updrec { + LINK(struct ns_updrec) r_link, r_glink; + ns_sect r_section; /* ZONE/PREREQUISITE/UPDATE */ + char * r_dname; /* owner of the RR */ + ns_class r_class; /* class number */ + ns_type r_type; /* type number */ + u_int32_t r_ttl; /* time to live */ + u_char * r_data; /* rdata fields as text string */ + u_int r_size; /* size of r_data field */ + int r_opcode; /* type of operation */ + /* following fields for private use by the resolver/server routines */ + struct databuf *r_dp; /* databuf to process */ + struct databuf *r_deldp; /* databuf's deleted/overwritten */ + u_int r_zone; /* zone number on server */ +}; +typedef struct ns_updrec ns_updrec; +typedef LIST(ns_updrec) ns_updque; + +#define res_mkupdate __res_mkupdate +#define res_update __res_update +#define res_mkupdrec __res_mkupdrec +#define res_freeupdrec __res_freeupdrec +#define res_nmkupdate __res_nmkupdate +#define res_nupdate __res_nupdate + +int res_mkupdate __P((ns_updrec *, u_char *, int)); +int res_update __P((ns_updrec *)); +ns_updrec * res_mkupdrec __P((int, const char *, u_int, u_int, u_long)); +void res_freeupdrec __P((ns_updrec *)); +int res_nmkupdate __P((res_state, ns_updrec *, u_char *, int)); +int res_nupdate __P((res_state, ns_updrec *, ns_tsig_key *)); + +#endif /*__RES_UPDATE_H*/ diff --git a/lib/bind/include/resolv.h b/lib/bind/include/resolv.h new file mode 100644 index 0000000000..f1667178f4 --- /dev/null +++ b/lib/bind/include/resolv.h @@ -0,0 +1,447 @@ +/* + * Copyright (c) 1983, 1987, 1989 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * @(#)resolv.h 8.1 (Berkeley) 6/2/93 + * $Id: resolv.h,v 1.1 2001/03/29 06:31:34 marka Exp $ + */ + +#ifndef _RESOLV_H_ +#define _RESOLV_H_ + +#include +#if (!defined(BSD)) || (BSD < 199306) +# include +#else +# include +#endif +#include +#include +#include + +/* + * Revision information. This is the release date in YYYYMMDD format. + * It can change every day so the right thing to do with it is use it + * in preprocessor commands such as "#if (__RES > 19931104)". Do not + * compare for equality; rather, use it to determine whether your resolver + * is new enough to contain a certain feature. + */ + +#define __RES 19991006 + +/* + * This used to be defined in res_query.c, now it's in herror.c. + * [XXX no it's not. It's in irs/irs_data.c] + * It was + * never extern'd by any *.h file before it was placed here. For thread + * aware programs, the last h_errno value set is stored in res->h_errno. + * + * XXX: There doesn't seem to be a good reason for exposing RES_SET_H_ERRNO + * (and __h_errno_set) to the public via . + * XXX: __h_errno_set is really part of IRS, not part of the resolver. + * If somebody wants to build and use a resolver that doesn't use IRS, + * what do they do? Perhaps something like + * #ifdef WANT_IRS + * # define RES_SET_H_ERRNO(r,x) __h_errno_set(r,x) + * #else + * # define RES_SET_H_ERRNO(r,x) (h_errno = (r)->res_h_errno = (x)) + * #endif + */ + +#define RES_SET_H_ERRNO(r,x) __h_errno_set(r,x) +struct __res_state; /* forward */ +void __h_errno_set(struct __res_state *res, int err); + +/* + * Resolver configuration file. + * Normally not present, but may contain the address of the + * inital name server(s) to query and the domain search list. + */ + +#ifndef _PATH_RESCONF +#define _PATH_RESCONF "/etc/resolv.conf" +#endif + +typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error } + res_sendhookact; + +typedef res_sendhookact (*res_send_qhook)__P((struct sockaddr * const *ns, + const u_char **query, + int *querylen, + u_char *ans, + int anssiz, + int *resplen)); + +typedef res_sendhookact (*res_send_rhook)__P((const struct sockaddr *ns, + const u_char *query, + int querylen, + u_char *ans, + int anssiz, + int *resplen)); + +struct res_sym { + int number; /* Identifying number, like T_MX */ + const char * name; /* Its symbolic name, like "MX" */ + const char * humanname; /* Its fun name, like "mail exchanger" */ +}; + +/* + * Global defines and variables for resolver stub. + */ +#define MAXNS 3 /* max # name servers we'll track */ +#define MAXDFLSRCH 3 /* # default domain levels to try */ +#define MAXDNSRCH 6 /* max # domains in search path */ +#define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */ + +#define RES_TIMEOUT 5 /* min. seconds between retries */ +#define MAXRESOLVSORT 10 /* number of net to sort on */ +#define RES_MAXNDOTS 15 /* should reflect bit field size */ +#define RES_MAXRETRANS 30 /* only for resolv.conf/RES_OPTIONS */ +#define RES_MAXRETRY 5 /* only for resolv.conf/RES_OPTIONS */ +#define RES_DFLRETRY 2 /* Default #/tries. */ +#define RES_MAXTIME 65535 /* Infinity, in milliseconds. */ + +union __res_sockaddr_union { + struct sockaddr_in sin; +#if 1 /*def INET6*/ + struct sockaddr_in6 sin6; +#endif + int64_t __align; /* 64bit alignment */ + char __space[128]; /* max size */ +}; + +struct __res_state_ext { + union __res_sockaddr_union nsaddrs[MAXNS]; + struct sort_list { + int af; + union { + struct in_addr ina; + struct in6_addr in6a; + } addr, mask; + } sort_list[MAXRESOLVSORT]; +}; + +struct __res_state { + int retrans; /* retransmition time interval */ + int retry; /* number of times to retransmit */ + u_long options; /* option flags - see below. */ + int nscount; /* number of name servers */ + struct sockaddr_in + nsaddr_list[MAXNS]; /* address of name server */ +#define nsaddr nsaddr_list[0] /* for backward compatibility */ + u_short id; /* current message id */ + char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */ + char defdname[256]; /* default domain (deprecated) */ + u_long pfcode; /* RES_PRF_ flags - see below. */ + unsigned ndots:4; /* threshold for initial abs. query */ + unsigned nsort:4; /* number of elements in sort_list[] */ + char unused[3]; + struct { + struct in_addr addr; + u_int32_t mask; + } sort_list[MAXRESOLVSORT]; + res_send_qhook qhook; /* query hook */ + res_send_rhook rhook; /* response hook */ + int res_h_errno; /* last one set for this context */ + int _vcsock; /* PRIVATE: for res_send VC i/o */ + u_int _flags; /* PRIVATE: see below */ + union { + char pad[52]; /* On an i386 this means 512b total. */ + struct { + u_int16_t nscount; + u_int16_t nstimes[MAXNS]; /* ms. */ + int nssocks[MAXNS]; + struct __res_state_ext *ext; /* extention for IPv6 */ + } _ext; + } _u; +}; + +typedef struct __res_state *res_state; + +/* + * Resolver flags (used to be discrete per-module statics ints). + */ +#define RES_F_VC 0x00000001 /* socket is TCP */ +#define RES_F_CONN 0x00000002 /* socket is connected */ +#define RES_F_EDNS0ERR 0x00000004 /* EDNS0 caused errors */ + +/* res_findzonecut() options */ +#define RES_EXHAUSTIVE 0x00000001 /* always do all queries */ + +/* + * Resolver options (keep these in synch with res_debug.c, please) + */ +#define RES_INIT 0x00000001 /* address initialized */ +#define RES_DEBUG 0x00000002 /* print debug messages */ +#define RES_AAONLY 0x00000004 /* authoritative answers only (!IMPL)*/ +#define RES_USEVC 0x00000008 /* use virtual circuit */ +#define RES_PRIMARY 0x00000010 /* query primary server only (!IMPL) */ +#define RES_IGNTC 0x00000020 /* ignore trucation errors */ +#define RES_RECURSE 0x00000040 /* recursion desired */ +#define RES_DEFNAMES 0x00000080 /* use default domain name */ +#define RES_STAYOPEN 0x00000100 /* Keep TCP socket open */ +#define RES_DNSRCH 0x00000200 /* search up local domain tree */ +#define RES_INSECURE1 0x00000400 /* type 1 security disabled */ +#define RES_INSECURE2 0x00000800 /* type 2 security disabled */ +#define RES_NOALIASES 0x00001000 /* shuts off HOSTALIASES feature */ +#define RES_USE_INET6 0x00002000 /* use/map IPv6 in gethostbyname() */ +#define RES_ROTATE 0x00004000 /* rotate ns list after each query */ +#define RES_NOCHECKNAME 0x00008000 /* do not check names for sanity. */ +#define RES_KEEPTSIG 0x00010000 /* do not strip TSIG records */ +#define RES_BLAST 0x00020000 /* blast all recursive servers */ +/* KAME extensions: use higher bit to avoid conflict with ISC use */ +#define RES_USE_EDNS0 0x40000000 /* use EDNS0 if configured */ +#define RES_USE_A6 0x20000000 /* use A6 */ +#define RES_USE_DNAME 0x10000000 /* use DNAME */ + +#define RES_DEFAULT (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH) + +/* + * Resolver "pfcode" values. Used by dig. + */ +#define RES_PRF_STATS 0x00000001 +#define RES_PRF_UPDATE 0x00000002 +#define RES_PRF_CLASS 0x00000004 +#define RES_PRF_CMD 0x00000008 +#define RES_PRF_QUES 0x00000010 +#define RES_PRF_ANS 0x00000020 +#define RES_PRF_AUTH 0x00000040 +#define RES_PRF_ADD 0x00000080 +#define RES_PRF_HEAD1 0x00000100 +#define RES_PRF_HEAD2 0x00000200 +#define RES_PRF_TTLID 0x00000400 +#define RES_PRF_HEADX 0x00000800 +#define RES_PRF_QUERY 0x00001000 +#define RES_PRF_REPLY 0x00002000 +#define RES_PRF_INIT 0x00004000 +/* 0x00008000 */ + +/* Things involving an internal (static) resolver context. */ +#ifdef _REENTRANT +extern struct __res_state *__res_state(void); +#define _res (*__res_state()) +#else +#ifndef __BIND_NOSTATIC +extern struct __res_state _res; +#endif +#endif + +#ifndef __BIND_NOSTATIC +#define fp_nquery __fp_nquery +#define fp_query __fp_query +#define hostalias __hostalias +#define p_query __p_query +#define res_close __res_close +#define res_init __res_init +#define res_isourserver __res_isourserver +#define res_mkquery __res_mkquery +#define res_query __res_query +#define res_querydomain __res_querydomain +#define res_search __res_search +#define res_send __res_send +#define res_sendsigned __res_sendsigned + +__BEGIN_DECLS +void fp_nquery __P((const u_char *, int, FILE *)); +void fp_query __P((const u_char *, FILE *)); +const char * hostalias __P((const char *)); +void p_query __P((const u_char *)); +void res_close __P((void)); +int res_init __P((void)); +int res_isourserver __P((const struct sockaddr_in *)); +int res_mkquery __P((int, const char *, int, int, const u_char *, + int, const u_char *, u_char *, int)); +int res_query __P((const char *, int, int, u_char *, int)); +int res_querydomain __P((const char *, const char *, int, int, + u_char *, int)); +int res_search __P((const char *, int, int, u_char *, int)); +int res_send __P((const u_char *, int, u_char *, int)); +int res_sendsigned __P((const u_char *, int, ns_tsig_key *, + u_char *, int)); +__END_DECLS +#endif + +#if !defined(SHARED_LIBBIND) || defined(LIB) +/* + * If libbind is a shared object (well, DLL anyway) + * these externs break the linker when resolv.h is + * included by a lib client (like named) + * Make them go away if a client is including this + * + */ +extern const struct res_sym __p_key_syms[]; +extern const struct res_sym __p_cert_syms[]; +extern const struct res_sym __p_class_syms[]; +extern const struct res_sym __p_type_syms[]; +extern const struct res_sym __p_rcode_syms[]; +#endif /* SHARED_LIBBIND */ + +#define b64_ntop __b64_ntop +#define b64_pton __b64_pton +#define dn_comp __dn_comp +#define dn_count_labels __dn_count_labels +#define dn_expand __dn_expand +#define dn_skipname __dn_skipname +#define fp_resstat __fp_resstat +#define loc_aton __loc_aton +#define loc_ntoa __loc_ntoa +#define p_cdname __p_cdname +#define p_cdnname __p_cdnname +#define p_class __p_class +#define p_fqname __p_fqname +#define p_fqnname __p_fqnname +#define p_option __p_option +#define p_secstodate __p_secstodate +#define p_section __p_section +#define p_time __p_time +#define p_type __p_type +#define p_rcode __p_rcode +#define putlong __putlong +#define putshort __putshort +#define res_dnok __res_dnok +#define res_findzonecut __res_findzonecut +#define res_hnok __res_hnok +#define res_hostalias __res_hostalias +#define res_mailok __res_mailok +#define res_nameinquery __res_nameinquery +#define res_nclose __res_nclose +#define res_ninit __res_ninit +#define res_nmkquery __res_nmkquery +#define res_pquery __res_pquery +#define res_nquery __res_nquery +#define res_nquerydomain __res_nquerydomain +#define res_nsearch __res_nsearch +#define res_nsend __res_nsend +#define res_nsendsigned __res_nsendsigned +#define res_nisourserver __res_nisourserver +#define res_ownok __res_ownok +#define res_queriesmatch __res_queriesmatch +#define res_randomid __res_randomid +#define sym_ntop __sym_ntop +#define sym_ntos __sym_ntos +#define sym_ston __sym_ston +#define res_nopt __res_nopt +__BEGIN_DECLS +int res_hnok __P((const char *)); +int res_ownok __P((const char *)); +int res_mailok __P((const char *)); +int res_dnok __P((const char *)); +int sym_ston __P((const struct res_sym *, const char *, int *)); +const char * sym_ntos __P((const struct res_sym *, int, int *)); +const char * sym_ntop __P((const struct res_sym *, int, int *)); +int b64_ntop __P((u_char const *, size_t, char *, size_t)); +int b64_pton __P((char const *, u_char *, size_t)); +int loc_aton __P((const char *ascii, u_char *binary)); +const char * loc_ntoa __P((const u_char *binary, char *ascii)); +int dn_skipname __P((const u_char *, const u_char *)); +void putlong __P((u_int32_t, u_char *)); +void putshort __P((u_int16_t, u_char *)); +#ifndef __ultrix__ +u_int16_t _getshort __P((const u_char *src)); +u_int32_t _getlong __P((const u_char *src)); +#endif +const char * p_class __P((int)); +const char * p_time __P((u_int32_t)); +const char * p_type __P((int)); +const char * p_rcode __P((int)); +const u_char * p_cdnname __P((const u_char *, const u_char *, int, FILE *)); +const u_char * p_cdname __P((const u_char *, const u_char *, FILE *)); +const u_char * p_fqnname __P((const u_char *cp, const u_char *msg, + int, char *, int)); +const u_char * p_fqname __P((const u_char *, const u_char *, FILE *)); +const char * p_option __P((u_long option)); +char * p_secstodate __P((u_long)); +int dn_count_labels __P((const char *)); +int dn_comp __P((const char *, u_char *, int, + u_char **, u_char **)); +int dn_expand __P((const u_char *, const u_char *, const u_char *, + char *, int)); +u_int res_randomid __P((void)); +int res_nameinquery __P((const char *, int, int, + const u_char *, const u_char *)); +int res_queriesmatch __P((const u_char *, const u_char *, + const u_char *, const u_char *)); +const char * p_section __P((int section, int opcode)); +/* Things involving a resolver context. */ +int res_ninit __P((res_state)); +int res_nisourserver __P((const res_state, + const struct sockaddr_in *)); +void fp_resstat __P((const res_state, FILE *)); +void res_pquery __P((const res_state, const u_char *, int, FILE *)); +const char * res_hostalias __P((const res_state, const char *, + char *, size_t)); +int res_nquery __P((res_state, + const char *, int, int, u_char *, int)); +int res_nsearch __P((res_state, const char *, int, + int, u_char *, int)); +int res_nquerydomain __P((res_state, + const char *, const char *, int, int, + u_char *, int)); +int res_nmkquery __P((res_state, + int, const char *, int, int, const u_char *, + int, const u_char *, u_char *, int)); +int res_nsend __P((res_state, const u_char *, int, u_char *, int)); +int res_nsendsigned __P((res_state, const u_char *, int, + ns_tsig_key *, u_char *, int)); +int res_findzonecut __P((res_state, const char *, ns_class, int, + char *, size_t, struct in_addr *, int)); +void res_nclose __P((res_state)); +int res_nopt __P((res_state, int, u_char *, int, int)); +void res_send_setqhook __P((res_send_qhook hook)); +void res_send_setrhook __P((res_send_rhook hook)); +int __res_vinit __P((res_state, int)); +void res_destroyservicelist __P((void)); +const char * res_servicename __P((u_int16_t port, const char *proto)); +const char * res_protocolname __P((int num)); +void res_destroyprotolist __P((void)); +void res_buildprotolist __P((void)); +__END_DECLS + +#endif /* !_RESOLV_H_ */ diff --git a/lib/bind/inet/Makefile.in b/lib/bind/inet/Makefile.in new file mode 100644 index 0000000000..34cee176d9 --- /dev/null +++ b/lib/bind/inet/Makefile.in @@ -0,0 +1,16 @@ +OBJS= inet_addr.@O@ inet_cidr_ntop.@O@ inet_cidr_pton.@O@ inet_data.@O@ \ + inet_lnaof.@O@ inet_makeaddr.@O@ inet_net_ntop.@O@ inet_net_pton.@O@ \ + inet_neta.@O@ inet_netof.@O@ inet_network.@O@ inet_ntoa.@O@ \ + inet_ntop.@O@ inet_pton.@O@ nsap_addr.@O@ + +SRCS= inet_addr.c inet_cidr_ntop.c inet_cidr_pton.c inet_data.c \ + inet_lnaof.c inet_makeaddr.c inet_net_ntop.c inet_net_pton.c \ + inet_neta.c inet_netof.c inet_network.c inet_ntoa.c \ + inet_ntop.c inet_pton.c nsap_addr.c + +TARGETS= ${OBJS} + +CINCLUDES= -I.. -I../include +CWARNINGS= -Werror + +@BIND9_MAKE_RULES@ diff --git a/lib/bind/inet/inet_addr.c b/lib/bind/inet/inet_addr.c new file mode 100644 index 0000000000..c978a8771b --- /dev/null +++ b/lib/bind/inet/inet_addr.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 1983, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; +static const char rcsid[] = "$Id: inet_addr.c,v 1.1 2001/03/29 06:31:37 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include + +#include +#include + +#include + +#include "port_after.h" + +/* + * Ascii internet address interpretation routine. + * The value returned is in network order. + */ +u_long +inet_addr(const char *cp) { + struct in_addr val; + + if (inet_aton(cp, &val)) + return (val.s_addr); + return (INADDR_NONE); +} + +/* + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + */ +int +inet_aton(const char *cp, struct in_addr *addr) { + u_long val; + int base, n; + char c; + u_int8_t parts[4]; + u_int8_t *pp = parts; + int digit; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, isdigit=decimal. + */ + if (!isdigit(c)) + return (0); + val = 0; base = 10; digit = 0; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') + base = 16, c = *++cp; + else { + base = 8; + digit = 1 ; + } + } + for (;;) { + if (isascii(c) && isdigit(c)) { + if (base == 8 && (c == '8' || c == '9')) + return (0); + val = (val * base) + (c - '0'); + c = *++cp; + digit = 1; + } else if (base == 16 && isascii(c) && isxdigit(c)) { + val = (val << 4) | + (c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + digit = 1; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3 || val > 0xff) + return (0); + *pp++ = val; + c = *++cp; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && (!isascii(c) || !isspace(c))) + return (0); + /* + * Did we get a valid digit? + */ + if (!digit) + return (0); + /* + * Concoct the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + switch (n) { + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffff) + return (0); + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + if (addr != NULL) + addr->s_addr = htonl(val); + return (1); +} diff --git a/lib/bind/inet/inet_cidr_ntop.c b/lib/bind/inet/inet_cidr_ntop.c new file mode 100644 index 0000000000..35d9f7e685 --- /dev/null +++ b/lib/bind/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 1.1 2001/03/29 06:31:37 marka Exp $"; +#endif + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +static char * inet_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; + size_t 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/lib/bind/inet/inet_cidr_pton.c b/lib/bind/inet/inet_cidr_pton.c new file mode 100644 index 0000000000..67e222bf56 --- /dev/null +++ b/lib/bind/inet/inet_cidr_pton.c @@ -0,0 +1,154 @@ +/* + * 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 1.1 2001/03/29 06:31:37 marka Exp $"; +#endif + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +static int inet_cidr_pton_ipv4 __P((const char *src, u_char *dst, + int *bits)); + +/* + * int + * inet_cidr_pton(af, src, dst, *bits) + * convert network address from presentation to network format. + * accepts inet_pton()'s input for this "af" plus trailing "/CIDR". + * "dst" is assumed large enough for its "af". "bits" is set to the + * /CIDR prefix length, which can have defaults (like /32 for IPv4). + * return: + * -1 if an error occurred (inspect errno; ENOENT means bad format). + * 0 if successful conversion occurred. + * note: + * 192.5.5.1/28 has a nonzero host part, which means it isn't a network + * as called for by inet_net_pton() but it can be a host address with + * an included netmask. + * author: + * Paul Vixie (ISC), October 1998 + */ +int +inet_cidr_pton(int af, const char *src, void *dst, int *bits) { + switch (af) { + case AF_INET: + return (inet_cidr_pton_ipv4(src, dst, bits)); + default: + errno = EAFNOSUPPORT; + return (-1); + } +} + +static int +inet_cidr_pton_ipv4(const char *src, u_char *dst, int *pbits) { + static const char digits[] = "0123456789"; + const u_char *odst = dst; + int n, ch, tmp, bits; + size_t size = 4; + + /* Get the mantissa. */ + while (ch = *src++, (isascii(ch) && isdigit(ch))) { + tmp = 0; + do { + n = strchr(digits, ch) - digits; + INSIST(n >= 0 && n <= 9); + tmp *= 10; + tmp += n; + if (tmp > 255) + goto enoent; + } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch)); + if (size-- == 0) + goto emsgsize; + *dst++ = (u_char) tmp; + if (ch == '\0' || ch == '/') + break; + if (ch != '.') + goto enoent; + } + + /* Get the prefix length if any. */ + bits = -1; + if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) { + /* CIDR width specifier. Nothing can follow it. */ + ch = *src++; /* Skip over the /. */ + bits = 0; + do { + n = strchr(digits, ch) - digits; + INSIST(n >= 0 && n <= 9); + bits *= 10; + bits += n; + } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch)); + if (ch != '\0') + goto enoent; + if (bits > 32) + goto emsgsize; + } + + /* Firey death and destruction unless we prefetched EOS. */ + if (ch != '\0') + goto enoent; + + /* Prefix length can default to /32 only if all four octets spec'd. */ + if (bits == -1) { + if (dst - odst == 4) + bits = 32; + else + goto enoent; + } + + /* If nothing was written to the destination, we found no address. */ + if (dst == odst) + goto enoent; + + /* If prefix length overspecifies mantissa, life is bad. */ + if ((bits / 8) > (dst - odst)) + goto enoent; + + /* Extend address to four octets. */ + while (size-- > 0) + *dst++ = 0; + + *pbits = bits; + return (0); + + enoent: + errno = ENOENT; + return (-1); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} diff --git a/lib/bind/inet/inet_data.c b/lib/bind/inet/inet_data.c new file mode 100644 index 0000000000..197ee67661 --- /dev/null +++ b/lib/bind/inet/inet_data.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1995-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: inet_data.c,v 1.1 2001/03/29 06:31:37 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +#ifndef IN6ADDR_ANY_INIT +#define IN6ADDR_ANY_INIT {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}} +#endif +#ifndef IN6ADDR_LOOPBACK_INIT +#define IN6ADDR_LOOPBACK_INIT {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}} +#endif + + +#ifndef HAS_INET6_STRUCTS +const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; +const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; +#endif diff --git a/lib/bind/inet/inet_lnaof.c b/lib/bind/inet/inet_lnaof.c new file mode 100644 index 0000000000..97b80cffdb --- /dev/null +++ b/lib/bind/inet/inet_lnaof.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_lnaof.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include + +#include "port_after.h" + +/* + * Return the local network address portion of an + * internet address; handles class a/b/c network + * number formats. + */ +u_long +inet_lnaof(in) + struct in_addr in; +{ + register u_long i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return ((i)&IN_CLASSA_HOST); + else if (IN_CLASSB(i)) + return ((i)&IN_CLASSB_HOST); + else + return ((i)&IN_CLASSC_HOST); +} diff --git a/lib/bind/inet/inet_makeaddr.c b/lib/bind/inet/inet_makeaddr.c new file mode 100644 index 0000000000..49ea023df9 --- /dev/null +++ b/lib/bind/inet/inet_makeaddr.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_makeaddr.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include + +#include "port_after.h" + +/* + * Formulate an Internet address from network + host. Used in + * building addresses stored in the ifnet structure. + */ +struct in_addr +inet_makeaddr(net, host) + u_long net, host; +{ + u_long addr; + + if (net < 128) + addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST); + else if (net < 65536) + addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST); + else if (net < 16777216L) + addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST); + else + addr = net | host; + addr = htonl(addr); + return (*(struct in_addr *)&addr); +} diff --git a/lib/bind/inet/inet_net_ntop.c b/lib/bind/inet/inet_net_ntop.c new file mode 100644 index 0000000000..ee6de06f05 --- /dev/null +++ b/lib/bind/inet/inet_net_ntop.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.1 2001/03/29 06:31:38 marka Exp $"; +#endif + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +static char * inet_net_ntop_ipv4 __P((const u_char *src, int bits, + char *dst, size_t size)); + +/* + * char * + * inet_net_ntop(af, src, bits, dst, size) + * convert network number from network to presentation format. + * generates CIDR style result always. + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * author: + * Paul Vixie (ISC), July 1996 + */ +char * +inet_net_ntop(af, src, bits, dst, size) + int af; + const void *src; + int bits; + char *dst; + size_t size; +{ + switch (af) { + case AF_INET: + return (inet_net_ntop_ipv4(src, bits, dst, size)); + default: + errno = EAFNOSUPPORT; + return (NULL); + } +} + +/* + * static char * + * inet_net_ntop_ipv4(src, bits, dst, size) + * convert IPv4 network number from network to presentation format. + * generates CIDR style result always. + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0b11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), July 1996 + */ +static char * +inet_net_ntop_ipv4(src, bits, dst, size) + const u_char *src; + int bits; + char *dst; + size_t size; +{ + char *odst = dst; + char *t; + u_int m; + int b; + + if (bits < 0 || bits > 32) { + errno = EINVAL; + return (NULL); + } + if (bits == 0) { + if (size < sizeof "0") + goto emsgsize; + *dst++ = '0'; + size--; + *dst = '\0'; + } + + /* Format whole octets. */ + for (b = bits / 8; b > 0; b--) { + if (size <= sizeof "255.") + goto emsgsize; + t = dst; + dst += SPRINTF((dst, "%u", *src++)); + if (b > 1) { + *dst++ = '.'; + *dst = '\0'; + } + size -= (size_t)(dst - t); + } + + /* Format partial octet. */ + b = bits % 8; + if (b > 0) { + if (size <= sizeof ".255") + goto emsgsize; + t = dst; + if (dst != odst) + *dst++ = '.'; + m = ((1 << b) - 1) << (8 - b); + dst += SPRINTF((dst, "%u", *src & m)); + size -= (size_t)(dst - t); + } + + /* Format CIDR /width. */ + if (size <= sizeof "/32") + goto emsgsize; + dst += SPRINTF((dst, "/%u", bits)); + return (odst); + + emsgsize: + errno = EMSGSIZE; + return (NULL); +} diff --git a/lib/bind/inet/inet_net_pton.c b/lib/bind/inet/inet_net_pton.c new file mode 100644 index 0000000000..523af34eb5 --- /dev/null +++ b/lib/bind/inet/inet_net_pton.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_net_pton.c,v 1.1 2001/03/29 06:31:38 marka Exp $"; +#endif + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +static int inet_net_pton_ipv4 __P((const char *src, u_char *dst, + size_t size)); + +/* + * static int + * inet_net_pton(af, src, dst, size) + * convert network number from presentation to network format. + * accepts hex octets, hex strings, decimal octets, and /CIDR. + * "size" is in bytes and describes "dst". + * return: + * number of bits, either imputed classfully or specified with /CIDR, + * or -1 if some failure occurred (check errno). ENOENT means it was + * not a valid network specification. + * author: + * Paul Vixie (ISC), June 1996 + */ +int +inet_net_pton(af, src, dst, size) + int af; + const char *src; + void *dst; + size_t size; +{ + switch (af) { + case AF_INET: + return (inet_net_pton_ipv4(src, dst, size)); + default: + errno = EAFNOSUPPORT; + return (-1); + } +} + +/* + * static int + * inet_net_pton_ipv4(src, dst, size) + * convert IPv4 network number from presentation to network format. + * accepts hex octets, hex strings, decimal octets, and /CIDR. + * "size" is in bytes and describes "dst". + * return: + * number of bits, either imputed classfully or specified with /CIDR, + * or -1 if some failure occurred (check errno). ENOENT means it was + * not an IPv4 network specification. + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0b11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), June 1996 + */ +static int +inet_net_pton_ipv4(src, dst, size) + const char *src; + u_char *dst; + size_t size; +{ + static const char + xdigits[] = "0123456789abcdef", + digits[] = "0123456789"; + int n, ch, tmp = 0, dirty, bits; + const u_char *odst = dst; + + ch = *src++; + if (ch == '0' && (src[0] == 'x' || src[0] == 'X') + && isascii(src[1]) && isxdigit(src[1])) { + /* Hexadecimal: Eat nybble string. */ + if (size <= 0) + goto emsgsize; + dirty = 0; + src++; /* skip x or X. */ + while ((ch = *src++) != '\0' && isascii(ch) && isxdigit(ch)) { + if (isupper(ch)) + ch = tolower(ch); + n = strchr(xdigits, ch) - xdigits; + INSIST(n >= 0 && n <= 15); + if (dirty == 0) + tmp = n; + else + tmp = (tmp << 4) | n; + if (++dirty == 2) { + if (size-- <= 0) + goto emsgsize; + *dst++ = (u_char) tmp; + dirty = 0; + } + } + if (dirty) { /* Odd trailing nybble? */ + if (size-- <= 0) + goto emsgsize; + *dst++ = (u_char) (tmp << 4); + } + } else if (isascii(ch) && isdigit(ch)) { + /* Decimal: eat dotted digit string. */ + for (;;) { + tmp = 0; + do { + n = strchr(digits, ch) - digits; + INSIST(n >= 0 && n <= 9); + tmp *= 10; + tmp += n; + if (tmp > 255) + goto enoent; + } while ((ch = *src++) != '\0' && + isascii(ch) && isdigit(ch)); + if (size-- <= 0) + goto emsgsize; + *dst++ = (u_char) tmp; + if (ch == '\0' || ch == '/') + break; + if (ch != '.') + goto enoent; + ch = *src++; + if (!isascii(ch) || !isdigit(ch)) + goto enoent; + } + } else + goto enoent; + + bits = -1; + if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) { + /* CIDR width specifier. Nothing can follow it. */ + ch = *src++; /* Skip over the /. */ + bits = 0; + do { + n = strchr(digits, ch) - digits; + INSIST(n >= 0 && n <= 9); + bits *= 10; + bits += n; + } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch)); + if (ch != '\0') + goto enoent; + if (bits > 32) + goto emsgsize; + } + + /* Firey death and destruction unless we prefetched EOS. */ + if (ch != '\0') + goto enoent; + + /* If nothing was written to the destination, we found no address. */ + if (dst == odst) + goto enoent; + /* If no CIDR spec was given, infer width from net class. */ + if (bits == -1) { + if (*odst >= 240) /* Class E */ + bits = 32; + else if (*odst >= 224) /* Class D */ + bits = 4; + else if (*odst >= 192) /* Class C */ + bits = 24; + else if (*odst >= 128) /* Class B */ + bits = 16; + else /* Class A */ + bits = 8; + /* If imputed mask is narrower than specified octets, widen. */ + if (bits >= 8 && bits < ((dst - odst) * 8)) + bits = (dst - odst) * 8; + } + /* Extend network to cover the actual mask. */ + while (bits > ((dst - odst) * 8)) { + if (size-- <= 0) + goto emsgsize; + *dst++ = '\0'; + } + return (bits); + + enoent: + errno = ENOENT; + return (-1); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} diff --git a/lib/bind/inet/inet_neta.c b/lib/bind/inet/inet_neta.c new file mode 100644 index 0000000000..0f6124a8c2 --- /dev/null +++ b/lib/bind/inet/inet_neta.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_neta.c,v 1.1 2001/03/29 06:31:38 marka Exp $"; +#endif + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* + * char * + * inet_neta(src, dst, size) + * format a u_long network number into presentation format. + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * format of ``src'' is as for inet_network(). + * author: + * Paul Vixie (ISC), July 1996 + */ +char * +inet_neta(src, dst, size) + u_long src; + char *dst; + size_t size; +{ + char *odst = dst; + char *tp; + + while (src & 0xffffffff) { + u_char b = (src & 0xff000000) >> 24; + + src <<= 8; + if (b) { + if (size < sizeof "255.") + goto emsgsize; + tp = dst; + dst += SPRINTF((dst, "%u", b)); + if (src != 0L) { + *dst++ = '.'; + *dst = '\0'; + } + size -= (size_t)(dst - tp); + } + } + if (dst == odst) { + if (size < sizeof "0.0.0.0") + goto emsgsize; + strcpy(dst, "0.0.0.0"); + } + return (odst); + + emsgsize: + errno = EMSGSIZE; + return (NULL); +} diff --git a/lib/bind/inet/inet_netof.c b/lib/bind/inet/inet_netof.c new file mode 100644 index 0000000000..e887530088 --- /dev/null +++ b/lib/bind/inet/inet_netof.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_netof.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include + +#include "port_after.h" + +/* + * Return the network number from an internet + * address; handles class a/b/c network #'s. + */ +u_long +inet_netof(in) + struct in_addr in; +{ + register u_long i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); + else if (IN_CLASSB(i)) + return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); + else + return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); +} diff --git a/lib/bind/inet/inet_network.c b/lib/bind/inet/inet_network.c new file mode 100644 index 0000000000..d26369cf16 --- /dev/null +++ b/lib/bind/inet/inet_network.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_network.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include "port_after.h" + +/* + * Internet network address interpretation routine. + * The library routines call this routine to interpret + * network numbers. + */ +u_long +inet_network(cp) + register const char *cp; +{ + register u_long val, base, n, i; + register char c; + u_long parts[4], *pp = parts; + int digit; + +again: + val = 0; base = 10; digit = 0; + if (*cp == '0') + digit = 1, base = 8, cp++; + if (*cp == 'x' || *cp == 'X') + base = 16, cp++; + while ((c = *cp) != 0) { + if (isdigit(c)) { + if (base == 8 && (c == '8' || c == '9')) + return (INADDR_NONE); + val = (val * base) + (c - '0'); + cp++; + digit = 1; + continue; + } + if (base == 16 && isxdigit(c)) { + val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A')); + cp++; + digit = 1; + continue; + } + break; + } + if (!digit) + return (INADDR_NONE); + if (*cp == '.') { + if (pp >= parts + 4 || val > 0xff) + return (INADDR_NONE); + *pp++ = val, cp++; + goto again; + } + if (*cp && !isspace(*cp)) + return (INADDR_NONE); + *pp++ = val; + n = pp - parts; + if (n > 4) + return (INADDR_NONE); + for (val = 0, i = 0; i < n; i++) { + val <<= 8; + val |= parts[i] & 0xff; + } + return (val); +} diff --git a/lib/bind/inet/inet_ntoa.c b/lib/bind/inet/inet_ntoa.c new file mode 100644 index 0000000000..7fad4b8902 --- /dev/null +++ b/lib/bind/inet/inet_ntoa.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_ntoa.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: inet_ntoa.c,v 1.1 2001/03/29 06:31:38 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +/* + * Convert network-format internet address + * to base 256 d.d.d.d representation. + */ +/*const*/ char * +inet_ntoa(struct in_addr in) { + static char ret[18]; + + strcpy(ret, "[inet_ntoa error]"); + (void) inet_ntop(AF_INET, &in, ret, sizeof ret); + return (ret); +} diff --git a/lib/bind/inet/inet_ntop.c b/lib/bind/inet/inet_ntop.c new file mode 100644 index 0000000000..27d558ecec --- /dev/null +++ b/lib/bind/inet/inet_ntop.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_ntop.c,v 1.1 2001/03/29 06:31:39 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *inet_ntop4 __P((const u_char *src, char *dst, size_t size)); +static const char *inet_ntop6 __P((const u_char *src, char *dst, size_t size)); + +/* char * + * inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +inet_ntop(af, src, dst, size) + int af; + const void *src; + char *dst; + size_t size; +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); + case AF_INET6: + return (inet_ntop6(src, dst, size)); + default: + errno = EAFNOSUPPORT; + return (NULL); + } + /* NOTREACHED */ +} + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(src, dst, size) + const u_char *src; + char *dst; + size_t size; +{ + static const char fmt[] = "%u.%u.%u.%u"; + char tmp[sizeof "255.255.255.255"]; + + if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) >= size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} + +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop6(src, dst, size) + const u_char *src; + char *dst; + size_t size; +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; + struct { int base, len; } best, cur; + u_int words[NS_IN6ADDRSZ / NS_INT16SZ]; + int i; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < NS_IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + cur.base = -1; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) + return (NULL); + tp += strlen(tp); + break; + } + tp += SPRINTF((tp, "%x", words[i])); + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == + (NS_IN6ADDRSZ / NS_INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((size_t)(tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} diff --git a/lib/bind/inet/inet_pton.c b/lib/bind/inet/inet_pton.c new file mode 100644 index 0000000000..6939843456 --- /dev/null +++ b/lib/bind/inet/inet_pton.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_pton.c,v 1.1 2001/03/29 06:31:41 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "port_after.h" + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static int inet_pton4 __P((const char *src, u_char *dst)); +static int inet_pton6 __P((const char *src, u_char *dst)); + +/* int + * inet_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * author: + * Paul Vixie, 1996. + */ +int +inet_pton(af, src, dst) + int af; + const char *src; + void *dst; +{ + switch (af) { + case AF_INET: + return (inet_pton4(src, dst)); + case AF_INET6: + return (inet_pton6(src, dst)); + default: + errno = EAFNOSUPPORT; + return (-1); + } + /* NOTREACHED */ +} + +/* int + * inet_pton4(src, dst) + * like inet_aton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(src, dst) + const char *src; + u_char *dst; +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + u_char tmp[NS_INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr(digits, ch)) != NULL) { + u_int new = *tp * 10 + (pch - digits); + + if (new > 255) + return (0); + *tp = new; + if (! saw_digit) { + if (++octets > 4) + return (0); + saw_digit = 1; + } + } else if (ch == '.' && saw_digit) { + if (octets == 4) + return (0); + *++tp = 0; + saw_digit = 0; + } else + return (0); + } + if (octets < 4) + return (0); + memcpy(dst, tmp, NS_INADDRSZ); + return (1); +} + +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton6(src, dst) + const char *src; + u_char *dst; +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + u_int val; + + memset((tp = tmp), '\0', NS_IN6ADDRSZ); + endp = tp + NS_IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } else if (*src == '\0') { + return (0); + } + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return (0); + } + if (saw_xdigit) { + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + if (tp == endp) + return (0); + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return (0); + memcpy(dst, tmp, NS_IN6ADDRSZ); + return (1); +} diff --git a/lib/bind/inet/nsap_addr.c b/lib/bind/inet/nsap_addr.c new file mode 100644 index 0000000000..f6a6d67eb2 --- /dev/null +++ b/lib/bind/inet/nsap_addr.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAI! + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANT! + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF TH! + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nsap_addr.c,v 1.1 2001/03/29 06:31:41 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "port_after.h" + +static char +xtob(int c) { + return (c - (((c >= '0') && (c <= '9')) ? '0' : '7')); +} + +u_int +inet_nsap_addr(const char *ascii, u_char *binary, int maxlen) { + u_char c, nib; + u_int len = 0; + + while ((c = *ascii++) != '\0' && len < (u_int)maxlen) { + if (c == '.' || c == '+' || c == '/') + continue; + if (!isascii(c)) + return (0); + if (islower(c)) + c = toupper(c); + if (isxdigit(c)) { + nib = xtob(c); + c = *ascii++; + if (c != '\0') { + c = toupper(c); + if (isxdigit(c)) { + *binary++ = (nib << 4) | xtob(c); + len++; + } else + return (0); + } + else + return (0); + } + else + return (0); + } + return (len); +} + +char * +inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii) { + int nib; + int i; + static char tmpbuf[255*3]; + char *start; + + if (ascii) + start = ascii; + else { + ascii = tmpbuf; + start = tmpbuf; + } + + if (binlen > 255) + binlen = 255; + + for (i = 0; i < binlen; i++) { + nib = *binary >> 4; + *ascii++ = nib + (nib < 10 ? '0' : '7'); + nib = *binary++ & 0x0f; + *ascii++ = nib + (nib < 10 ? '0' : '7'); + if (((i % 2) == 0 && (i + 1) < binlen)) + *ascii++ = '.'; + } + *ascii = '\0'; + return (start); +} diff --git a/lib/bind/irs/Makefile.in b/lib/bind/irs/Makefile.in new file mode 100644 index 0000000000..69bd9c69d8 --- /dev/null +++ b/lib/bind/irs/Makefile.in @@ -0,0 +1,49 @@ +WANT_IRS_THREADS_OBJS= gethostent_r.@O@ getnetgrent_r.@O@ \ + getprotoent_r.@O@ getservent_r.@O@ + +WANT_IRS_NISGR_OBJ= nis_gr.@O@ +WANT_IRS_GR_OBJS= dns_gr.@O@ irp_gr.@O@ lcl_gr.@O@ gen_gr.@O@ getgrent.@O@ \ + @WANT_IRS_NISGR_OBJS@ @WANT_IRS_THREADSGR_OBJS@ + +WANT_IRS_THREADSPW_OBJS=getpwent_r.@O@ +WANT_IRS_NISPW_OBJS= nis_pw.@O@ +WANT_IRS_PW_OBJS= dns_pw.@O@ irp_pw.@O@ lcl_pw.@O@ gen_pw.@O@ getpwent.@O@ \ + @WANT_IRS_NISPW_OBJS@ @WANT_IRS_THREADSPW_OBJS@ + +WANT_IRS_NIS_OBJS= \ + nis_ho.@O@ nis_ng.@O@ nis_nw.@O@ nis_pr.@O@ nis_sv.@O@ + +OBJS= @WANT_IRS_GR_OBJS@ @WANT_IRS_NIS_OBJS@ @WANT_IRS_THREADS_OBJS@ \ + dns.@O@ dns_ho.@O@ dns_nw.@O@ dns_pr.@O@ \ + dns_sv.@O@ gai_strerror.@O@ gen.@O@ gen_ho.@O@ \ + gen_ng.@O@ gen_nw.@O@ gen_pr.@O@ gen_sv.@O@ \ + getaddrinfo.@O@ gethostent.@O@ \ + getnameinfo.@O@ getnetent.@O@ getnetent_r.@O@ \ + getnetgrent.@O@ getprotoent.@O@ getservent.@O@ \ + hesiod.@O@ irp.@O@ irp_ho.@O@ irp_ng.@O@ irp_nw.@O@ \ + irp_pr.@O@ irp_sv.@O@ irpmarshall.@O@ irs_data.@O@ \ + lcl.@O@ lcl_ho.@O@ lcl_ng.@O@ lcl_nw.@O@ lcl_pr.@O@ \ + lcl_sv.@O@ nis.@O@ nul_ng.@O@ util.@O@ + +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 gethostent.c \ + getnameinfo.c getnetent.c getnetent_r.c \ + getnetgrent.c getprotoent.c getpwent.c getservent.c \ + hesiod.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 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 getgrent_r.c gethostent_r.c getnetgrent_r.c getprotoent_r.c \ + getpwent_r.c getservent_r.c + +WANT_IRS_THREADSGR_OBJS=getgrent_r.@O@ + +TARGETS= ${OBJS} + +CINCLUDES= -I.. -I../include +CWARNINGS= -Werror + +@BIND9_MAKE_RULES@ diff --git a/lib/bind/irs/dns.c b/lib/bind/irs/dns.c new file mode 100644 index 0000000000..1077623d41 --- /dev/null +++ b/lib/bind/irs/dns.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns.c,v 1.1 2001/03/29 06:31:42 marka Exp $"; +#endif + +/* + * dns.c --- this is the top-level accessor function for the dns + */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* forward */ + +static void dns_close(struct irs_acc *); +static struct __res_state * dns_res_get(struct irs_acc *); +static void dns_res_set(struct irs_acc *, struct __res_state *, + void (*)(void *)); + +/* public */ + +struct irs_acc * +irs_dns_acc(const char *options) { + struct irs_acc *acc; + struct dns_p *dns; + + UNUSED(options); + + if (!(acc = memget(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(dns = memget(sizeof *dns))) { + errno = ENOMEM; + memput(acc, sizeof *acc); + return (NULL); + } + memset(dns, 0x5e, sizeof *dns); + dns->res = NULL; + dns->free_res = NULL; + if (hesiod_init(&dns->hes_ctx) < 0) { + /* + * We allow the dns accessor class to initialize + * despite hesiod failing to initialize correctly, + * since dns host queries don't depend on hesiod. + */ + dns->hes_ctx = NULL; + } + acc->private = dns; +#ifdef WANT_IRS_GR + acc->gr_map = irs_dns_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_dns_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_dns_sv; + acc->pr_map = irs_dns_pr; + acc->ho_map = irs_dns_ho; + acc->nw_map = irs_dns_nw; + acc->ng_map = irs_nul_ng; + acc->res_get = dns_res_get; + acc->res_set = dns_res_set; + acc->close = dns_close; + return (acc); +} + +/* methods */ +static struct __res_state * +dns_res_get(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + + if (dns->res == NULL) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) + return (NULL); + memset(dns->res, 0, sizeof *dns->res); + dns_res_set(this, res, free); + } + + if ((dns->res->options & RES_INIT) == 0 && + res_ninit(dns->res) < 0) + return (NULL); + + return (dns->res); +} + +static void +dns_res_set(struct irs_acc *this, struct __res_state *res, + void (*free_res)(void *)) { + struct dns_p *dns = (struct dns_p *)this->private; + + if (dns->res && dns->free_res) { + res_nclose(dns->res); + (*dns->free_res)(dns->res); + } + dns->res = res; + dns->free_res = free_res; +} + +static void +dns_close(struct irs_acc *this) { + struct dns_p *dns; + + dns = (struct dns_p *)this->private; + if (dns->res && dns->free_res) + (*dns->free_res)(dns->res); + if (dns->hes_ctx) + hesiod_end(dns->hes_ctx); + memput(dns, sizeof *dns); + memput(this, sizeof *this); +} + diff --git a/lib/bind/irs/dns_gr.c b/lib/bind/irs/dns_gr.c new file mode 100644 index 0000000000..a47ba1e412 --- /dev/null +++ b/lib/bind/irs/dns_gr.c @@ -0,0 +1,293 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_gr.c,v 1.1 2001/03/29 06:31:42 marka Exp $"; +#endif + +/* + * dns_gr.c --- this file contains the functions for accessing + * group information from Hesiod. + */ + +#include "port_before.h" + +#ifndef WANT_IRS_GR +static int __bind_irs_gr_unneeded; +#else + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Types. */ + +struct pvt { + /* + * This is our private accessor data. It has a shared hesiod context. + */ + struct dns_p * dns; + /* + * Need space to store the entries read from the group file. + * The members list also needs space per member, and the + * strings making up the user names must be allocated + * somewhere. Rather than doing lots of small allocations, + * we keep one buffer and resize it as needed. + */ + struct group group; + size_t nmemb; /* Malloc'd max index of gr_mem[]. */ + char * membuf; + size_t membufsize; +}; + +/* Forward. */ + +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static void gr_close(struct irs_gr *); +static int gr_list(struct irs_gr *, const char *, + gid_t, gid_t *, int *); +static void gr_minimize(struct irs_gr *); +static struct __res_state * gr_res_get(struct irs_gr *); +static void gr_res_set(struct irs_gr *, + struct __res_state *, + void (*)(void *)); + +static struct group * get_hes_group(struct irs_gr *this, + const char *name, + const char *type); + +/* Public. */ + +struct irs_gr * +irs_dns_gr(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + struct irs_gr *gr; + struct pvt *pvt; + + if (!dns || !dns->hes_ctx) { + errno = ENODEV; + return (NULL); + } + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->dns = dns; + if (!(gr = memget(sizeof *gr))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x5e, sizeof *gr); + gr->private = pvt; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->close = gr_close; + gr->list = gr_list; + gr->minimize = gr_minimize; + gr->res_get = gr_res_get; + gr->res_set = gr_res_set; + return (gr); +} + +/* methods */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->group.gr_mem) + free(pvt->group.gr_mem); + if (pvt->membuf) + free(pvt->membuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct group * +gr_next(struct irs_gr *this) { + + UNUSED(this); + + return (NULL); +} + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + return (get_hes_group(this, name, "group")); +} + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + char name[32]; + + sprintf(name, "%ld", (long)gid); + return (get_hes_group(this, name, "gid")); +} + +static void +gr_rewind(struct irs_gr *this) { + + UNUSED(this); + + /* NOOP */ +} + +static int +gr_list(struct irs_gr *this, const char *name, + gid_t basegid, gid_t *groups, int *ngroups) +{ + UNUSED(this); + UNUSED(name); + UNUSED(basegid); + UNUSED(groups); + + *ngroups = 0; + /* There's some way to do this in Hesiod. */ + return (-1); +} + +static void +gr_minimize(struct irs_gr *this) { + + UNUSED(this); + /* NOOP */ +} + +/* Private. */ + +static struct group * +get_hes_group(struct irs_gr *this, const char *name, const char *type) { + struct pvt *pvt = (struct pvt *)this->private; + char **hes_list, *cp, **new; + size_t num_members = 0; + u_long t; + + hes_list = hesiod_resolve(pvt->dns->hes_ctx, name, type); + if (!hes_list) + return (NULL); + + /* + * Copy the returned hesiod string into storage space. + */ + if (pvt->membuf) + free(pvt->membuf); + pvt->membuf = strdup(*hes_list); + hesiod_free_list(pvt->dns->hes_ctx, hes_list); + + cp = pvt->membuf; + pvt->group.gr_name = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->group.gr_passwd = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + errno = -1; + t = strtoul(cp, NULL, 10); + if (errno == ERANGE) + goto cleanup; + pvt->group.gr_gid = (gid_t) t; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + cp++; + + /* + * Parse the members out. + */ + while (*cp) { + if (num_members+1 >= pvt->nmemb || pvt->group.gr_mem == NULL) { + pvt->nmemb += 10; + new = realloc(pvt->group.gr_mem, + pvt->nmemb * sizeof(char *)); + if (new == NULL) + goto cleanup; + pvt->group.gr_mem = new; + } + pvt->group.gr_mem[num_members++] = cp; + if (!(cp = strchr(cp, ','))) + break; + *cp++ = '\0'; + } + if (!pvt->group.gr_mem) { + pvt->group.gr_mem = malloc(sizeof(char*)); + if (!pvt->group.gr_mem) + goto cleanup; + } + pvt->group.gr_mem[num_members] = NULL; + + return (&pvt->group); + + cleanup: + if (pvt->group.gr_mem) { + free(pvt->group.gr_mem); + pvt->group.gr_mem = NULL; + } + if (pvt->membuf) { + free(pvt->membuf); + pvt->membuf = NULL; + } + return (NULL); +} + +static struct __res_state * +gr_res_get(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + return (__hesiod_res_get(dns->hes_ctx)); +} + +static void +gr_res_set(struct irs_gr *this, struct __res_state * res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + __hesiod_res_set(dns->hes_ctx, res, free_res); +} + +#endif /* WANT_IRS_GR */ diff --git a/lib/bind/irs/dns_ho.c b/lib/bind/irs/dns_ho.c new file mode 100644 index 0000000000..fedbc0ed9d --- /dev/null +++ b/lib/bind/irs/dns_ho.c @@ -0,0 +1,1606 @@ +/* + * Copyright (c) 1985, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* from gethostnamadr.c 8.1 (Berkeley) 6/4/93 */ +/* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_ho.c,v 1.1 2001/03/29 06:31:42 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "dns_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +/* Definitions. */ + +#define MAXALIASES 35 +#define MAXADDRS 35 + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +#define BOUNDS_CHECK(ptr, count) \ + if ((ptr) + (count) > eom) { \ + had_error++; \ + continue; \ + } else (void)0 + +typedef union { + HEADER hdr; + u_char buf[MAXPACKET]; +} querybuf; + +struct dns_res_target { + struct dns_res_target *next; + querybuf qbuf; /* query buffer */ + u_char *answer; /* buffer to put answer */ + int anslen; /* size of answer buffer */ + int qclass, qtype; /* class and type of query */ + int action; /* condition whether query is really issued */ + char qname[MAXDNAME +1]; /* domain name */ +#if 0 + int n; /* result length */ +#endif +}; +enum {RESTGT_DOALWAYS, RESTGT_AFTERFAILURE, RESTGT_IGNORE}; +enum {RESQRY_SUCCESS, RESQRY_FAIL}; + +struct pvt { + struct hostent host; + char * h_addr_ptrs[MAXADDRS + 1]; + char * host_aliases[MAXALIASES]; + char hostbuf[8*1024]; + u_char host_addr[16]; /* IPv4 or IPv6 */ + struct __res_state *res; + void (*free_res)(void *); +}; + +typedef union { + int32_t al; + char ac; +} align; + +static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; +static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; +/* Note: the IPv6 loopback address is in the "tunnel" space */ +static const u_char v6local[] = { 0,0, 0,1 }; /* last 4 bytes of IPv6 addr */ + +/* Forwards. */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); +static struct __res_state * ho_res_get(struct irs_ho *this); +static void ho_res_set(struct irs_ho *this, + struct __res_state *res, + void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +static void map_v4v6_hostent(struct hostent *hp, char **bp, + int *len); +static void addrsort(res_state, char **, int); +static struct hostent * gethostans(struct irs_ho *this, + const u_char *ansbuf, int anslen, + const char *qname, int qtype, + int af, int size, + struct addrinfo **ret_aip, + const struct addrinfo *pai); +static int add_hostent(struct pvt *pvt, char *bp, char **hap, + struct addrinfo *ai); +static const u_char * ar_head(const u_char *, int, const u_char *, + const u_char *, struct pvt *, + int (*)(const char *)); +static struct addrinfo * a6_expand(const u_char *, const u_char *, int, + const u_char *, const u_char *, + const struct in6_addr *, int, + const struct addrinfo *, + struct pvt *, int (*)(const char *), int *); +static const char *dname_subst(const char *, const char *, const char *); +static int init(struct irs_ho *this); + +/* Exports. */ + +struct irs_ho * +irs_dns_ho(struct irs_acc *this) { + struct irs_ho *ho; + struct pvt *pvt; + + UNUSED(this); + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + + if (!(ho = memget(sizeof *ho))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->res_get = ho_res_get; + ho->res_set = ho_res_set; + ho->addrinfo = ho_addrinfo; + return (ho); +} + +/* Methods. */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + if (pvt) + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + + if (init(this) == -1) + return (NULL); + + if (pvt->res->options & RES_USE_INET6) { + hp = ho_byname2(this, name, AF_INET6); + if (hp) + return (hp); + } + return (ho_byname2(this, name, AF_INET)); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp = NULL; + int n, size; + char tmp[NS_MAXDNAME]; + const char *cp; + struct addrinfo ai; + struct dns_res_target q, q2, *p; + int querystate = RESQRY_FAIL; + + if (init(this) == -1) + return (NULL); + + memset(&q, 0, sizeof(q2)); + memset(&q2, 0, sizeof(q2)); + + switch (af) { + case AF_INET: + size = INADDRSZ; + q.qclass = C_IN; + q.qtype = T_A; + q.answer = q.qbuf.buf; + q.anslen = sizeof(q.qbuf); + q.action = RESTGT_DOALWAYS; + break; + case AF_INET6: + size = IN6ADDRSZ; + q.qclass = C_IN; + q.qtype = ns_t_a6; + q.answer = q.qbuf.buf; + q.anslen = sizeof(q.qbuf); + q.next = &q2; +#ifdef RES_USE_A6 + if ((pvt->res->options & RES_USE_A6) == 0) + q.action = RESTGT_IGNORE; + else +#endif + q.action = RESTGT_DOALWAYS; + q2.qclass = C_IN; + q2.qtype = T_AAAA; + q2.answer = q2.qbuf.buf; + q2.anslen = sizeof(q2.qbuf); + q2.action = RESTGT_AFTERFAILURE; + break; + default: + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + return (NULL); + } + + /* + * if there aren't any dots, it could be a user-level alias. + * this is also done in res_nquery() since we are not the only + * function that looks up host names. + */ + if (!strchr(name, '.') && (cp = res_hostalias(pvt->res, name, + tmp, sizeof tmp))) + name = cp; + + for (p = &q; p; p = p->next) { + switch(p->action) { + case RESTGT_DOALWAYS: + break; + case RESTGT_AFTERFAILURE: + if (querystate == RESQRY_SUCCESS) + continue; + break; + case RESTGT_IGNORE: + continue; + } + + if ((n = res_nsearch(pvt->res, name, p->qclass, p->qtype, + p->answer, p->anslen)) < 0) { + querystate = RESQRY_FAIL; + continue; + } + + memset(&ai, 0, sizeof(ai)); + ai.ai_family = af; + if ((hp = gethostans(this, p->answer, n, name, p->qtype, + af, size, NULL, + (const struct addrinfo *)&ai)) != NULL) + return(hp); /* no more loop is necessary */ + + querystate = RESQRY_FAIL; + continue; + } + + return(hp); /* should be NULL */ +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) +{ + struct pvt *pvt = (struct pvt *)this->private; + const u_char *uaddr = addr; + char *qp; + struct hostent *hp; + struct addrinfo ai; + struct dns_res_target q, q2, *p; + int n, size; + int querystate = RESQRY_FAIL; + + if (init(this) == -1) + return (NULL); + + memset(&q, 0, sizeof(q2)); + memset(&q2, 0, sizeof(q2)); + + if (af == AF_INET6 && len == IN6ADDRSZ && + (!memcmp(uaddr, mapped, sizeof mapped) || + (!memcmp(uaddr, tunnelled, sizeof tunnelled) && + memcmp(&uaddr[sizeof tunnelled], v6local, sizeof(v6local))))) { + /* Unmap. */ + addr = (const char *)addr + sizeof mapped; + uaddr += sizeof mapped; + af = AF_INET; + len = INADDRSZ; + } + switch (af) { + case AF_INET: + size = INADDRSZ; + q.qclass = C_IN; + q.qtype = T_PTR; + q.answer = q.qbuf.buf; + q.anslen = sizeof(q.qbuf); + q.action = RESTGT_DOALWAYS; + break; + case AF_INET6: + size = IN6ADDRSZ; + q.qclass = C_IN; + q.qtype = T_PTR; + q.answer = q.qbuf.buf; + q.anslen = sizeof(q.qbuf); + q.next = &q2; +#ifdef RES_USE_DNAME + if ((pvt->res->options & RES_USE_DNAME) == 0) + q.action = RESTGT_IGNORE; + else +#endif + q.action = RESTGT_DOALWAYS; + q2.qclass = C_IN; + q2.qtype = T_PTR; + q2.answer = q2.qbuf.buf; + q2.anslen = sizeof(q2.qbuf); + q2.action = RESTGT_AFTERFAILURE; + break; + default: + errno = EAFNOSUPPORT; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + if (size > len) { + errno = EINVAL; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + switch (af) { + case AF_INET: + qp = q.qname; + (void) sprintf(qp, "%u.%u.%u.%u.in-addr.arpa", + (uaddr[3] & 0xff), + (uaddr[2] & 0xff), + (uaddr[1] & 0xff), + (uaddr[0] & 0xff)); + break; + case AF_INET6: + if (q.action != RESTGT_IGNORE) { + qp = q.qname; + qp += SPRINTF((qp, "\\[x")); + for (n = 0; n < IN6ADDRSZ; n++) + qp += SPRINTF((qp, "%02x", uaddr[n])); + strcpy(qp, "/128].ip6.arpa"); + } + qp = q2.qname; + for (n = IN6ADDRSZ - 1; n >= 0; n--) { + qp += SPRINTF((qp, "%x.%x.", + uaddr[n] & 0xf, + (uaddr[n] >> 4) & 0xf)); + } + strcpy(qp, "ip6.int"); + break; + default: + abort(); + } + + for (p = &q; p; p = p->next) { + switch(p->action) { + case RESTGT_DOALWAYS: + break; + case RESTGT_AFTERFAILURE: + if (querystate == RESQRY_SUCCESS) + continue; + break; + case RESTGT_IGNORE: + continue; + } + + if ((n = res_nsearch(pvt->res, p->qname, p->qclass, p->qtype, + p->answer, p->anslen)) < 0) { + querystate = RESQRY_FAIL; + continue; + } + + if ((n = res_nquery(pvt->res, p->qname, C_IN, T_PTR, p->answer, + p->anslen)) < 0) { + querystate = RESQRY_FAIL; + continue; + } + + memset(&ai, 0, sizeof(ai)); + ai.ai_family = af; + hp = gethostans(this, p->answer, n, p->qname, T_PTR, af, size, + NULL, (const struct addrinfo *)&ai); + if (!hp) { + querystate = RESQRY_FAIL; + continue; + } + + memcpy(pvt->host_addr, addr, len); + pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; + pvt->h_addr_ptrs[1] = NULL; + if (af == AF_INET && (pvt->res->options & RES_USE_INET6)) { + map_v4v6_address((char*)pvt->host_addr, + (char*)pvt->host_addr); + pvt->host.h_addrtype = AF_INET6; + pvt->host.h_length = IN6ADDRSZ; + } + + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (hp); /* no more loop is necessary. */ + } + + return(NULL); /* H_ERRNO was set by subroutines */ +} + +static struct hostent * +ho_next(struct irs_ho *this) { + + UNUSED(this); + + return (NULL); +} + +static void +ho_rewind(struct irs_ho *this) { + + UNUSED(this); + + /* NOOP */ +} + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +ho_res_get(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + ho_res_set(this, res, free); + } + + return (pvt->res); +} + +/* XXX */ +extern struct addrinfo *addr2addrinfo __P((const struct addrinfo *, + const char *)); + +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + int n; + char tmp[NS_MAXDNAME]; + const char *cp; + struct dns_res_target q, q2, q3, *p; + struct addrinfo sentinel, *cur; + int querystate = RESQRY_FAIL; + + if (init(this) == -1) + return (NULL); + + memset(&q, 0, sizeof(q2)); + memset(&q2, 0, sizeof(q2)); + memset(&q3, 0, sizeof(q3)); + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + switch (pai->ai_family) { + case AF_UNSPEC: + /* prefer IPv6 */ + q.qclass = C_IN; + q.qtype = ns_t_a6; + q.answer = q.qbuf.buf; + q.anslen = sizeof(q.qbuf); + q.next = &q2; +#ifdef RES_USE_A6 + if ((pvt->res->options & RES_USE_A6) == 0) + q.action = RESTGT_IGNORE; + else +#endif + q.action = RESTGT_DOALWAYS; + q2.qclass = C_IN; + q2.qtype = T_AAAA; + q2.answer = q2.qbuf.buf; + q2.anslen = sizeof(q2.qbuf); + q2.next = &q3; + /* try AAAA only when A6 query fails */ + q2.action = RESTGT_AFTERFAILURE; + q3.qclass = C_IN; + q3.qtype = T_A; + q3.answer = q3.qbuf.buf; + q3.anslen = sizeof(q3.qbuf); + q3.action = RESTGT_DOALWAYS; + break; + case AF_INET: + q.qclass = C_IN; + q.qtype = T_A; + q.answer = q.qbuf.buf; + q.anslen = sizeof(q.qbuf); + q.action = RESTGT_DOALWAYS; + break; + case AF_INET6: + q.qclass = C_IN; + q.qtype = ns_t_a6; + q.answer = q.qbuf.buf; + q.anslen = sizeof(q.qbuf); + q.next = &q2; +#ifdef RES_USE_A6 + if ((pvt->res->options & RES_USE_A6) == 0) + q.action = RESTGT_IGNORE; + else +#endif + q.action = RESTGT_DOALWAYS; + q2.qclass = C_IN; + q2.qtype = T_AAAA; + q2.answer = q2.qbuf.buf; + q2.anslen = sizeof(q2.qbuf); + q2.action = RESTGT_AFTERFAILURE; + break; + default: + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /* better error? */ + return(NULL); + } + + /* + * if there aren't any dots, it could be a user-level alias. + * this is also done in res_nquery() since we are not the only + * function that looks up host names. + */ + if (!strchr(name, '.') && (cp = res_hostalias(pvt->res, name, + tmp, sizeof tmp))) + name = cp; + + for (p = &q; p; p = p->next) { + struct addrinfo *ai; + + switch(p->action) { + case RESTGT_DOALWAYS: + break; + case RESTGT_AFTERFAILURE: + if (querystate == RESQRY_SUCCESS) + continue; + break; + case RESTGT_IGNORE: + continue; + } + + if ((n = res_nsearch(pvt->res, name, p->qclass, p->qtype, + p->answer, p->anslen)) < 0) { + querystate = RESQRY_FAIL; + continue; + } + (void)gethostans(this, p->answer, n, name, p->qtype, + pai->ai_family, /* XXX: meaningless */ + 0, &ai, pai); + if (ai) { + querystate = RESQRY_SUCCESS; + cur->ai_next = ai; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + else + querystate = RESQRY_FAIL; + } + + return(sentinel.ai_next); +} + +static const u_char * +ar_head(cp, count, msg, eom, pvt, name_ok) + const u_char *cp, *msg, *eom; + int count; + struct pvt *pvt; + int (*name_ok)(const char *); +{ + int n; + u_char buf[1024]; /* XXX */ + + while (count-- > 0 && cp < eom) { + n = dn_expand(msg, eom, cp, buf, sizeof(buf)); + if (n < 0 || !maybe_ok(pvt->res, buf, name_ok)) + goto end; + cp += n; /* name */ + if (cp + 3 * INT16SZ + INT32SZ >= eom) + goto end; + cp += INT16SZ; /* type */ + cp += INT16SZ + INT32SZ; /* class, TTL */ + n = ns_get16(cp); + cp += n + INT16SZ; /* len */ + } + return(cp); + + end: + return(eom); /* XXX */ +} + +/* XXX: too many arguments */ +static struct addrinfo * +a6_expand(const u_char *ansbuf, const u_char *a6p, + int a6len, const u_char *arp, const u_char *eom, + const struct in6_addr *in6, int plen, const struct addrinfo *pai, + struct pvt *pvt, int (*name_ok)(const char *), int *errorp) +{ + struct in6_addr a; + int n, pbyte, plen1, pbyte1, error = 0; + const u_char *cp; + struct addrinfo sentinel, *cur; + u_char pname[1024], buf[1024]; /* XXX */ + + *errorp = NETDB_SUCCESS; + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + /* + * Validate A6 parameters. + */ + if (a6len == 0) { /* an A6 record must contain at least 1 byte. */ + error = NO_RECOVERY; + goto bad; + } + /* prefix length check. */ + if ((plen1 = *a6p) > 128) { + error = NO_RECOVERY; + goto bad; + } + if (plen1 > plen) { + /* + * New length must not be greater than old one. + * Ignore the record as specified in RFC 2874 + * Section 3.1.2. + */ + return(NULL); /* just ignore. */ + } + /* boundary check for new plen and prefix addr */ + pbyte1 = (plen1 & ~7) / 8; + if ((int)sizeof(struct in6_addr) - pbyte1 > a6len - 1) { + error = NO_RECOVERY; + goto bad; + } + + /* + * merge the new prefix portion. + * <--- plen(bits) ---> + * <--- pbyte ---><-b-> + * 000000000000000pppppxxxxxxxxxxx(= in6, 0: unknown, x: known, p: pad) + * PP++++++++(+ should be merged. P: padding, must be 0) + * <-- plen1--> + * <-pbyte1-> + * ^a6p+1 + * The result should be: + * 0000000000PP++++++++xxxxxxxxxxx(= a) + */ + pbyte = (plen & ~7) / 8; + a = *in6; + if (pbyte > pbyte1) { + /* N.B. the case of "pbyte1 == 128" is implicitly excluded. */ + int b = plen % 8; /* = the length of "pp..." above */ + u_char c_hi, c_lo; + + memcpy(&a.s6_addr[pbyte1], a6p + 1, pbyte - pbyte1); + if (b > 0) { + c_hi = a6p[pbyte - pbyte1 + 1]; + c_lo = in6->s6_addr[pbyte]; + a.s6_addr[pbyte] = + (c_hi & (0xff << (8 - b))) | + ((0x00ff >> b) & c_lo); + } + } + +#if 0 /* for debug */ + if ((pvt->res->options & RES_DEBUG) != 0) { + u_char ntopbuf[INET6_ADDRSTRLEN]; + + inet_ntop(AF_INET6, &a, ntopbuf, sizeof(ntopbuf)); + printf("a6_expand: %s\\%d\n", ntopbuf, plen1); + } +#endif + + if (plen1 == 0) { + /* Here is the end of A6 chain. make addrinfo, then return. */ + return(addr2addrinfo(pai, (const char *)&a)); + } + + /* + * Expand the new prefix name. Since the prefix name must not be + * compressed (RFC 2874 Section 3.1.1), we could use ns_name_ntop() + * here if it had a stricter boundary check. + */ + cp = a6p + 1 + (sizeof(*in6) - pbyte1); + n = dn_expand(ansbuf, eom, cp, pname, sizeof(pname)); + if (n < 0 || !maybe_ok(pvt->res, pname, name_ok)) { + error = NO_RECOVERY; + goto bad; + } + if (cp + n != a6p + a6len) { /* length mismatch */ + error = NO_RECOVERY; + goto bad; + } + + /* + * we need (more) additional section records, but no one is + * available, which possibly means a malformed answer. + */ + if (arp == NULL) { + error = NO_RECOVERY; /* we can't resolve the chain. */ + goto bad; + } + + /* + * Loop thru the rest of the buffer, searching for the next A6 record + * that has the same owner name as the prefix name. If found, then + * recursively call this function to expand the whole A6 chain. + */ + plen = plen1; + for (cp = arp; cp != NULL && cp < eom; cp += n) { + int class, type; + + n = dn_expand(ansbuf, eom, cp, buf, sizeof(buf)); + if (n < 0 || !maybe_ok(pvt->res, buf, name_ok)) { + error = NO_RECOVERY; + goto bad; + } + cp += n; /* name */ + if (cp + 3 * INT16SZ + INT32SZ > eom) { + error = NO_RECOVERY; + goto bad; + } + type = ns_get16(cp); + cp += INT16SZ; /* type */ + class = ns_get16(cp); + cp += INT16SZ + INT32SZ; /* class, TTL */ + n = ns_get16(cp); + cp += INT16SZ; /* len */ + if (cp + n > eom) { + error = NO_RECOVERY; + goto bad; + } + if (class != C_IN || type != ns_t_a6) { + /* we are only interested in A6 records. skip others */ + continue; + } + + if (ns_samename(buf, pname) != 1) { + continue; + } + + /* Proceed to the next record in the chain. */ + cur->ai_next = a6_expand(ansbuf, cp, n, cp + n, eom, + (const struct in6_addr *)&a, + plen, pai, pvt, name_ok, &error); + if (error != NETDB_SUCCESS) + goto bad; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + + return(sentinel.ai_next); + + bad: + *errorp = error; + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + return(NULL); +} + +static const char * +dname_subst(const char *qname0, const char *owner0, const char *target) { + char owner[MAXDNAME]; + static char qname[MAXDNAME]; + const char blabelhead[] = "\\[x"; /* we can assume hex strings */ + int qlen, olen; + int bufsiz = sizeof(qname); + + /* make local copies, which are canonicalized. */ + if (ns_makecanon(qname0, qname, sizeof(qname)) < 0 || + ns_makecanon(owner0, owner, sizeof(owner)) < 0) + return(NULL); + qlen = strlen(qname); + olen = strlen(owner); + /* from now on, do not refer to qname0 nor owner0. */ + + /* + * check if QNAME is a subdomain of OWNER. + * XXX: currently, we only handle the following two cases: + * (A) none of the labels are bitlabels, or + * (B) both of the head labels are bitlabels (and the following + * labels are NOT bitlabels). + * If we pass the check, then subtract the remaining part from QNAME. + * ex. (A) qname=www.foo.com,owner=foo.com => new qname=www. + * (B) qname=\[x3ffe0501/32].foo.com,owner=\[x3ffe/16].foo.com + * => new qname=\[x0501/16]. + */ + if (ns_samedomain(qname, owner)) { /* check (A) */ + /* at this point, qlen must not be smaller than olen */ + qname[qlen - olen] = 0; + bufsiz -= (qlen - olen); + } else { /* check (B) */ + char *parent0, *parent1; + /* the following 3 have enough size to store 1 bitlabel */ + u_char qlabel[64], olabel[64], newlabel[64]; + int qlabellen, olabellen; + + if (strncmp(qname, blabelhead, 3) != 0 || + strncmp(owner, blabelhead, 3) != 0) + return(NULL); + /* + * Both two begin with bitlabels. The succeeding parts + * must exact match. + */ + if ((parent0 = strchr(qname, '.')) == NULL || + (parent1 = strchr(owner, '.')) == NULL) + return(NULL); + + /* ns_samename allows names to begin with '.' */ + if (ns_samename(parent0, parent1) != 1) + return(NULL); + + /* cut the upper domain parts off. */ + *(parent0 + 1) = 0; + *(parent1 + 1) = 0; + /* convert the textual form into binary one. */ + if (ns_name_pton(qname, qlabel, sizeof(qlabel)) < 0 || + ns_name_pton(owner, olabel, sizeof(olabel)) < 0) + return(NULL); + if ((qlabellen = *(qlabel + 1)) == 0) + qlabellen = 256; + if ((olabellen = *(olabel + 1)) == 0) + olabellen = 256; + if (olabellen > qlabellen) + return(NULL); /* owner does not contain qname. */ + else { + int qplen = (qlabellen + 7) / 8; + int oplen = (olabellen + 7) / 8; + int sft = olabellen % 8; + int nllen, n; + u_char *qp, *op, *np; + + /* skip ELT and Count. */ + qp = qlabel + 2; + op = olabel + 2; + + /* check if olabel is a "subdomain" of qlabel. */ + if (memcmp(qp, op, oplen - 1) != 0) + return(NULL); + if (sft > 0) { + /* compare trailing bits (between 1 and 7) */ + if ((qp[qplen - 1] & (0xff << sft)) != + op[qplen - 1]) + return(NULL); + } + + /* OK, get remaining bits from qlabel. */ + np = newlabel; + if (olabellen == qlabellen) { + /* + * Two names (including bitlabels) are exactly + * same. Discard the whole names. + * XXX: ns_samename() above should exclude + * this case... + */ + qname[0] = 0; + goto maketarget; + } + *np++ = 0x41; /* XXX hardcoding */ + *np++ = nllen = (qlabellen - olabellen); + if (sft == 0) { + /* + * No alignment issue. can just use memcpy. + * Note that the "else" part below contains + * this case. We separate the two cases just + * for efficiency. + * We assume that ns_name_pton above ensures + * QP does not contain trailing garbages. + */ + memcpy(np, qp + oplen, qplen - oplen); + np += qplen - oplen; + *np = 0; + } else { + /* + * copy the lower (8-SFT) bits of QP to the + * upper (8-SFT) bits of NP, then copy the + * upper SFT bits of QP+1 to the lower SFT bits + * of NP, and so on... + * if QP is xxxyyyyy zzzwww..., then + * NP would be yyyyyzzz ... + * Again, we assume QP does not contain + * trailing garbages. + */ + qp += (oplen - 1); + while (nllen > 0) { + *np = (*qp << sft) & 0xff; + if ((nllen -= (8 - sft)) <= 0) + break; /* done */ + qp++; + *np |= ((*qp >> sft) & 0xff); + np++; + nllen -= sft; + } + *++np = 0; + } + + /* + * make a new bitlabel with the remaining bits. + * Note that there's no buffer boundary issue, since + * qlabel, olabel, and newlabel all have the same size. + * ns_name_ntop() must not return 0, since we have + * a non-empty bitlabel. + */ + if ((n = ns_name_ntop(newlabel, qname, sizeof(qname))) + <= 0) + return(NULL); + bufsiz -= n; + if (qname[n - 1] != '.') { /* XXX no trailing dot */ + qname[n - 1] = '.'; + qname[n] = 0; + bufsiz--; + } + + } + } + + maketarget: + /* + * Finally, append the remaining part (maybe empty) to the new target. + */ + if (bufsiz < (int)strlen(target)) /* bufsiz takes care of the \0. */ + return(NULL); + strcat(qname, target); + + return((const char *)qname); +} + +static void +ho_res_set(struct irs_ho *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +/* Private. */ + +static struct hostent * +gethostans(struct irs_ho *this, + const u_char *ansbuf, int anslen, const char *qname, int qtype, + int af, int size, /* meaningless for addrinfo cases */ + struct addrinfo **ret_aip, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + int type, class, buflen, ancount, qdcount, n, haveanswer, had_error; + int error = NETDB_SUCCESS, arcount; + int (*name_ok)(const char *); + const HEADER *hp; + const u_char *eom; + const u_char *cp; + const char *tname; + const char *hname; + char *bp, **ap, **hap; + char tbuf[MAXDNAME+1]; + struct addrinfo sentinel, *cur, ai; + const u_char *arp = NULL; + + if (pai == NULL) abort(); + if (ret_aip != NULL) + *ret_aip = NULL; + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + tname = qname; + eom = ansbuf + anslen; + switch (qtype) { + case ns_t_a6: + case T_A: + case T_AAAA: + case T_ANY: /* use T_ANY only for T_A/T_AAAA lookup */ + name_ok = res_hnok; + break; + case T_PTR: + name_ok = res_dnok; + break; + default: + abort(); + } + + pvt->host.h_addrtype = af; + pvt->host.h_length = size; + hname = pvt->host.h_name = NULL; + + /* + * Find first satisfactory answer. + */ + if (ansbuf + HFIXEDSZ > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + hp = (const HEADER *)ansbuf; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + arcount = ntohs(hp->arcount); + bp = pvt->hostbuf; + buflen = sizeof pvt->hostbuf; + cp = ansbuf + HFIXEDSZ; + if (qdcount != 1) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + n = dn_expand(ansbuf, eom, cp, bp, buflen); + if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + cp += n + QFIXEDSZ; + if (cp > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + if (qtype == T_A || qtype == T_AAAA || + qtype == ns_t_a6 || qtype == T_ANY) { + /* res_nsend() has already verified that the query name is the + * same as the one we sent; this just gets the expanded name + * (i.e., with the succeeding search-domain tacked on). + */ + n = strlen(bp) + 1; /* for the \0 */ + if (n > MAXHOSTNAMELEN) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + pvt->host.h_name = bp; + hname = bp; + bp += n; + buflen -= n; + /* The qname can be abbreviated, but hname is now absolute. */ + qname = pvt->host.h_name; + } + ap = pvt->host_aliases; + *ap = NULL; + pvt->host.h_aliases = pvt->host_aliases; + hap = pvt->h_addr_ptrs; + *hap = NULL; + pvt->host.h_addr_list = pvt->h_addr_ptrs; + haveanswer = 0; + had_error = 0; + while (ancount-- > 0 && cp < eom && !had_error) { + n = dn_expand(ansbuf, eom, cp, bp, buflen); + if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) { + had_error++; + continue; + } + cp += n; /* name */ + BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); + type = ns_get16(cp); + cp += INT16SZ; /* type */ + class = ns_get16(cp); + cp += INT16SZ + INT32SZ; /* class, TTL */ + n = ns_get16(cp); + cp += INT16SZ; /* len */ + BOUNDS_CHECK(cp, n); + if (class != C_IN) { + cp += n; + continue; + } + if ((qtype == T_A || qtype == T_AAAA || qtype == ns_t_a6 || + qtype == T_ANY) && type == T_CNAME) { + if (ap >= &pvt->host_aliases[MAXALIASES-1]) + continue; + n = dn_expand(ansbuf, eom, cp, tbuf, sizeof tbuf); + if (n < 0 || !maybe_ok(pvt->res, tbuf, name_ok)) { + had_error++; + continue; + } + cp += n; + /* Store alias. */ + *ap++ = bp; + n = strlen(bp) + 1; /* for the \0 */ + bp += n; + buflen -= n; + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > buflen || n > MAXHOSTNAMELEN) { + had_error++; + continue; + } + strcpy(bp, tbuf); + pvt->host.h_name = bp; + hname = bp; + bp += n; + buflen -= n; + continue; + } + if (type == ns_t_dname) { + const char *t0, *t; + + /* + * just replace the query target; do not update the + * aliase list. (Or should we?) + */ + t0 = (qtype == T_PTR) ? tname : hname; + + n = dn_expand(ansbuf, eom, cp, tbuf, sizeof(tbuf)); + if (n < 0 || !maybe_dnok(pvt->res, tbuf)) { + had_error++; + continue; + } +#ifdef RES_USE_DNAME + if ((pvt ->res->options & RES_USE_DNAME) == 0) { + cp += n; + continue; + } +#endif + if ((t = dname_subst(t0, bp, tbuf)) == NULL) { + cp += n; + continue; + } +#if 0 /* for debug */ + if ((pvt->res->options & RES_DEBUG) != 0) { + printf("DNAME owner=%s, target=%s, next=%s\n", + bp, tbuf, t); + } +#endif + cp += n; + + n = strlen(t) + 1; /* for the \0 */ + if (n > buflen) { + had_error++; + continue; + } + strcpy(bp, t); + if (qtype == T_PTR) + tname = bp; + else + hname = bp; + bp += n; + buflen -= n; + + continue; + } + if (qtype == T_PTR && type == T_CNAME) { + n = dn_expand(ansbuf, eom, cp, tbuf, sizeof tbuf); + if (n < 0 || !maybe_dnok(pvt->res, tbuf)) { + had_error++; + continue; + } + cp += n; +#ifdef RES_USE_DNAME + if ((pvt->res->options & RES_USE_DNAME) != 0) +#endif + { + /* + * We may be able to check this regardless + * of the USE_DNAME bit, but we add the check + * for now since the DNAME support is + * experimental. + */ + if (ns_samename(tname, bp) != 1) + continue; + } + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > buflen) { + had_error++; + continue; + } + strcpy(bp, tbuf); + tname = bp; + bp += n; + buflen -= n; + continue; + } + if (qtype == T_ANY) { + if (!(type == T_A || type == T_AAAA || + type == ns_t_a6)) { + cp += n; + continue; + } + } else if (type != qtype) { + cp += n; + continue; + } + switch (type) { + case T_PTR: + if (ret_aip != NULL) { + /* addrinfo never needs T_PTR */ + cp += n; + continue; + } + if (ns_samename(tname, bp) != 1) { + cp += n; + continue; + } + n = dn_expand(ansbuf, eom, cp, bp, buflen); + if (n < 0 || !maybe_hnok(pvt->res, bp) || + n >= MAXHOSTNAMELEN) { + had_error++; + break; + } + cp += n; + if (!haveanswer) { + pvt->host.h_name = bp; + hname = bp; + } + else if (ap < &pvt->host_aliases[MAXALIASES-1]) + *ap++ = bp; + else + n = -1; + if (n != -1) { + n = strlen(bp) + 1; /* for the \0 */ + bp += n; + buflen -= n; + } + break; + case ns_t_a6: { + struct in6_addr in6; + struct addrinfo ai; + +#ifdef RES_USE_A6 + if ((pvt->res->options & RES_USE_A6) == 0) { + cp += n; + continue; + } +#endif + + if (ns_samename(hname, bp) != 1) { + cp += n; + continue; + } + + /* + * search for the top of the additional section. + * once found, keep it for the case where we have + * more than one A6 record. + * XXX: however, we may not need this part. + */ + if (arp == NULL && arcount > 0) { + int nscount = ntohs(hp->nscount); + + arp = ar_head(cp + n, nscount + ancount - 1, + ansbuf, eom, pvt, name_ok); + } + + /* recursively collect the whole A6 chain */ + ai = *pai; /* XXX: we can't override constant pai */ + ai.ai_family = AF_INET6; + memset(&in6, 0, sizeof(in6)); /* just for safety */ + cur->ai_next = a6_expand(ansbuf, cp, n, arp, eom, + &in6, 128, + (const struct addrinfo *)&ai, + pvt, name_ok, &error); + if (error != NETDB_SUCCESS) { +#ifdef DEBUG + /* in this case, cur->ai_next must be NULL. */ + if (cur->ai_next != NULL) + abort(); +#endif + had_error++; + continue; + } + + /* + * We don't bother even if cur->ai_next is NULL unless + * the expansion failed by a fatal error. The list + * can be NULL if the given A6 is incomplete, but we + * may have another complete A6 chain in this answer. + * See the last paragraph of RFC 2874 Section 3.1.4. + */ + if (cur->ai_next == NULL) { + cp += n; + continue; /* no error, no answer */ + } + goto convertinfo; + } /* FALLTHROUGH */ + case T_A: + case T_AAAA: + if (ns_samename(hname, bp) != 1) { + cp += n; + continue; + } + if (type == T_A && n != INADDRSZ) { + cp += n; + continue; + } + if (type == T_AAAA && n != IN6ADDRSZ) { + cp += n; + continue; + } + + /* make addrinfo. don't overwrite constant PAI */ + ai = *pai; + ai.ai_family = (type == T_AAAA) ? AF_INET6 : AF_INET; + cur->ai_next = addr2addrinfo((const struct addrinfo *)&ai, cp); + if (cur->ai_next == NULL) + had_error++; + + convertinfo: /* convert addrinfo into hostent form */ + if (!haveanswer) { + int nn; + + nn = strlen(bp) + 1; /* for the \0 */ + if (nn >= MAXHOSTNAMELEN) { + cp += n; + had_error++; + continue; + } + pvt->host.h_name = bp; + hname = bp; + bp += nn; + buflen -= nn; + } + /* Ensure alignment. */ + bp += sizeof(align) - ((u_long)bp % sizeof(align)); + /* Avoid overflows. */ + if (bp + n >= &pvt->hostbuf[sizeof pvt->hostbuf]) { + had_error++; + continue; + } + if (ret_aip) { /* need addrinfo. keep it. */ + while (cur && cur->ai_next) + cur = cur->ai_next; + } else if (cur->ai_next) { /* need hostent */ + struct addrinfo *aip = cur->ai_next; + + for (aip = cur->ai_next; aip; + aip = aip->ai_next) { + int m; + + m = add_hostent(pvt, bp, hap, aip); + if (m < 0) { + had_error++; + break; + } + if (hap < &pvt->h_addr_ptrs[MAXADDRS-1]) + hap++; + + bp += m; + } + + freeaddrinfo(cur->ai_next); + cur->ai_next = NULL; + } + cp += n; + break; + default: + abort(); + } + if (!had_error) + haveanswer++; + } + if (haveanswer) { + if (ret_aip == NULL) { + *ap = NULL; + *hap = NULL; + + if (pvt->res->nsort && haveanswer > 1 && qtype == T_A) + addrsort(pvt->res, pvt->h_addr_ptrs, + haveanswer); + if (pvt->host.h_name == NULL) { + n = strlen(qname) + 1; /* for the \0 */ + if (n > buflen || n >= MAXHOSTNAMELEN) + goto no_recovery; + strcpy(bp, qname); + pvt->host.h_name = bp; + bp += n; + buflen -= n; + } + if (pvt->res->options & RES_USE_INET6) + map_v4v6_hostent(&pvt->host, &bp, &buflen); + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (&pvt->host); + } else { + if ((pai->ai_flags & AI_CANONNAME) != 0) { + if (pvt->host.h_name == NULL) { + sentinel.ai_next->ai_canonname = + strdup(qname); + } + else { + sentinel.ai_next->ai_canonname = + strdup(pvt->host.h_name); + } + } + *ret_aip = sentinel.ai_next; + return(NULL); + } + } + no_recovery: + if (sentinel.ai_next) { + /* this should be impossible, but check it for safety */ + freeaddrinfo(sentinel.ai_next); + } + if (error == NETDB_SUCCESS) + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + else + RES_SET_H_ERRNO(pvt->res, error); + return(NULL); +} + +static int +add_hostent(struct pvt *pvt, char *bp, char **hap, struct addrinfo *ai) +{ + int addrlen; + char *addrp; + + switch(ai->ai_addr->sa_family) { + case AF_INET6: + addrlen = IN6ADDRSZ; + addrp = (char *)&((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr; + break; + case AF_INET: + addrlen = INADDRSZ; + addrp = (char *)&((struct sockaddr_in *)ai->ai_addr)->sin_addr; + break; + default: + return(-1); /* abort? */ + } + + bp += sizeof(align) - ((u_long)bp % sizeof(align)); + if (bp + addrlen >= &pvt->hostbuf[sizeof pvt->hostbuf]) + return(-1); + if (hap >= &pvt->h_addr_ptrs[MAXADDRS-1]) + return(addrlen); /* fail, but not treat it as an error. */ +#if 0 + /* Suppress duplicates. */ + for (tap = (const char **)pvt->h_addr_ptrs; + *tap != NULL; + tap++) + if (memcmp(*tap, cp, n) == 0) + break; + if (*tap != NULL) { + cp += n; + continue; + } +#endif + + memcpy(*hap = bp, addrp, addrlen); + return(addrlen); +} + +static void +map_v4v6_hostent(struct hostent *hp, char **bpp, int *lenp) { + char **ap; + + if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) + return; + hp->h_addrtype = AF_INET6; + hp->h_length = IN6ADDRSZ; + for (ap = hp->h_addr_list; *ap; ap++) { + int i = sizeof(align) - ((u_long)*bpp % sizeof(align)); + + if (*lenp < (i + IN6ADDRSZ)) { + /* Out of memory. Truncate address list here. */ + *ap = NULL; + return; + } + *bpp += i; + *lenp -= i; + map_v4v6_address(*ap, *bpp); + *ap = *bpp; + *bpp += IN6ADDRSZ; + *lenp -= IN6ADDRSZ; + } +} + +static void +addrsort(res_state statp, char **ap, int num) { + int i, j, needsort = 0, aval[MAXADDRS]; + char **p; + + p = ap; + for (i = 0; i < num; i++, p++) { + for (j = 0 ; (unsigned)j < statp->nsort; j++) + if (statp->sort_list[j].addr.s_addr == + (((struct in_addr *)(*p))->s_addr & + statp->sort_list[j].mask)) + break; + aval[i] = j; + if (needsort == 0 && i > 0 && j < aval[i-1]) + needsort = i; + } + if (!needsort) + return; + + while (needsort < num) { + for (j = needsort - 1; j >= 0; j--) { + if (aval[j] > aval[j+1]) { + char *hp; + + i = aval[j]; + aval[j] = aval[j+1]; + aval[j+1] = i; + + hp = ap[j]; + ap[j] = ap[j+1]; + ap[j+1] = hp; + + } else + break; + } + needsort++; + } +} + +static int +init(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !ho_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} diff --git a/lib/bind/irs/dns_nw.c b/lib/bind/irs/dns_nw.c new file mode 100644 index 0000000000..41984f7251 --- /dev/null +++ b/lib/bind/irs/dns_nw.c @@ -0,0 +1,566 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_nw.c,v 1.1 2001/03/29 06:31:42 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "dns_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +/* Definitions. */ + +#define MAXALIASES 35 + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +struct pvt { + struct nwent net; + char * ali[MAXALIASES]; + char buf[BUFSIZ+1]; + struct __res_state * res; + void (*free_res)(void *); +}; + +typedef union { + long al; + char ac; +} align; + +enum by_what { by_addr, by_name }; + +/* Forwards. */ + +static void nw_close(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static struct nwent * nw_next(struct irs_nw *); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); +static struct __res_state * nw_res_get(struct irs_nw *this); +static void nw_res_set(struct irs_nw *this, + struct __res_state *res, + void (*free_res)(void *)); + +static struct nwent * get1101byaddr(struct irs_nw *, u_char *, int); +static struct nwent * get1101byname(struct irs_nw *, const char *); +static struct nwent * get1101answer(struct irs_nw *, + u_char *ansbuf, int anslen, + enum by_what by_what, + int af, const char *name, + const u_char *addr, int addrlen); +static struct nwent * get1101mask(struct irs_nw *this, struct nwent *); +static int make1101inaddr(const u_char *, int, char *, int); +static void normalize_name(char *name); +static int init(struct irs_nw *this); + +/* Exports. */ + +struct irs_nw * +irs_dns_nw(struct irs_acc *this) { + struct irs_nw *nw; + struct pvt *pvt; + + UNUSED(this); + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + nw->private = pvt; + nw->close = nw_close; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->next = nw_next; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + nw->res_get = nw_res_get; + nw->res_set = nw_res_set; + return (nw); +} + +/* Methods. */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + + if (init(this) == -1) + return (NULL); + + switch (af) { + case AF_INET: + return (get1101byname(this, name)); + default: + (void)NULL; + } + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + return (NULL); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + + if (init(this) == -1) + return (NULL); + + switch (af) { + case AF_INET: + return (get1101byaddr(this, net, len)); + default: + (void)NULL; + } + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + return (NULL); +} + +static struct nwent * +nw_next(struct irs_nw *this) { + + UNUSED(this); + + return (NULL); +} + +static void +nw_rewind(struct irs_nw *this) { + UNUSED(this); + /* NOOP */ +} + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +nw_res_get(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + nw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +nw_res_set(struct irs_nw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +/* Private. */ + +static struct nwent * +get1101byname(struct irs_nw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + u_char ansbuf[MAXPACKET]; + int anslen; + + anslen = res_nsearch(pvt->res, name, C_IN, T_PTR, + ansbuf, sizeof ansbuf); + if (anslen < 0) + return (NULL); + return (get1101mask(this, get1101answer(this, ansbuf, anslen, by_name, + AF_INET, name, NULL, 0))); +} + +static struct nwent * +get1101byaddr(struct irs_nw *this, u_char *net, int len) { + struct pvt *pvt = (struct pvt *)this->private; + char qbuf[sizeof "255.255.255.255.in-addr.arpa"]; + u_char ansbuf[MAXPACKET]; + int anslen; + + if (len < 1 || len > 32) { + errno = EINVAL; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + if (make1101inaddr(net, len, qbuf, sizeof qbuf) < 0) + return (NULL); + anslen = res_nquery(pvt->res, qbuf, C_IN, T_PTR, + ansbuf, sizeof ansbuf); + if (anslen < 0) + return (NULL); + return (get1101mask(this, get1101answer(this, ansbuf, anslen, by_addr, + AF_INET, NULL, net, len))); +} + +static struct nwent * +get1101answer(struct irs_nw *this, + u_char *ansbuf, int anslen, enum by_what by_what, + int af, const char *name, const u_char *addr, int addrlen) +{ + struct pvt *pvt = (struct pvt *)this->private; + int type, class, buflen, ancount, qdcount, haveanswer; + char *bp, **ap; + u_char *cp, *eom; + HEADER *hp; + + /* Initialize, and parse header. */ + eom = ansbuf + anslen; + if (ansbuf + HFIXEDSZ > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + hp = (HEADER *)ansbuf; + cp = ansbuf + HFIXEDSZ; + qdcount = ntohs(hp->qdcount); + while (qdcount-- > 0) { + int n = dn_skipname(cp, eom); + cp += n + QFIXEDSZ; + if (n < 0 || cp > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + } + ancount = ntohs(hp->ancount); + if (!ancount) { + if (hp->aa) + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + else + RES_SET_H_ERRNO(pvt->res, TRY_AGAIN); + return (NULL); + } + + /* Prepare a return structure. */ + bp = pvt->buf; + buflen = sizeof pvt->buf; + pvt->net.n_name = NULL; + pvt->net.n_aliases = pvt->ali; + pvt->net.n_addrtype = af; + pvt->net.n_addr = NULL; + pvt->net.n_length = addrlen; + + /* Save input key if given. */ + switch (by_what) { + case by_name: + if (name != NULL) { + int n = strlen(name) + 1; + + if (n > buflen) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + pvt->net.n_name = strcpy(bp, name); + bp += n; + buflen -= n; + } + break; + case by_addr: + if (addr != NULL && addrlen != 0) { + int n = addrlen / 8 + ((addrlen % 8) != 0); + + if (INADDRSZ > buflen) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + memset(bp, 0, INADDRSZ); + memcpy(bp, addr, n); + pvt->net.n_addr = bp; + bp += INADDRSZ; + buflen -= INADDRSZ; + } + break; + default: + abort(); + } + + /* Parse the answer, collect aliases. */ + ap = pvt->ali; + haveanswer = 0; + while (--ancount >= 0 && cp < eom) { + int n = dn_expand(ansbuf, eom, cp, bp, buflen); + + cp += n; /* Owner */ + if (n < 0 || !maybe_dnok(pvt->res, bp) || + cp + 3 * INT16SZ + INT32SZ > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + GETSHORT(type, cp); /* Type */ + GETSHORT(class, cp); /* Class */ + cp += INT32SZ; /* TTL */ + GETSHORT(n, cp); /* RDLENGTH */ + if (class == C_IN && type == T_PTR) { + int nn; + + nn = dn_expand(ansbuf, eom, cp, bp, buflen); + if (nn < 0 || !maybe_hnok(pvt->res, bp) || nn != n) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + normalize_name(bp); + switch (by_what) { + case by_addr: { + if (pvt->net.n_name == NULL) + pvt->net.n_name = bp; + else if (ns_samename(pvt->net.n_name, bp) == 1) + break; + else + *ap++ = bp; + nn = strlen(bp) + 1; + bp += nn; + buflen -= nn; + haveanswer++; + break; + } + case by_name: { + u_int b1, b2, b3, b4; + + if (pvt->net.n_addr != NULL || + sscanf(bp, "%u.%u.%u.%u.in-addr.arpa", + &b1, &b2, &b3, &b4) != 4) + break; + if (buflen < INADDRSZ) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + pvt->net.n_addr = bp; + *bp++ = b4; + *bp++ = b3; + *bp++ = b2; + *bp++ = b1; + buflen -= INADDRSZ; + pvt->net.n_length = INADDRSZ * 8; + haveanswer++; + } + } + } + cp += n; /* RDATA */ + } + if (!haveanswer) { + RES_SET_H_ERRNO(pvt->res, TRY_AGAIN); + return (NULL); + } + *ap = NULL; + + return (&pvt->net); +} + +static struct nwent * +get1101mask(struct irs_nw *this, struct nwent *nwent) { + struct pvt *pvt = (struct pvt *)this->private; + char qbuf[sizeof "255.255.255.255.in-addr.arpa"], owner[MAXDNAME]; + int anslen, type, class, ancount, qdcount; + u_char ansbuf[MAXPACKET], *cp, *eom; + HEADER *hp; + + if (!nwent) + return (NULL); + if (make1101inaddr(nwent->n_addr, nwent->n_length, qbuf, sizeof qbuf) + < 0) { + /* "First, do no harm." */ + return (nwent); + } + + /* Query for the A RR that would hold this network's mask. */ + anslen = res_nquery(pvt->res, qbuf, C_IN, T_A, ansbuf, sizeof ansbuf); + if (anslen < HFIXEDSZ) + return (nwent); + + /* Initialize, and parse header. */ + hp = (HEADER *)ansbuf; + cp = ansbuf + HFIXEDSZ; + eom = ansbuf + anslen; + qdcount = ntohs(hp->qdcount); + while (qdcount-- > 0) { + int n = dn_skipname(cp, eom); + cp += n + QFIXEDSZ; + if (n < 0 || cp > eom) + return (nwent); + } + ancount = ntohs(hp->ancount); + + /* Parse the answer, collect aliases. */ + while (--ancount >= 0 && cp < eom) { + int n = dn_expand(ansbuf, eom, cp, owner, sizeof owner); + + if (n < 0 || !maybe_dnok(pvt->res, owner)) + break; + cp += n; /* Owner */ + if (cp + 3 * INT16SZ + INT32SZ > eom) + break; + GETSHORT(type, cp); /* Type */ + GETSHORT(class, cp); /* Class */ + cp += INT32SZ; /* TTL */ + GETSHORT(n, cp); /* RDLENGTH */ + if (cp + n > eom) + break; + if (n == INADDRSZ && class == C_IN && type == T_A && + ns_samename(qbuf, owner) == 1) { + /* This A RR indicates the actual netmask. */ + int nn, mm; + + nwent->n_length = 0; + for (nn = 0; nn < INADDRSZ; nn++) + for (mm = 7; mm >= 0; mm--) + if (cp[nn] & (1 << mm)) + nwent->n_length++; + else + break; + } + cp += n; /* RDATA */ + } + return (nwent); +} + +static int +make1101inaddr(const u_char *net, int bits, char *name, int size) { + int n, m; + + /* Zero fill any whole bytes left out of the prefix. */ + for (n = (32 - bits) / 8; n > 0; n--) { + if (size < (int)(sizeof "0.")) + goto emsgsize; + m = SPRINTF((name, "0.")); + name += m; + size -= m; + } + + /* Format the partial byte, if any, within the prefix. */ + if ((n = bits % 8) != 0) { + if (size < (int)(sizeof "255.")) + goto emsgsize; + m = SPRINTF((name, "%u.", + net[bits / 8] & ~((1 << (8 - n)) - 1))); + name += m; + size -= m; + } + + /* Format the whole bytes within the prefix. */ + for (n = bits / 8; n > 0; n--) { + if (size < (int)(sizeof "255.")) + goto emsgsize; + m = SPRINTF((name, "%u.", net[n - 1])); + name += m; + size -= m; + } + + /* Add the static text. */ + if (size < (int)(sizeof "in-addr.arpa")) + goto emsgsize; + (void) SPRINTF((name, "in-addr.arpa")); + return (0); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +static void +normalize_name(char *name) { + char *t; + + /* Make lower case. */ + for (t = name; *t; t++) + if (isascii(*t) && isupper(*t)) + *t = tolower(*t); + + /* Remove trailing dots. */ + while (t > name && t[-1] == '.') + *--t = '\0'; +} + +static int +init(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !nw_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} diff --git a/lib/bind/irs/dns_p.h b/lib/bind/irs/dns_p.h new file mode 100644 index 0000000000..3f9b55409a --- /dev/null +++ b/lib/bind/irs/dns_p.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: dns_p.h,v 1.1 2001/03/29 06:31:42 marka Exp $ + */ + +#ifndef _DNS_P_H_INCLUDED +#define _DNS_P_H_INCLUDED + +#define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0 || \ + (ok)(nm) != 0) +#define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok) +#define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok) + +/* + * Object state. + */ +struct dns_p { + void *hes_ctx; + struct __res_state *res; + void (*free_res) __P((void *)); +}; + +/* + * Methods. + */ + +extern struct irs_gr * irs_dns_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_dns_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_dns_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_dns_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_dns_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_dns_nw __P((struct irs_acc *)); + +#endif /*_DNS_P_H_INCLUDED*/ diff --git a/lib/bind/irs/dns_pr.c b/lib/bind/irs/dns_pr.c new file mode 100644 index 0000000000..fc0c8721ab --- /dev/null +++ b/lib/bind/irs/dns_pr.c @@ -0,0 +1,266 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_pr.c,v 1.1 2001/03/29 06:31:42 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Types. */ + +struct pvt { + struct dns_p * dns; + struct protoent proto; + char * prbuf; +}; + +/* Forward. */ + +static void pr_close(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static struct protoent * pr_next(struct irs_pr *); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); +static struct __res_state * pr_res_get(struct irs_pr *); +static void pr_res_set(struct irs_pr *, + struct __res_state *, + void (*)(void *)); + +static struct protoent * parse_hes_list(struct irs_pr *, char **); + +/* Public. */ + +struct irs_pr * +irs_dns_pr(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + struct pvt *pvt; + struct irs_pr *pr; + + if (!dns->hes_ctx) { + errno = ENODEV; + return (NULL); + } + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(pr = memget(sizeof *pr))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(pr, 0x5e, sizeof *pr); + pvt->dns = dns; + pr->private = pvt; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->next = pr_next; + pr->rewind = pr_rewind; + pr->close = pr_close; + pr->minimize = pr_minimize; + pr->res_get = pr_res_get; + pr->res_set = pr_res_set; + return (pr); +} + +/* Methods. */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->proto.p_aliases) + free(pvt->proto.p_aliases); + if (pvt->prbuf) + free(pvt->prbuf); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct protoent *proto; + char **hes_list; + + if (!(hes_list = hesiod_resolve(dns->hes_ctx, name, "protocol"))) + return (NULL); + + proto = parse_hes_list(this, hes_list); + hesiod_free_list(dns->hes_ctx, hes_list); + return (proto); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int num) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct protoent *proto; + char numstr[16]; + char **hes_list; + + sprintf(numstr, "%d", num); + if (!(hes_list = hesiod_resolve(dns->hes_ctx, numstr, "protonum"))) + return (NULL); + + proto = parse_hes_list(this, hes_list); + hesiod_free_list(dns->hes_ctx, hes_list); + return (proto); +} + +static struct protoent * +pr_next(struct irs_pr *this) { + UNUSED(this); + errno = ENODEV; + return (NULL); +} + +static void +pr_rewind(struct irs_pr *this) { + UNUSED(this); + /* NOOP */ +} + +static void +pr_minimize(struct irs_pr *this) { + UNUSED(this); + /* NOOP */ +} + +static struct __res_state * +pr_res_get(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + return (__hesiod_res_get(dns->hes_ctx)); +} + +static void +pr_res_set(struct irs_pr *this, struct __res_state * res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + __hesiod_res_set(dns->hes_ctx, res, free_res); +} + +/* Private. */ + +static struct protoent * +parse_hes_list(struct irs_pr *this, char **hes_list) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *cp, **cpp, **new; + int num = 0; + int max = 0; + + for (cpp = hes_list; *cpp; cpp++) { + cp = *cpp; + + /* Strip away comments, if any. */ + if ((p = strchr(cp, '#'))) + *p = 0; + + /* Skip blank lines. */ + p = cp; + while (*p && !isspace(*p)) + p++; + if (!*p) + continue; + + /* OK, we've got a live one. Let's parse it for real. */ + if (pvt->prbuf) + free(pvt->prbuf); + pvt->prbuf = strdup(cp); + + p = pvt->prbuf; + pvt->proto.p_name = p; + while (*p && !isspace(*p)) + p++; + if (!*p) + continue; + *p++ = '\0'; + + pvt->proto.p_proto = atoi(p); + while (*p && !isspace(*p)) + p++; + if (*p) + *p++ = '\0'; + + while (*p) { + if ((num + 1) >= max || !pvt->proto.p_aliases) { + max += 10; + new = realloc(pvt->proto.p_aliases, + max * sizeof(char *)); + if (!new) { + errno = ENOMEM; + goto cleanup; + } + pvt->proto.p_aliases = new; + } + pvt->proto.p_aliases[num++] = p; + while (*p && !isspace(*p)) + p++; + if (*p) + *p++ = '\0'; + } + if (!pvt->proto.p_aliases) + pvt->proto.p_aliases = malloc(sizeof(char *)); + if (!pvt->proto.p_aliases) + goto cleanup; + pvt->proto.p_aliases[num] = NULL; + return (&pvt->proto); + } + + cleanup: + if (pvt->proto.p_aliases) { + free(pvt->proto.p_aliases); + pvt->proto.p_aliases = NULL; + } + if (pvt->prbuf) { + free(pvt->prbuf); + pvt->prbuf = NULL; + } + return (NULL); +} diff --git a/lib/bind/irs/dns_pw.c b/lib/bind/irs/dns_pw.c new file mode 100644 index 0000000000..f387848167 --- /dev/null +++ b/lib/bind/irs/dns_pw.c @@ -0,0 +1,231 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_pw.c,v 1.1 2001/03/29 06:31:42 marka Exp $"; +#endif + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_pw_unneeded; +#else + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Types. */ + +struct pvt { + struct dns_p * dns; + struct passwd passwd; + char * pwbuf; +}; + +/* Forward. */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static struct passwd * pw_next(struct irs_pw *); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); +static struct __res_state * pw_res_get(struct irs_pw *); +static void pw_res_set(struct irs_pw *, + struct __res_state *, + void (*)(void *)); + +static struct passwd * getpwcommon(struct irs_pw *, const char *, + const char *); + +/* Public. */ + +struct irs_pw * +irs_dns_pw(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + struct irs_pw *pw; + struct pvt *pvt; + + if (!dns || !dns->hes_ctx) { + errno = ENODEV; + return (NULL); + } + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->dns = dns; + if (!(pw = memget(sizeof *pw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(pw, 0x5e, sizeof *pw); + pw->private = pvt; + pw->close = pw_close; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->next = pw_next; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + pw->res_get = pw_res_get; + pw->res_set = pw_res_set; + return (pw); +} + +/* Methods. */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->pwbuf) + free(pvt->pwbuf); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct passwd * +pw_byname(struct irs_pw *this, const char *nam) { + return (getpwcommon(this, nam, "passwd")); +} + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + char uidstr[16]; + + sprintf(uidstr, "%lu", (u_long)uid); + return (getpwcommon(this, uidstr, "uid")); +} + +static struct passwd * +pw_next(struct irs_pw *this) { + UNUSED(this); + errno = ENODEV; + return (NULL); +} + +static void +pw_rewind(struct irs_pw *this) { + UNUSED(this); + /* NOOP */ +} + +static void +pw_minimize(struct irs_pw *this) { + UNUSED(this); + /* NOOP */ +} + +static struct __res_state * +pw_res_get(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + return (__hesiod_res_get(dns->hes_ctx)); +} + +static void +pw_res_set(struct irs_pw *this, struct __res_state * res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + __hesiod_res_set(dns->hes_ctx, res, free_res); +} + +/* Private. */ + +static struct passwd * +getpwcommon(struct irs_pw *this, const char *arg, const char *type) { + struct pvt *pvt = (struct pvt *)this->private; + char **hes_list, *cp; + + if (!(hes_list = hesiod_resolve(pvt->dns->hes_ctx, arg, type))) + return (NULL); + if (!*hes_list) { + hesiod_free_list(pvt->dns->hes_ctx, hes_list); + errno = ENOENT; + return (NULL); + } + + memset(&pvt->passwd, 0, sizeof pvt->passwd); + if (pvt->pwbuf) + free(pvt->pwbuf); + pvt->pwbuf = strdup(*hes_list); + hesiod_free_list(pvt->dns->hes_ctx, hes_list); + + cp = pvt->pwbuf; + pvt->passwd.pw_name = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_passwd = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_uid = atoi(cp); + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_gid = atoi(cp); + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_gecos = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_dir = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_shell = cp; + return (&pvt->passwd); + + cleanup: + free(pvt->pwbuf); + pvt->pwbuf = NULL; + return (NULL); +} + +#endif /* WANT_IRS_PW */ diff --git a/lib/bind/irs/dns_sv.c b/lib/bind/irs/dns_sv.c new file mode 100644 index 0000000000..73db16463b --- /dev/null +++ b/lib/bind/irs/dns_sv.c @@ -0,0 +1,298 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_sv.c,v 1.1 2001/03/29 06:31:43 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Definitions */ + +struct pvt { + struct dns_p * dns; + struct servent serv; + char * svbuf; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward. */ + +static void sv_close(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, + const char *, const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static struct servent * sv_next(struct irs_sv *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); +#ifdef SV_RES_SETGET +static struct __res_state * sv_res_get(struct irs_sv *); +static void sv_res_set(struct irs_sv *, + struct __res_state *, + void (*)(void *)); +#endif + +static struct servent * parse_hes_list(struct irs_sv *, + char **, const char *); + +/* Public */ + +struct irs_sv * +irs_dns_sv(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + struct irs_sv *sv; + struct pvt *pvt; + + if (!dns || !dns->hes_ctx) { + errno = ENODEV; + return (NULL); + } + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->dns = dns; + if (!(sv = memget(sizeof *sv))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + sv->private = pvt; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->next = sv_next; + sv->rewind = sv_rewind; + sv->close = sv_close; + sv->minimize = sv_minimize; +#ifdef SV_RES_SETGET + sv->res_get = sv_res_get; + sv->res_set = sv_res_set; +#else + sv->res_get = NULL; /* sv_res_get; */ + sv->res_set = NULL; /* sv_res_set; */ +#endif + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->serv.s_aliases) + free(pvt->serv.s_aliases); + if (pvt->svbuf) + free(pvt->svbuf); + + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct servent *s; + char **hes_list; + + if (!(hes_list = hesiod_resolve(dns->hes_ctx, name, "service"))) + return (NULL); + + s = parse_hes_list(this, hes_list, proto); + hesiod_free_list(dns->hes_ctx, hes_list); + return (s); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct servent *s; + char portstr[16]; + char **hes_list; + + sprintf(portstr, "%d", ntohs(port)); + if (!(hes_list = hesiod_resolve(dns->hes_ctx, portstr, "port"))) + return (NULL); + + s = parse_hes_list(this, hes_list, proto); + hesiod_free_list(dns->hes_ctx, hes_list); + return (s); +} + +static struct servent * +sv_next(struct irs_sv *this) { + UNUSED(this); + errno = ENODEV; + return (NULL); +} + +static void +sv_rewind(struct irs_sv *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static struct servent * +parse_hes_list(struct irs_sv *this, char **hes_list, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *cp, **cpp, **new; + int proto_len; + int num = 0; + int max = 0; + + for (cpp = hes_list; *cpp; cpp++) { + cp = *cpp; + + /* Strip away comments, if any. */ + if ((p = strchr(cp, '#'))) + *p = 0; + + /* Check to make sure the protocol matches. */ + p = cp; + while (*p && !isspace(*p)) + p++; + if (!*p) + continue; + if (proto) { + proto_len = strlen(proto); + if (strncasecmp(++p, proto, proto_len) != 0) + continue; + if (p[proto_len] && !isspace(p[proto_len])) + continue; + } + /* OK, we've got a live one. Let's parse it for real. */ + if (pvt->svbuf) + free(pvt->svbuf); + pvt->svbuf = strdup(cp); + + p = pvt->svbuf; + pvt->serv.s_name = p; + while (*p && !isspace(*p)) + p++; + if (!*p) + continue; + *p++ = '\0'; + + pvt->serv.s_proto = p; + while (*p && !isspace(*p)) + p++; + if (!*p) + continue; + *p++ = '\0'; + + pvt->serv.s_port = htons((u_short) atoi(p)); + while (*p && !isspace(*p)) + p++; + if (*p) + *p++ = '\0'; + + while (*p) { + if ((num + 1) >= max || !pvt->serv.s_aliases) { + max += 10; + new = realloc(pvt->serv.s_aliases, + max * sizeof(char *)); + if (!new) { + errno = ENOMEM; + goto cleanup; + } + pvt->serv.s_aliases = new; + } + pvt->serv.s_aliases[num++] = p; + while (*p && !isspace(*p)) + p++; + if (*p) + *p++ = '\0'; + } + if (!pvt->serv.s_aliases) + pvt->serv.s_aliases = malloc(sizeof(char *)); + if (!pvt->serv.s_aliases) + goto cleanup; + pvt->serv.s_aliases[num] = NULL; + return (&pvt->serv); + } + + cleanup: + if (pvt->serv.s_aliases) { + free(pvt->serv.s_aliases); + pvt->serv.s_aliases = NULL; + } + if (pvt->svbuf) { + free(pvt->svbuf); + pvt->svbuf = NULL; + } + return (NULL); +} + +static void +sv_minimize(struct irs_sv *this) { + UNUSED(this); + /* NOOP */ +} + +#ifdef SV_RES_SETGET +static struct __res_state * +sv_res_get(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + return (__hesiod_res_get(dns->hes_ctx)); +} + +static void +sv_res_set(struct irs_sv *this, struct __res_state * res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + __hesiod_res_set(dns->hes_ctx, res, free_res); +} +#endif diff --git a/lib/bind/irs/gai_strerror.c b/lib/bind/irs/gai_strerror.c new file mode 100644 index 0000000000..55fa1f7d97 --- /dev/null +++ b/lib/bind/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 . + +*/ + +#include +#include +#include +#include + +const 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/lib/bind/irs/gen.c b/lib/bind/irs/gen.c new file mode 100644 index 0000000000..9a208d701e --- /dev/null +++ b/lib/bind/irs/gen.c @@ -0,0 +1,427 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen.c,v 1.1 2001/03/29 06:31:43 marka Exp $"; +#endif + +/* + * this is the top level dispatcher + * + * The dispatcher is implemented as an accessor class; it is an + * accessor class that calls other accessor classes, as controlled by a + * configuration file. + * + * A big difference between this accessor class and others is that the + * map class initializers are NULL, and the map classes are already + * filled in with method functions that will do the right thing. + */ + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Definitions */ + +struct nameval { + const char * name; + int val; +}; + +static const struct nameval acc_names[irs_nacc+1] = { + { "local", irs_lcl }, + { "dns", irs_dns }, + { "nis", irs_nis }, + { "irp", irs_irp }, + { NULL, irs_nacc } +}; + +typedef struct irs_acc *(*accinit) __P((const char *options)); + +static const accinit accs[irs_nacc+1] = { + irs_lcl_acc, + irs_dns_acc, +#ifdef WANT_IRS_NIS + irs_nis_acc, +#else + NULL, +#endif + irs_irp_acc, + NULL +}; + +static const struct nameval map_names[irs_nmap+1] = { + { "group", irs_gr }, + { "passwd", irs_pw }, + { "services", irs_sv }, + { "protocols", irs_pr }, + { "hosts", irs_ho }, + { "networks", irs_nw }, + { "netgroup", irs_ng }, + { NULL, irs_nmap } +}; + +static const struct nameval option_names[] = { + { "merge", IRS_MERGE }, + { "continue", IRS_CONTINUE }, + { NULL, 0 } +}; + +/* Forward */ + +static void gen_close(struct irs_acc *); +static struct __res_state * gen_res_get(struct irs_acc *); +static void gen_res_set(struct irs_acc *, struct __res_state *, + void (*)(void *)); +static int find_name(const char *, const struct nameval nv[]); +static void init_map_rules(struct gen_p *, const char *conf_file); +static struct irs_rule *release_rule(struct irs_rule *); +static int add_rule(struct gen_p *, + enum irs_map_id, enum irs_acc_id, + const char *); + +/* Public */ + +struct irs_acc * +irs_gen_acc(const char *options, const char *conf_file) { + struct irs_acc *acc; + struct gen_p *irs; + + if (!(acc = memget(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(irs = memget(sizeof *irs))) { + errno = ENOMEM; + memput(acc, sizeof *acc); + return (NULL); + } + memset(irs, 0x5e, sizeof *irs); + irs->options = strdup(options); + irs->res = NULL; + irs->free_res = NULL; + memset(irs->accessors, 0, sizeof irs->accessors); + memset(irs->map_rules, 0, sizeof irs->map_rules); + init_map_rules(irs, conf_file); + acc->private = irs; +#ifdef WANT_IRS_GR + acc->gr_map = irs_gen_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_gen_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_gen_sv; + acc->pr_map = irs_gen_pr; + acc->ho_map = irs_gen_ho; + acc->nw_map = irs_gen_nw; + acc->ng_map = irs_gen_ng; + acc->res_get = gen_res_get; + acc->res_set = gen_res_set; + acc->close = gen_close; + return (acc); +} + +/* Methods */ + +static struct __res_state * +gen_res_get(struct irs_acc *this) { + struct gen_p *irs = (struct gen_p *)this->private; + + if (irs->res == NULL) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) + return (NULL); + memset(res, 0, sizeof *res); + gen_res_set(this, res, free); + } + + if (((irs->res->options & RES_INIT) == 0) && res_ninit(irs->res) < 0) + return (NULL); + + return (irs->res); +} + +static void +gen_res_set(struct irs_acc *this, struct __res_state *res, + void (*free_res)(void *)) { + struct gen_p *irs = (struct gen_p *)this->private; +#if 0 + struct irs_rule *rule; + struct irs_ho *ho; + struct irs_nw *nw; +#endif + + if (irs->res && irs->free_res) { + res_nclose(irs->res); + (*irs->free_res)(irs->res); + } + + irs->res = res; + irs->free_res = free_res; + +#if 0 + for (rule = irs->map_rules[irs_ho]; rule; rule = rule->next) { + ho = rule->inst->ho; + + (*ho->res_set)(ho, res, NULL); + } + for (rule = irs->map_rules[irs_nw]; rule; rule = rule->next) { + nw = rule->inst->nw; + + (*nw->res_set)(nw, res, NULL); + } +#endif +} + +static void +gen_close(struct irs_acc *this) { + struct gen_p *irs = (struct gen_p *)this->private; + int n; + + /* Search rules. */ + for (n = 0; n < irs_nmap; n++) + while (irs->map_rules[n] != NULL) + irs->map_rules[n] = release_rule(irs->map_rules[n]); + + /* Access methods. */ + for (n = 0; n < irs_nacc; n++) { + /* Map objects. */ + if (irs->accessors[n].gr != NULL) + (*irs->accessors[n].gr->close)(irs->accessors[n].gr); + if (irs->accessors[n].pw != NULL) + (*irs->accessors[n].pw->close)(irs->accessors[n].pw); + if (irs->accessors[n].sv != NULL) + (*irs->accessors[n].sv->close)(irs->accessors[n].sv); + if (irs->accessors[n].pr != NULL) + (*irs->accessors[n].pr->close)(irs->accessors[n].pr); + if (irs->accessors[n].ho != NULL) + (*irs->accessors[n].ho->close)(irs->accessors[n].ho); + if (irs->accessors[n].nw != NULL) + (*irs->accessors[n].nw->close)(irs->accessors[n].nw); + if (irs->accessors[n].ng != NULL) + (*irs->accessors[n].ng->close)(irs->accessors[n].ng); + /* Enclosing accessor. */ + if (irs->accessors[n].acc != NULL) + (*irs->accessors[n].acc->close)(irs->accessors[n].acc); + } + + /* The options string was strdup'd. */ + free((void*)irs->options); + + if (irs->res && irs->free_res) + (*irs->free_res)(irs->res); + + /* The private data container. */ + memput(irs, sizeof *irs); + + /* The object. */ + memput(this, sizeof *this); +} + +/* Private */ + +static int +find_name(const char *name, const struct nameval names[]) { + int n; + + for (n = 0; names[n].name != NULL; n++) + if (strcmp(name, names[n].name) == 0) + return (names[n].val); + return (-1); +} + +static struct irs_rule * +release_rule(struct irs_rule *rule) { + struct irs_rule *next = rule->next; + + memput(rule, sizeof *rule); + return (next); +} + +static int +add_rule(struct gen_p *irs, + enum irs_map_id map, enum irs_acc_id acc, + const char *options) +{ + struct irs_rule **rules, *last, *tmp, *new; + struct irs_inst *inst; + const char *cp; + int n; + +#ifndef WANT_IRS_GR + if (map == irs_gr) + return (-1); +#endif +#ifndef WANT_IRS_PW + if (map == irs_pw) + return (-1); +#endif +#ifndef WANT_IRS_NIS + if (acc == irs_nis) + return (-1); +#endif + new = memget(sizeof *new); + if (new == NULL) + return (-1); + memset(new, 0x5e, sizeof *new); + new->next = NULL; + + new->inst = &irs->accessors[acc]; + + new->flags = 0; + cp = options; + while (cp && *cp) { + char option[50], *next; + + next = strchr(cp, ','); + if (next) + n = next++ - cp; + else + n = strlen(cp); + if ((size_t)n > sizeof option - 1) + n = sizeof option - 1; + strncpy(option, cp, n); + option[n] = '\0'; + + n = find_name(option, option_names); + if (n >= 0) + new->flags |= n; + + cp = next; + } + + rules = &irs->map_rules[map]; + for (last = NULL, tmp = *rules; + tmp != NULL; + last = tmp, tmp = tmp->next) + (void)NULL; + if (last == NULL) + *rules = new; + else + last->next = new; + + /* Try to instantiate map accessors for this if necessary & approp. */ + inst = &irs->accessors[acc]; + if (inst->acc == NULL && accs[acc] != NULL) + inst->acc = (*accs[acc])(irs->options); + if (inst->acc != NULL) { + if (inst->gr == NULL && inst->acc->gr_map != NULL) + inst->gr = (*inst->acc->gr_map)(inst->acc); + if (inst->pw == NULL && inst->acc->pw_map != NULL) + inst->pw = (*inst->acc->pw_map)(inst->acc); + if (inst->sv == NULL && inst->acc->sv_map != NULL) + inst->sv = (*inst->acc->sv_map)(inst->acc); + if (inst->pr == NULL && inst->acc->pr_map != NULL) + inst->pr = (*inst->acc->pr_map)(inst->acc); + if (inst->ho == NULL && inst->acc->ho_map != NULL) + inst->ho = (*inst->acc->ho_map)(inst->acc); + if (inst->nw == NULL && inst->acc->nw_map != NULL) + inst->nw = (*inst->acc->nw_map)(inst->acc); + if (inst->ng == NULL && inst->acc->ng_map != NULL) + inst->ng = (*inst->acc->ng_map)(inst->acc); + } + + return (0); +} + +static void +default_map_rules(struct gen_p *irs) { + /* Install time honoured and proved BSD style rules as default. */ + add_rule(irs, irs_gr, irs_lcl, ""); + add_rule(irs, irs_pw, irs_lcl, ""); + add_rule(irs, irs_sv, irs_lcl, ""); + add_rule(irs, irs_pr, irs_lcl, ""); + add_rule(irs, irs_ho, irs_dns, "continue"); + add_rule(irs, irs_ho, irs_lcl, ""); + add_rule(irs, irs_nw, irs_dns, "continue"); + add_rule(irs, irs_nw, irs_lcl, ""); + add_rule(irs, irs_ng, irs_lcl, ""); +} + +static void +init_map_rules(struct gen_p *irs, const char *conf_file) { + char line[1024], pattern[40], mapname[20], accname[20], options[100]; + FILE *conf; + + if (conf_file == NULL) + conf_file = _PATH_IRS_CONF ; + + /* A conf file of "" means compiled in defaults. Irpd wants this */ + if (conf_file[0] == '\0' || (conf = fopen(conf_file, "r")) == NULL) { + default_map_rules(irs); + return; + } + (void) sprintf(pattern, "%%%ds %%%ds %%%ds\n", + sizeof mapname, sizeof accname, sizeof options); + while (fgets(line, sizeof line, conf)) { + enum irs_map_id map; + enum irs_acc_id acc; + char *tmp; + int n; + + for (tmp = line; isascii(*tmp) && isspace(*tmp); tmp++) + (void)NULL; + if (*tmp == '#' || *tmp == '\n' || *tmp == '\0') + continue; + n = sscanf(tmp, pattern, mapname, accname, options); + if (n < 2) + continue; + if (n < 3) + options[0] = '\0'; + + n = find_name(mapname, map_names); + INSIST(n < irs_nmap); + if (n < 0) + continue; + map = (enum irs_map_id) n; + + n = find_name(accname, acc_names); + INSIST(n < irs_nacc); + if (n < 0) + continue; + acc = (enum irs_acc_id) n; + + add_rule(irs, map, acc, options); + } + fclose(conf); +} diff --git a/lib/bind/irs/gen_gr.c b/lib/bind/irs/gen_gr.c new file mode 100644 index 0000000000..e75236201b --- /dev/null +++ b/lib/bind/irs/gen_gr.c @@ -0,0 +1,454 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_gr.c,v 1.1 2001/03/29 06:31:43 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_GR +static int __bind_irs_gr_unneeded; +#else + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Definitions */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct irs_gr * gr; + /* + * Need space to store the entries read from the group file. + * The members list also needs space per member, and the + * strings making up the user names must be allocated + * somewhere. Rather than doing lots of small allocations, + * we keep one buffer and resize it as needed. + */ + struct group group; + size_t nmemb; /* Malloc'd max index of gr_mem[]. */ + char * membuf; + size_t membufsize; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void gr_close(struct irs_gr *); +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static int gr_list(struct irs_gr *, const char *, + gid_t, gid_t *, int *); +static void gr_minimize(struct irs_gr *); +static struct __res_state * gr_res_get(struct irs_gr *); +static void gr_res_set(struct irs_gr *, + struct __res_state *, + void (*)(void *)); + +static void grmerge(struct irs_gr *gr, const struct group *src, + int preserve); + +static int countvec(char **vec); +static int isnew(char **old, char *new); +static int countnew(char **old, char **new); +static size_t sizenew(char **old, char **new); +static int newgid(int, gid_t *, gid_t); + +/* Public */ + +struct irs_gr * +irs_gen_gr(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_gr *gr; + struct pvt *pvt; + + if (!(gr = memget(sizeof *gr))) { + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x5e, sizeof *gr); + if (!(pvt = memget(sizeof *pvt))) { + memput(gr, sizeof *gr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_gr]; + pvt->rule = pvt->rules; + gr->private = pvt; + gr->close = gr_close; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->list = gr_list; + gr->minimize = gr_minimize; + gr->res_get = gr_res_get; + gr->res_set = gr_res_set; + return (gr); +} + +/* Methods. */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct group * +gr_next(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct group *rval; + struct irs_gr *gr; + + while (pvt->rule) { + gr = pvt->rule->inst->gr; + rval = (*gr->next)(gr); + if (rval) + return (rval); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + gr = pvt->rule->inst->gr; + (*gr->rewind)(gr); + } + } + return (NULL); +} + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct group *tval; + struct irs_gr *gr; + int dirty; + + dirty = 0; + for (rule = pvt->rules; rule; rule = rule->next) { + gr = rule->inst->gr; + tval = (*gr->byname)(gr, name); + if (tval) { + grmerge(this, tval, dirty++); + if (!(rule->flags & IRS_MERGE)) + break; + } else { + if (!(rule->flags & IRS_CONTINUE)) + break; + } + } + if (dirty) + return (&pvt->group); + return (NULL); +} + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct group *tval; + struct irs_gr *gr; + int dirty; + + dirty = 0; + for (rule = pvt->rules; rule; rule = rule->next) { + gr = rule->inst->gr; + tval = (*gr->bygid)(gr, gid); + if (tval) { + grmerge(this, tval, dirty++); + if (!(rule->flags & IRS_MERGE)) + break; + } else { + if (!(rule->flags & IRS_CONTINUE)) + break; + } + } + if (dirty) + return (&pvt->group); + return (NULL); +} + +static void +gr_rewind(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_gr *gr; + + pvt->rule = pvt->rules; + if (pvt->rule) { + gr = pvt->rule->inst->gr; + (*gr->rewind)(gr); + } +} + +static int +gr_list(struct irs_gr *this, const char *name, + gid_t basegid, gid_t *groups, int *ngroups) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct irs_gr *gr; + int t_ngroups, maxgroups; + gid_t *t_groups; + int n, t, rval = 0; + + maxgroups = *ngroups; + *ngroups = 0; + t_groups = (gid_t *)malloc(maxgroups * sizeof(gid_t)); + if (!t_groups) { + errno = ENOMEM; + return (-1); + } + + for (rule = pvt->rules; rule; rule = rule->next) { + t_ngroups = maxgroups; + gr = rule->inst->gr; + t = (*gr->list)(gr, name, basegid, t_groups, &t_ngroups); + for (n = 0; n < t_ngroups; n++) { + if (newgid(*ngroups, groups, t_groups[n])) { + if (*ngroups == maxgroups) { + rval = -1; + goto done; + } + groups[(*ngroups)++] = t_groups[n]; + } + } + if (t == 0) { + if (!(rule->flags & IRS_MERGE)) + break; + } else { + if (!(rule->flags & IRS_CONTINUE)) + break; + } + } + done: + free(t_groups); + return (rval); +} + +static void +gr_minimize(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_gr *gr = rule->inst->gr; + + (*gr->minimize)(gr); + } +} + +static struct __res_state * +gr_res_get(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + gr_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +gr_res_set(struct irs_gr *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_gr *gr = rule->inst->gr; + + if (gr->res_set) + (*gr->res_set)(gr, pvt->res, NULL); + } +} + +/* Private. */ + +static void +grmerge(struct irs_gr *this, const struct group *src, int preserve) { + struct pvt *pvt = (struct pvt *)this->private; + char *cp, **m, **p; + int n, ndst, nnew, memadj; + + if (!preserve) { + pvt->group.gr_gid = src->gr_gid; + if (pvt->nmemb < 1) { + m = malloc(sizeof *m); + if (!m) { + /* No harm done, no work done. */ + return; + } + pvt->group.gr_mem = m; + pvt->nmemb = 1; + } + pvt->group.gr_mem[0] = NULL; + } + ndst = countvec(pvt->group.gr_mem); + nnew = countnew(pvt->group.gr_mem, src->gr_mem); + + /* + * Make sure destination member array is large enough. + * p points to new portion. + */ + n = ndst + nnew + 1; + if ((size_t)n > pvt->nmemb) { + m = realloc(pvt->group.gr_mem, n * sizeof *m); + if (!m) { + /* No harm done, no work done. */ + return; + } + pvt->group.gr_mem = m; + pvt->nmemb = n; + } + p = pvt->group.gr_mem + ndst; + + /* + * Enlarge destination membuf; cp points at new portion. + */ + n = sizenew(pvt->group.gr_mem, src->gr_mem); + INSIST((nnew == 0) == (n == 0)); + if (!preserve) { + n += strlen(src->gr_name) + 1; + n += strlen(src->gr_passwd) + 1; + } + if (n == 0) { + /* No work to do. */ + return; + } + cp = realloc(pvt->membuf, pvt->membufsize + n); + if (!cp) { + /* No harm done, no work done. */ + return; + } + memadj = cp - pvt->membuf; + pvt->membuf = cp; + cp += pvt->membufsize; + pvt->membufsize += n; + + /* + * Add new elements. + */ + for (m = src->gr_mem; *m; m++) + if (isnew(pvt->group.gr_mem, *m)) { + *p++ = cp; + *p = NULL; + strcpy(cp, *m); + cp += strlen(cp) + 1; + } + if (preserve) { + pvt->group.gr_name += memadj; + pvt->group.gr_passwd += memadj; + } else { + pvt->group.gr_name = cp; + strcpy(cp, src->gr_name); + cp += strlen(src->gr_name) + 1; + pvt->group.gr_passwd = cp; + strcpy(cp, src->gr_passwd); + cp += strlen(src->gr_passwd) + 1; + } + INSIST(cp >= pvt->membuf && cp <= &pvt->membuf[pvt->membufsize]); +} + +static int +countvec(char **vec) { + int n = 0; + + while (*vec++) + n++; + return (n); +} + +static int +isnew(char **old, char *new) { + for (; *old; old++) + if (strcmp(*old, new) == 0) + return (0); + return (1); +} + +static int +countnew(char **old, char **new) { + int n = 0; + + for (; *new; new++) + n += isnew(old, *new); + return (n); +} + +static size_t +sizenew(char **old, char **new) { + size_t n = 0; + + for (; *new; new++) + if (isnew(old, *new)) + n += strlen(*new) + 1; + return (n); +} + +static int +newgid(int ngroups, gid_t *groups, gid_t group) { + ngroups--, groups++; + for (; ngroups-- > 0; groups++) + if (*groups == group) + return (0); + return (1); +} + +#endif /* WANT_IRS_GR */ diff --git a/lib/bind/irs/gen_ho.c b/lib/bind/irs/gen_ho.c new file mode 100644 index 0000000000..0fec9092b0 --- /dev/null +++ b/lib/bind/irs/gen_ho.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: gen_ho.c,v 1.1 2001/03/29 06:31:43 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Definitions */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct irs_ho * ho; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forwards */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); +static struct __res_state * ho_res_get(struct irs_ho *this); +static void ho_res_set(struct irs_ho *this, + struct __res_state *res, + void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +static int init(struct irs_ho *this); + +/* Exports */ + +struct irs_ho * +irs_gen_ho(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_ho *ho; + struct pvt *pvt; + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(ho = memget(sizeof *ho))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + pvt->rules = accpvt->map_rules[irs_ho]; + pvt->rule = pvt->rules; + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->res_get = ho_res_get; + ho->res_set = ho_res_set; + ho->addrinfo = ho_addrinfo; + return (ho); +} + +/* Methods. */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct hostent *rval; + struct irs_ho *ho; + int therrno = NETDB_INTERNAL; + int softerror = 0; + + if (init(this) == -1) + return (NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = 0; + rval = (*ho->byname)(ho, name); + if (rval != NULL) + return (rval); + if (softerror == 0 && + pvt->res->res_h_errno != HOST_NOT_FOUND && + pvt->res->res_h_errno != NETDB_INTERNAL) { + softerror = 1; + therrno = pvt->res->res_h_errno; + } + if (rule->flags & IRS_CONTINUE) + continue; + /* + * The value TRY_AGAIN can mean that the service + * is not available, or just that this particular name + * cannot be resolved now. We use the errno ECONNREFUSED + * to distinguish. If a lookup sets that errno when + * H_ERRNO is TRY_AGAIN, we continue to try other lookup + * functions, otherwise we return the TRY_AGAIN error. + */ + if (pvt->res->res_h_errno != TRY_AGAIN || errno != ECONNREFUSED) + break; + } + if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND) + RES_SET_H_ERRNO(pvt->res, therrno); + return (NULL); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct hostent *rval; + struct irs_ho *ho; + int therrno = NETDB_INTERNAL; + int softerror = 0; + + if (init(this) == -1) + return (NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = 0; + rval = (*ho->byname2)(ho, name, af); + if (rval != NULL) + return (rval); + if (softerror == 0 && + pvt->res->res_h_errno != HOST_NOT_FOUND && + pvt->res->res_h_errno != NETDB_INTERNAL) { + softerror = 1; + therrno = pvt->res->res_h_errno; + } + if (rule->flags & IRS_CONTINUE) + continue; + /* + * See the comments in ho_byname() explaining + * the interpretation of TRY_AGAIN and ECONNREFUSED. + */ + if (pvt->res->res_h_errno != TRY_AGAIN || errno != ECONNREFUSED) + break; + } + if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND) + RES_SET_H_ERRNO(pvt->res, therrno); + return (NULL); +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct hostent *rval; + struct irs_ho *ho; + int therrno = NETDB_INTERNAL; + int softerror = 0; + + + if (init(this) == -1) + return (NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = 0; + rval = (*ho->byaddr)(ho, addr, len, af); + if (rval != NULL) + return (rval); + if (softerror == 0 && + pvt->res->res_h_errno != HOST_NOT_FOUND && + pvt->res->res_h_errno != NETDB_INTERNAL) { + softerror = 1; + therrno = pvt->res->res_h_errno; + } + + if (rule->flags & IRS_CONTINUE) + continue; + /* + * See the comments in ho_byname() explaining + * the interpretation of TRY_AGAIN and ECONNREFUSED. + */ + if (pvt->res->res_h_errno != TRY_AGAIN || errno != ECONNREFUSED) + break; + } + if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND) + RES_SET_H_ERRNO(pvt->res, therrno); + return (NULL); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *rval; + struct irs_ho *ho; + + while (pvt->rule) { + ho = pvt->rule->inst->ho; + rval = (*ho->next)(ho); + if (rval) + return (rval); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + ho = pvt->rule->inst->ho; + (*ho->rewind)(ho); + } + } + return (NULL); +} + +static void +ho_rewind(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_ho *ho; + + pvt->rule = pvt->rules; + if (pvt->rule) { + ho = pvt->rule->inst->ho; + (*ho->rewind)(ho); + } +} + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res) + res_nclose(pvt->res); + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_ho *ho = rule->inst->ho; + + (*ho->minimize)(ho); + } +} + +static struct __res_state * +ho_res_get(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + ho_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +ho_res_set(struct irs_ho *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_ho *ho = rule->inst->ho; + + (*ho->res_set)(ho, pvt->res, NULL); + } +} + +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct addrinfo *rval = NULL; + struct irs_ho *ho; + int therrno = NETDB_INTERNAL; + int softerror = 0; + + if (init(this) == -1) + return (NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = 0; + if (ho->addrinfo == NULL) /* for safety */ + continue; + rval = (*ho->addrinfo)(ho, name, pai); + if (rval != NULL) + return (rval); + if (softerror == 0 && + pvt->res->res_h_errno != HOST_NOT_FOUND && + pvt->res->res_h_errno != NETDB_INTERNAL) { + softerror = 1; + therrno = pvt->res->res_h_errno; + } + if (rule->flags & IRS_CONTINUE) + continue; + /* + * See the comments in ho_byname() explaining + * the interpretation of TRY_AGAIN and ECONNREFUSED. + */ + if (pvt->res->res_h_errno != TRY_AGAIN || + errno != ECONNREFUSED) + break; + } + if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND) + RES_SET_H_ERRNO(pvt->res, therrno); + if (rval) + freeaddrinfo(rval); + return (NULL); +} + +static int +init(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !ho_res_get(this)) + return (-1); + + if (((pvt->res->options & RES_INIT) == 0) && + (res_ninit(pvt->res) == -1)) + return (-1); + + return (0); +} diff --git a/lib/bind/irs/gen_ng.c b/lib/bind/irs/gen_ng.c new file mode 100644 index 0000000000..51e1fede62 --- /dev/null +++ b/lib/bind/irs/gen_ng.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_ng.c,v 1.1 2001/03/29 06:31:43 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + char * curgroup; +}; + +/* Forward */ + +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); +static int ng_test(struct irs_ng *, const char *, + const char *, const char *, + const char *); +static void ng_rewind(struct irs_ng *, const char *); +static void ng_minimize(struct irs_ng *); + +/* Public */ + +struct irs_ng * +irs_gen_ng(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_ng *ng; + struct pvt *pvt; + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + if (!(pvt = memget(sizeof *pvt))) { + memput(ng, sizeof *ng); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_ng]; + pvt->rule = pvt->rules; + ng->private = pvt; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods */ + +static void +ng_close(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ng_minimize(this); + if (pvt->curgroup) + free(pvt->curgroup); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static int +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct irs_ng *ng; + + while (pvt->rule) { + ng = pvt->rule->inst->ng; + if ((*ng->next)(ng, host, user, domain) == 1) + return (1); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + ng = pvt->rule->inst->ng; + (*ng->rewind)(ng, pvt->curgroup); + } + } + return (0); +} + +static int +ng_test(struct irs_ng *this, const char *name, + const char *user, const char *host, const char *domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct irs_ng *ng; + int rval; + + rval = 0; + for (rule = pvt->rules; rule; rule = rule->next) { + ng = rule->inst->ng; + rval = (*ng->test)(ng, name, user, host, domain); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +ng_rewind(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_ng *ng; + + pvt->rule = pvt->rules; + if (pvt->rule) { + if (pvt->curgroup) + free(pvt->curgroup); + pvt->curgroup = strdup(group); + ng = pvt->rule->inst->ng; + (*ng->rewind)(ng, pvt->curgroup); + } +} + +static void +ng_minimize(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_ng *ng = rule->inst->ng; + + (*ng->minimize)(ng); + } +} diff --git a/lib/bind/irs/gen_nw.c b/lib/bind/irs/gen_nw.c new file mode 100644 index 0000000000..c436fa0e5c --- /dev/null +++ b/lib/bind/irs/gen_nw.c @@ -0,0 +1,262 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_nw.c,v 1.1 2001/03/29 06:31:44 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void nw_close(struct irs_nw*); +static struct nwent * nw_next(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); +static struct __res_state * nw_res_get(struct irs_nw *this); +static void nw_res_set(struct irs_nw *this, + struct __res_state *res, + void (*free_res)(void *)); + +static int init(struct irs_nw *this); + +/* Public */ + +struct irs_nw * +irs_gen_nw(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_nw *nw; + struct pvt *pvt; + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + pvt->rules = accpvt->map_rules[irs_nw]; + pvt->rule = pvt->rules; + nw->private = pvt; + nw->close = nw_close; + nw->next = nw_next; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + nw->res_get = nw_res_get; + nw->res_set = nw_res_set; + return (nw); +} + +/* Methods */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct nwent * +nw_next(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *rval; + struct irs_nw *nw; + + if (init(this) == -1) + return(NULL); + + while (pvt->rule) { + nw = pvt->rule->inst->nw; + rval = (*nw->next)(nw); + if (rval) + return (rval); + if (!(pvt->rules->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + nw = pvt->rule->inst->nw; + (*nw->rewind)(nw); + } + } + return (NULL); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int type) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct nwent *rval; + struct irs_nw *nw; + + if (init(this) == -1) + return(NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + nw = rule->inst->nw; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + rval = (*nw->byname)(nw, name, type); + if (rval != NULL) + return (rval); + if (pvt->res->res_h_errno != TRY_AGAIN && + !(rule->flags & IRS_CONTINUE)) + break; + } + return (NULL); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int length, int type) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct nwent *rval; + struct irs_nw *nw; + + if (init(this) == -1) + return(NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + nw = rule->inst->nw; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + rval = (*nw->byaddr)(nw, net, length, type); + if (rval != NULL) + return (rval); + if (pvt->res->res_h_errno != TRY_AGAIN && + !(rule->flags & IRS_CONTINUE)) + break; + } + return (NULL); +} + +static void +nw_rewind(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_nw *nw; + + pvt->rule = pvt->rules; + if (pvt->rule) { + nw = pvt->rule->inst->nw; + (*nw->rewind)(nw); + } +} + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res) + res_nclose(pvt->res); + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_nw *nw = rule->inst->nw; + + (*nw->minimize)(nw); + } +} + +static struct __res_state * +nw_res_get(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + nw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +nw_res_set(struct irs_nw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_nw *nw = rule->inst->nw; + + (*nw->res_set)(nw, pvt->res, NULL); + } +} + +static int +init(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !nw_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} diff --git a/lib/bind/irs/gen_p.h b/lib/bind/irs/gen_p.h new file mode 100644 index 0000000000..e0ad838c04 --- /dev/null +++ b/lib/bind/irs/gen_p.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: gen_p.h,v 1.1 2001/03/29 06:31:44 marka Exp $ + */ + +/* Notes: + * We hope to create a complete set of thread-safe entry points someday, + * which will mean a set of getXbyY() functions that take as an argument + * a pointer to the map class, which will have a pointer to the private + * data, which will be used preferentially to the static variables that + * are necessary to support the "classic" interface. This "classic" + * interface will then be reimplemented as stubs on top of the thread + * safe modules, and will keep the map class pointers as their only + * static data. HOWEVER, we are not there yet. So while we will call + * the just-barely-converted map class methods with map class pointers, + * right now they probably all still use statics. We're not fooling + * anybody, and we're not trying to (yet). + */ + +#ifndef _GEN_P_H_INCLUDED +#define _GEN_P_H_INCLUDED + +/* + * These are the access methods. + */ +enum irs_acc_id { + irs_lcl, /* Local. */ + irs_dns, /* DNS or Hesiod. */ + irs_nis, /* Sun NIS ("YP"). */ + irs_irp, /* IR protocol. */ + irs_nacc +}; + +/* + * These are the map types. + */ +enum irs_map_id { + irs_gr, /* "group" */ + irs_pw, /* "passwd" */ + irs_sv, /* "services" */ + irs_pr, /* "protocols" */ + irs_ho, /* "hosts" */ + irs_nw, /* "networks" */ + irs_ng, /* "netgroup" */ + irs_nmap +}; + +/* + * This is an accessor instance. + */ +struct irs_inst { + struct irs_acc *acc; + struct irs_gr * gr; + struct irs_pw * pw; + struct irs_sv * sv; + struct irs_pr * pr; + struct irs_ho * ho; + struct irs_nw * nw; + struct irs_ng * ng; +}; + +/* + * This is a search rule for some map type. + */ +struct irs_rule { + struct irs_rule * next; + struct irs_inst * inst; + int flags; +}; +#define IRS_MERGE 0x0001 /* Don't stop if acc. has data? */ +#define IRS_CONTINUE 0x0002 /* Don't stop if acc. has no data? */ + +/* + * This is the private data for a search access class. + */ +struct gen_p { + char * options; + struct irs_rule * map_rules[(int)irs_nmap]; + struct irs_inst accessors[(int)irs_nacc]; + struct __res_state * res; + void (*free_res) __P((void *)); +}; + +/* + * Externs. + */ + +extern struct irs_acc * irs_gen_acc __P((const char *, const char *conf_file)); +extern struct irs_gr * irs_gen_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_gen_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_gen_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_gen_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_gen_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_gen_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_gen_ng __P((struct irs_acc *)); + +#endif /*_IRS_P_H_INCLUDED*/ diff --git a/lib/bind/irs/gen_pr.c b/lib/bind/irs/gen_pr.c new file mode 100644 index 0000000000..661ff7e4a8 --- /dev/null +++ b/lib/bind/irs/gen_pr.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_pr.c,v 1.1 2001/03/29 06:31:44 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void pr_close(struct irs_pr*); +static struct protoent * pr_next(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); +static struct __res_state * pr_res_get(struct irs_pr *); +static void pr_res_set(struct irs_pr *, + struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_pr * +irs_gen_pr(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_pr *pr; + struct pvt *pvt; + + if (!(pr = memget(sizeof *pr))) { + errno = ENOMEM; + return (NULL); + } + memset(pr, 0x5e, sizeof *pr); + if (!(pvt = memget(sizeof *pvt))) { + memput(pr, sizeof *pr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_pr]; + pvt->rule = pvt->rules; + pr->private = pvt; + pr->close = pr_close; + pr->next = pr_next; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->rewind = pr_rewind; + pr->minimize = pr_minimize; + pr->res_get = pr_res_get; + pr->res_set = pr_res_set; + return (pr); +} + +/* Methods */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct protoent * +pr_next(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *rval; + struct irs_pr *pr; + + while (pvt->rule) { + pr = pvt->rule->inst->pr; + rval = (*pr->next)(pr); + if (rval) + return (rval); + if (!(pvt->rules->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + pr = pvt->rule->inst->pr; + (*pr->rewind)(pr); + } + } + return (NULL); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct protoent *rval; + struct irs_pr *pr; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + pr = rule->inst->pr; + rval = (*pr->byname)(pr, name); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct protoent *rval; + struct irs_pr *pr; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + pr = rule->inst->pr; + rval = (*pr->bynumber)(pr, proto); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +pr_rewind(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_pr *pr; + + pvt->rule = pvt->rules; + if (pvt->rule) { + pr = pvt->rule->inst->pr; + (*pr->rewind)(pr); + } +} + +static void +pr_minimize(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_pr *pr = rule->inst->pr; + + (*pr->minimize)(pr); + } +} + +static struct __res_state * +pr_res_get(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + pr_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +pr_res_set(struct irs_pr *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_pr *pr = rule->inst->pr; + + if (pr->res_set) + (*pr->res_set)(pr, pvt->res, NULL); + } +} diff --git a/lib/bind/irs/gen_pw.c b/lib/bind/irs/gen_pw.c new file mode 100644 index 0000000000..63e9157f81 --- /dev/null +++ b/lib/bind/irs/gen_pw.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_pw.c,v 1.1 2001/03/29 06:31:44 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_pw_unneeded; +#else + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_next(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); +static struct __res_state * pw_res_get(struct irs_pw *); +static void pw_res_set(struct irs_pw *, + struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_pw * +irs_gen_pw(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_pw *pw; + struct pvt *pvt; + + if (!(pw = memget(sizeof *pw))) { + errno = ENOMEM; + return (NULL); + } + memset(pw, 0x5e, sizeof *pw); + if (!(pvt = memget(sizeof *pvt))) { + memput(pw, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_pw]; + pvt->rule = pvt->rules; + pw->private = pvt; + pw->close = pw_close; + pw->next = pw_next; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + pw->res_get = pw_res_get; + pw->res_set = pw_res_set; + return (pw); +} + +/* Methods */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct passwd * +pw_next(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct passwd *rval; + struct irs_pw *pw; + + while (pvt->rule) { + pw = pvt->rule->inst->pw; + rval = (*pw->next)(pw); + if (rval) + return (rval); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + pw = pvt->rule->inst->pw; + (*pw->rewind)(pw); + } + } + return (NULL); +} + +static void +pw_rewind(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_pw *pw; + + pvt->rule = pvt->rules; + if (pvt->rule) { + pw = pvt->rule->inst->pw; + (*pw->rewind)(pw); + } +} + +static struct passwd * +pw_byname(struct irs_pw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct passwd *rval; + struct irs_pw *pw; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + pw = rule->inst->pw; + rval = (*pw->byname)(pw, name); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct passwd *rval; + struct irs_pw *pw; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + pw = rule->inst->pw; + rval = (*pw->byuid)(pw, uid); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +pw_minimize(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_pw *pw = rule->inst->pw; + + (*pw->minimize)(pw); + } +} + +static struct __res_state * +pw_res_get(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + pw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +pw_res_set(struct irs_pw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_pw *pw = rule->inst->pw; + + if (pw->res_set) + (*pw->res_set)(pw, pvt->res, NULL); + } +} + +#endif /* WANT_IRS_PW */ diff --git a/lib/bind/irs/gen_sv.c b/lib/bind/irs/gen_sv.c new file mode 100644 index 0000000000..9062394748 --- /dev/null +++ b/lib/bind/irs/gen_sv.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_sv.c,v 1.1 2001/03/29 06:31:44 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void sv_close(struct irs_sv*); +static struct servent * sv_next(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, const char *, + const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); +static struct __res_state * sv_res_get(struct irs_sv *); +static void sv_res_set(struct irs_sv *, + struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_sv * +irs_gen_sv(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_sv *sv; + struct pvt *pvt; + + if (!(sv = memget(sizeof *sv))) { + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + if (!(pvt = memget(sizeof *pvt))) { + memput(sv, sizeof *sv); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_sv]; + pvt->rule = pvt->rules; + sv->private = pvt; + sv->close = sv_close; + sv->next = sv_next; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->rewind = sv_rewind; + sv->minimize = sv_minimize; + sv->res_get = sv_res_get; + sv->res_set = sv_res_set; + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct servent * +sv_next(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *rval; + struct irs_sv *sv; + + while (pvt->rule) { + sv = pvt->rule->inst->sv; + rval = (*sv->next)(sv); + if (rval) + return (rval); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + sv = pvt->rule->inst->sv; + (*sv->rewind)(sv); + } + } + return (NULL); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct servent *rval; + struct irs_sv *sv; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + sv = rule->inst->sv; + rval = (*sv->byname)(sv, name, proto); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct servent *rval; + struct irs_sv *sv; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + sv = rule->inst->sv; + rval = (*sv->byport)(sv, port, proto); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +sv_rewind(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_sv *sv; + + pvt->rule = pvt->rules; + if (pvt->rule) { + sv = pvt->rule->inst->sv; + (*sv->rewind)(sv); + } +} + +static void +sv_minimize(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_sv *sv = rule->inst->sv; + + (*sv->minimize)(sv); + } +} + +static struct __res_state * +sv_res_get(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + sv_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +sv_res_set(struct irs_sv *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_sv *sv = rule->inst->sv; + + if (sv->res_set) + (*sv->res_set)(sv, pvt->res, NULL); + } +} diff --git a/lib/bind/irs/getaddrinfo.c b/lib/bind/irs/getaddrinfo.c new file mode 100644 index 0000000000..3a904b5689 --- /dev/null +++ b/lib/bind/irs/getaddrinfo.c @@ -0,0 +1,1254 @@ +/* $KAME: getaddrinfo.c,v 1.14 2001/01/06 09:41:15 jinmei Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Issues to be discussed: + * - Thread safe-ness must be checked. + * - Return values. There are nonstandard return values defined and used + * in the source code. This is because RFC2553 is silent about which error + * code must be returned for which situation. + * - IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2 + * says to use inet_aton() to convert IPv4 numeric to binary (allows + * classful form as a result). + * current code - disallow classful form for IPv4 (due to use of inet_pton). + * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is + * invalid. + * current code - SEGV on freeaddrinfo(NULL) + * Note: + * - We use getipnodebyname() just for thread-safeness. There's no intent + * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to + * getipnodebyname(). + * - The code filters out AFs that are not supported by the kernel, + * when globbing NULL hostname (to loopback, or wildcard). Is it the right + * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG + * in ai_flags? + * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague. + * (1) what should we do against numeric hostname (2) what should we do + * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready? + * non-loopback address configured? global address configured? + * - To avoid search order issue, we have a big amount of code duplicate + * from gethnamaddr.c and some other places. The issues that there's no + * lower layer function to lookup "IPv4 or IPv6" record. Calling + * gethostbyname2 from getaddrinfo will end up in wrong search order, as + * follows: + * - The code makes use of following calls when asked to resolver with + * ai_family = PF_UNSPEC: + * getipnodebyname(host, AF_INET6); + * getipnodebyname(host, AF_INET); + * This will result in the following queries if the node is configure to + * prefer /etc/hosts than DNS: + * lookup /etc/hosts for IPv6 address + * lookup DNS for IPv6 address + * lookup /etc/hosts for IPv4 address + * lookup DNS for IPv4 address + * which may not meet people's requirement. + * The right thing to happen is to have underlying layer which does + * PF_UNSPEC lookup (lookup both) and return chain of addrinfos. + * This would result in a bit of code duplicate with _dns_ghbyname() and + * friends. + */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "port_after.h" + +#include "irs_data.h" + +/* + * if we enable it, we will see duplicated addrinfo entries on reply if both + * AAAA and A6 records are found. disable it for default installation. + */ +#undef T_A6 + +#define SUCCESS 0 +#define ANY 0 +#define YES 1 +#define NO 0 + +static const char in_addrany[] = { 0, 0, 0, 0 }; +static const char in6_addrany[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +static const char in_loopback[] = { 127, 0, 0, 1 }; +static const char in6_loopback[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 +}; + +static const struct afd { + int a_af; + int a_addrlen; + int a_socklen; + int a_off; + const char *a_addrany; + const char *a_loopback; + int a_scoped; +} afdl [] = { +#ifdef INET6 + {PF_INET6, sizeof(struct in6_addr), + sizeof(struct sockaddr_in6), + offsetof(struct sockaddr_in6, sin6_addr), + in6_addrany, in6_loopback, 1}, +#endif + {PF_INET, sizeof(struct in_addr), + sizeof(struct sockaddr_in), + offsetof(struct sockaddr_in, sin_addr), + in_addrany, in_loopback, 0}, + {0, 0, 0, 0, NULL, NULL, 0}, +}; + +struct explore { + int e_af; + int e_socktype; + int e_protocol; + const char *e_protostr; + int e_wild; +#define WILD_AF(ex) ((ex)->e_wild & 0x01) +#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) +#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) +}; + +static const struct explore explore[] = { +#if 0 + { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 }, +#endif +#ifdef INET6 + { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, + { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, + { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 }, +#endif + { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, + { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, + { PF_INET, SOCK_RAW, ANY, NULL, 0x05 }, + { -1, 0, 0, NULL, 0 }, +}; + +#ifdef INET6 +#define PTON_MAX 16 +#else +#define PTON_MAX 4 +#endif + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +typedef union { + HEADER hdr; + u_char buf[MAXPACKET]; +} querybuf; + +static int str_isnumber __P((const char *)); +static int explore_fqdn __P((const struct addrinfo *, const char *, + const char *, struct addrinfo **)); +static int explore_copy __P((const struct addrinfo *, const struct addrinfo *, + struct addrinfo **)); +static int explore_null __P((const struct addrinfo *, + const char *, struct addrinfo **)); +static int explore_numeric __P((const struct addrinfo *, const char *, + const char *, struct addrinfo **)); +static int explore_numeric_scope __P((const struct addrinfo *, const char *, + const char *, struct addrinfo **)); +static int get_canonname __P((const struct addrinfo *, + struct addrinfo *, const char *)); +static struct addrinfo *get_ai __P((const struct addrinfo *, + const struct afd *, const char *)); +static struct addrinfo *copy_ai __P((const struct addrinfo *)); +static int get_portmatch __P((const struct addrinfo *, const char *)); +static int get_port __P((const struct addrinfo *, const char *, int)); +static const struct afd *find_afd __P((int)); +static int addrconfig __P((int)); +#ifdef INET6 +static int ip6_str2scopeid __P((char *, struct sockaddr_in6 *)); +#endif +static struct net_data *init __P((void)); + +struct addrinfo *hostent2addrinfo __P((struct hostent *, + const struct addrinfo *)); +struct addrinfo *addr2addrinfo __P((const struct addrinfo *, + const char *)); + +#if 0 +static const char *ai_errlist[] = { + "Success", + "Address family for hostname not supported", /* EAI_ADDRFAMILY */ + "Temporary failure in name resolution", /* EAI_AGAIN */ + "Invalid value for ai_flags", /* EAI_BADFLAGS */ + "Non-recoverable failure in name resolution", /* EAI_FAIL */ + "ai_family not supported", /* EAI_FAMILY */ + "Memory allocation failure", /* EAI_MEMORY */ + "No address associated with hostname", /* EAI_NODATA */ + "hostname nor servname provided, or not known", /* EAI_NONAME */ + "servname not supported for ai_socktype", /* EAI_SERVICE */ + "ai_socktype not supported", /* EAI_SOCKTYPE */ + "System error returned in errno", /* EAI_SYSTEM */ + "Invalid value for hints", /* EAI_BADHINTS */ + "Resolved protocol is unknown", /* EAI_PROTOCOL */ + "Unknown error", /* EAI_MAX */ +}; +#endif + +/* XXX macros that make external reference is BAD. */ + +#define GET_AI(ai, afd, addr) \ +do { \ + /* external reference: pai, error, and label free */ \ + (ai) = get_ai(pai, (afd), (addr)); \ + if ((ai) == NULL) { \ + error = EAI_MEMORY; \ + goto free; \ + } \ +} while (/*CONSTCOND*/0) + +#define GET_PORT(ai, serv) \ +do { \ + /* external reference: error and label free */ \ + error = get_port((ai), (serv), 0); \ + if (error != 0) \ + goto free; \ +} while (/*CONSTCOND*/0) + +#define GET_CANONNAME(ai, str) \ +do { \ + /* external reference: pai, error and label free */ \ + error = get_canonname(pai, (ai), (str)); \ + if (error != 0) \ + goto free; \ +} while (/*CONSTCOND*/0) + +#define ERR(err) \ +do { \ + /* external reference: error, and label bad */ \ + error = (err); \ + goto bad; \ + /*NOTREACHED*/ \ +} while (/*CONSTCOND*/0) + +#define MATCH_FAMILY(x, y, w) \ + ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC))) +#define MATCH(x, y, w) \ + ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY))) + +#if 0 /* bind8 has its own version */ +char * +gai_strerror(ecode) + int ecode; +{ + if (ecode < 0 || ecode > EAI_MAX) + ecode = EAI_MAX; + return ai_errlist[ecode]; +} +#endif + +void +freeaddrinfo(ai) + struct addrinfo *ai; +{ + struct addrinfo *next; + + do { + next = ai->ai_next; + if (ai->ai_canonname) + free(ai->ai_canonname); + /* no need to free(ai->ai_addr) */ + free(ai); + ai = next; + } while (ai); +} + +static int +str_isnumber(p) + const char *p; +{ + char *ep; + + if (*p == '\0') + return NO; + ep = NULL; + (void)strtoul(p, &ep, 10); + if (ep && *ep == '\0') + return YES; + else + return NO; +} + +int +getaddrinfo(hostname, servname, hints, res) + const char *hostname, *servname; + const struct addrinfo *hints; + struct addrinfo **res; +{ + struct addrinfo sentinel; + struct addrinfo *cur; + int error = 0; + struct addrinfo ai, ai0, *afai; + struct addrinfo *pai; + const struct explore *ex; + + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + pai = &ai; + pai->ai_flags = 0; + pai->ai_family = PF_UNSPEC; + pai->ai_socktype = ANY; + pai->ai_protocol = ANY; + pai->ai_addrlen = 0; + pai->ai_canonname = NULL; + pai->ai_addr = NULL; + pai->ai_next = NULL; + + if (hostname == NULL && servname == NULL) + return EAI_NONAME; + if (hints) { + /* error check for hints */ + if (hints->ai_addrlen || hints->ai_canonname || + hints->ai_addr || hints->ai_next) + ERR(EAI_BADHINTS); /* xxx */ + if (hints->ai_flags & ~AI_MASK) + ERR(EAI_BADFLAGS); + switch (hints->ai_family) { + case PF_UNSPEC: + case PF_INET: +#ifdef INET6 + case PF_INET6: +#endif + break; + default: + ERR(EAI_FAMILY); + } + memcpy(pai, hints, sizeof(*pai)); + + /* + * if both socktype/protocol are specified, check if they + * are meaningful combination. + */ + if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { + for (ex = explore; ex->e_af >= 0; ex++) { + if (pai->ai_family != ex->e_af) + continue; + if (ex->e_socktype == ANY) + continue; + if (ex->e_protocol == ANY) + continue; + if (pai->ai_socktype == ex->e_socktype && + pai->ai_protocol != ex->e_protocol) { + ERR(EAI_BADHINTS); + } + } + } + } + + /* + * post-2553: AI_ALL and AI_V4MAPPED are effective only against + * AF_INET6 query. They needs to be ignored if specified in other + * occassions. + */ + switch (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) { + case AI_V4MAPPED: + case AI_ALL | AI_V4MAPPED: + if (pai->ai_family != AF_INET6) + pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); + break; + case AI_ALL: +#if 1 + /* illegal */ + ERR(EAI_BADFLAGS); +#else + pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); +#endif + break; + } + + /* + * check for special cases. (1) numeric servname is disallowed if + * socktype/protocol are left unspecified. (2) servname is disallowed + * for raw and other inet{,6} sockets. + */ + if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) +#ifdef PF_INET6 + || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) +#endif + ) { + ai0 = *pai; /* backup *pai */ + + if (pai->ai_family == PF_UNSPEC) { +#ifdef PF_INET6 + pai->ai_family = PF_INET6; +#else + pai->ai_family = PF_INET; +#endif + } + error = get_portmatch(pai, servname); + if (error) + ERR(error); + + *pai = ai0; + } + + ai0 = *pai; + + /* NULL hostname, or numeric hostname */ + for (ex = explore; ex->e_af >= 0; ex++) { + *pai = ai0; + + if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) + continue; + if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) + continue; + if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) + continue; + + if (pai->ai_family == PF_UNSPEC) + pai->ai_family = ex->e_af; + if (pai->ai_socktype == ANY && ex->e_socktype != ANY) + pai->ai_socktype = ex->e_socktype; + if (pai->ai_protocol == ANY && ex->e_protocol != ANY) + pai->ai_protocol = ex->e_protocol; + + /* + * if the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + continue; + + if (hostname == NULL) { + /* + * filter out AFs that are not supported by the kernel + * XXX errno? + */ + if (!addrconfig(pai->ai_family)) + continue; + error = explore_null(pai, servname, &cur->ai_next); + } else + error = explore_numeric_scope(pai, hostname, servname, + &cur->ai_next); + + if (error) + goto free; + + while (cur && cur->ai_next) + cur = cur->ai_next; + } + + /* + * XXX + * If numreic representation of AF1 can be interpreted as FQDN + * representation of AF2, we need to think again about the code below. + */ + if (sentinel.ai_next) + goto good; + + if (pai->ai_flags & AI_NUMERICHOST) + ERR(EAI_NODATA); + if (hostname == NULL) + ERR(EAI_NODATA); + + /* + * hostname as alphabetical name. + * We'll make sure that + * - if returning addrinfo list is empty, return non-zero error + * value (already known one or EAI_NODATA). + * - otherwise, + * + if we haven't had any errors, return 0 (i.e. success). + * + if we've had an error, free the list and return the error. + * without any assumption on the behavior of explore_fqdn(). + */ + + /* first, try to query DNS for all possible address families. */ + *pai = ai0; + error = explore_fqdn(pai, hostname, servname, &afai); + if (error) { + if (afai != NULL) + freeaddrinfo(afai); + goto free; + } + if (afai == NULL) { + error = EAI_NODATA; /* we've had no errors. */ + goto free; + } + + /* + * we would like to prefer AF_INET6 than AF_INET, so we'll make an + * outer loop by AFs. + */ + for (ex = explore; ex->e_af >= 0; ex++) { + *pai = ai0; + + if (pai->ai_family == PF_UNSPEC) + pai->ai_family = ex->e_af; + + if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) + continue; + if (!MATCH(pai->ai_socktype, ex->e_socktype, + WILD_SOCKTYPE(ex))) { + continue; + } + if (!MATCH(pai->ai_protocol, ex->e_protocol, + WILD_PROTOCOL(ex))) { + continue; + } + +#ifdef AI_ADDRCONFIG + /* + * If AI_ADDRCONFIG is specified, check if we are + * expected to return the address family or not. + */ + if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && + !addrconfig(pai->ai_family)) + continue; +#endif + + if (pai->ai_family == PF_UNSPEC) + pai->ai_family = ex->e_af; + if (pai->ai_socktype == ANY && ex->e_socktype != ANY) + pai->ai_socktype = ex->e_socktype; + if (pai->ai_protocol == ANY && ex->e_protocol != ANY) + pai->ai_protocol = ex->e_protocol; + + /* + * if the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + continue; + + if ((error = explore_copy(pai, afai, &cur->ai_next)) != 0) { + freeaddrinfo(afai); + goto free; + } + + while (cur && cur->ai_next) + cur = cur->ai_next; + } + + freeaddrinfo(afai); /* afai must not be NULL at this point. */ + + /* we must not have got any errors. */ + if (error != 0) /* just for diagnosis */ + abort(); + + if (sentinel.ai_next) { +good: + *res = sentinel.ai_next; + return(SUCCESS); + } else { + /* + * All the process succeeded, but we've had an empty list. + * This can happen if the given hints do not match our + * candidates. + */ + error = EAI_NODATA; + } + +free: +bad: + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + *res = NULL; + return(error); +} + +/* + * FQDN hostname, DNS lookup + */ +static int +explore_fqdn(pai, hostname, servname, res) + const struct addrinfo *pai; + const char *hostname; + const char *servname; + struct addrinfo **res; +{ + struct addrinfo *result; + struct addrinfo *cur; + struct net_data *net_data = init(); + struct irs_ho *ho; + int error = 0; + char tmp[NS_MAXDNAME]; + const char *cp; + + result = NULL; + + /* + * if the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + return(0); + + if (!net_data || !(ho = net_data->ho)) + return(0); +#if 0 /* XXX (notyet) */ + if (net_data->ho_stayopen && net_data->ho_last && + net_data->ho_last->h_addrtype == af) { + if (ns_samename(name, net_data->ho_last->h_name) == 1) + return (net_data->ho_last); + for (hap = net_data->ho_last->h_aliases; hap && *hap; hap++) + if (ns_samename(name, *hap) == 1) + return (net_data->ho_last); + } +#endif + if (!strchr(hostname, '.') && + (cp = res_hostalias(net_data->res, hostname, + tmp, sizeof(tmp)))) + hostname = cp; + result = (*ho->addrinfo)(ho, hostname, pai); + if (!net_data->ho_stayopen) { + (*ho->minimize)(ho); + } + if (result == NULL) { + int *e = __h_errno(); + + switch(*e) { + case NETDB_INTERNAL: + error = EAI_SYSTEM; + break; + case TRY_AGAIN: + error = EAI_AGAIN; + break; + case NO_RECOVERY: + error = EAI_FAIL; + break; + case HOST_NOT_FOUND: + case NO_DATA: + error = EAI_NODATA; + break; + default: + case NETDB_SUCCESS: /* should be impossible... */ + error = EAI_NODATA; + break; + } + goto free; + } + + for (cur = result; cur; cur = cur->ai_next) { + GET_PORT(cur, servname); /* XXX: redundant lookups... */ + /* canonname should already be filled. */ + } + + *res = result; + + return(0); + +free: + if (result) + freeaddrinfo(result); + return error; +} + +static int +explore_copy(pai, src0, res) + const struct addrinfo *pai; /* seed */ + const struct addrinfo *src0; /* source */ + struct addrinfo **res; +{ + int error; + struct addrinfo sentinel, *cur; + const struct addrinfo *src; + + error = 0; + sentinel.ai_next = NULL; + cur = &sentinel; + + for (src = src0; src != NULL; src = src->ai_next) { + if (src->ai_family != pai->ai_family) + continue; + + cur->ai_next = copy_ai(src); + if (!cur->ai_next) { + error = EAI_MEMORY; + goto fail; + } + + cur->ai_next->ai_socktype = pai->ai_socktype; + cur->ai_next->ai_protocol = pai->ai_protocol; + cur = cur->ai_next; + } + + *res = sentinel.ai_next; + return 0; + +fail: + freeaddrinfo(sentinel.ai_next); + return error; +} + +/* + * hostname == NULL. + * passive socket -> anyaddr (0.0.0.0 or ::) + * non-passive socket -> localhost (127.0.0.1 or ::1) + */ +static int +explore_null(pai, servname, res) + const struct addrinfo *pai; + const char *servname; + struct addrinfo **res; +{ + const struct afd *afd; + struct addrinfo *cur; + struct addrinfo sentinel; + int error; + + *res = NULL; + sentinel.ai_next = NULL; + cur = &sentinel; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return 0; + + if (pai->ai_flags & AI_PASSIVE) { + GET_AI(cur->ai_next, afd, afd->a_addrany); + /* xxx meaningless? + * GET_CANONNAME(cur->ai_next, "anyaddr"); + */ + GET_PORT(cur->ai_next, servname); + } else { + GET_AI(cur->ai_next, afd, afd->a_loopback); + /* xxx meaningless? + * GET_CANONNAME(cur->ai_next, "localhost"); + */ + GET_PORT(cur->ai_next, servname); + } + cur = cur->ai_next; + + *res = sentinel.ai_next; + return 0; + +free: + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + return error; +} + +/* + * numeric hostname + */ +static int +explore_numeric(pai, hostname, servname, res) + const struct addrinfo *pai; + const char *hostname; + const char *servname; + struct addrinfo **res; +{ + const struct afd *afd; + struct addrinfo *cur; + struct addrinfo sentinel; + int error; + char pton[PTON_MAX]; + + *res = NULL; + sentinel.ai_next = NULL; + cur = &sentinel; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return 0; + + switch (afd->a_af) { +#if 0 /*X/Open spec*/ + case AF_INET: + if (inet_aton(hostname, (struct in_addr *)pton) == 1) { + if (pai->ai_family == afd->a_af || + pai->ai_family == PF_UNSPEC /*?*/) { + GET_AI(cur->ai_next, afd, pton); + GET_PORT(cur->ai_next, servname); + while (cur && cur->ai_next) + cur = cur->ai_next; + } else + ERR(EAI_FAMILY); /*xxx*/ + } + break; +#endif + default: + if (inet_pton(afd->a_af, hostname, pton) == 1) { + if (pai->ai_family == afd->a_af || + pai->ai_family == PF_UNSPEC /*?*/) { + GET_AI(cur->ai_next, afd, pton); + GET_PORT(cur->ai_next, servname); + while (cur && cur->ai_next) + cur = cur->ai_next; + } else + ERR(EAI_FAMILY); /*xxx*/ + } + break; + } + + *res = sentinel.ai_next; + return 0; + +free: +bad: + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + return error; +} + +/* + * numeric hostname with scope + */ +static int +explore_numeric_scope(pai, hostname, servname, res) + const struct addrinfo *pai; + const char *hostname; + const char *servname; + struct addrinfo **res; +{ +#if !defined(SCOPE_DELIMITER) || !defined(INET6) + return explore_numeric(pai, hostname, servname, res); +#else + const struct afd *afd; + struct addrinfo *cur; + int error; + char *cp, *hostname2 = NULL, *scope, *addr; + struct sockaddr_in6 *sin6; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return 0; + + if (!afd->a_scoped) + return explore_numeric(pai, hostname, servname, res); + + cp = strchr(hostname, SCOPE_DELIMITER); + if (cp == NULL) + return explore_numeric(pai, hostname, servname, res); + +#if 0 + /* + * Handle special case of + */ + hostname2 = strdup(hostname); + if (hostname2 == NULL) + return EAI_MEMORY; + /* terminate at the delimiter */ + hostname2[cp - hostname] = '\0'; + scope = hostname2; + addr = cp + 1; +#else + /* + * Handle special case of + */ + hostname2 = strdup(hostname); + if (hostname2 == NULL) + return EAI_MEMORY; + /* terminate at the delimiter */ + hostname2[cp - hostname] = '\0'; + addr = hostname2; + scope = cp + 1; +#endif + + error = explore_numeric(pai, addr, servname, res); + if (error == 0) { + int scopeid; + + for (cur = *res; cur; cur = cur->ai_next) { + if (cur->ai_family != AF_INET6) + continue; + sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr; + if ((scopeid = ip6_str2scopeid(scope, sin6)) == -1) { + free(hostname2); + return(EAI_NODATA); /* XXX: is return OK? */ + } + sin6->sin6_scope_id = scopeid; + } + } + + free(hostname2); + + return error; +#endif +} + +static int +get_canonname(pai, ai, str) + const struct addrinfo *pai; + struct addrinfo *ai; + const char *str; +{ + if ((pai->ai_flags & AI_CANONNAME) != 0) { + ai->ai_canonname = (char *)malloc(strlen(str) + 1); + if (ai->ai_canonname == NULL) + return EAI_MEMORY; + strcpy(ai->ai_canonname, str); + } + return 0; +} + +static struct addrinfo * +get_ai(pai, afd, addr) + const struct addrinfo *pai; + const struct afd *afd; + const char *addr; +{ + char *p; + struct addrinfo *ai; + + ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + + (afd->a_socklen)); + if (ai == NULL) + return NULL; + + memcpy(ai, pai, sizeof(struct addrinfo)); + ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); + memset(ai->ai_addr, 0, (size_t)afd->a_socklen); + ai->ai_addr->sa_len = afd->a_socklen; + ai->ai_addrlen = afd->a_socklen; + ai->ai_addr->sa_family = ai->ai_family = afd->a_af; + p = (char *)(void *)(ai->ai_addr); + memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); + return ai; +} + +/* XXX need to malloc() the same way we do from other functions! */ +static struct addrinfo * +copy_ai(pai) + const struct addrinfo *pai; +{ + struct addrinfo *ai; + size_t l; + + l = sizeof(*ai) + pai->ai_addrlen; + if ((ai = (struct addrinfo *)malloc(l)) == NULL) + return NULL; + memset(ai, 0, l); + memcpy(ai, pai, sizeof(*ai)); + ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); + memcpy(ai->ai_addr, pai->ai_addr, pai->ai_addrlen); + + if (pai->ai_canonname) { + l = strlen(pai->ai_canonname) + 1; + if ((ai->ai_canonname = malloc(l)) == NULL) { + free(ai); + return NULL; + } +#ifdef HAVE_STRLCPY + strlcpy(ai->ai_canonname, pai->ai_canonname, l); +#else + strncpy(ai->ai_canonname, pai->ai_canonname, l); +#endif + } else { + /* just to make sure */ + ai->ai_canonname = NULL; + } + + ai->ai_next = NULL; + + return ai; +} + +static int +get_portmatch(const struct addrinfo *ai, const char *servname) { + + /* get_port does not touch first argument. when matchonly == 1. */ + /* LINTED const cast */ + return get_port((const struct addrinfo *)ai, servname, 1); +} + +static int +get_port(const struct addrinfo *ai, const char *servname, int matchonly) { + const char *proto; + struct servent *sp; + int port; + int allownumeric; + + if (servname == NULL) + return 0; + switch (ai->ai_family) { + case AF_INET: +#ifdef AF_INET6 + case AF_INET6: +#endif + break; + default: + return 0; + } + + switch (ai->ai_socktype) { + case SOCK_RAW: + return EAI_SERVICE; + case SOCK_DGRAM: + case SOCK_STREAM: + allownumeric = 1; + break; + case ANY: + allownumeric = 0; + break; + default: + return EAI_SOCKTYPE; + } + + if (str_isnumber(servname)) { + if (!allownumeric) + return EAI_SERVICE; + port = htons(atoi(servname)); + if (port < 0 || port > 65535) + return EAI_SERVICE; + } else { + switch (ai->ai_socktype) { + case SOCK_DGRAM: + proto = "udp"; + break; + case SOCK_STREAM: + proto = "tcp"; + break; + default: + proto = NULL; + break; + } + + if ((sp = getservbyname(servname, proto)) == NULL) + return EAI_SERVICE; + port = sp->s_port; + } + + if (!matchonly) { + switch (ai->ai_family) { + case AF_INET: + ((struct sockaddr_in *)(void *) + ai->ai_addr)->sin_port = port; + break; +#ifdef INET6 + case AF_INET6: + ((struct sockaddr_in6 *)(void *) + ai->ai_addr)->sin6_port = port; + break; +#endif + } + } + + return 0; +} + +static const struct afd * +find_afd(af) + int af; +{ + const struct afd *afd; + + if (af == PF_UNSPEC) + return NULL; + for (afd = afdl; afd->a_af; afd++) { + if (afd->a_af == af) + return afd; + } + return NULL; +} + +/* + * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend + * will take care of it. + * the semantics of AI_ADDRCONFIG is not defined well. we are not sure + * if the code is right or not. + */ +static int +addrconfig(af) + int af; +{ + int s; + + /* XXX errno */ + s = socket(af, SOCK_DGRAM, 0); + if (s < 0) { + if (errno != EMFILE) + return 0; + } else + close(s); + return 1; +} + +#ifdef INET6 +/* convert a string to a scope identifier. XXX: IPv6 specific */ +static int +ip6_str2scopeid(scope, sin6) + char *scope; + struct sockaddr_in6 *sin6; +{ + int scopeid; + struct in6_addr *a6 = &sin6->sin6_addr; + char *ep; + + /* empty scopeid portion is invalid */ + if (*scope == '\0') + return -1; + + if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) { + /* + * We currently assume a one-to-one mapping between links + * and interfaces, so we simply use interface indices for + * like-local scopes. + */ + scopeid = if_nametoindex(scope); + if (scopeid == 0) + goto trynumeric; + return(scopeid); + } + + /* still unclear about literal, allow numeric only - placeholder */ + if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) + goto trynumeric; + if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) + goto trynumeric; + else + goto trynumeric; /* global */ + + /* try to convert to a numeric id as a last resort */ +trynumeric: + scopeid = (int)strtoul(scope, &ep, 10); + if (*ep == '\0') + return scopeid; + else + return -1; +} +#endif + +struct addrinfo * +hostent2addrinfo(hp, pai) + struct hostent *hp; + const struct addrinfo *pai; +{ + int i, af, error = 0; + char **aplist = NULL, *ap; + struct addrinfo sentinel, *cur; + const struct afd *afd; + + af = hp->h_addrtype; + if (pai->ai_family != AF_UNSPEC && af != pai->ai_family) + return(NULL); + + afd = find_afd(af); + if (afd == NULL) + return(NULL); + + aplist = hp->h_addr_list; + + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + for (i = 0; (ap = aplist[i]) != NULL; i++) { +#if 0 /* the trick seems too much */ +#ifdef INET6 + af = hp->h_addr_list; + if (af == AF_INET6 && + IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) { + af = AF_INET; + ap = ap + sizeof(struct in6_addr) + - sizeof(struct in_addr); + } + afd = find_afd(af); + if (afd == NULL) + continue; +#endif +#endif /* 0 */ + + GET_AI(cur->ai_next, afd, ap); + + /* GET_PORT(cur->ai_next, servname); */ + if ((pai->ai_flags & AI_CANONNAME) != 0) { + /* + * RFC2553 says that ai_canonname will be set only for + * the first element. we do it for all the elements, + * just for convenience. + */ + GET_CANONNAME(cur->ai_next, hp->h_name); + } + while (cur && cur->ai_next) /* no need to loop, actually. */ + cur = cur->ai_next; + continue; + + free: + if (cur->ai_next) + freeaddrinfo(cur->ai_next); + cur->ai_next = NULL; + /* continue, without tht pointer CUR advanced. */ + } + + return(sentinel.ai_next); +} + +struct addrinfo * +addr2addrinfo(pai, cp) + const struct addrinfo *pai; + const char *cp; +{ + const struct afd *afd; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return(NULL); + + return(get_ai(pai, afd, cp)); +} + +static struct net_data * +init() +{ + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->ho) { + net_data->ho = (*net_data->irs->ho_map)(net_data->irs); + if (!net_data->ho || !net_data->res) { +error: + errno = EIO; + if (net_data && net_data->res) + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + + (*net_data->ho->res_set)(net_data->ho, net_data->res, NULL); + } + + return (net_data); +} diff --git a/lib/bind/irs/getgrent.c b/lib/bind/irs/getgrent.c new file mode 100644 index 0000000000..1b10e33b2a --- /dev/null +++ b/lib/bind/irs/getgrent.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: getgrent.c,v 1.1 2001/03/29 06:31:45 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(WANT_IRS_GR) || defined(__BIND_NOSTATIC) +static int __bind_irs_gr_unneeded; +#else + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct net_data *init(void); +void endgrent(void); + +/* Public */ + +struct group * +getgrent() { + struct net_data *net_data = init(); + + return (getgrent_p(net_data)); +} + +struct group * +getgrnam(const char *name) { + struct net_data *net_data = init(); + + return (getgrnam_p(name, net_data)); +} + +struct group * +getgrgid(gid_t gid) { + struct net_data *net_data = init(); + + return (getgrgid_p(gid, net_data)); +} + +int +setgroupent(int stayopen) { + struct net_data *net_data = init(); + + return (setgroupent_p(stayopen, net_data)); +} + +#ifdef SETGRENT_VOID +void +setgrent() { + struct net_data *net_data = init(); + + return (setgrent_p(net_data)); +} +#else +int +setgrent() { + struct net_data *net_data = init(); + + return (setgrent_p(net_data)); +} +#endif /* SETGRENT_VOID */ + +void +endgrent() { + struct net_data *net_data = init(); + + endgrent_p(net_data); +} + +int +getgrouplist(GETGROUPLIST_ARGS) { + struct net_data *net_data = init(); + + return (getgrouplist_p(name, basegid, groups, ngroups, net_data)); +} + +/* Shared private. */ + +struct group * +getgrent_p(struct net_data *net_data) { + struct irs_gr *gr; + + if (!net_data || !(gr = net_data->gr)) + return (NULL); + net_data->gr_last = (*gr->next)(gr); + return (net_data->gr_last); +} + +struct group * +getgrnam_p(const char *name, struct net_data *net_data) { + struct irs_gr *gr; + + if (!net_data || !(gr = net_data->gr)) + return (NULL); + if (net_data->gr_stayopen && net_data->gr_last && + !strcmp(net_data->gr_last->gr_name, name)) + return (net_data->gr_last); + net_data->gr_last = (*gr->byname)(gr, name); + if (!net_data->gr_stayopen) + endgrent(); + return (net_data->gr_last); +} + +struct group * +getgrgid_p(gid_t gid, struct net_data *net_data) { + struct irs_gr *gr; + + if (!net_data || !(gr = net_data->gr)) + return (NULL); + if (net_data->gr_stayopen && net_data->gr_last && + (gid_t)net_data->gr_last->gr_gid == gid) + return (net_data->gr_last); + net_data->gr_last = (*gr->bygid)(gr, gid); + if (!net_data->gr_stayopen) + endgrent(); + return (net_data->gr_last); +} + +int +setgroupent_p(int stayopen, struct net_data *net_data) { + struct irs_gr *gr; + + if (!net_data || !(gr = net_data->gr)) + return (0); + (*gr->rewind)(gr); + net_data->gr_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); + return (1); +} + +#ifdef SETGRENT_VOID +void +setgrent_p(struct net_data *net_data) { + (void)setgroupent_p(0, net_data); +} +#else +int +setgrent_p(struct net_data *net_data) { + return (setgroupent_p(0, net_data)); +} +#endif /* SETGRENT_VOID */ + +void +endgrent_p(struct net_data *net_data) { + struct irs_gr *gr; + + if ((net_data != NULL) && ((gr = net_data->gr) != NULL)) + (*gr->minimize)(gr); +} + +int +getgrouplist_p(const char *name, gid_t basegid, gid_t *groups, int *ngroups, + struct net_data *net_data) { + struct irs_gr *gr; + + if (!net_data || !(gr = net_data->gr)) { + *ngroups = 0; + return (-1); + } + return ((*gr->list)(gr, name, basegid, groups, ngroups)); +} + +/* Private */ + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->gr) { + net_data->gr = (*net_data->irs->gr_map)(net_data->irs); + + if (!net_data->gr || !net_data->res) { + error: + errno = EIO; + return (NULL); + } + (*net_data->gr->res_set)(net_data->gr, net_data->res, + NULL); + } + + return (net_data); +} + +#endif /* WANT_IRS_GR */ diff --git a/lib/bind/irs/getgrent_r.c b/lib/bind/irs/getgrent_r.c new file mode 100644 index 0000000000..0db7f22189 --- /dev/null +++ b/lib/bind/irs/getgrent_r.c @@ -0,0 +1,220 @@ +/* + * 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 1.1 2001/03/29 06:31:45 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) || !defined(WANT_IRS_PW) + static int getgrent_r_not_required = 0; +#else +#include +#include +#include +#include +#include +#include +#include + +#ifdef GROUP_R_RETURN + +static int +copy_group(struct group *, struct group *, char *buf, int buflen); + +/* POSIX 1003.1c */ +#ifdef POSIX_GETGRNAM_R +int +__posix_getgrnam_r(const char *name, struct group *gptr, + char *buf, int buflen, struct group **result) { +#else +int +getgrnam_r(const char *name, struct group *gptr, + char *buf, size_t buflen, struct group **result) { +#endif + struct group *ge = getgrnam(name); + int res; + + if (ge == NULL) { + *result = NULL; + return (-1); + } + + res = copy_group(ge, gptr, buf, buflen); + *result = res ? NULL : gptr; + return (res); +} + +#ifdef POSIX_GETGRNAM_R +struct group * +getgrnam_r(const char *name, struct group *gptr, + char *buf, int buflen) { + struct group *ge = getgrnam(name); + int res; + + if (ge == NULL) + return (NULL); + res = copy_group(ge, gptr, buf, buflen); + return (res ? NULL : gptr); +} +#endif /* POSIX_GETGRNAM_R */ + +/* POSIX 1003.1c */ +#ifdef POSIX_GETGRGID_R +int +__posix_getgrgid_r(const gid_t gid, struct group *gptr, + char *buf, int buflen, struct group **result) { +#else /* POSIX_GETGRGID_R */ +int +getgrgid_r(const gid_t gid, struct group *gptr, + char *buf, size_t buflen, struct group **result) { +#endif /* POSIX_GETGRGID_R */ + struct group *ge = getgrgid(gid); + int res; + + if (ge == NULL) { + *result = NULL; + return (-1); + } + + res = copy_group(ge, gptr, buf, buflen); + *result = res ? NULL : gptr; + return (res); +} + +#ifdef POSIX_GETGRGID_R +struct group * +getgrgid_r(const gid_t gid, struct group *gptr, + char *buf, int buflen) { + struct group *ge = getgrgid(gid); + int res; + + if (ge == NULL) + return (NULL); + + res = copy_group(ge, gptr, buf, buflen); + return (res ? NULL : gptr); +} +#endif + +/* + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +GROUP_R_RETURN +getgrent_r(struct group *gptr, GROUP_R_ARGS) { + struct group *ge = getgrent(); + int res; + + if (ge == NULL) { + return (GROUP_R_BAD); + } + + res = copy_group(ge, gptr, buf, buflen); + return (res ? GROUP_R_BAD : GROUP_R_OK); +} + +GROUP_R_SET_RETURN +setgrent_r(GROUP_R_ENT_ARGS) { + + setgrent(); +#ifdef GROUP_R_SET_RESULT + return (GROUP_R_SET_RESULT); +#endif +} + +GROUP_R_END_RETURN +endgrent_r(GROUP_R_ENT_ARGS) { + + endgrent(); + GROUP_R_END_RESULT(GROUP_R_OK); +} + + +#if 0 + /* XXX irs does not have a fgetgrent() */ +GROUP_R_RETURN +fgetgrent_r(FILE *f, struct group *gptr, GROUP_R_ARGS) { + struct group *ge = fgetgrent(f); + int res; + + if (ge == NULL) + return (GROUP_R_BAD); + + res = copy_group(ge, gptr, buf, buflen); + return (res ? GROUP_R_BAD : GROUP_R_OK); +} +#endif + +/* Private */ + +static int +copy_group(struct group *ge, struct group *gptr, char *buf, int buflen) { + char *cp; + int i, n; + int numptr, len; + + /* Find out the amount of space required to store the answer. */ + numptr = 1; /* NULL ptr */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; ge->gr_mem[i]; i++, numptr++) { + len += strlen(ge->gr_mem[i]) + 1; + } + len += strlen(ge->gr_name) + 1; + len += strlen(ge->gr_passwd) + 1; + len += numptr * sizeof(char*); + + if (len > buflen) { + errno = ERANGE; + return (-1); + } + + /* copy group id */ + gptr->gr_gid = ge->gr_gid; + + cp = (char *)ALIGN(buf) + numptr * sizeof(char *); + + /* copy official name */ + n = strlen(ge->gr_name) + 1; + strcpy(cp, ge->gr_name); + gptr->gr_name = cp; + cp += n; + + /* copy member list */ + gptr->gr_mem = (char **)ALIGN(buf); + for (i = 0 ; ge->gr_mem[i]; i++) { + n = strlen(ge->gr_mem[i]) + 1; + strcpy(cp, ge->gr_mem[i]); + gptr->gr_mem[i] = cp; + cp += n; + } + gptr->gr_mem[i] = NULL; + + /* copy password */ + n = strlen(ge->gr_passwd) + 1; + strcpy(cp, ge->gr_passwd); + gptr->gr_passwd = cp; + cp += n; + + return (0); +} +#else /* GROUP_R_RETURN */ + static int getgrent_r_unknown_system = 0; +#endif /* GROUP_R_RETURN */ +#endif /* !def(_REENTRANT) || !def(DO_PTHREADS) || !def(WANT_IRS_PW) */ diff --git a/lib/bind/irs/gethostent.c b/lib/bind/irs/gethostent.c new file mode 100644 index 0000000000..a664a4b442 --- /dev/null +++ b/lib/bind/irs/gethostent.c @@ -0,0 +1,900 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gethostent.c,v 1.1 2001/03/29 06:31:45 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "irs_data.h" + +/* Definitions */ + +struct pvt { + char * aliases[1]; + char * addrs[2]; + char addr[NS_IN6ADDRSZ]; + char name[NS_MAXDNAME + 1]; + struct hostent host; +}; + +/* Forward */ + +static struct net_data *init(void); +static void freepvt(struct net_data *); +static struct hostent *fakeaddr(const char *, int, struct net_data *); + + +/* Public */ + +struct hostent * +gethostbyname(const char *name) { + struct net_data *net_data = init(); + + return (gethostbyname_p(name, net_data)); +} + +struct hostent * +gethostbyname2(const char *name, int af) { + struct net_data *net_data = init(); + + return (gethostbyname2_p(name, af, net_data)); +} + +struct hostent * +gethostbyaddr(const char *addr, int len, int af) { + struct net_data *net_data = init(); + + return (gethostbyaddr_p(addr, len, af, net_data)); +} + +struct hostent * +gethostent() { + struct net_data *net_data = init(); + + return (gethostent_p(net_data)); +} + +void +sethostent(int stayopen) { + struct net_data *net_data = init(); + sethostent_p(stayopen, net_data); +} + + +void +endhostent() { + struct net_data *net_data = init(); + endhostent_p(net_data); +} + +/* Shared private. */ + +struct hostent * +gethostbyname_p(const char *name, struct net_data *net_data) { + struct hostent *hp; + + if (!net_data) + return (NULL); + + if (net_data->res->options & RES_USE_INET6) { + hp = gethostbyname2_p(name, AF_INET6, net_data); + if (hp) + return (hp); + } + return (gethostbyname2_p(name, AF_INET, net_data)); +} + +struct hostent * +gethostbyname2_p(const char *name, int af, struct net_data *net_data) { + struct irs_ho *ho; + char tmp[NS_MAXDNAME]; + struct hostent *hp; + const char *cp; + char **hap; + + if (!net_data || !(ho = net_data->ho)) + return (NULL); + if (net_data->ho_stayopen && net_data->ho_last && + net_data->ho_last->h_addrtype == af) { + if (ns_samename(name, net_data->ho_last->h_name) == 1) + return (net_data->ho_last); + for (hap = net_data->ho_last->h_aliases; hap && *hap; hap++) + if (ns_samename(name, *hap) == 1) + return (net_data->ho_last); + } + if (!strchr(name, '.') && (cp = res_hostalias(net_data->res, name, + tmp, sizeof tmp))) + name = cp; + if ((hp = fakeaddr(name, af, net_data)) != NULL) + return (hp); + net_data->ho_last = (*ho->byname2)(ho, name, af); + if (!net_data->ho_stayopen) + endhostent(); + return (net_data->ho_last); +} + +struct hostent * +gethostbyaddr_p(const char *addr, int len, int af, struct net_data *net_data) { + struct irs_ho *ho; + char **hap; + + if (!net_data || !(ho = net_data->ho)) + return (NULL); + if (net_data->ho_stayopen && net_data->ho_last && + net_data->ho_last->h_length == len) + for (hap = net_data->ho_last->h_addr_list; + hap && *hap; + hap++) + if (!memcmp(addr, *hap, len)) + return (net_data->ho_last); + net_data->ho_last = (*ho->byaddr)(ho, addr, len, af); + if (!net_data->ho_stayopen) + endhostent(); + return (net_data->ho_last); +} + + +struct hostent * +gethostent_p(struct net_data *net_data) { + struct irs_ho *ho; + struct hostent *hp; + + if (!net_data || !(ho = net_data->ho)) + return (NULL); + while ((hp = (*ho->next)(ho)) != NULL && + hp->h_addrtype == AF_INET6 && + (net_data->res->options & RES_USE_INET6) == 0) + continue; + net_data->ho_last = hp; + return (net_data->ho_last); +} + + +void +sethostent_p(int stayopen, struct net_data *net_data) { + struct irs_ho *ho; + + if (!net_data || !(ho = net_data->ho)) + return; + freepvt(net_data); + (*ho->rewind)(ho); + net_data->ho_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); +} + +void +endhostent_p(struct net_data *net_data) { + struct irs_ho *ho; + + if ((net_data != NULL) && ((ho = net_data->ho) != NULL)) + (*ho->minimize)(ho); +} + +#ifndef IN6_IS_ADDR_V4COMPAT +static const unsigned char in6addr_compat[12] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +#define IN6_IS_ADDR_V4COMPAT(x) (!memcmp((x)->s6_addr, in6addr_compat, 12) && \ + ((x)->s6_addr[12] != 0 || \ + (x)->s6_addr[13] != 0 || \ + (x)->s6_addr[14] != 0 || \ + ((x)->s6_addr[15] != 0 && \ + (x)->s6_addr[15] != 1))) +#endif +#ifndef IN6_IS_ADDR_V4MAPPED +#define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12)) +#endif + +static const unsigned char in6addr_mapped[12] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; + +static int scan_interfaces(int *, int *); +static struct hostent *copyandmerge(struct hostent *, struct hostent *, int, int *); + +/* + * Public functions + */ + +/* + * AI_V4MAPPED + AF_INET6 + * If no IPv6 address then a query for IPv4 and map returned values. + * + * AI_ALL + AI_V4MAPPED + AF_INET6 + * Return IPv6 and IPv4 mapped. + * + * AI_ADDRCONFIG + * Only return IPv6 / IPv4 address if there is an interface of that + * type active. + */ + +struct hostent * +getipnodebyname(const char *name, int af, int flags, int *error_num) { + int have_v4 = 1, have_v6 = 1; + struct in_addr in4; + struct in6_addr in6; + struct hostent he, *he1 = NULL, *he2 = NULL, *he3; + int v4 = 0, v6 = 0; + struct net_data *net_data = init(); + u_long options; + int tmp_err; + + if (net_data == NULL) { + *error_num = NO_RECOVERY; + return (NULL); + } + + /* If we care about active interfaces then check. */ + if ((flags & AI_ADDRCONFIG) != 0) + if (scan_interfaces(&have_v4, &have_v6) == -1) { + *error_num = NO_RECOVERY; + return (NULL); + } + + /* Check for literal address. */ + if ((v4 = inet_pton(AF_INET, name, &in4)) != 1) + v6 = inet_pton(AF_INET6, name, &in6); + + /* Impossible combination? */ + + if ((af == AF_INET6 && (flags & AI_V4MAPPED) == 0 && v4 == 1) || + (af == AF_INET && v6 == 1) || + (have_v4 == 0 && v4 == 1) || + (have_v6 == 0 && v6 == 1) || + (have_v4 == 0 && af == AF_INET) || + (have_v6 == 0 && af == AF_INET6)) { + *error_num = HOST_NOT_FOUND; + return (NULL); + } + + /* Literal address? */ + if (v4 == 1 || v6 == 1) { + char *addr_list[2]; + char *aliases[1]; + + DE_CONST(name, he.h_name); + he.h_addr_list = addr_list; + he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6; + he.h_addr_list[1] = NULL; + he.h_aliases = aliases; + he.h_aliases[0] = NULL; + he.h_length = (v4 == 1) ? INADDRSZ : IN6ADDRSZ; + he.h_addrtype = (v4 == 1) ? AF_INET : AF_INET6; + return (copyandmerge(&he, NULL, af, error_num)); + } + + options = net_data->res->options; + net_data->res->options &= ~RES_USE_INET6; + + tmp_err = NO_RECOVERY; + if (have_v6 && af == AF_INET6) { + he2 = gethostbyname2_p(name, AF_INET6, net_data); + if (he2 != NULL) { + he1 = copyandmerge(he2, NULL, af, error_num); + if (he1 == NULL) + return (NULL); + he2 = NULL; + } else { + tmp_err = net_data->res->res_h_errno; + } + } + + if (have_v4 && + ((af == AF_INET) || + (af == AF_INET6 && (flags & AI_V4MAPPED) != 0 && + (he1 == NULL || (flags & AI_ALL) != 0)))) { + he2 = gethostbyname2_p(name, AF_INET, net_data); + if (he1 == NULL && he2 == NULL) { + *error_num = net_data->res->res_h_errno; + return (NULL); + } + } else + *error_num = tmp_err; + + net_data->res->options = options; + + he3 = copyandmerge(he1, he2, af, error_num); + + if (he1 != NULL) + freehostent(he1); + return (he3); +} + +struct hostent * +getipnodebyaddr(const void *src, size_t len, int af, int *error_num) { + struct hostent *he1, *he2; + struct net_data *net_data = init(); + + /* Sanity Checks. */ + if (src == NULL) { + *error_num = NO_RECOVERY; + return (NULL); + } + + switch (af) { + case AF_INET: + if (len != INADDRSZ) { + *error_num = NO_RECOVERY; + return (NULL); + } + break; + case AF_INET6: + if (len != IN6ADDRSZ) { + *error_num = NO_RECOVERY; + return (NULL); + } + break; + default: + *error_num = NO_RECOVERY; + return (NULL); + } + + /* + * Lookup IPv4 and IPv4 mapped/compatible addresses + */ + if ((af == AF_INET6 && + IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)src)) || + (af == AF_INET6 && + IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src)) || + (af == AF_INET)) { + const char *cp = src; + + if (af == AF_INET6) + cp += 12; + he1 = gethostbyaddr_p(cp, 4, AF_INET, net_data); + if (he1 == NULL) { + *error_num = net_data->res->res_h_errno; + return (NULL); + } + he2 = copyandmerge(he1, NULL, af, error_num); + if (he2 == NULL) + return (NULL); + /* + * Restore original address if mapped/compatible. + */ + if (af == AF_INET6) + memcpy(he1->h_addr, src, len); + return (he2); + } + + /* + * Lookup IPv6 address. + */ + if (memcmp((const struct in6_addr *)src, &in6addr_any, 16) == 0) { + *error_num = HOST_NOT_FOUND; + return (NULL); + } + + he1 = gethostbyaddr_p(src, 16, AF_INET6, net_data); + if (he1 == NULL) { + *error_num = net_data->res->res_h_errno; + return (NULL); + } + return (copyandmerge(he1, NULL, af, error_num)); +} + +void +freehostent(struct hostent *he) { + char **cpp; + int names = 1; + int addresses = 1; + + memput(he->h_name, strlen(he->h_name) + 1); + + cpp = he->h_addr_list; + while (*cpp != NULL) { + memput(*cpp, (he->h_addrtype == AF_INET) ? + INADDRSZ : IN6ADDRSZ); + *cpp = NULL; + cpp++; + addresses++; + } + + cpp = he->h_aliases; + while (*cpp != NULL) { + memput(*cpp, strlen(*cpp) + 1); + cpp++; + names++; + } + + memput(he->h_aliases, sizeof(char *) * (names)); + memput(he->h_addr_list, sizeof(char *) * (addresses)); + memput(he, sizeof *he); +} + +/* + * Private + */ + +/* + * Scan the interface table and set have_v4 and have_v6 depending + * upon whether there are IPv4 and IPv6 interface addresses. + * + * Returns: + * 0 on success + * -1 on failure. + */ + +static int +scan_interfaces(int *have_v4, int *have_v6) { +#ifndef SIOCGLIFCONF +/* map new to old */ +#define SIOCGLIFCONF SIOCGIFCONF +#define lifc_len ifc_len +#define lifc_buf ifc_buf + struct ifconf lifc; +#else +#define SETFAMILYFLAGS + struct lifconf lifc; +#endif + +#ifndef SIOCGLIFADDR +/* map new to old */ +#define SIOCGLIFADDR SIOCGIFADDR +#endif + +#ifndef SIOCGLIFFLAGS +#define SIOCGLIFFLAGS SIOCGIFFLAGS +#define lifr_addr ifr_addr +#define lifr_name ifr_name +#define lifr_flags ifr_flags +#define ss_family sa_family + struct ifreq lifreq; +#else + struct lifreq lifreq; +#endif + struct in_addr in4; + struct in6_addr in6; + char *buf = NULL, *cp, *cplim; + static unsigned int bufsiz = 4095; + int s, cpsize, n; + + /* Set to zero. Used as loop terminators below. */ + *have_v4 = *have_v6 = 0; + + /* Get interface list from system. */ + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) + goto err_ret; + + /* + * Grow buffer until large enough to contain all interface + * descriptions. + */ + for (;;) { + buf = memget(bufsiz); + if (buf == NULL) + goto err_ret; +#ifdef SETFAMILYFLAGS + lifc.lifc_family = AF_UNSPEC; + lifc.lifc_flags = 0; +#endif + lifc.lifc_len = bufsiz; + lifc.lifc_buf = buf; +#ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF + /* + * This is a fix for IRIX OS in which the call to ioctl with + * the flag SIOCGIFCONF may not return an entry for all the + * interfaces like most flavors of Unix. + */ + if (emul_ioctl(&lifc) >= 0) + break; +#else + if ((n = ioctl(s, SIOCGLIFCONF, (char *)&lifc)) != -1) { + /* + * Some OS's just return what will fit rather + * than set EINVAL if the buffer is too small + * to fit all the interfaces in. If + * lifc.lifc_len is too near to the end of the + * buffer we will grow it just in case and + * retry. + */ + if (lifc.lifc_len + 2 * sizeof(lifreq) < bufsiz) + break; + } +#endif + if ((n == -1) && errno != EINVAL) + goto err_ret; + + if (bufsiz > 1000000) + goto err_ret; + + memput(buf, bufsiz); + bufsiz += 4096; + } + + /* Parse system's interface list. */ + cplim = buf + lifc.lifc_len; /* skip over if's with big ifr_addr's */ + for (cp = buf; + (*have_v4 == 0 || *have_v6 == 0) && cp < cplim; + cp += cpsize) { + memcpy(&lifreq, cp, sizeof lifreq); +#ifdef HAVE_SA_LEN +#ifdef FIX_ZERO_SA_LEN + if (lifreq.lifr_addr.sa_len == 0) + lifreq.lifr_addr.sa_len = 16; +#endif +#ifdef HAVE_MINIMUM_IFREQ + cpsize = sizeof lifreq; + if (lifreq.lifr_addr.sa_len > sizeof (struct sockaddr)) + cpsize += (int)lifreq.lifr_addr.sa_len - + (int)(sizeof (struct sockaddr)); +#else + cpsize = sizeof lifreq.lifr_name + lifreq.lifr_addr.sa_len; +#endif /* HAVE_MINIMUM_IFREQ */ +#elif defined SIOCGIFCONF_ADDR + cpsize = sizeof lifreq; +#else + cpsize = sizeof lifreq.lifr_name; + /* XXX maybe this should be a hard error? */ + if (ioctl(s, SIOCGLIFADDR, (char *)&lifreq) < 0) + continue; +#endif + switch (lifreq.lifr_addr.ss_family) { + case AF_INET: + if (*have_v4 == 0) { + memcpy(&in4, + &((struct sockaddr_in *) + &lifreq.lifr_addr)->sin_addr, + sizeof in4); + if (in4.s_addr == INADDR_ANY) + break; + n = ioctl(s, SIOCGLIFFLAGS, (char *)&lifreq); + if (n < 0) + break; + if ((lifreq.lifr_flags & IFF_UP) == 0) + break; + *have_v4 = 1; + } + break; + case AF_INET6: + if (*have_v6 == 0) { + memcpy(&in6, + &((struct sockaddr_in6 *) + &lifreq.lifr_addr)->sin6_addr, sizeof in6); + if (memcmp(&in6, &in6addr_any, sizeof in6) == 0) + break; + n = ioctl(s, SIOCGLIFFLAGS, (char *)&lifreq); + if (n < 0) + break; + if ((lifreq.lifr_flags & IFF_UP) == 0) + break; + *have_v6 = 1; + } + break; + } + } + if (buf != NULL) + memput(buf, bufsiz); + close(s); + /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */ + return (0); + err_ret: + if (buf != NULL) + memput(buf, bufsiz); + if (s != -1) + close(s); + /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */ + return (-1); +} + +static struct hostent * +copyandmerge(struct hostent *he1, struct hostent *he2, int af, int *error_num) { + struct hostent *he = NULL; + int addresses = 1; /* NULL terminator */ + int names = 1; /* NULL terminator */ + int len = 0; + char **cpp, **npp; + + /* + * Work out array sizes; + */ + if (he1 != NULL) { + cpp = he1->h_addr_list; + while (*cpp != NULL) { + addresses++; + cpp++; + } + cpp = he1->h_aliases; + while (*cpp != NULL) { + names++; + cpp++; + } + } + + if (he2 != NULL) { + cpp = he2->h_addr_list; + while (*cpp != NULL) { + addresses++; + cpp++; + } + if (he1 == NULL) { + cpp = he2->h_aliases; + while (*cpp != NULL) { + names++; + cpp++; + } + } + } + + if (addresses == 1) { + *error_num = NO_ADDRESS; + return (NULL); + } + + he = memget(sizeof *he); + if (he == NULL) + goto no_recovery; + + he->h_addr_list = memget(sizeof(char *) * (addresses)); + if (he->h_addr_list == NULL) + goto cleanup0; + memset(he->h_addr_list, 0, sizeof(char *) * (addresses)); + + /* copy addresses */ + npp = he->h_addr_list; + if (he1 != NULL) { + cpp = he1->h_addr_list; + while (*cpp != NULL) { + *npp = memget((af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + if (*npp == NULL) + goto cleanup1; + /* convert to mapped if required */ + if (af == AF_INET6 && he1->h_addrtype == AF_INET) { + memcpy(*npp, in6addr_mapped, + sizeof in6addr_mapped); + memcpy(*npp + sizeof in6addr_mapped, *cpp, + INADDRSZ); + } else { + memcpy(*npp, *cpp, + (af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + } + cpp++; + npp++; + } + } + + if (he2 != NULL) { + cpp = he2->h_addr_list; + while (*cpp != NULL) { + *npp = memget((af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + if (*npp == NULL) + goto cleanup1; + /* convert to mapped if required */ + if (af == AF_INET6 && he2->h_addrtype == AF_INET) { + memcpy(*npp, in6addr_mapped, + sizeof in6addr_mapped); + memcpy(*npp + sizeof in6addr_mapped, *cpp, + INADDRSZ); + } else { + memcpy(*npp, *cpp, + (af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + } + cpp++; + npp++; + } + } + + he->h_aliases = memget(sizeof(char *) * (names)); + if (he->h_aliases == NULL) + goto cleanup1; + memset(he->h_aliases, 0, sizeof(char *) * (names)); + + /* copy aliases */ + npp = he->h_aliases; + cpp = (he1 != NULL) ? he1->h_aliases : he2->h_aliases; + while (*cpp != NULL) { + len = strlen (*cpp) + 1; + *npp = memget(len); + if (*npp == NULL) + goto cleanup2; + strcpy(*npp, *cpp); + npp++; + cpp++; + } + + /* copy hostname */ + he->h_name = memget(strlen((he1 != NULL) ? + he1->h_name : he2->h_name) + 1); + if (he->h_name == NULL) + goto cleanup2; + strcpy(he->h_name, (he1 != NULL) ? he1->h_name : he2->h_name); + + /* set address type and length */ + he->h_addrtype = af; + he->h_length = (af == AF_INET) ? INADDRSZ : IN6ADDRSZ; + return(he); + + cleanup2: + cpp = he->h_aliases; + while (*cpp != NULL) { + memput(*cpp, strlen(*cpp) + 1); + cpp++; + } + memput(he->h_aliases, sizeof(char *) * (names)); + + cleanup1: + cpp = he->h_addr_list; + while (*cpp != NULL) { + memput(*cpp, (af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + *cpp = NULL; + cpp++; + } + memput(he->h_addr_list, sizeof(char *) * (addresses)); + + cleanup0: + memput(he, sizeof *he); + + no_recovery: + *error_num = NO_RECOVERY; + return (NULL); +} + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->ho) { + net_data->ho = (*net_data->irs->ho_map)(net_data->irs); + if (!net_data->ho || !net_data->res) { + error: + errno = EIO; + if (net_data && net_data->res) + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + + (*net_data->ho->res_set)(net_data->ho, net_data->res, NULL); + } + + return (net_data); +} + +static void +freepvt(struct net_data *net_data) { + if (net_data->ho_data) { + free(net_data->ho_data); + net_data->ho_data = NULL; + } +} + +static struct hostent * +fakeaddr(const char *name, int af, struct net_data *net_data) { + struct pvt *pvt; + + freepvt(net_data); + net_data->ho_data = malloc(sizeof (struct pvt)); + if (!net_data->ho_data) { + errno = ENOMEM; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + pvt = net_data->ho_data; +#ifndef __bsdi__ + /* + * Unlike its forebear(inet_aton), our friendly inet_pton() is strict + * in its interpretation of its input, and it will only return "1" if + * the input string is a formally valid(and thus unambiguous with + * respect to host names) internet address specification for this AF. + * + * This means "telnet 0xdeadbeef" and "telnet 127.1" are dead now. + */ + if (inet_pton(af, name, pvt->addr) != 1) { +#else + /* BSDI XXX + * We put this back to inet_aton -- we really want the old behavior + * Long live 127.1... + */ + if ((af != AF_INET || + inet_aton(name, (struct in_addr *)pvt->addr) != 1) && + inet_pton(af, name, pvt->addr) != 1) { +#endif + RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); + return (NULL); + } + strncpy(pvt->name, name, NS_MAXDNAME); + pvt->name[NS_MAXDNAME] = '\0'; + if (af == AF_INET && (net_data->res->options & RES_USE_INET6) != 0) { + map_v4v6_address(pvt->addr, pvt->addr); + af = AF_INET6; + } + pvt->host.h_addrtype = af; + switch(af) { + case AF_INET: + pvt->host.h_length = NS_INADDRSZ; + break; + case AF_INET6: + pvt->host.h_length = NS_IN6ADDRSZ; + break; + default: + errno = EAFNOSUPPORT; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + pvt->host.h_name = pvt->name; + pvt->host.h_aliases = pvt->aliases; + pvt->aliases[0] = NULL; + pvt->addrs[0] = (char *)pvt->addr; + pvt->addrs[1] = NULL; + pvt->host.h_addr_list = pvt->addrs; + RES_SET_H_ERRNO(net_data->res, NETDB_SUCCESS); + return (&pvt->host); +} + +#ifdef grot /* for future use in gethostbyaddr(), for "SUNSECURITY" */ + struct hostent *rhp; + char **haddr; + u_long old_options; + char hname2[MAXDNAME+1]; + + if (af == AF_INET) { + /* + * turn off search as the name should be absolute, + * 'localhost' should be matched by defnames + */ + strncpy(hname2, hp->h_name, MAXDNAME); + hname2[MAXDNAME] = '\0'; + old_options = net_data->res->options; + net_data->res->options &= ~RES_DNSRCH; + net_data->res->options |= RES_DEFNAMES; + if (!(rhp = gethostbyname(hname2))) { + net_data->res->options = old_options; + RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); + return (NULL); + } + net_data->res->options = old_options; + for (haddr = rhp->h_addr_list; *haddr; haddr++) + if (!memcmp(*haddr, addr, INADDRSZ)) + break; + if (!*haddr) { + RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); + return (NULL); + } + } +#endif /* grot */ + +#endif /*__BIND_NOSTATIC*/ diff --git a/lib/bind/irs/gethostent_r.c b/lib/bind/irs/gethostent_r.c new file mode 100644 index 0000000000..fd174b409a --- /dev/null +++ b/lib/bind/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 1.1 2001/03/29 06:31:45 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int gethostent_r_not_required = 0; +#else +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HOST_R_RETURN + +static HOST_R_RETURN +copy_hostent(struct hostent *, struct hostent *, HOST_R_COPY_ARGS); + +HOST_R_RETURN +gethostbyname_r(const char *name, struct hostent *hptr, HOST_R_ARGS) { + struct hostent *he = gethostbyname(name); + + 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; + } + 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/lib/bind/irs/getnameinfo.c b/lib/bind/irs/getnameinfo.c new file mode 100644 index 0000000000..44756db207 --- /dev/null +++ b/lib/bind/irs/getnameinfo.c @@ -0,0 +1,226 @@ +/* + * Issues to be discussed: + * - Thread safe-ness must be checked + * - Return values. There seems to be no standard for return value (RFC2133) + * but INRIA implementation returns EAI_xxx defined for getaddrinfo(). + */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by WIDE Project and + * its contributors. + * 4. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#define SUCCESS 0 +#define ANY 0 +#define YES 1 +#define NO 0 + +/* + * Note that a_off will be dynamically adjusted so that to be consistent + * with the definition of sockaddr_in{,6}. + * The value presented below is just a guess. + */ +static struct afd { + int a_af; + int a_addrlen; + size_t 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, 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 + size_t len; +#endif + int family, i; + const char *addr; + char *p; + u_char pfx; + static int firsttime = 1; + static char numserv[512]; + static char numaddr[512]; + + + /* dynamically adjust a_off */ + if (firsttime) { + struct afd *p; + u_char *q; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + + for (p = &afdl[0]; p->a_af; p++) { + switch (p->a_af) { + case PF_INET: + q = (u_char *)&sin.sin_addr.s_addr; + p->a_off = q - (u_char *)&sin; + break; + case PF_INET6: + q = (u_char *)&sin6.sin6_addr.s6_addr; + p->a_off = q - (u_char *)&sin6; + break; + default: + break; + } + } + firsttime = 0; + } + + if (sa == NULL) + return ENI_NOSOCKET; + +#ifdef HAVE_SA_LEN + len = sa->sa_len; + if (len != salen) return ENI_SALEN; +#endif + + family = sa->sa_family; + for (i = 0; afdl[i].a_af; i++) + if (afdl[i].a_af == family) { + afd = &afdl[i]; + goto found; + } + return ENI_FAMILY; + + found: + if (salen != afd->a_socklen) return ENI_SALEN; + + port = ((const struct sockinet *)sa)->si_port; /* network byte order */ + addr = (const char *)sa + afd->a_off; + + if (serv == NULL || servlen == 0) { + /* what we should do? */ + } else if (flags & NI_NUMERICSERV) { + snprintf(numserv, sizeof(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) + 1 > servlen) + return ENI_MEMORY; + strcpy(serv, sp->s_name); + } else + return ENI_NOSERVNAME; + } + + switch (sa->sa_family) { + case AF_INET: + if (ntohl(*(const u_long *)addr) >> IN_CLASSA_NSHIFT == 0) + flags |= NI_NUMERICHOST; + break; + case AF_INET6: + pfx = *addr; + if (pfx == 0 || pfx == 0xfe || pfx == 0xff) + flags |= NI_NUMERICHOST; + break; + } + if (host == NULL || hostlen == 0) { + /* what should we do? */ + } else if (flags & NI_NUMERICHOST) { + if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) + == NULL) + return ENI_SYSTEM; + if (strlen(numaddr) + 1 > 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) + 1 > 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) + 1 > hostlen) + return ENI_MEMORY; + strcpy(host, numaddr); + } + } + return SUCCESS; +} diff --git a/lib/bind/irs/getnetent.c b/lib/bind/irs/getnetent.c new file mode 100644 index 0000000000..b71f9b2823 --- /dev/null +++ b/lib/bind/irs/getnetent.c @@ -0,0 +1,342 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: getnetent.c,v 1.1 2001/03/29 06:31:46 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "irs_data.h" + +/* Definitions */ + +struct pvt { + struct netent netent; + char * aliases[1]; + char name[MAXDNAME + 1]; +}; + +/* Forward */ + +static struct net_data *init(void); +static struct netent *nw_to_net(struct nwent *, struct net_data *); +static void freepvt(struct net_data *); +static struct netent *fakeaddr(const char *, int af, struct net_data *); + +/* Portability */ + +#ifndef INADDR_NONE +# define INADDR_NONE 0xffffffff +#endif + +/* Public */ + +struct netent * +getnetent() { + struct net_data *net_data = init(); + + return (getnetent_p(net_data)); +} + +struct netent * +getnetbyname(const char *name) { + struct net_data *net_data = init(); + + return (getnetbyname_p(name, net_data)); +} + +struct netent * +getnetbyaddr(unsigned long net, int type) { + struct net_data *net_data = init(); + + return (getnetbyaddr_p(net, type, net_data)); +} + +void +setnetent(int stayopen) { + struct net_data *net_data = init(); + + setnetent_p(stayopen, net_data); +} + + +void +endnetent() { + struct net_data *net_data = init(); + + endnetent_p(net_data); +} + +/* Shared private. */ + +struct netent * +getnetent_p(struct net_data *net_data) { + struct irs_nw *nw; + + if (!net_data || !(nw = net_data->nw)) + return (NULL); + net_data->nww_last = (*nw->next)(nw); + net_data->nw_last = nw_to_net(net_data->nww_last, net_data); + return (net_data->nw_last); +} + +struct netent * +getnetbyname_p(const char *name, struct net_data *net_data) { + struct irs_nw *nw; + struct netent *np; + char **nap; + + if (!net_data || !(nw = net_data->nw)) + return (NULL); + if (net_data->nw_stayopen && net_data->nw_last) { + if (!strcmp(net_data->nw_last->n_name, name)) + return (net_data->nw_last); + for (nap = net_data->nw_last->n_aliases; nap && *nap; nap++) + if (!strcmp(name, *nap)) + return (net_data->nw_last); + } + if ((np = fakeaddr(name, AF_INET, net_data)) != NULL) + return (np); + net_data->nww_last = (*nw->byname)(nw, name, AF_INET); + net_data->nw_last = nw_to_net(net_data->nww_last, net_data); + if (!net_data->nw_stayopen) + endnetent(); + return (net_data->nw_last); +} + +struct netent * +getnetbyaddr_p(unsigned long net, int type, struct net_data *net_data) { + struct irs_nw *nw; + u_char addr[4]; + int bits; + + if (!net_data || !(nw = net_data->nw)) + return (NULL); + if (net_data->nw_stayopen && net_data->nw_last) + if (type == net_data->nw_last->n_addrtype && + net == net_data->nw_last->n_net) + return (net_data->nw_last); + + /* cannonize net(host order) */ + if (net < 256) { + net <<= 24; + bits = 8; + } else if (net < 65536) { + net <<= 16; + bits = 16; + } else if (net < 16777216) { + net <<= 8; + bits = 24; + } else + bits = 32; + + /* convert to net order */ + addr[0] = (0xFF000000 & net) >> 24; + addr[1] = (0x00FF0000 & net) >> 16; + addr[2] = (0x0000FF00 & net) >> 8; + addr[3] = (0x000000FF & net); + + /* reduce bits to as close to natural number as possible */ + if ((bits == 32) && (addr[0] < 224) && (addr[3] == 0)) { + if ((addr[0] < 192) && (addr[2] == 0)) { + if ((addr[0] < 128) && (addr[1] == 0)) + bits = 8; + else + bits = 16; + } else { + bits = 24; + } + } + + net_data->nww_last = (*nw->byaddr)(nw, addr, bits, AF_INET); + net_data->nw_last = nw_to_net(net_data->nww_last, net_data); + if (!net_data->nw_stayopen) + endnetent(); + return (net_data->nw_last); +} + + + + +void +setnetent_p(int stayopen, struct net_data *net_data) { + struct irs_nw *nw; + + if (!net_data || !(nw = net_data->nw)) + return; + freepvt(net_data); + (*nw->rewind)(nw); + net_data->nw_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); +} + +void +endnetent_p(struct net_data *net_data) { + struct irs_nw *nw; + + if ((net_data != NULL) && ((nw = net_data->nw) != NULL)) + (*nw->minimize)(nw); +} + +/* Private */ + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->nw) { + net_data->nw = (*net_data->irs->nw_map)(net_data->irs); + + if (!net_data->nw || !net_data->res) { + error: + errno = EIO; + return (NULL); + } + (*net_data->nw->res_set)(net_data->nw, net_data->res, NULL); + } + + return (net_data); +} + +static void +freepvt(struct net_data *net_data) { + if (net_data->nw_data) { + free(net_data->nw_data); + net_data->nw_data = NULL; + } +} + +static struct netent * +fakeaddr(const char *name, int af, struct net_data *net_data) { + struct pvt *pvt; + const char *cp; + u_long tmp; + + if (af != AF_INET) { + /* XXX should support IPv6 some day */ + errno = EAFNOSUPPORT; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + if (!isascii(name[0]) || !isdigit(name[0])) + return (NULL); + for (cp = name; *cp; ++cp) + if (!isascii(*cp) || (!isdigit(*cp) && *cp != '.')) + return (NULL); + if (*--cp == '.') + return (NULL); + + /* All-numeric, no dot at the end. */ + + tmp = inet_network(name); + if (tmp == INADDR_NONE) { + RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); + return (NULL); + } + + /* Valid network number specified. + * Fake up a netent as if we'd actually + * done a lookup. + */ + freepvt(net_data); + net_data->nw_data = malloc(sizeof (struct pvt)); + if (!net_data->nw_data) { + errno = ENOMEM; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + pvt = net_data->nw_data; + + strncpy(pvt->name, name, MAXDNAME); + pvt->name[MAXDNAME] = '\0'; + pvt->netent.n_name = pvt->name; + pvt->netent.n_addrtype = AF_INET; + pvt->netent.n_aliases = pvt->aliases; + pvt->aliases[0] = NULL; + pvt->netent.n_net = tmp; + + return (&pvt->netent); +} + +static struct netent * +nw_to_net(struct nwent *nwent, struct net_data *net_data) { + struct pvt *pvt; + u_long addr = 0; + int i; + int msbyte; + + if (!nwent || nwent->n_addrtype != AF_INET) + return (NULL); + freepvt(net_data); + net_data->nw_data = malloc(sizeof (struct pvt)); + if (!net_data->nw_data) { + errno = ENOMEM; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + pvt = net_data->nw_data; + pvt->netent.n_name = nwent->n_name; + pvt->netent.n_aliases = nwent->n_aliases; + pvt->netent.n_addrtype = nwent->n_addrtype; + +/* + * What this code does: Converts net addresses from network to host form. + * + * msbyte: the index of the most significant byte in the n_addr array. + * + * Shift bytes in significant order into addr. When all signicant + * bytes are in, zero out bits in the LSB that are not part of the network. + */ + msbyte = nwent->n_length / 8 + + ((nwent->n_length % 8) != 0 ? 1 : 0) - 1; + for (i = 0; i <= msbyte; i++) + addr = (addr << 8) | ((unsigned char *)nwent->n_addr)[i]; + i = (32 - nwent->n_length) % 8; + if (i != 0) + addr &= ~((1 << (i + 1)) - 1); + pvt->netent.n_net = addr; + return (&pvt->netent); +} + +#endif /*__BIND_NOSTATIC*/ diff --git a/lib/bind/irs/getnetent_r.c b/lib/bind/irs/getnetent_r.c new file mode 100644 index 0000000000..43e41face4 --- /dev/null +++ b/lib/bind/irs/getnetent_r.c @@ -0,0 +1,192 @@ +/* + * 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 1.1 2001/03/29 06:31:46 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int getnetent_r_not_required = 0; +#else +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef NET_R_RETURN + +static NET_R_RETURN +copy_netent(struct netent *, struct netent *, NET_R_COPY_ARGS); + +NET_R_RETURN +getnetbyname_r(const char *name, struct netent *nptr, NET_R_ARGS) { + struct netent *ne = getnetbyname(name); + + 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/lib/bind/irs/getnetgrent.c b/lib/bind/irs/getnetgrent.c new file mode 100644 index 0000000000..07f39a7508 --- /dev/null +++ b/lib/bind/irs/getnetgrent.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getnetgrent.c,v 1.1 2001/03/29 06:31:46 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include + +#include +#include + +#include +#include +#include + +#include + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct net_data *init(void); + + +/* Public */ + +void +setnetgrent(const char *netgroup) { + struct net_data *net_data = init(); + + setnetgrent_p(netgroup, net_data); +} + +void +endnetgrent(void) { + struct net_data *net_data = init(); + + endnetgrent_p(net_data); +} + +int +innetgr(const char *netgroup, const char *host, + const char *user, const char *domain) { + struct net_data *net_data = init(); + + return (innetgr_p(netgroup, host, user, domain, net_data)); +} + +int +getnetgrent(const char **host, const char **user, const char **domain) { + struct net_data *net_data = init(); + + return (getnetgrent_p(host, user, domain, net_data)); +} + +/* Shared private. */ + +void +setnetgrent_p(const char *netgroup, struct net_data *net_data) { + struct irs_ng *ng; + + if ((net_data != NULL) && ((ng = net_data->ng) != NULL)) + (*ng->rewind)(ng, netgroup); +} + +void +endnetgrent_p(struct net_data *net_data) { + struct irs_ng *ng; + + if (!net_data) + return; + if ((ng = net_data->ng) != NULL) + (*ng->close)(ng); + net_data->ng = NULL; +} + +int +innetgr_p(const char *netgroup, const char *host, + const char *user, const char *domain, + struct net_data *net_data) { + struct irs_ng *ng; + + if (!net_data || !(ng = net_data->ng)) + return (0); + return ((*ng->test)(ng, netgroup, host, user, domain)); +} + +int +getnetgrent_p(const char **host, const char **user, const char **domain, + struct net_data *net_data ) { + struct irs_ng *ng; + + if (!net_data || !(ng = net_data->ng)) + return (0); + return ((*ng->next)(ng, host, user, domain)); +} + +/* Private */ + +static struct net_data * +init(void) { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->ng) { + net_data->ng = (*net_data->irs->ng_map)(net_data->irs); + if (!net_data->ng) { + error: + errno = EIO; + return (NULL); + } + } + + return (net_data); +} + +#endif /*__BIND_NOSTATIC*/ diff --git a/lib/bind/irs/getnetgrent_r.c b/lib/bind/irs/getnetgrent_r.c new file mode 100644 index 0000000000..b0a25afd3e --- /dev/null +++ b/lib/bind/irs/getnetgrent_r.c @@ -0,0 +1,142 @@ +/* + * 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 1.1 2001/03/29 06:31:47 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int getnetgrent_r_not_required = 0; +#else +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef NGR_R_RETURN + +static NGR_R_RETURN +copy_protoent(char **, char **, char **, const char *, const char *, + const char *, NGR_R_COPY_ARGS); + +NGR_R_RETURN +innetgr_r(const char *netgroup, const char *host, const char *user, + const char *domain) { + + return (innetgr(netgroup, host, user, domain)); +} + +/* + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +NGR_R_RETURN +getnetgrent_r(char **machinep, char **userp, char **domainp, NGR_R_ARGS) { + const char *mp, *up, *dp; + int res = getnetgrent(&mp, &up, &dp); + + if (res != 1) + return (res); + + return (copy_protoent(machinep, userp, domainp, + mp, up, dp, NGR_R_COPY)); +} + +NGR_R_SET_RETURN +#ifdef NGR_R_ENT_ARGS +setnetgrent_r(const char *netgroup, NGR_R_ENT_ARGS) +#else +setnetgrent_r(const char *netgroup) +#endif +{ + setnetgrent(netgroup); +#ifdef NGR_R_SET_RESULT + return (NGR_R_SET_RESULT); +#endif +} + +NGR_R_END_RETURN +#ifdef NGR_R_ENT_ARGS +endnetgrent_r(NGR_R_ENT_ARGS) +#else +endnetgrent_r(void) +#endif +{ + endnetgrent(); + NGR_R_END_RESULT(NGR_R_OK); +} + +/* Private */ + +static int +copy_protoent(char **machinep, char **userp, char **domainp, + const char *mp, const char *up, const char *dp, + NGR_R_COPY_ARGS) { + char *cp; + int n; + int len; + + /* Find out the amount of space required to store the answer. */ + len = 0; + if (mp != NULL) len += strlen(mp) + 1; + if (up != NULL) len += strlen(up) + 1; + if (dp != NULL) len += strlen(dp) + 1; + + 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/lib/bind/irs/getprotoent.c b/lib/bind/irs/getprotoent.c new file mode 100644 index 0000000000..e15437911a --- /dev/null +++ b/lib/bind/irs/getprotoent.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: getprotoent.c,v 1.1 2001/03/29 06:31:47 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include + +#include +#include + +#include +#include +#include + +#include + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct net_data *init(void); + +/* Public */ + +struct protoent * +getprotoent() { + struct net_data *net_data = init(); + + return (getprotoent_p(net_data)); +} + +struct protoent * +getprotobyname(const char *name) { + struct net_data *net_data = init(); + + return (getprotobyname_p(name, net_data)); +} + +struct protoent * +getprotobynumber(int proto) { + struct net_data *net_data = init(); + + return (getprotobynumber_p(proto, net_data)); +} + +void +setprotoent(int stayopen) { + struct net_data *net_data = init(); + + setprotoent_p(stayopen, net_data); +} + +void +endprotoent() { + struct net_data *net_data = init(); + + endprotoent_p(net_data); +} + +/* Shared private. */ + +struct protoent * +getprotoent_p(struct net_data *net_data) { + struct irs_pr *pr; + + if (!net_data || !(pr = net_data->pr)) + return (NULL); + net_data->pr_last = (*pr->next)(pr); + return (net_data->pr_last); +} + +struct protoent * +getprotobyname_p(const char *name, struct net_data *net_data) { + struct irs_pr *pr; + char **pap; + + if (!net_data || !(pr = net_data->pr)) + return (NULL); + if (net_data->pr_stayopen && net_data->pr_last) { + if (!strcmp(net_data->pr_last->p_name, name)) + return (net_data->pr_last); + for (pap = net_data->pr_last->p_aliases; pap && *pap; pap++) + if (!strcmp(name, *pap)) + return (net_data->pr_last); + } + net_data->pr_last = (*pr->byname)(pr, name); + if (!net_data->pr_stayopen) + endprotoent(); + return (net_data->pr_last); +} + +struct protoent * +getprotobynumber_p(int proto, struct net_data *net_data) { + struct irs_pr *pr; + + if (!net_data || !(pr = net_data->pr)) + return (NULL); + if (net_data->pr_stayopen && net_data->pr_last) + if (net_data->pr_last->p_proto == proto) + return (net_data->pr_last); + net_data->pr_last = (*pr->bynumber)(pr, proto); + if (!net_data->pr_stayopen) + endprotoent(); + return (net_data->pr_last); +} + +void +setprotoent_p(int stayopen, struct net_data *net_data) { + struct irs_pr *pr; + + if (!net_data || !(pr = net_data->pr)) + return; + (*pr->rewind)(pr); + net_data->pr_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); +} + +void +endprotoent_p(struct net_data *net_data) { + struct irs_pr *pr; + + if ((net_data != NULL) && ((pr = net_data->pr) != NULL)) + (*pr->minimize)(pr); +} + +/* Private */ + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->pr) { + net_data->pr = (*net_data->irs->pr_map)(net_data->irs); + + if (!net_data->pr || !net_data->res) { + error: + errno = EIO; + return (NULL); + } + (*net_data->pr->res_set)(net_data->pr, net_data->res, NULL); + } + + return (net_data); +} + +#endif /*__BIND_NOSTATIC*/ diff --git a/lib/bind/irs/getprotoent_r.c b/lib/bind/irs/getprotoent_r.c new file mode 100644 index 0000000000..08876dad6e --- /dev/null +++ b/lib/bind/irs/getprotoent_r.c @@ -0,0 +1,186 @@ +/* + * 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 1.1 2001/03/29 06:31:47 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int getprotoent_r_not_required = 0; +#else +#include +#include +#include +#include +#include +#include +#include + +#ifdef PROTO_R_RETURN + +static PROTO_R_RETURN +copy_protoent(struct protoent *, struct protoent *, PROTO_R_COPY_ARGS); + +PROTO_R_RETURN +getprotobyname_r(const char *name, struct protoent *pptr, PROTO_R_ARGS) { + struct protoent *pe = getprotobyname(name); + + 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/lib/bind/irs/getpwent.c b/lib/bind/irs/getpwent.c new file mode 100644 index 0000000000..b9cc9e3271 --- /dev/null +++ b/lib/bind/irs/getpwent.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: getpwent.c,v 1.1 2001/03/29 06:31:47 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(WANT_IRS_PW) || defined(__BIND_NOSTATIC) +static int __bind_irs_pw_unneeded; +#else + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct net_data * init(void); + +/* Public */ + +struct passwd * +getpwent(void) { + struct net_data *net_data = init(); + + return (getpwent_p(net_data)); +} + +struct passwd * +getpwnam(const char *name) { + struct net_data *net_data = init(); + + return (getpwnam_p(name, net_data)); +} + +struct passwd * +getpwuid(uid_t uid) { + struct net_data *net_data = init(); + + return (getpwuid_p(uid, net_data)); +} + +int +setpassent(int stayopen) { + struct net_data *net_data = init(); + + return (setpassent_p(stayopen, net_data)); +} + +#ifdef SETPWENT_VOID +void +setpwent() { + struct net_data *net_data = init(); + + setpwent_p(net_data); +} +#else +int +setpwent() { + struct net_data *net_data = init(); + + return (setpwent_p(net_data)); +} +#endif + +void +endpwent() { + struct net_data *net_data = init(); + + endpwent_p(net_data); +} + +/* Shared private. */ + +struct passwd * +getpwent_p(struct net_data *net_data) { + struct irs_pw *pw; + + if (!net_data || !(pw = net_data->pw)) + return (NULL); + net_data->pw_last = (*pw->next)(pw); + return (net_data->pw_last); +} + +struct passwd * +getpwnam_p(const char *name, struct net_data *net_data) { + struct irs_pw *pw; + + if (!net_data || !(pw = net_data->pw)) + return (NULL); + if (net_data->pw_stayopen && net_data->pw_last && + !strcmp(net_data->pw_last->pw_name, name)) + return (net_data->pw_last); + net_data->pw_last = (*pw->byname)(pw, name); + if (!net_data->pw_stayopen) + endpwent(); + return (net_data->pw_last); +} + +struct passwd * +getpwuid_p(uid_t uid, struct net_data *net_data) { + struct irs_pw *pw; + + if (!net_data || !(pw = net_data->pw)) + return (NULL); + if (net_data->pw_stayopen && net_data->pw_last && + net_data->pw_last->pw_uid == uid) + return (net_data->pw_last); + net_data->pw_last = (*pw->byuid)(pw, uid); + if (!net_data->pw_stayopen) + endpwent(); + return (net_data->pw_last); +} + +int +setpassent_p(int stayopen, struct net_data *net_data) { + struct irs_pw *pw; + + if (!net_data || !(pw = net_data->pw)) + return (0); + (*pw->rewind)(pw); + net_data->pw_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); + return (1); +} + +#ifdef SETPWENT_VOID +void +setpwent_p(struct net_data *net_data) { + (void) setpassent_p(0, net_data); +} +#else +int +setpwent_p(struct net_data *net_data) { + return (setpassent_p(0, net_data)); +} +#endif + +void +endpwent_p(struct net_data *net_data) { + struct irs_pw *pw; + + if ((net_data != NULL) && ((pw = net_data->pw) != NULL)) + (*pw->minimize)(pw); +} + +/* Private */ + +static struct net_data * +init() { + struct net_data *net_data; + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->pw) { + net_data->pw = (*net_data->irs->pw_map)(net_data->irs); + + if (!net_data->pw || !net_data->res) { + error: + errno = EIO; + return (NULL); + } + (*net_data->pw->res_set)(net_data->pw, net_data->res, NULL); + } + + return (net_data); +} + +#endif /* WANT_IRS_PW */ diff --git a/lib/bind/irs/getpwent_r.c b/lib/bind/irs/getpwent_r.c new file mode 100644 index 0000000000..ef400dfd63 --- /dev/null +++ b/lib/bind/irs/getpwent_r.c @@ -0,0 +1,263 @@ +/* + * 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 1.1 2001/03/29 06:31:47 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) || !defined(WANT_IRS_PW) + static int getpwent_r_not_required = 0; +#else +#include +#include +#include +#include +#include +#include + +#ifdef PASS_R_RETURN + +static int +copy_passwd(struct passwd *, struct passwd *, char *buf, int buflen); + +/* POSIX 1003.1c */ +#ifdef POSIX_GETPWNAM_R +int +__posix_getpwnam_r(const char *login, struct passwd *pwptr, + char *buf, size_t buflen, struct passwd **result) { +#else +int +getpwnam_r(const char *login, struct passwd *pwptr, + char *buf, size_t buflen, struct passwd **result) { +#endif + struct passwd *pw = getpwnam(login); + int res; + + if (pw == NULL) { + *result = NULL; + return (-1); + } + + res = copy_passwd(pw, pwptr, buf, buflen); + *result = res ? NULL : pwptr; + return (res); +} + +#ifdef POSIX_GETPWNAM_R +struct passwd * +getpwnam_r(const char *login, struct passwd *pwptr, char *buf, int buflen) { + struct passwd *pw = getpwnam(login); + int res; + + if (pw == NULL) + return (NULL); + + res = copy_passwd(pw, pwptr, buf, buflen); + return (res ? NULL : pwptr); +} +#endif + +/* POSIX 1003.1c */ +#ifdef POSIX_GETPWUID_R +int +__posix_getpwuid_r(uid_t uid, struct passwd *pwptr, + char *buf, int buflen, struct passwd **result) { +#else +int +getpwuid_r(uid_t uid, struct passwd *pwptr, + char *buf, size_t buflen, struct passwd **result) { +#endif + struct passwd *pw = getpwuid(uid); + int res; + + if (pw == NULL) { + *result = NULL; + return (-1); + } + + res = copy_passwd(pw, pwptr, buf, buflen); + *result = res ? NULL : pwptr; + return (res); +} + +#ifdef POSIX_GETPWUID_R +struct passwd * +getpwuid_r(uid_t uid, struct passwd *pwptr, char *buf, int buflen) { + struct passwd *pw = getpwuid(uid); + int res; + + if (pw == NULL) + return (NULL); + + res = copy_passwd(pw, pwptr, buf, buflen); + return (res ? NULL : pwptr); +} +#endif + +/* + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +PASS_R_RETURN +getpwent_r(struct passwd *pwptr, PASS_R_ARGS) { + struct passwd *pw = getpwent(); + int res; + + if (pw == NULL) + return (PASS_R_BAD); + + res = copy_passwd(pw, pwptr, buf, buflen); + return (res ? PASS_R_BAD : PASS_R_OK); +} + +PASS_R_SET_RETURN +#ifdef PASS_R_ENT_ARGS +setpassent_r(int stayopen, PASS_R_ENT_ARGS) +#else +setpassent_r(int stayopen) +#endif +{ + + setpassent(stayopen); +#ifdef PASS_R_SET_RESULT + return (PASS_R_SET_RESULT); +#endif +} + +PASS_R_SET_RETURN +#ifdef PASS_R_ENT_ARGS +setpwent_r(PASS_R_ENT_ARGS) +#else +setpwent_r(void) +#endif +{ + + setpwent(); +#ifdef PASS_R_SET_RESULT + return (PASS_R_SET_RESULT); +#endif +} + +PASS_R_END_RETURN +#ifdef PASS_R_ENT_ARGS +endpwent_r(PASS_R_ENT_ARGS) +#else +endpwent_r(void) +#endif +{ + + endpwent(); + PASS_R_END_RESULT(PASS_R_OK); +} + + +#ifdef HAS_FGETPWENT +PASS_R_RETURN +fgetpwent_r(FILE *f, struct passwd *pwptr, PASS_R_COPY_ARGS) { + struct passwd *pw = fgetpwent(f); + int res; + + if (pw == NULL) + return (PASS_R_BAD); + + res = copy_passwd(pw, pwptr, PASS_R_COPY); + return (res ? PASS_R_BAD : PASS_R_OK ); +} +#endif + +/* Private */ + +static int +copy_passwd(struct passwd *pw, struct passwd *pwptr, char *buf, int buflen) { + char *cp; + int n; + int len; + + /* Find out the amount of space required to store the answer. */ + len = strlen(pw->pw_name) + 1; + len += strlen(pw->pw_passwd) + 1; +#ifdef HAVE_PW_CLASS + len += strlen(pw->pw_class) + 1; +#endif + len += strlen(pw->pw_gecos) + 1; + len += strlen(pw->pw_dir) + 1; + len += strlen(pw->pw_shell) + 1; + + if (len > buflen) { + errno = ERANGE; + return (-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/lib/bind/irs/getservent.c b/lib/bind/irs/getservent.c new file mode 100644 index 0000000000..56cc107596 --- /dev/null +++ b/lib/bind/irs/getservent.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: getservent.c,v 1.1 2001/03/29 06:31:47 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include + +#include +#include + +#include +#include +#include + +#include + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct net_data *init(void); + +/* Public */ + +struct servent * +getservent(void) { + struct net_data *net_data = init(); + + return (getservent_p(net_data)); +} + +struct servent * +getservbyname(const char *name, const char *proto) { + struct net_data *net_data = init(); + + return (getservbyname_p(name, proto, net_data)); +} + +struct servent * +getservbyport(int port, const char *proto) { + struct net_data *net_data = init(); + + return (getservbyport_p(port, proto, net_data)); +} + +void +setservent(int stayopen) { + struct net_data *net_data = init(); + + setservent_p(stayopen, net_data); +} + +void +endservent() { + struct net_data *net_data = init(); + + endservent_p(net_data); +} + +/* Shared private. */ + +struct servent * +getservent_p(struct net_data *net_data) { + struct irs_sv *sv; + + if (!net_data || !(sv = net_data->sv)) + return (NULL); + net_data->sv_last = (*sv->next)(sv); + return (net_data->sv_last); +} + +struct servent * +getservbyname_p(const char *name, const char *proto, + struct net_data *net_data) { + struct irs_sv *sv; + char **sap; + + if (!net_data || !(sv = net_data->sv)) + return (NULL); + if (net_data->sv_stayopen && net_data->sv_last) + if (!proto || !strcmp(net_data->sv_last->s_proto, proto)) { + if (!strcmp(net_data->sv_last->s_name, name)) + return (net_data->sv_last); + for (sap = net_data->sv_last->s_aliases; + sap && *sap; sap++) + if (!strcmp(name, *sap)) + return (net_data->sv_last); + } + net_data->sv_last = (*sv->byname)(sv, name, proto); + if (!net_data->sv_stayopen) + endservent(); + return (net_data->sv_last); +} + +struct servent * +getservbyport_p(int port, const char *proto, struct net_data *net_data) { + struct irs_sv *sv; + + if (!net_data || !(sv = net_data->sv)) + return (NULL); + if (net_data->sv_stayopen && net_data->sv_last) + if (port == net_data->sv_last->s_port && + ( !proto || + !strcmp(net_data->sv_last->s_proto, proto))) + return (net_data->sv_last); + net_data->sv_last = (*sv->byport)(sv, port, proto); + return (net_data->sv_last); +} + +void +setservent_p(int stayopen, struct net_data *net_data) { + struct irs_sv *sv; + + if (!net_data || !(sv = net_data->sv)) + return; + (*sv->rewind)(sv); + net_data->sv_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); +} + +void +endservent_p(struct net_data *net_data) { + struct irs_sv *sv; + + if ((net_data != NULL) && ((sv = net_data->sv) != NULL)) + (*sv->minimize)(sv); +} + +/* Private */ + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->sv) { + net_data->sv = (*net_data->irs->sv_map)(net_data->irs); + + if (!net_data->sv || !net_data->res) { + error: + errno = EIO; + return (NULL); + } + (*net_data->sv->res_set)(net_data->sv, net_data->res, NULL); + } + + return (net_data); +} + +#endif /*__BIND_NOSTATIC*/ diff --git a/lib/bind/irs/getservent_r.c b/lib/bind/irs/getservent_r.c new file mode 100644 index 0000000000..b9ecb2f3e8 --- /dev/null +++ b/lib/bind/irs/getservent_r.c @@ -0,0 +1,207 @@ +/* + * 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 1.1 2001/03/29 06:31:48 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int getservent_r_not_required = 0; +#else +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef SERV_R_RETURN + +static SERV_R_RETURN +copy_servent(struct servent *, struct servent *, SERV_R_COPY_ARGS); + +SERV_R_RETURN +getservbyname_r(const char *name, const char *proto, + struct servent *sptr, SERV_R_ARGS) { + struct servent *se = getservbyname(name, proto); + + 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/lib/bind/irs/hesiod.c b/lib/bind/irs/hesiod.c new file mode 100644 index 0000000000..242e875f13 --- /dev/null +++ b/lib/bind/irs/hesiod.c @@ -0,0 +1,506 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: hesiod.c,v 1.1 2001/03/29 06:31:48 marka Exp $"; +#endif + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * This file is primarily maintained by and . + */ + +/* + * hesiod.c --- the core portion of the hesiod resolver. + * + * This file is derived from the hesiod library from Project Athena; + * It has been extensively rewritten by Theodore Ts'o to have a more + * thread-safe interface. + */ + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +#include "pathnames.h" +#include "hesiod.h" +#include "hesiod_p.h" + +/* Forward */ + +int hesiod_init(void **context); +void hesiod_end(void *context); +char * hesiod_to_bind(void *context, const char *name, + const char *type); +char ** hesiod_resolve(void *context, const char *name, + const char *type); +void hesiod_free_list(void *context, char **list); + +static int parse_config_file(struct hesiod_p *ctx, const char *filename); +static char ** get_txt_records(struct hesiod_p *ctx, int class, + const char *name); +static int init(struct hesiod_p *ctx); + +/* Public */ + +/* + * This function is called to initialize a hesiod_p. + */ +int +hesiod_init(void **context) { + struct hesiod_p *ctx; + char *cp; + + ctx = malloc(sizeof(struct hesiod_p)); + if (ctx == 0) { + errno = ENOMEM; + return (-1); + } + + ctx->LHS = NULL; + ctx->RHS = NULL; + ctx->res = NULL; + + if (parse_config_file(ctx, _PATH_HESIOD_CONF) < 0) { +#ifdef DEF_RHS + /* + * Use compiled in defaults. + */ + ctx->LHS = malloc(strlen(DEF_LHS)+1); + ctx->RHS = malloc(strlen(DEF_RHS)+1); + if (ctx->LHS == 0 || ctx->RHS == 0) { + errno = ENOMEM; + goto cleanup; + } + strcpy(ctx->LHS, DEF_LHS); + strcpy(ctx->RHS, DEF_RHS); +#else + goto cleanup; +#endif + } + /* + * The default RHS can be overridden by an environment + * variable. + */ + if ((cp = getenv("HES_DOMAIN")) != NULL) { + if (ctx->RHS) + free(ctx->RHS); + ctx->RHS = malloc(strlen(cp)+2); + if (!ctx->RHS) { + errno = ENOMEM; + goto cleanup; + } + if (cp[0] == '.') + strcpy(ctx->RHS, cp); + else { + strcpy(ctx->RHS, "."); + strcat(ctx->RHS, cp); + } + } + + /* + * If there is no default hesiod realm set, we return an + * error. + */ + if (!ctx->RHS) { + errno = ENOEXEC; + goto cleanup; + } + +#if 0 + if (res_ninit(ctx->res) < 0) + goto cleanup; +#endif + + *context = ctx; + return (0); + + cleanup: + hesiod_end(ctx); + return (-1); +} + +/* + * This function deallocates the hesiod_p + */ +void +hesiod_end(void *context) { + struct hesiod_p *ctx = (struct hesiod_p *) context; + int save_errno = errno; + + if (ctx->res) + res_nclose(ctx->res); + if (ctx->RHS) + free(ctx->RHS); + if (ctx->LHS) + free(ctx->LHS); + if (ctx->res && ctx->free_res) + (*ctx->free_res)(ctx->res); + free(ctx); + errno = save_errno; +} + +/* + * This function takes a hesiod (name, type) and returns a DNS + * name which is to be resolved. + */ +char * +hesiod_to_bind(void *context, const char *name, const char *type) { + struct hesiod_p *ctx = (struct hesiod_p *) context; + char *bindname; + char **rhs_list = NULL; + const char *RHS, *cp; + + /* Decide what our RHS is, and set cp to the end of the actual name. */ + if ((cp = strchr(name, '@')) != NULL) { + if (strchr(cp + 1, '.')) + RHS = cp + 1; + else if ((rhs_list = hesiod_resolve(context, cp + 1, + "rhs-extension")) != NULL) + RHS = *rhs_list; + else { + errno = ENOENT; + return (NULL); + } + } else { + RHS = ctx->RHS; + cp = name + strlen(name); + } + + /* + * Allocate the space we need, including up to three periods and + * the terminating NUL. + */ + if ((bindname = malloc((cp - name) + strlen(type) + strlen(RHS) + + (ctx->LHS ? strlen(ctx->LHS) : 0) + 4)) == NULL) { + errno = ENOMEM; + if (rhs_list) + hesiod_free_list(context, rhs_list); + return NULL; + } + + /* Now put together the DNS name. */ + memcpy(bindname, name, cp - name); + bindname[cp - name] = '\0'; + strcat(bindname, "."); + strcat(bindname, type); + if (ctx->LHS) { + if (ctx->LHS[0] != '.') + strcat(bindname, "."); + strcat(bindname, ctx->LHS); + } + if (RHS[0] != '.') + strcat(bindname, "."); + strcat(bindname, RHS); + + if (rhs_list) + hesiod_free_list(context, rhs_list); + + return (bindname); +} + +/* + * This is the core function. Given a hesiod (name, type), it + * returns an array of strings returned by the resolver. + */ +char ** +hesiod_resolve(void *context, const char *name, const char *type) { + struct hesiod_p *ctx = (struct hesiod_p *) context; + char *bindname = hesiod_to_bind(context, name, type); + char **retvec; + + if (bindname == NULL) + return (NULL); + if (init(ctx) == -1) { + free(bindname); + return (NULL); + } + + if ((retvec = get_txt_records(ctx, C_IN, bindname))) { + free(bindname); + return (retvec); + } + + if (errno != ENOENT) + return (NULL); + + retvec = get_txt_records(ctx, C_HS, bindname); + free(bindname); + return (retvec); +} + +void +hesiod_free_list(void *context, char **list) { + char **p; + + UNUSED(context); + + for (p = list; *p; p++) + free(*p); + free(list); +} + +/* + * This function parses the /etc/hesiod.conf file + */ +static int +parse_config_file(struct hesiod_p *ctx, const char *filename) { + char *key, *data, *cp, **cpp; + char buf[MAXDNAME+7]; + FILE *fp; + + /* + * Clear the existing configuration variable, just in case + * they're set. + */ + if (ctx->RHS) + free(ctx->RHS); + if (ctx->LHS) + free(ctx->LHS); + ctx->RHS = ctx->LHS = 0; + + /* + * Now open and parse the file... + */ + if (!(fp = fopen(filename, "r"))) + return (-1); + + while (fgets(buf, sizeof(buf), fp) != NULL) { + cp = buf; + if (*cp == '#' || *cp == '\n' || *cp == '\r') + continue; + while(*cp == ' ' || *cp == '\t') + cp++; + key = cp; + while(*cp != ' ' && *cp != '\t' && *cp != '=') + cp++; + *cp++ = '\0'; + + while(*cp == ' ' || *cp == '\t' || *cp == '=') + cp++; + data = cp; + while(*cp != ' ' && *cp != '\n' && *cp != '\r') + cp++; + *cp++ = '\0'; + + if (strcmp(key, "lhs") == 0) + cpp = &ctx->LHS; + else if (strcmp(key, "rhs") == 0) + cpp = &ctx->RHS; + else + continue; + + *cpp = malloc(strlen(data) + 1); + if (!*cpp) { + errno = ENOMEM; + goto cleanup; + } + strcpy(*cpp, data); + } + fclose(fp); + return (0); + + cleanup: + fclose(fp); + if (ctx->RHS) + free(ctx->RHS); + if (ctx->LHS) + free(ctx->LHS); + ctx->RHS = ctx->LHS = 0; + return (-1); +} + +/* + * Given a DNS class and a DNS name, do a lookup for TXT records, and + * return a list of them. + */ +static char ** +get_txt_records(struct hesiod_p *ctx, int class, const char *name) { + struct { + int type; /* RR type */ + int class; /* RR class */ + int dlen; /* len of data section */ + u_char *data; /* pointer to data */ + } rr; + HEADER *hp; + u_char qbuf[MAX_HESRESP], abuf[MAX_HESRESP]; + u_char *cp, *erdata, *eom; + char *dst, *edst, **list; + int ancount, qdcount; + int i, j, n, skip; + + /* + * Construct the query and send it. + */ + n = res_nmkquery(ctx->res, QUERY, name, class, T_TXT, NULL, 0, + NULL, qbuf, MAX_HESRESP); + if (n < 0) { + errno = EMSGSIZE; + return (NULL); + } + n = res_nsend(ctx->res, qbuf, n, abuf, MAX_HESRESP); + if (n < 0) { + errno = ECONNREFUSED; + return (NULL); + } + if (n < HFIXEDSZ) { + errno = EMSGSIZE; + return (NULL); + } + + /* + * OK, parse the result. + */ + hp = (HEADER *) abuf; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + cp = abuf + sizeof(HEADER); + eom = abuf + n; + + /* Skip query, trying to get to the answer section which follows. */ + for (i = 0; i < qdcount; i++) { + skip = dn_skipname(cp, eom); + if (skip < 0 || cp + skip + QFIXEDSZ > eom) { + errno = EMSGSIZE; + return (NULL); + } + cp += skip + QFIXEDSZ; + } + + list = malloc((ancount + 1) * sizeof(char *)); + if (!list) { + errno = ENOMEM; + return (NULL); + } + j = 0; + for (i = 0; i < ancount; i++) { + skip = dn_skipname(cp, eom); + if (skip < 0) { + errno = EMSGSIZE; + goto cleanup; + } + cp += skip; + if (cp + 3 * INT16SZ + INT32SZ > eom) { + errno = EMSGSIZE; + goto cleanup; + } + rr.type = ns_get16(cp); + cp += INT16SZ; + rr.class = ns_get16(cp); + cp += INT16SZ + INT32SZ; /* skip the ttl, too */ + rr.dlen = ns_get16(cp); + cp += INT16SZ; + if (cp + rr.dlen > eom) { + errno = EMSGSIZE; + goto cleanup; + } + rr.data = cp; + cp += rr.dlen; + if (rr.class != class || rr.type != T_TXT) + continue; + if (!(list[j] = malloc(rr.dlen))) + goto cleanup; + dst = list[j++]; + edst = dst + rr.dlen; + erdata = rr.data + rr.dlen; + cp = rr.data; + while (cp < erdata) { + n = (unsigned char) *cp++; + if (cp + n > eom || dst + n > edst) { + errno = EMSGSIZE; + goto cleanup; + } + memcpy(dst, cp, n); + cp += n; + dst += n; + } + if (cp != erdata) { + errno = EMSGSIZE; + goto cleanup; + } + *dst = '\0'; + } + list[j] = NULL; + if (j == 0) { + errno = ENOENT; + goto cleanup; + } + return (list); + + cleanup: + for (i = 0; i < j; i++) + free(list[i]); + free(list); + return (NULL); +} + +struct __res_state * +__hesiod_res_get(void *context) { + struct hesiod_p *ctx = context; + + if (!ctx->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + __hesiod_res_set(ctx, res, free); + } + + return (ctx->res); +} + +void +__hesiod_res_set(void *context, struct __res_state *res, + void (*free_res)(void *)) { + struct hesiod_p *ctx = context; + + if (ctx->res && ctx->free_res) { + res_nclose(ctx->res); + (*ctx->free_res)(ctx->res); + } + + ctx->res = res; + ctx->free_res = free_res; +} + +static int +init(struct hesiod_p *ctx) { + + if (!ctx->res && !__hesiod_res_get(ctx)) + return (-1); + + if (((ctx->res->options & RES_INIT) == 0) && + (res_ninit(ctx->res) == -1)) + return (-1); + + return (0); +} diff --git a/lib/bind/irs/hesiod_p.h b/lib/bind/irs/hesiod_p.h new file mode 100644 index 0000000000..180e01daf1 --- /dev/null +++ b/lib/bind/irs/hesiod_p.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * This file is primarily maintained by and . + */ + +/* + * $Id: hesiod_p.h,v 1.1 2001/03/29 06:31:48 marka Exp $ + */ + +/* + * hesiod_p.h -- private definitions for the hesiod library + */ + +#ifndef _HESIOD_P_H_INCLUDED +#define _HESIOD_P_H_INCLUDED + +#define DEF_RHS ".Athena.MIT.EDU" /* Defaults if HESIOD_CONF */ +#define DEF_LHS ".ns" /* file is not */ + /* present. */ +struct hesiod_p { + char * LHS; /* normally ".ns" */ + char * RHS; /* AKA the default hesiod domain */ + struct __res_state * res; /* resolver context */ + void (*free_res)(void *); + void (*res_set)(struct hesiod_p *, struct __res_state *, + void (*)(void *)); + struct __res_state * (*res_get)(struct hesiod_p *); +}; + +#define MAX_HESRESP 1024 + +#endif /*_HESIOD_P_H_INCLUDED*/ diff --git a/lib/bind/irs/irp.c b/lib/bind/irs/irp.c new file mode 100644 index 0000000000..ed985d792c --- /dev/null +++ b/lib/bind/irs/irp.c @@ -0,0 +1,592 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: irp.c,v 1.1 2001/03/29 06:31:48 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "irs_p.h" +#include "irp_p.h" + +#include "port_after.h" + +/* Forward. */ + +static void irp_close(struct irs_acc *); + +#define LINEINCR 128 + +#if !defined(SUN_LEN) +#define SUN_LEN(su) \ + (sizeof (*(su)) - sizeof ((su)->sun_path) + strlen((su)->sun_path)) +#endif + + +/* Public */ + + +/* send errors to syslog if true. */ +int irp_log_errors = 1; + +/* + * This module handles the irp module connection to irpd. + * + * The client expects a synchronous interface to functions like + * getpwnam(3), so we can't use the ctl_* i/o library on this end of + * the wire (it's used in the server). + */ + +/* + * irs_acc *irs_irp_acc(const char *options); + * + * Initialize the irp module. + */ +struct irs_acc * +irs_irp_acc(const char *options) { + struct irs_acc *acc; + struct irp_p *irp; + + UNUSED(options); + + if (!(acc = memget(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(irp = memget(sizeof *irp))) { + errno = ENOMEM; + free(acc); + return (NULL); + } + irp->inlast = 0; + irp->incurr = 0; + irp->fdCxn = -1; + acc->private = irp; + +#ifdef WANT_IRS_GR + acc->gr_map = irs_irp_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_irp_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_irp_sv; + acc->pr_map = irs_irp_pr; + acc->ho_map = irs_irp_ho; + acc->nw_map = irs_irp_nw; + acc->ng_map = irs_irp_ng; + acc->close = irp_close; + return (acc); +} + + +int +irs_irp_connection_setup(struct irp_p *cxndata, int *warned) { + if (irs_irp_is_connected(cxndata)) { + return (0); + } else if (irs_irp_connect(cxndata) != 0) { + if (warned != NULL && !*warned) { + syslog(LOG_ERR, "irpd connection failed: %m\n"); + (*warned)++; + } + + return (-1); + } + + return (0); +} + + +/* + * int irs_irp_connect(void); + * + * Sets up the connection to the remote irpd server. + * + * Returns: + * + * 0 on success, -1 on failure. + * + */ +int +irs_irp_connect(struct irp_p *pvt) { + int flags; + struct sockaddr *addr; + struct sockaddr_in iaddr; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un uaddr; +#endif + long ipaddr; + const char *irphost; + int code; + char text[256]; + int socklen = 0; + + if (pvt->fdCxn != -1) { + perror("fd != 1"); + return (-1); + } + +#ifndef NO_SOCKADDR_UN + memset(&uaddr, 0, sizeof uaddr); +#endif + memset(&iaddr, 0, sizeof iaddr); + + irphost = getenv(IRPD_HOST_ENV); + if (irphost == NULL) { + irphost = "127.0.0.1"; + } + +#ifndef NO_SOCKADDR_UN + if (irphost[0] == '/') { + addr = (struct sockaddr *)&uaddr; + strncpy(uaddr.sun_path, irphost, sizeof uaddr.sun_path); + uaddr.sun_family = AF_UNIX; + socklen = SUN_LEN(&uaddr); +#ifdef HAVE_SA_LEN + uaddr.sun_len = socklen; +#endif + } else +#endif + { + if (inet_pton(AF_INET, irphost, &ipaddr) != 1) { + errno = EADDRNOTAVAIL; + perror("inet_pton"); + return (-1); + } + + addr = (struct sockaddr *)&iaddr; + socklen = sizeof iaddr; +#ifdef HAVE_SA_LEN + iaddr.sin_len = socklen; +#endif + iaddr.sin_family = AF_INET; + iaddr.sin_port = htons(IRPD_PORT); + iaddr.sin_addr.s_addr = ipaddr; + } + + + pvt->fdCxn = socket(addr->sa_family, SOCK_STREAM, PF_UNSPEC); + if (pvt->fdCxn < 0) { + perror("socket"); + return (-1); + } + + if (connect(pvt->fdCxn, addr, socklen) != 0) { + perror("connect"); + return (-1); + } + + flags = fcntl(pvt->fdCxn, F_GETFL, 0); + if (flags < 0) { + close(pvt->fdCxn); + perror("close"); + return (-1); + } + +#if 0 + flags |= O_NONBLOCK; + if (fcntl(pvt->fdCxn, F_SETFL, flags) < 0) { + close(pvt->fdCxn); + perror("fcntl"); + return (-1); + } +#endif + + code = irs_irp_read_response(pvt, text, sizeof text); + if (code != IRPD_WELCOME_CODE) { + if (irp_log_errors) { + syslog(LOG_WARNING, "Connection failed: %s", text); + } + irs_irp_disconnect(pvt); + return (-1); + } + + return (0); +} + + + +/* + * int irs_irp_is_connected(struct irp_p *pvt); + * + * Returns: + * + * Non-zero if streams are setup to remote. + * + */ + +int +irs_irp_is_connected(struct irp_p *pvt) { + return (pvt->fdCxn >= 0); +} + + + +/* + * void + * irs_irp_disconnect(struct irp_p *pvt); + * + * Closes streams to remote. + */ + +void +irs_irp_disconnect(struct irp_p *pvt) { + if (pvt->fdCxn != -1) { + close(pvt->fdCxn); + pvt->fdCxn = -1; + } +} + + + +int +irs_irp_read_line(struct irp_p *pvt, char *buffer, int len) { + char *realstart = &pvt->inbuffer[0]; + char *p, *start, *end; + int spare; + int i; + int buffpos = 0; + int left = len - 1; + + while (left > 0) { + start = p = &pvt->inbuffer[pvt->incurr]; + end = &pvt->inbuffer[pvt->inlast]; + + while (p != end && *p != '\n') + p++; + + if (p == end) { + /* Found no newline so shift data down if necessary + * and append new data to buffer + */ + if (start > realstart) { + memmove(realstart, start, end - start); + pvt->inlast = end - start; + start = realstart; + pvt->incurr = 0; + end = &pvt->inbuffer[pvt->inlast]; + } + + spare = sizeof (pvt->inbuffer) - pvt->inlast; + + p = end; + i = read(pvt->fdCxn, end, spare); + if (i < 0) { + close(pvt->fdCxn); + pvt->fdCxn = -1; + return (buffpos > 0 ? buffpos : -1); + } else if (i == 0) { + return (buffpos); + } + + end += i; + pvt->inlast += i; + + while (p != end && *p != '\n') + p++; + } + + if (p == end) { + /* full buffer and still no newline */ + i = sizeof pvt->inbuffer; + } else { + /* include newline */ + i = p - start + 1; + } + + if (i > left) + i = left; + memcpy(buffer + buffpos, start, i); + pvt->incurr += i; + buffpos += i; + buffer[buffpos] = '\0'; + + if (p != end) { + left = 0; + } else { + left -= i; + } + } + +#if 0 + fprintf(stderr, "read line: %s\n", buffer); +#endif + return (buffpos); +} + + + + + +/* + * int irp_read_response(struct irp_p *pvt); + * + * Returns: + * + * The number found at the beginning of the line read from + * FP. 0 on failure(0 is not a legal response code). The + * rest of the line is discarded. + * + */ + +int +irs_irp_read_response(struct irp_p *pvt, char *text, size_t textlen) { + char line[1024]; + int code; + char *p; + + if (irs_irp_read_line(pvt, line, sizeof line) <= 0) { + return (0); + } + + p = strchr(line, '\n'); + if (p == NULL) { + return (0); + } + + if (sscanf(line, "%d", &code) != 1) { + code = 0; + } else if (text != NULL && textlen > 0) { + p = line; + while (isspace(*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 > (int)sizeof(buffer) - 3) { + syslog(LOG_CRIT, "memory overrun in irs_irp_send_command()"); + exit(1); + } + strcat(buffer, "\r\n"); + todo = strlen(buffer); + + while (todo > 0) { + i = write(pvt->fdCxn, buffer + pos, todo); +#if 0 + /* XXX brister */ + fprintf(stderr, "Wrote: \""); + fwrite(buffer + pos, sizeof (char), todo, stderr); + fprintf(stderr, "\"\n"); +#endif + if (i < 0) { + close(pvt->fdCxn); + pvt->fdCxn = -1; + return (-1); + } + todo -= i; + } + 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/lib/bind/irs/irp_gr.c b/lib/bind/irs/irp_gr.c new file mode 100644 index 0000000000..1e2efa11de --- /dev/null +++ b/lib/bind/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 1.1 2001/03/29 06:31:48 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_gr_unneeded; +#else + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "irs_p.h" +#include "lcl_p.h" +#include "irp_p.h" + +#include "port_after.h" + + +/* Types. */ + +/* + * Module for the getnetgrent(3) family to use when connected to a + * remote irp daemon. + * + * See irpd.c for justification of caching done here. + * + */ + +struct pvt { + struct irp_p *girpdata; /* global IRP data */ + int warned; + struct group group; +}; + +/* Forward. */ + +static void gr_close(struct irs_gr *); +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static void gr_minimize(struct irs_gr *); + +/* Private */ +static void free_group(struct group *gr); + + +/* Public. */ + + + + + +/* + * struct irs_gr * irs_irp_gr(struct irs_acc *this) + * + * Notes: + * + * Initialize the group sub-module. + * + * Notes: + * + * Module data. + * + */ + +struct irs_gr * +irs_irp_gr(struct irs_acc *this) { + struct irs_gr *gr; + struct pvt *pvt; + + if (!(gr = memget(sizeof *gr))) { + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x0, sizeof *gr); + + if (!(pvt = memget(sizeof *pvt))) { + memput(gr, sizeof *gr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0x0, sizeof *pvt); + pvt->girpdata = this->private; + + gr->private = pvt; + gr->close = gr_close; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->list = make_group_list; + gr->minimize = gr_minimize; + return (gr); +} + +/* Methods. */ + + + +/* + * void gr_close(struct irs_gr *this) + * + * Notes: + * + * Close the sub-module. + * + */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + gr_minimize(this); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + + +/* + * struct group * gr_next(struct irs_gr *this) + * + * Notes: + * + * Gets the next group out of the cached data and returns it. + * + */ + +static struct group * +gr_next(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct group *gr = &pvt->group; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getgrent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + if (irp_log_errors) { + syslog(LOG_WARNING, "getgrent failed: %s", text); + } + return (NULL); + } + + if (code == IRPD_GETGROUP_OK) { + free_group(gr); + if (irp_unmarshall_gr(gr, body) != 0) { + gr = NULL; + } + } else { + gr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (gr); +} + + + + + +/* + * struct group * gr_byname(struct irs_gr *this, const char *name) + * + * Notes: + * + * Gets a group by name from irpd and returns it. + * + */ + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct group *gr = &pvt->group; + char *body; + size_t bodylen; + int code; + char text[256]; + + + if (gr->gr_name != NULL && strcmp(name, gr->gr_name) == 0) { + return (gr); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getgrnam %s", name) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETGROUP_OK) { + free_group(gr); + if (irp_unmarshall_gr(gr, body) != 0) { + gr = NULL; + } + } else { + gr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (gr); +} + + + + + +/* + * struct group * gr_bygid(struct irs_gr *this, gid_t gid) + * + * Notes: + * + * Gets a group by gid from irpd and returns it. + * + */ + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + struct pvt *pvt = (struct pvt *)this->private; + struct group *gr = &pvt->group; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (gr->gr_name != NULL && (gid_t)gr->gr_gid == gid) { + return (gr); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getgrgid %d", gid) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETGROUP_OK) { + free_group(gr); + if (irp_unmarshall_gr(gr, body) != 0) { + gr = NULL; + } + } else { + gr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (gr); +} + + + + +/* + * void gr_rewind(struct irs_gr *this) + * + */ + +static void +gr_rewind(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "setgrent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETGROUP_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setgrent failed: %s", text); + } + } + + return; +} + + + + +/* + * void gr_minimize(struct irs_gr *this) + * + * Notes: + * + * Frees up cached data and disconnects(if necessary) from the remote. + * + */ + +static void +gr_minimize(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + free_group(&pvt->group); + irs_irp_disconnect(pvt->girpdata); +} + +/* Private. */ + + + +/* + * static void free_group(struct group *gr); + * + * Deallocate all the memory irp_unmarshall_gr allocated. + * + */ + +static void +free_group(struct group *gr) { + char **p; + + if (gr == NULL) + return; + + if (gr->gr_name != NULL) + free(gr->gr_name); + + if (gr->gr_passwd != NULL) + free(gr->gr_passwd); + + for (p = gr->gr_mem ; p != NULL && *p != NULL ; p++) + free(*p); + + if (p != NULL) + free(p); +} + + +#endif /* WANT_IRS_GR */ diff --git a/lib/bind/irs/irp_ho.c b/lib/bind/irs/irp_ho.c new file mode 100644 index 0000000000..6556b8f76b --- /dev/null +++ b/lib/bind/irs/irp_ho.c @@ -0,0 +1,429 @@ +/* + * Portions Copyright (c) 1996,1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irp_ho.c,v 1.1 2001/03/29 06:31:49 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "irs_p.h" +#include "dns_p.h" +#include "irp_p.h" + +#include "port_after.h" + +/* Definitions. */ + +#define MAXALIASES 35 +#define MAXADDRS 35 +#define Max(a,b) ((a) > (b) ? (a) : (b)) + + +struct pvt { + struct irp_p *girpdata; + int warned; + struct hostent host; +}; + +/* Forward. */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); + +static void free_host(struct hostent *ho); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +/* Public. */ + + + +/* + * struct irs_ho * irs_irp_ho(struct irs_acc *this) + * + * Notes: + * + * Initializes the irp_ho module. + * + */ + +struct irs_ho * +irs_irp_ho(struct irs_acc *this) { + struct irs_ho *ho; + struct pvt *pvt; + + if (!(ho = memget(sizeof *ho))) { + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x0, sizeof *ho); + + if (!(pvt = memget(sizeof *pvt))) { + memput(ho, sizeof *ho); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->addrinfo = ho_addrinfo; + + return (ho); +} + +/* Methods. */ + + + +/* + * void ho_close(struct irs_ho *this) + * + * Notes: + * + * Closes down the module. + * + */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + + free_host(&pvt->host); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + +/* + * struct hostent * ho_byname(struct irs_ho *this, const char *name) + * + */ + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + return (ho_byname2(this, name, AF_INET)); +} + + + + + +/* + * struct hostent * ho_byname2(struct irs_ho *this, const char *name, int af) + * + */ + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *ho = &pvt->host; + char *body = NULL; + size_t bodylen; + int code; + char text[256]; + + if (ho->h_name != NULL && + strcmp(name, ho->h_name) == 0 && + af == ho->h_addrtype) { + return (ho); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "gethostbyname2 %s %s", + name, ADDR_T_STR(af)) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETHOST_OK) { + free_host(ho); + if (irp_unmarshall_ho(ho, body) != 0) { + ho = NULL; + } + } else { + ho = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (ho); +} + + + +/* + * struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + * int len, int af) + * + */ + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *ho = &pvt->host; + char *body = NULL; + size_t bodylen; + int code; + char **p; + char paddr[MAXPADDRSIZE]; + char text[256]; + + if (ho->h_name != NULL && + af == ho->h_addrtype && + len == ho->h_length) { + for (p = ho->h_addr_list ; *p != NULL ; p++) { + if (memcmp(*p, addr, len) == 0) + return (ho); + } + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (inet_ntop(af, addr, paddr, sizeof paddr) == NULL) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "gethostbyaddr %s %s", + paddr, ADDR_T_STR(af)) != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETHOST_OK) { + free_host(ho); + if (irp_unmarshall_ho(ho, body) != 0) { + ho = NULL; + } + } else { + ho = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (ho); +} + + + + + +/* + * struct hostent * ho_next(struct irs_ho *this) + * + * Notes: + * + * The implementation for gethostent(3). The first time it's + * called all the data is pulled from the remote(i.e. what + * the maximum number of gethostent(3) calls would return) + * and that data is cached. + * + */ + +static struct hostent * +ho_next(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *ho = &pvt->host; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "gethostent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETHOST_OK) { + free_host(ho); + if (irp_unmarshall_ho(ho, body) != 0) { + ho = NULL; + } + } else { + ho = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (ho); +} + + + + + +/* + * void ho_rewind(struct irs_ho *this) + * + */ + +static void +ho_rewind(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "sethostent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETHOST_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "sethostent failed: %s", text); + } + } + + return; +} + + + + +/* + * void ho_minimize(struct irs_ho *this) + * + */ + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + free_host(&pvt->host); + + irs_irp_disconnect(pvt->girpdata); +} + + + + +/* + * void free_host(struct hostent *ho) + * + */ + +static void +free_host(struct hostent *ho) { + char **p; + + if (ho == NULL) { + return; + } + + if (ho->h_name != NULL) + free(ho->h_name); + + if (ho->h_aliases != NULL) { + for (p = ho->h_aliases ; *p != NULL ; p++) + free(*p); + free(ho->h_aliases); + } + + if (ho->h_addr_list != NULL) { + for (p = ho->h_addr_list ; *p != NULL ; p++) + free(*p); + free(ho->h_addr_list); + } +} + +/* dummy */ +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + UNUSED(this); + UNUSED(name); + UNUSED(pai); + return(NULL); +} diff --git a/lib/bind/irs/irp_ng.c b/lib/bind/irs/irp_ng.c new file mode 100644 index 0000000000..86192ec78a --- /dev/null +++ b/lib/bind/irs/irp_ng.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: irp_ng.c,v 1.1 2001/03/29 06:31:49 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "irs_p.h" +#include "irp_p.h" + +#include "port_after.h" + +/* Definitions */ + +struct pvt { + struct irp_p *girpdata; + int warned; +}; + + +/* Forward */ + +static void ng_rewind(struct irs_ng *, const char*); +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, const char **, + const char **); +static int ng_test(struct irs_ng *, const char *, + const char *, const char *, + const char *); +static void ng_minimize(struct irs_ng *); + + +/* Public */ + + + +/* + * struct irs_ng * irs_irp_ng(struct irs_acc *this) + * + * Notes: + * + * Intialize the irp netgroup module. + * + */ + +struct irs_ng * +irs_irp_ng(struct irs_acc *this) { + struct irs_ng *ng; + struct pvt *pvt; + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + + if (!(pvt = memget(sizeof *pvt))) { + memput(ng, sizeof *ng); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + ng->private = pvt; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods */ + + + +/* + * void ng_close(struct irs_ng *this) + * + */ + +static void +ng_close(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ng_minimize(this); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + + +/* + * void ng_rewind(struct irs_ng *this, const char *group) + * + * + */ + +static void +ng_rewind(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, + "setnetgrent %s", group) != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETNETGR_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setnetgrent(%s) failed: %s", + group, text); + } + } + + return; +} + + + + +/* + * int ng_next(struct irs_ng *this, const char **host, const char **user, + * const char **domain) + * + * Notes: + * + * Get the next netgroup item from the cache. + * + */ + +static int +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + int code; + char *body = NULL; + size_t bodylen; + int rval = 0; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (0); + } + + if (irs_irp_send_command(pvt->girpdata, "getnetgrent") != 0) + return (0); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (0); + } + + if (code == IRPD_GETNETGR_OK) { + if (irp_unmarshall_ng(host, user, domain, body) == 0) { + rval = 1; + } + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (rval); +} + + + +/* + * int ng_test(struct irs_ng *this, const char *name, const char *host, + * const char *user, const char *domain) + * + * Notes: + * + * Search for a match in a netgroup. + * + */ + +static int +ng_test(struct irs_ng *this, const char *name, + const char *host, const char *user, const char *domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + char *body = NULL; + size_t bodylen = 0; + int code; + char text[256]; + int rval = 0; + + UNUSED(name); + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (0); + } + + if (irp_marshall_ng(host, user, domain, &body, &bodylen) != 0) { + return (0); + } + + if (irs_irp_send_command(pvt->girpdata, "innetgr %s", body) == 0) { + memput(body, bodylen); + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code == IRPD_GETNETGR_MATCHES) { + rval = 1; + } + } + + return (rval); +} + + + + +/* + * void ng_minimize(struct irs_ng *this) + * + */ + +static void +ng_minimize(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + + + + +/* Private */ + diff --git a/lib/bind/irs/irp_nw.c b/lib/bind/irs/irp_nw.c new file mode 100644 index 0000000000..9255557adb --- /dev/null +++ b/lib/bind/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 1.1 2001/03/29 06:31:49 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#if 0 + +#endif + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "irs_p.h" +#include "lcl_p.h" +#include "irp_p.h" + +#include "port_after.h" + +#define MAXALIASES 35 +#define MAXADDRSIZE 4 + +struct pvt { + struct irp_p *girpdata; + int warned; + struct nwent net; +}; + +/* Forward */ + +static void nw_close(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static struct nwent * nw_next(struct irs_nw *); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); + +static void free_nw(struct nwent *nw); + + +/* Public */ + + + +/* + * struct irs_nw * irs_irp_nw(struct irs_acc *this) + * + */ + +struct irs_nw * +irs_irp_nw(struct irs_acc *this) { + struct irs_nw *nw; + struct pvt *pvt; + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x0, sizeof *nw); + pvt->girpdata = this->private; + + nw->private = pvt; + nw->close = nw_close; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->next = nw_next; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + return (nw); +} + +/* Methods */ + + + +/* + * void nw_close(struct irs_nw *this) + * + */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + + free_nw(&pvt->net); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + + +/* + * struct nwent * nw_byaddr(struct irs_nw *this, void *net, + * int length, int type) + * + */ + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int length, int type) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *nw = &pvt->net; + char *body = NULL; + size_t bodylen; + int code; + char paddr[24]; /* bigenough for ip4 w/ cidr spec. */ + char text[256]; + + if (inet_net_ntop(type, net, length, paddr, sizeof paddr) == NULL) { + return (NULL); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getnetbyaddr %s %s", + paddr, ADDR_T_STR(type)) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETNET_OK) { + free_nw(nw); + if (irp_unmarshall_nw(nw, body) != 0) { + nw = NULL; + } + } else { + nw = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (nw); +} + + + + +/* + * struct nwent * nw_byname(struct irs_nw *this, const char *name, int type) + * + */ + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int type) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *nw = &pvt->net; + char *body = NULL; + size_t bodylen; + int code; + char text[256]; + + if (nw->n_name != NULL && + strcmp(name, nw->n_name) == 0 && + nw->n_addrtype == type) { + return (nw); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getnetbyname %s", name) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETNET_OK) { + free_nw(nw); + if (irp_unmarshall_nw(nw, body) != 0) { + nw = NULL; + } + } else { + nw = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (nw); +} + + + + +/* + * void nw_rewind(struct irs_nw *this) + * + */ + +static void +nw_rewind(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "setnetent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETNET_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setnetent failed: %s", text); + } + } + + return; +} + + + + + + +/* + * struct nwent * nw_next(struct irs_nw *this) + * + * Notes: + * + * Prepares the cache if necessary and returns the first, or + * next item from it. + */ + +static struct nwent * +nw_next(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *nw = &pvt->net; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getnetent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETNET_OK) { + free_nw(nw); + if (irp_unmarshall_nw(nw, body) != 0) { + nw = NULL; + } + } else { + nw = NULL; + } + + return (nw); +} + + + + + + +/* + * void nw_minimize(struct irs_nw *this) + * + */ + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + + + + +/* private. */ + + + +/* + * static void free_passwd(struct passwd *pw); + * + * deallocate all the memory irp_unmarshall_pw allocated. + * + */ + +static void +free_nw(struct nwent *nw) { + char **p; + + if (nw == NULL) + return; + + if (nw->n_name != NULL) + free(nw->n_name); + + if (nw->n_aliases != NULL) { + for (p = nw->n_aliases ; *p != NULL ; p++) { + free(*p); + } + free(nw->n_aliases); + } + + if (nw->n_addr != NULL) + free(nw->n_addr); +} diff --git a/lib/bind/irs/irp_p.h b/lib/bind/irs/irp_p.h new file mode 100644 index 0000000000..5fa881b7ac --- /dev/null +++ b/lib/bind/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 1.1 2001/03/29 06:31:49 marka Exp $ + */ + +#ifndef _IRP_P_H_INCLUDED +#define _IRP_P_H_INCLUDED + +#include + +struct irp_p { + char inbuffer[1024]; + int inlast; /* index of one past the last char in buffer */ + int incurr; /* index of the next char to be read from buffer */ + + int fdCxn; +}; + +/* + * Externs. + */ + +extern struct irs_acc * irs_irp_acc __P((const char *)); +extern struct irs_gr * irs_irp_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_irp_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_irp_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_irp_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_irp_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_irp_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_irp_ng __P((struct irs_acc *)); + +int irs_irp_connect(struct irp_p *pvt); +int irs_irp_is_connected(struct irp_p *pvt); +void irs_irp_disconnect(struct irp_p *pvt); +int irs_irp_read_response(struct irp_p *pvt, char *text, size_t textlen); +char *irs_irp_read_body(struct irp_p *pvt, size_t *size); +int irs_irp_get_full_response(struct irp_p *pvt, int *code, + char *text, size_t textlen, + char **body, size_t *bodylen); +int irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...); + + +extern int irp_log_errors; + +#endif diff --git a/lib/bind/irs/irp_pr.c b/lib/bind/irs/irp_pr.c new file mode 100644 index 0000000000..8b9e9a95d6 --- /dev/null +++ b/lib/bind/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 1.1 2001/03/29 06:31:49 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "irs_p.h" +#include "lcl_p.h" +#include "irp_p.h" + +#include "port_after.h" + + +#define MAXALIASES 35 + +/* Types */ + +struct pvt { + struct irp_p *girpdata; + int warned; + struct protoent proto; +}; + +/* Forward */ + +static void pr_close(struct irs_pr *); +static struct protoent * pr_next(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); + +static void free_proto(struct protoent *pr); + +/* Public */ + + + +/* + * struct irs_pr * irs_irp_pr(struct irs_acc *this) + * + */ + +struct irs_pr * +irs_irp_pr(struct irs_acc *this) { + struct irs_pr *pr; + struct pvt *pvt; + + if (!(pr = memget(sizeof *pr))) { + errno = ENOMEM; + return (NULL); + } + memset(pr, 0x0, sizeof *pr); + + if (!(pvt = memget(sizeof *pvt))) { + memput(pr, sizeof *pr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + pr->private = pvt; + pr->close = pr_close; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->next = pr_next; + pr->rewind = pr_rewind; + pr->minimize = pr_minimize; + return (pr); +} + +/* Methods */ + + + +/* + * void pr_close(struct irs_pr *this) + * + */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pr_minimize(this); + + free_proto(&pvt->proto); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + +/* + * struct protoent * pr_byname(struct irs_pr *this, const char *name) + * + */ + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *pr = &pvt->proto; + char *body = NULL; + size_t bodylen; + int code; + int i; + char text[256]; + + if (pr->p_name != NULL && strcmp(name, pr->p_name) == 0) { + return (pr); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + i = irs_irp_send_command(pvt->girpdata, "getprotobyname %s", name); + if (i != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETPROTO_OK) { + free_proto(pr); + if (irp_unmarshall_pr(pr, body) != 0) { + pr = NULL; + } + } else { + pr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pr); +} + + + +/* + * struct protoent * pr_bynumber(struct irs_pr *this, int proto) + * + */ + +static struct protoent * +pr_bynumber(struct irs_pr *this, int proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *pr = &pvt->proto; + char *body = NULL; + size_t bodylen; + int code; + int i; + char text[256]; + + if (pr->p_name != NULL && proto == pr->p_proto) { + return (pr); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + i = irs_irp_send_command(pvt->girpdata, "getprotobynumber %d", proto); + if (i != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETPROTO_OK) { + free_proto(pr); + if (irp_unmarshall_pr(pr, body) != 0) { + pr = NULL; + } + } else { + pr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pr); +} + + + + +/* + * void pr_rewind(struct irs_pr *this) + * + */ + +static void +pr_rewind(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "setprotoent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETPROTO_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setprotoent failed: %s", text); + } + } + + return; +} + + + + +/* + * struct protoent * pr_next(struct irs_pr *this) + * + * Notes: + * + * Prepares the cache if necessary and returns the next item in it. + * + */ + +static struct protoent * +pr_next(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *pr = &pvt->proto; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getprotoent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETPROTO_OK) { + free_proto(pr); + if (irp_unmarshall_pr(pr, body) != 0) { + pr = NULL; + } + } else { + pr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pr); +} + + + + +/* + * void pr_minimize(struct irs_pr *this) + * + */ + +static void +pr_minimize(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + + + + + + +/* + * static void free_proto(struct protoent *pw); + * + * Deallocate all the memory irp_unmarshall_pr allocated. + * + */ + +static void +free_proto(struct protoent *pr) { + char **p; + + if (pr == NULL) + return; + + if (pr->p_name != NULL) + free(pr->p_name); + + for (p = pr->p_aliases ; p != NULL && *p != NULL ; p++) + free(*p); +} diff --git a/lib/bind/irs/irp_pw.c b/lib/bind/irs/irp_pw.c new file mode 100644 index 0000000000..567ef24a10 --- /dev/null +++ b/lib/bind/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 1.1 2001/03/29 06:31:49 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Extern */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_pw_unneeded; +#else + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "irp_p.h" + + +/* Types */ + +struct pvt { + struct irp_p *girpdata; /* global IRP data */ + int warned; + struct passwd passwd; /* password structure */ +}; + +/* Forward */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_next(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); + +static void free_passwd(struct passwd *pw); + +/* Public */ +struct irs_pw * +irs_irp_pw(struct irs_acc *this) { + struct irs_pw *pw; + struct pvt *pvt; + + if (!(pw = memget(sizeof *pw))) { + errno = ENOMEM; + return (NULL); + } + memset(pw, 0, sizeof *pw); + + if (!(pvt = memget(sizeof *pvt))) { + memput(pw, sizeof *pw); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + pw->private = pvt; + pw->close = pw_close; + pw->next = pw_next; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + + return (pw); +} + +/* Methods */ + + + +/* + * void pw_close(struct irs_pw *this) + * + */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pw_minimize(this); + + free_passwd(&pvt->passwd); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + + +/* + * struct passwd * pw_next(struct irs_pw *this) + * + */ + +static struct passwd * +pw_next(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct passwd *pw = &pvt->passwd; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getpwent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETUSER_OK) { + free_passwd(pw); + if (irp_unmarshall_pw(pw, body) != 0) { + pw = NULL; + } + } else { + pw = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pw); +} + + + + +/* + * struct passwd * pw_byname(struct irs_pw *this, const char *name) + * + */ + +static struct passwd * +pw_byname(struct irs_pw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct passwd *pw = &pvt->passwd; + char *body = NULL; + char text[256]; + size_t bodylen; + int code; + + if (pw->pw_name != NULL && strcmp(name, pw->pw_name) == 0) { + return (pw); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getpwnam %s", name) != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETUSER_OK) { + free_passwd(pw); + if (irp_unmarshall_pw(pw, body) != 0) { + pw = NULL; + } + } else { + pw = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pw); +} + + + + +/* + * struct passwd * pw_byuid(struct irs_pw *this, uid_t uid) + * + */ + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + struct pvt *pvt = (struct pvt *)this->private; + char *body; + char text[256]; + size_t bodylen; + int code; + struct passwd *pw = &pvt->passwd; + + if (pw->pw_name != NULL && pw->pw_uid == uid) { + return (pw); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getpwuid %d", uid) != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETUSER_OK) { + free_passwd(pw); + if (irp_unmarshall_pw(pw, body) != 0) { + pw = NULL; + } + } else { + pw = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pw); +} + + + + +/* + * void pw_rewind(struct irs_pw *this) + * + */ + +static void +pw_rewind(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "setpwent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETUSER_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setpwent failed: %s", text); + } + } + + return; +} + + +/* + * void pw_minimize(struct irs_pw *this) + * + */ + +static void +pw_minimize(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + + +/* Private. */ + + + +/* + * static void free_passwd(struct passwd *pw); + * + * Deallocate all the memory irp_unmarshall_pw allocated. + * + */ + +static void +free_passwd(struct passwd *pw) { + if (pw == NULL) + return; + + if (pw->pw_name != NULL) + free(pw->pw_name); + + if (pw->pw_passwd != NULL) + free(pw->pw_passwd); + + 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/lib/bind/irs/irp_sv.c b/lib/bind/irs/irp_sv.c new file mode 100644 index 0000000000..4f14b87b48 --- /dev/null +++ b/lib/bind/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 1.1 2001/03/29 06:31:49 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#include +#include +#include + +#ifdef IRS_LCL_SV_DB +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "irs_p.h" +#include "lcl_p.h" +#include "irp_p.h" + +#include "port_after.h" + +/* Types */ + +struct pvt { + struct irp_p *girpdata; + int warned; + struct servent service; +}; + +/* Forward */ + +static void sv_close(struct irs_sv*); +static struct servent * sv_next(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, const char *, + const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); + +static void free_service(struct servent *sv); + + + +/* Public */ + + + +/* + * struct irs_sv * irs_irp_sv(struct irs_acc *this) + * + */ + +struct irs_sv * +irs_irp_sv(struct irs_acc *this) { + struct irs_sv *sv; + struct pvt *pvt; + + if ((sv = memget(sizeof *sv)) == NULL) { + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x0, sizeof *sv); + + if ((pvt = memget(sizeof *pvt)) == NULL) { + memput(sv, sizeof *sv); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + sv->private = pvt; + sv->close = sv_close; + sv->next = sv_next; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->rewind = sv_rewind; + sv->minimize = sv_minimize; + + return (sv); +} + +/* Methods */ + + + +/* + * void sv_close(struct irs_sv *this) + * + */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + sv_minimize(this); + + free_service(&pvt->service); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + + +/* + * struct servent * sv_next(struct irs_sv *this) + * + * Notes: + * + * Fills the cache if necessary and returns the next item from it. + * + */ + +static struct servent * +sv_next(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *sv = &pvt->service; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getservent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETSERVICE_OK) { + free_service(sv); + if (irp_unmarshall_sv(sv, body) != 0) { + sv = NULL; + } + } else { + sv = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (sv); +} + + + + +/* + * struct servent * sv_byname(struct irs_sv *this, const char *name, + * const char *proto) + * + */ + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *sv = &pvt->service; + char *body; + char text[256]; + size_t bodylen; + int code; + + if (sv->s_name != NULL && + strcmp(name, sv->s_name) == 0 && + strcasecmp(proto, sv->s_proto) == 0) { + return (sv); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getservbyname %s %s", + name, proto) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETSERVICE_OK) { + free_service(sv); + if (irp_unmarshall_sv(sv, body) != 0) { + sv = NULL; + } + } else { + sv = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (sv); +} + + + + +/* + * struct servent * sv_byport(struct irs_sv *this, int port, + * const char *proto) + * + */ + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *sv = &pvt->service; + char *body; + size_t bodylen; + char text[256]; + int code; + + if (sv->s_name != NULL && + port == sv->s_port && + strcasecmp(proto, sv->s_proto) == 0) { + return (sv); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getservbyport %d %s", + ntohs((short)port), proto) != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETSERVICE_OK) { + free_service(sv); + if (irp_unmarshall_sv(sv, body) != 0) { + sv = NULL; + } + } else { + sv = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (sv); +} + + + + + +/* + * void sv_rewind(struct irs_sv *this) + * + */ + +static void +sv_rewind(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "setservent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETSERVICE_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setservent failed: %s", text); + } + } + + return; +} + + + + + +/* + * void sv_minimize(struct irs_sv *this) + * + */ + +static void +sv_minimize(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + + + + + + +static void +free_service(struct servent *sv) { + char **p; + + if (sv == NULL) { + return; + } + + if (sv->s_name != NULL) { + free(sv->s_name); + } + + for (p = sv->s_aliases ; p != NULL && *p != NULL ; p++) { + free(*p); + } + + if (sv->s_proto != NULL) { + free(sv->s_proto); + } +} + + diff --git a/lib/bind/irs/irpmarshall.c b/lib/bind/irs/irpmarshall.c new file mode 100644 index 0000000000..d8d8ffa0f0 --- /dev/null +++ b/lib/bind/irs/irpmarshall.c @@ -0,0 +1,2344 @@ +/* + * Copyright(c) 1989, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irpmarshall.c,v 1.1 2001/03/29 06:31:50 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#if 0 + +Check values are in approrpriate endian order. + +Double check memory allocations on unmarhsalling + +#endif + + +/* Extern */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "port_after.h" + + +#ifndef HAVE_STRNDUP +static char *strndup(const char *str, size_t len); +#endif + +static char **splitarray(const char *buffer, const char *buffend, char delim); +static int joinarray(char * const * argv, char *buffer, char delim); +static char *getfield(char **res, size_t reslen, char **buffer, char delim); +static size_t joinlength(char * const *argv); +static void free_array(char **argv, size_t entries); + +#define ADDR_T_STR(x) (x == AF_INET ? "AF_INET" :\ + (x == AF_INET6 ? "AF_INET6" : "UNKNOWN")) + +#define MAXPADDRSIZE (sizeof "255.255.255.255" + 1) + +static char COMMA = ','; + +static const char *COMMASTR = ","; +static const char *COLONSTR = ":"; + + + +/* See big comment at bottom of irpmarshall.h for description. */ + + +#ifdef WANT_IRS_PW +/* +++++++++++++++++++++++++ struct passwd +++++++++++++++++++++++++ */ + + +/* + * int irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len) + * + * notes: + * + * See above + * + * return: + * + * 0 on sucess, -1 on failure. + * + */ + +int +irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len) { + size_t need = 1 ; /* for null byte */ + char pwUid[24]; + char pwGid[24]; + char pwChange[24]; + char pwExpire[24]; + const char *pwClass; + const char *fieldsep = COLONSTR; + + if (pw == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + sprintf(pwUid, "%ld", (long)pw->pw_uid); + sprintf(pwGid, "%ld", (long)pw->pw_gid); + +#ifdef HAVE_PW_CHANGE + sprintf(pwChange, "%ld", (long)pw->pw_change); +#else + pwChange[0] = '0'; + pwChange[1] = '\0'; +#endif + +#ifdef HAVE_PW_EXPIRE + sprintf(pwExpire, "%ld", (long)pw->pw_expire); +#else + pwExpire[0] = '0'; + pwExpire[1] = '\0'; +#endif + +#ifdef HAVE_PW_CLASS + pwClass = pw->pw_class; +#else + pwClass = ""; +#endif + + need += strlen(pw->pw_name) + 1; /* one for fieldsep */ + need += strlen(pw->pw_passwd) + 1; + need += strlen(pwUid) + 1; + need += strlen(pwGid) + 1; + need += strlen(pwClass) + 1; + need += strlen(pwChange) + 1; + need += strlen(pwExpire) + 1; + need += strlen(pw->pw_gecos) + 1; + need += strlen(pw->pw_dir) + 1; + need += strlen(pw->pw_shell) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, pw->pw_name); strcat(*buffer, fieldsep); + strcat(*buffer, pw->pw_passwd); strcat(*buffer, fieldsep); + strcat(*buffer, pwUid); strcat(*buffer, fieldsep); + strcat(*buffer, pwGid); strcat(*buffer, fieldsep); + strcat(*buffer, pwClass); strcat(*buffer, fieldsep); + strcat(*buffer, pwChange); strcat(*buffer, fieldsep); + strcat(*buffer, pwExpire); strcat(*buffer, fieldsep); + strcat(*buffer, pw->pw_gecos); strcat(*buffer, fieldsep); + strcat(*buffer, pw->pw_dir); strcat(*buffer, fieldsep); + strcat(*buffer, pw->pw_shell); strcat(*buffer, fieldsep); + + return (0); +} + + + + + +/* + * int irp_unmarshall_pw(struct passwd *pw, char *buffer) + * + * notes: + * + * see above + * + * return: + * + * 0 on success, -1 on failure + * + */ + +int +irp_unmarshall_pw(struct passwd *pw, char *buffer) { + char *name, *pass, *class, *gecos, *dir, *shell; + uid_t pwuid; + gid_t pwgid; + time_t pwchange; + time_t pwexpire; + char *p; + long t; + char tmpbuf[24]; + char *tb = &tmpbuf[0]; + char fieldsep = ':'; + int myerrno = EINVAL; + + name = pass = class = gecos = dir = shell = NULL; + p = buffer; + + /* pw_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + /* pw_passwd field */ + pass = NULL; + if (getfield(&pass, 0, &p, fieldsep) == NULL) { /* field can be empty */ + goto error; + } + + + /* pw_uid field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + pwuid = (uid_t)t; + if ((long) pwuid != t) { /* value must have been too big. */ + goto error; + } + + + + /* pw_gid field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + pwgid = (gid_t)t; + if ((long)pwgid != t) { /* value must have been too big. */ + goto error; + } + + + + /* pw_class field */ + class = NULL; + if (getfield(&class, 0, &p, fieldsep) == NULL) { + goto error; + } + + + + /* pw_change field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + pwchange = (time_t)t; + if ((long)pwchange != t) { /* value must have been too big. */ + goto error; + } + + + + /* pw_expire field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + pwexpire = (time_t)t; + if ((long) pwexpire != t) { /* value must have been too big. */ + goto error; + } + + + + /* pw_gecos field */ + gecos = NULL; + if (getfield(&gecos, 0, &p, fieldsep) == NULL) { + goto error; + } + + + + /* pw_dir field */ + dir = NULL; + if (getfield(&dir, 0, &p, fieldsep) == NULL) { + goto error; + } + + + + /* pw_shell field */ + shell = NULL; + if (getfield(&shell, 0, &p, fieldsep) == NULL) { + goto error; + } + + + + pw->pw_name = name; + pw->pw_passwd = pass; + pw->pw_uid = pwuid; + pw->pw_gid = pwgid; + pw->pw_gecos = gecos; + pw->pw_dir = dir; + pw->pw_shell = shell; + +#ifdef HAVE_PW_CHANGE + pw->pw_change = pwchange; +#endif +#ifdef HAVE_PW_CLASS + pw->pw_class = class; +#endif +#ifdef HAVE_PW_EXPIRE + pw->pw_expire = pwexpire; +#endif + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + if (pass != NULL) free(pass); + if (gecos != NULL) free(gecos); + if (dir != NULL) free(dir); + if (shell != NULL) free(shell); + + return (-1); +} + +/* ------------------------- struct passwd ------------------------- */ +#endif /* WANT_IRS_PW */ + + + +/* +++++++++++++++++++++++++ struct group +++++++++++++++++++++++++ */ + + + +/* + * int irp_marshall_gr(const struct group *gr, char **buffer, size_t *len) + * + * notes: + * + * see above. + * + * return: + * + * 0 on success, -1 on failure + */ + +int +irp_marshall_gr(const struct group *gr, char **buffer, size_t *len) { + size_t need = 1; /* for null byte */ + char grGid[24]; + const char *fieldsep = COLONSTR; + + if (gr == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + sprintf(grGid, "%ld", (long)gr->gr_gid); + + need += strlen(gr->gr_name) + 1; +#ifndef MISSING_GR_PASSWD + need += strlen(gr->gr_passwd) + 1; +#else + need++; +#endif + need += strlen(grGid) + 1; + need += joinlength(gr->gr_mem) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, gr->gr_name); strcat(*buffer, fieldsep); +#ifndef MISSING_GR_PASSWD + strcat(*buffer, gr->gr_passwd); +#endif + strcat(*buffer, fieldsep); + strcat(*buffer, grGid); strcat(*buffer, fieldsep); + joinarray(gr->gr_mem, *buffer, COMMA) ; strcat(*buffer, fieldsep); + + return (0); +} + + + + +/* + * int irp_unmarshall_gr(struct group *gr, char *buffer) + * + * notes: + * + * see above + * + * return: + * + * 0 on success and -1 on failure. + * + */ + +int +irp_unmarshall_gr(struct group *gr, char *buffer) { + char *p, *q; + gid_t grgid; + long t; + char *name = NULL; + char *pass = NULL; + char **members = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (gr == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + p = buffer; + + /* gr_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + + /* gr_passwd field */ + pass = NULL; + if (getfield(&pass, 0, &p, fieldsep) == NULL) { + goto error; + } + + + /* gr_gid field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + grgid = (gid_t)t; + if ((long) grgid != t) { /* value must have been too big. */ + goto error; + } + + + /* gr_mem field. Member names are separated by commas */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + members = splitarray(p, q, COMMA); + if (members == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + gr->gr_name = name; +#ifndef MISSING_GR_PASSWD + gr->gr_passwd = pass; +#endif + gr->gr_gid = grgid; + gr->gr_mem = members; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + if (pass != NULL) free(pass); + + return (-1); +} + + +/* ------------------------- struct group ------------------------- */ + + + + +/* +++++++++++++++++++++++++ struct servent +++++++++++++++++++++++++ */ + + + +/* + * int irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len) + * + * notes: + * + * see above + * + * return: + * + * 0 on success, -1 on failure. + * + */ + +int +irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len) { + size_t need = 1; /* for null byte */ + char svPort[24]; + const char *fieldsep = COLONSTR; + short realport; + + if (sv == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + /* the int s_port field is actually a short in network order. We + want host order to make the marshalled data look correct */ + realport = ntohs((short)sv->s_port); + sprintf(svPort, "%d", realport); + + need += strlen(sv->s_name) + 1; + need += joinlength(sv->s_aliases) + 1; + need += strlen(svPort) + 1; + need += strlen(sv->s_proto) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, sv->s_name); strcat(*buffer, fieldsep); + joinarray(sv->s_aliases, *buffer, COMMA); strcat(*buffer, fieldsep); + strcat(*buffer, svPort); strcat(*buffer, fieldsep); + strcat(*buffer, sv->s_proto); strcat(*buffer, fieldsep); + + return (0); +} + + + + + +/* + * int irp_unmarshall_sv(struct servent *sv, char *buffer) + * + * notes: + * + * see above + * + * return: + * + * 0 on success, -1 on failure. + * + */ + +int +irp_unmarshall_sv(struct servent *sv, char *buffer) { + char *p, *q; + short svport; + long t; + char *name = NULL; + char *proto = NULL; + char **aliases = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (sv == NULL || buffer == NULL) + return (-1); + + p = buffer; + + + /* s_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + + /* s_aliases field */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* s_port field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + svport = (short)t; + if ((long) svport != t) { /* value must have been too big. */ + goto error; + } + svport = htons(svport); + + /* s_proto field */ + proto = NULL; + if (getfield(&proto, 0, &p, fieldsep) == NULL) { + goto error; + } + + sv->s_name = name; + sv->s_aliases = aliases; + sv->s_port = svport; + sv->s_proto = proto; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + if (proto != NULL) free(proto); + free_array(aliases, 0); + + return (-1); +} + + +/* ------------------------- struct servent ------------------------- */ + +/* +++++++++++++++++++++++++ struct protoent +++++++++++++++++++++++++ */ + + + +/* + * int irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len) + * + * notes: + * + * see above + * + * return: + * + * 0 on success and -1 on failure. + * + */ + +int +irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len) { + size_t need = 1; /* for null byte */ + char prProto[24]; + const char *fieldsep = COLONSTR; + + if (pr == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + sprintf(prProto, "%d", (int)pr->p_proto); + + need += strlen(pr->p_name) + 1; + need += joinlength(pr->p_aliases) + 1; + need += strlen(prProto) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, pr->p_name); strcat(*buffer, fieldsep); + joinarray(pr->p_aliases, *buffer, COMMA); strcat(*buffer, fieldsep); + strcat(*buffer, prProto); strcat(*buffer, fieldsep); + + return (0); + +} + + + +/* + * int irp_unmarshall_pr(struct protoent *pr, char *buffer) + * + * notes: + * + * See above + * + * return: + * + * 0 on success, -1 on failure + * + */ + +int irp_unmarshall_pr(struct protoent *pr, char *buffer) { + char *p, *q; + int prproto; + long t; + char *name = NULL; + char **aliases = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (pr == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + p = buffer; + + /* p_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + + /* p_aliases field */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* p_proto field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + prproto = (int)t; + if ((long) prproto != t) { /* value must have been too big. */ + goto error; + } + + pr->p_name = name; + pr->p_aliases = aliases; + pr->p_proto = prproto; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + free_array(aliases, 0); + + return (-1); +} + +/* ------------------------- struct protoent ------------------------- */ + + + +/* +++++++++++++++++++++++++ struct hostent +++++++++++++++++++++++++ */ + + +/* + * int irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len) + * + * notes: + * + * see above. + * + * return: + * + * 0 on success, -1 on failure. + * + */ + +int +irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len) { + size_t need = 1; /* for null byte */ + char hoaddrtype[24]; + char holength[24]; + char **av; + char *p; + int addrlen; + int malloced = 0; + size_t remlen; + const char *fieldsep = "@"; + + if (ho == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + switch(ho->h_addrtype) { + case AF_INET: + strcpy(hoaddrtype, "AF_INET"); + break; + + case AF_INET6: + strcpy(hoaddrtype, "AF_INET6"); + break; + + default: + errno = EINVAL; + return (-1); + } + + sprintf(holength, "%d", ho->h_length); + + need += strlen(ho->h_name) + 1; + need += joinlength(ho->h_aliases) + 1; + need += strlen(hoaddrtype) + 1; + need += strlen(holength) + 1; + + /* we determine an upper bound on the string length needed, not an + exact length. */ + addrlen = (ho->h_addrtype == AF_INET ? 16 : 46) ; /* XX other AF's?? */ + for (av = ho->h_addr_list; av != NULL && *av != NULL ; av++) + need += addrlen; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + malloced = 1; + } + + strcpy(*buffer, ho->h_name); strcat(*buffer, fieldsep); + joinarray(ho->h_aliases, *buffer, COMMA); strcat(*buffer, fieldsep); + strcat(*buffer, hoaddrtype); strcat(*buffer, fieldsep); + strcat(*buffer, holength); strcat(*buffer, fieldsep); + + p = *buffer + strlen(*buffer); + remlen = need - strlen(*buffer); + for (av = ho->h_addr_list ; av != NULL && *av != NULL ; av++) { + if (inet_ntop(ho->h_addrtype, *av, p, remlen) == NULL) { + goto error; + } + if (*(av + 1) != NULL) + strcat(p, COMMASTR); + remlen -= strlen(p); + p += strlen(p); + } + strcat(*buffer, fieldsep); + + return (0); + + error: + if (malloced) { + memput(*buffer, need); + } + + return (-1); +} + + + +/* + * int irp_unmarshall_ho(struct hostent *ho, char *buffer) + * + * notes: + * + * See above. + * + * return: + * + * 0 on success, -1 on failure. + * + */ + +int +irp_unmarshall_ho(struct hostent *ho, char *buffer) { + char *p, *q, *r; + int hoaddrtype; + int holength; + long t; + char *name = NULL; + char **aliases = NULL; + char **hohaddrlist = NULL; + size_t hoaddrsize; + char tmpbuf[24]; + char *tb; + char **alist; + int addrcount; + char fieldsep = '@'; + int myerrno = EINVAL; + + if (ho == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + p = buffer; + + /* h_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + + /* h_aliases field */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* h_addrtype field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + if (strcmp(tmpbuf, "AF_INET") == 0) + hoaddrtype = AF_INET; + else if (strcmp(tmpbuf, "AF_INET6") == 0) + hoaddrtype = AF_INET6; + else + goto error; + + + /* h_length field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + holength = (int)t; + if ((long) holength != t) { /* value must have been too big. */ + goto error; + } + + + /* h_addr_list field */ + q = strchr(p, fieldsep); + if (q == NULL) + goto error; + + /* count how many addresss are in there */ + if (q > p + 1) { + for (addrcount = 1, r = p ; r != q ; r++) { + if (*r == COMMA) + addrcount++; + } + } else { + addrcount = 0; + } + + hoaddrsize = (addrcount + 1) * sizeof (char *); + hohaddrlist = malloc(hoaddrsize); + if (hohaddrlist == NULL) { + myerrno = ENOMEM; + goto error; + } + + memset(hohaddrlist, 0x0, hoaddrsize); + + alist = hohaddrlist; + for (t = 0, r = p ; r != q ; p = r + 1, t++) { + char saved; + while (r != q && *r != COMMA) r++; + saved = *r; + *r = 0x0; + + alist[t] = malloc(hoaddrtype == AF_INET ? 4 : 16); + if (alist[t] == NULL) { + myerrno = ENOMEM; + goto error; + } + + if (inet_pton(hoaddrtype, p, alist[t]) == -1) + goto error; + *r = saved; + } + alist[t] = NULL; + + ho->h_name = name; + ho->h_aliases = aliases; + ho->h_addrtype = hoaddrtype; + ho->h_length = holength; + ho->h_addr_list = hohaddrlist; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + free_array(aliases, 0); + + return (-1); +} + +/* ------------------------- struct hostent------------------------- */ + + + +/* +++++++++++++++++++++++++ struct netgrp +++++++++++++++++++++++++ */ + + +/* + * int irp_marshall_ng(const char *host, const char *user, + * const char *domain, char *buffer, size_t *len) + * + * notes: + * + * See note for irp_marshall_ng_start + * + * return: + * + * 0 on success, 0 on failure. + * + */ + +int +irp_marshall_ng(const char *host, const char *user, const char *domain, + char **buffer, size_t *len) { + size_t need = 1; /* for nul byte */ + const char *fieldsep = ","; + + if (len == NULL) { + errno = EINVAL; + return (-1); + } + + need += 4; /* two parens and two commas */ + need += (host == NULL ? 0 : strlen(host)); + need += (user == NULL ? 0 : strlen(user)); + need += (domain == NULL ? 0 : strlen(domain)); + + if (buffer == NULL) { + *len = need; + return (0); + } else if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + (*buffer)[0] = '('; + (*buffer)[1] = '\0'; + + if (host != NULL) + strcat(*buffer, host); + strcat(*buffer, fieldsep); + + if (user != NULL) + strcat(*buffer, user); + strcat(*buffer, fieldsep); + + if (domain != NULL) + strcat(*buffer, domain); + strcat(*buffer, ")"); + + return (0); +} + + + +/* ---------- */ + + +/* + * int irp_unmarshall_ng(const char **host, const char **user, + * const char **domain, char *buffer) + * + * notes: + * + * Unpacks the BUFFER into 3 character arrays it allocates and assigns + * to *HOST, *USER and *DOMAIN. If any field of the value is empty, + * then the corresponding paramater value will be set to NULL. + * + * return: + * + * 0 on success and -1 on failure. + */ + +int +irp_unmarshall_ng(const char **hostp, const char **userp, const char **domainp, + char *buffer) +{ + char *p, *q; + char fieldsep = ','; + int myerrno = EINVAL; + char *host, *user, *domain; + + if (userp == NULL || hostp == NULL || + domainp == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + host = user = domain = NULL; + + p = buffer; + while (isspace(*p)) { + p++; + } + if (*p != '(') { + goto error; + } + + q = p + 1; + while (*q && *q != fieldsep) + q++; + if (!*q) { + goto error; + } else if (q > p + 1) { + host = strndup(p, q - p); + } + + p = q + 1; + if (!*p) { + goto error; + } else if (*p != fieldsep) { + q = p + 1; + while (*q && *q != fieldsep) + q++; + if (!*q) { + goto error; + } + user = strndup(p, q - p); + } else { + p++; + } + + if (!*p) { + goto error; + } else if (*p != ')') { + q = p + 1; + while (*q && *q != ')') + q++; + if (!*q) { + goto error; + } + domain = strndup(p, q - p); + } + *hostp = host; + *userp = user; + *domainp = domain; + + return (0); + + error: + errno = myerrno; + + if (host != NULL) free(host); + if (user != NULL) free(user); + if (domain != NULL) free(domain); + + return (-1); +} + +/* ------------------------- struct netgrp ------------------------- */ + + + + +/* +++++++++++++++++++++++++ struct nwent +++++++++++++++++++++++++ */ + + +/* + * int irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len) + * + * notes: + * + * See at top. + * + * return: + * + * 0 on success and -1 on failure. + * + */ + +int +irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len) { + size_t need = 1; /* for null byte */ + char nAddrType[24]; + char nNet[MAXPADDRSIZE]; + const char *fieldsep = COLONSTR; + + if (ne == NULL || len == NULL) { + return (-1); + } + + strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype)); + + if (inet_net_ntop(ne->n_addrtype, ne->n_addr, ne->n_length, + nNet, sizeof nNet) == NULL) { + return (-1); + } + + + need += strlen(ne->n_name) + 1; + need += joinlength(ne->n_aliases) + 1; + need += strlen(nAddrType) + 1; + need += strlen(nNet) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, ne->n_name); strcat(*buffer, fieldsep); + joinarray(ne->n_aliases, *buffer, COMMA) ; strcat(*buffer, fieldsep); + strcat(*buffer, nAddrType); strcat(*buffer, fieldsep); + strcat(*buffer, nNet); strcat(*buffer, fieldsep); + + return (0); +} + + + +/* + * int irp_unmarshall_nw(struct nwent *ne, char *buffer) + * + * notes: + * + * See note up top. + * + * return: + * + * 0 on success and -1 on failure. + * + */ + +int +irp_unmarshall_nw(struct nwent *ne, char *buffer) { + char *p, *q; + int naddrtype; + long nnet; + int bits; + char *name = NULL; + char **aliases = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (ne == NULL || buffer == NULL) { + goto error; + } + + p = buffer; + + /* n_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + + /* n_aliases field. Aliases are separated by commas */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* h_addrtype field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + if (strcmp(tmpbuf, "AF_INET") == 0) + naddrtype = AF_INET; + else if (strcmp(tmpbuf, "AF_INET6") == 0) + naddrtype = AF_INET6; + else + goto error; + + + /* n_net field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + nnet = 0; + bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet); + if (bits < 0) { + goto error; + } + + /* nnet = ntohl(nnet); */ /* keep in network order for nwent */ + + ne->n_name = name; + ne->n_aliases = aliases; + ne->n_addrtype = naddrtype; + ne->n_length = bits; + ne->n_addr = malloc(sizeof nnet); + if (ne->n_addr == NULL) { + goto error; + } + + memcpy(ne->n_addr, &nnet, sizeof nnet); + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + free_array(aliases, 0); + + return (-1); +} + + +/* ------------------------- struct nwent ------------------------- */ + + +/* +++++++++++++++++++++++++ struct netent +++++++++++++++++++++++++ */ + + +/* + * int irp_marshall_ne(struct netent *ne, char **buffer, size_t *len) + * + * notes: + * + * See at top. + * + * return: + * + * 0 on success and -1 on failure. + * + */ + +int +irp_marshall_ne(struct netent *ne, char **buffer, size_t *len) { + size_t need = 1; /* for null byte */ + char nAddrType[24]; + char nNet[MAXPADDRSIZE]; + const char *fieldsep = COLONSTR; + long nval; + + if (ne == NULL || len == NULL) { + return (-1); + } + + strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype)); + + nval = htonl(ne->n_net); + if (inet_ntop(ne->n_addrtype, &nval, nNet, sizeof nNet) == NULL) { + return (-1); + } + + need += strlen(ne->n_name) + 1; + need += joinlength(ne->n_aliases) + 1; + need += strlen(nAddrType) + 1; + need += strlen(nNet) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, ne->n_name); strcat(*buffer, fieldsep); + joinarray(ne->n_aliases, *buffer, COMMA) ; strcat(*buffer, fieldsep); + strcat(*buffer, nAddrType); strcat(*buffer, fieldsep); + strcat(*buffer, nNet); strcat(*buffer, fieldsep); + + return (0); +} + + + +/* + * int irp_unmarshall_ne(struct netent *ne, char *buffer) + * + * notes: + * + * See note up top. + * + * return: + * + * 0 on success and -1 on failure. + * + */ + +int +irp_unmarshall_ne(struct netent *ne, char *buffer) { + char *p, *q; + int naddrtype; + long nnet; + int bits; + char *name = NULL; + char **aliases = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (ne == NULL || buffer == NULL) { + goto error; + } + + p = buffer; + + /* n_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + + /* n_aliases field. Aliases are separated by commas */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* h_addrtype field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + if (strcmp(tmpbuf, "AF_INET") == 0) + naddrtype = AF_INET; + else if (strcmp(tmpbuf, "AF_INET6") == 0) + naddrtype = AF_INET6; + else + goto error; + + + /* n_net field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet); + if (bits < 0) { + goto error; + } + nnet = ntohl(nnet); + + ne->n_name = name; + ne->n_aliases = aliases; + ne->n_addrtype = naddrtype; + ne->n_net = nnet; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + free_array(aliases, 0); + + return (-1); +} + + +/* ------------------------- struct netent ------------------------- */ + + +/* =========================================================================== */ + + +/* + * static char ** splitarray(const char *buffer, const char *buffend, char delim) + * + * notes: + * + * Split a delim separated astring. Not allowed + * to have two delims next to each other. BUFFER points to begining of + * string, BUFFEND points to one past the end of the string + * (i.e. points at where the null byte would be if null + * terminated). + * + * return: + * + * Returns a malloced array of pointers, each pointer pointing to a + * malloced string. If BUFEER is an empty string, then return values is + * array of 1 pointer that is NULL. Returns NULL on failure. + * + */ + +static char ** +splitarray(const char *buffer, const char *buffend, char delim) { + const char *p, *q; + int count = 0; + char **arr = NULL; + char **aptr; + + if (buffend < buffer) + return (NULL); + else if (buffend > buffer && *buffer == delim) + return (NULL); + else if (buffend > buffer && *(buffend - 1) == delim) + return (NULL); + + /* count the number of field and make sure none are empty */ + if (buffend > buffer + 1) { + for (count = 1, q = buffer ; q != buffend ; q++) { + if (*q == delim) { + if (q > buffer && (*(q - 1) == delim)) { + errno = EINVAL; + return (NULL); + } + count++; + } + } + } + + if (count > 0) { + count++ ; /* for NULL at end */ + aptr = arr = malloc(count * sizeof (char *)); + if (aptr == NULL) { + errno = ENOMEM; + return (NULL); + } + + memset(arr, 0x0, count * sizeof (char *)); + for (p = buffer ; p < buffend ; p++) { + for (q = p ; *q != delim && q != buffend ; q++) + /* nothing */; + *aptr = strndup(p, q - p); + + p = q; + aptr++; + } + *aptr = NULL; + } else { + arr = malloc(sizeof (char *)); + if (arr == NULL) { + errno = ENOMEM; + return (NULL); + } + + *arr = NULL; + } + + return (arr); +} + + + + +/* + * static size_t joinlength(char * const *argv) + * + * return: + * + * the number of bytes in all the arrays pointed at + * by argv, including their null bytes(which will usually be turned + * into commas). + * + * + */ + +static size_t +joinlength(char * const *argv) { + int len = 0; + + while (argv && *argv) { + len += (strlen(*argv) + 1); + argv++; + } + + return (len); +} + + + +/* + * int joinarray(char * const *argv, char *buffer, char delim) + * + * notes: + * + * Copy all the ARGV strings into the end of BUFFER + * separating them with DELIM. BUFFER is assumed to have + * enough space to hold everything and to be already null-terminated. + * + * return: + * + * 0 unless argv or buffer is NULL. + * + * + */ + +static int +joinarray(char * const *argv, char *buffer, char delim) { + char * const *p; + char sep[2]; + + if (argv == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + sep[0] = delim; + sep[1] = 0x0; + + for (p = argv ; *p != NULL ; p++) { + strcat(buffer, *p); + if (*(p + 1) != NULL) { + strcat(buffer, sep); + } + } + + return (0); +} + + +/* + * static char * getfield(char **res, size_t reslen, char **ptr, char delim) + * + * notes: + * + * Stores in *RES, which is a buffer of length RESLEN, a + * copy of the bytes from *PTR up to and including the first + * instance of DELIM. If *RES is NULL, then it will be + * assigned a malloced buffer to hold the copy. *PTR is + * modified to point at the found delimiter. + * + * return: + * + * If there was no delimiter, then NULL is returned, + * otherewise *RES is returned. + * + */ + +static char * +getfield(char **res, size_t reslen, char **ptr, char delim) { + char *q; + + if (res == NULL || ptr == NULL || *ptr == NULL) { + errno = EINVAL; + return (NULL); + } + + q = strchr(*ptr, delim); + + if (q == NULL) { + errno = EINVAL; + return (NULL); + } else { + if (*res == NULL) { + *res = strndup(*ptr, q - *ptr); + } else { + if ((size_t)(q - *ptr + 1) > reslen) { /* to big for res */ + errno = EINVAL; + return (NULL); + } else { + strncpy(*res, *ptr, q - *ptr); + (*res)[q - *ptr] = 0x0; + } + } + *ptr = q + 1; + } + + return (*res); +} + + + + + +#ifndef HAVE_STRNDUP +/* + * static char * strndup(const char *str, size_t len) + * + * notes: + * + * like strdup, except do len bytes instead of the whole string. Always + * null-terminates. + * + * return: + * + * The newly malloced string. + * + */ + +static char * +strndup(const char *str, size_t len) { + char *p = malloc(len + 1); + + if (p == NULL) + return (NULL); + strncpy(p, str, len); + p[len] = 0x0; + return (p); +} +#endif + +#if WANT_MAIN + +/* + * static int strcmp_nws(const char *a, const char *b) + * + * notes: + * + * do a strcmp, except uneven lengths of whitespace compare the same + * + * return: + * + */ + +static int +strcmp_nws(const char *a, const char *b) { + while (*a && *b) { + if (isspace(*a) && isspace(*b)) { + do { + a++; + } while (isspace(*a)); + do { + b++; + } while (isspace(*b)); + } + if (*a < *b) + return (-1); + else if (*a > *b) + return (1); + + a++; + b++;; + } + + if (*a == *b) + return (0); + else if (*a > *b) + return (1); + else + return (-1); +} + +#endif + + + + + +/* + * static void free_array(char **argv, size_t entries) + * + * notes: + * + * Free argv and each of the pointers inside it. The end of + * the array is when a NULL pointer is found inside. If + * entries is > 0, then NULL pointers inside the array do + * not indicate the end of the array. + * + */ + +static void +free_array(char **argv, size_t entries) { + char **p = argv; + int useEntries = (entries > 0); + + if (argv == NULL) + return; + + while ((useEntries && entries > 0) || *p) { + if (*p) + free(*p); + p++; + if (useEntries) + entries--; + } + free(argv); +} + + + + + +/* ************************************************** */ + +#if WANT_MAIN + +/* takes an option to indicate what sort of marshalling(read the code) and + an argument. If the argument looks like a marshalled buffer(has a ':' + embedded) then it's unmarshalled and the remarshalled and the new string + is compared to the old one. +*/ + +int +main(int argc, char **argv) { + char buffer[1024]; + char *b = &buffer[0]; + size_t len = sizeof buffer; + char option; + + if (argc < 2 || argv[1][0] != '-') + exit(1); + + option = argv[1][1]; + argv++; + argc--; + + +#if 0 + { + char buff[10]; + char *p = argv[1], *q = &buff[0]; + + while (getfield(&q, sizeof buff, &p, ':') != NULL) { + printf("field: \"%s\"\n", q); + p++; + } + printf("p is now \"%s\"\n", p); + } +#endif + +#if 0 + { + char **x = splitarray(argv[1], argv[1] + strlen(argv[1]), + argv[2][0]); + char **p; + + if (x == NULL) + printf("split failed\n"); + + for (p = x ; p != NULL && *p != NULL ; p++) { + printf("\"%s\"\n", *p); + } + } +#endif + +#if 1 + switch(option) { + case 'n': { + struct nwent ne; + int i; + + if (strchr(argv[1], ':') != NULL) { + if (irp_unmarshall_nw(&ne, argv[1]) != 0) { + printf("Unmarhsalling failed\n"); + exit(1); + } + + printf("Name: \"%s\"\n", ne.n_name); + printf("Aliases:"); + for (i = 0 ; ne.n_aliases[i] != NULL ; i++) + printf("\n\t\"%s\"", ne.n_aliases[i]); + printf("\nAddrtype: %s\n", ADDR_T_STR(ne.n_addrtype)); + inet_net_ntop(ne.n_addrtype, ne.n_addr, ne.n_length, + buffer, sizeof buffer); + printf("Net: \"%s\"\n", buffer); + *((long*)ne.n_addr) = htonl(*((long*)ne.n_addr)); + inet_net_ntop(ne.n_addrtype, ne.n_addr, ne.n_length, + buffer, sizeof buffer); + printf("Corrected Net: \"%s\"\n", buffer); + } else { + struct netent *np1 = getnetbyname(argv[1]); + ne.n_name = np1->n_name; + ne.n_aliases = np1->n_aliases; + ne.n_addrtype = np1->n_addrtype; + ne.n_addr = &np1->n_net; + ne.n_length = (IN_CLASSA(np1->n_net) ? + 8 : + (IN_CLASSB(np1->n_net) ? + 16 : + (IN_CLASSC(np1->n_net) ? + 24 : -1))); + np1->n_net = htonl(np1->n_net); + if (irp_marshall_nw(&ne, &b, &len) != 0) { + printf("Marshalling failed\n"); + } + printf("%s\n", b); + } + break; + } + + + case 'r': { + char **hosts, **users, **domains; + size_t entries; + int i; + char *buff; + size_t size; + char *ngname; + + if (strchr(argv[1], '(') != NULL) { + if (irp_unmarshall_ng(&ngname, &entries, + &hosts, &users, &domains, + argv[1]) != 0) { + printf("unmarshall failed\n"); + exit(1); + } + +#define STRVAL(x) (x == NULL ? "*" : x) + + printf("%s {\n", ngname); + for (i = 0 ; i < entries ; i++) + printf("\t\"%s\" : \"%s\" : \"%s\"\n", + STRVAL(hosts[i]), + STRVAL(users[i]), + STRVAL(domains[i])); + printf("}\n\n\n"); + + + irp_marshall_ng_start(ngname, NULL, &size); + for (i = 0 ; i < entries ; i++) + irp_marshall_ng_next(hosts[i], users[i], + domains[i], NULL, &size); + irp_marshall_ng_end(NULL, &size); + + buff = malloc(size); + + irp_marshall_ng_start(ngname, buff, &size); + for (i = 0 ; i < entries ; i++) { + if (irp_marshall_ng_next(hosts[i], users[i], + domains[i], buff, + &size) != 0) + printf("next marshalling failed.\n"); + } + irp_marshall_ng_end(buff, &size); + + if (strcmp_nws(argv[1], buff) != 0) { + printf("compare failed:\n\t%s\n\t%s\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + char *h, *u, *d, *buff; + size_t size; + + /* run through two times. First to figure out how + much of a buffer we need. Second to do the + actual marshalling */ + + setnetgrent(argv[1]); + irp_marshall_ng_start(argv[1], NULL, &size); + while (getnetgrent(&h, &u, &d) == 1) + irp_marshall_ng_next(h, u, d, NULL, &size); + irp_marshall_ng_end(NULL, &size); + endnetgrent(argv[1]); + + buff = malloc(size); + + setnetgrent(argv[1]); + if (irp_marshall_ng_start(argv[1], buff, &size) != 0) + printf("Marshalling start failed\n"); + + while (getnetgrent(&h, &u, &d) == 1) { + if (irp_marshall_ng_next(h, u, d, buff, &size) + != 0) { + printf("Marshalling failed\n"); + } + } + + irp_marshall_ng_end(buff, &size); + endnetgrent(); + + printf("success: %s\n", buff); + } + break; + } + + + + case 'h': { + struct hostent he, *hp; + int i; + + + if (strchr(argv[1], '@') != NULL) { + if (irp_unmarshall_ho(&he, argv[1]) != 0) { + printf("unmarshall failed\n"); + exit(1); + } + + printf("Host: \"%s\"\nAliases:", he.h_name); + for (i = 0 ; he.h_aliases[i] != NULL ; i++) + printf("\n\t\t\"%s\"", he.h_aliases[i]); + printf("\nAddr Type: \"%s\"\n", + ADDR_T_STR(he.h_addrtype)); + printf("Length: %d\nAddresses:", he.h_length); + for (i = 0 ; he.h_addr_list[i] != 0 ; i++) { + inet_ntop(he.h_addrtype, he.h_addr_list[i], + buffer, sizeof buffer); + printf("\n\t\"%s\"\n", buffer); + } + printf("\n\n"); + + irp_marshall_ho(&he, &b, &len); + if (strcmp(argv[1], buffer) != 0) { + printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + if ((hp = gethostbyname(argv[1])) == NULL) { + perror("gethostbyname"); + printf("\"%s\"\n", argv[1]); + exit(1); + } + + if (irp_marshall_ho(hp, &b, &len) != 0) { + printf("irp_marshall_ho failed\n"); + exit(1); + } + + printf("success: \"%s\"\n", buffer); + } + break; + } + + + case 's': { + struct servent *sv; + struct servent sv1; + + if (strchr(argv[1], ':') != NULL) { + sv = &sv1; + memset(sv, 0xef, sizeof (struct servent)); + if (irp_unmarshall_sv(sv, argv[1]) != 0) { + printf("unmarshall failed\n"); + + } + + irp_marshall_sv(sv, &b, &len); + if (strcmp(argv[1], buffer) != 0) { + printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + if ((sv = getservbyname(argv[1], argv[2])) == NULL) { + perror("getservent"); + exit(1); + } + + if (irp_marshall_sv(sv, &b, &len) != 0) { + printf("irp_marshall_sv failed\n"); + exit(1); + } + + printf("success: \"%s\"\n", buffer); + } + break; + } + + case 'g': { + struct group *gr; + struct group gr1; + + if (strchr(argv[1], ':') != NULL) { + gr = &gr1; + memset(gr, 0xef, sizeof (struct group)); + if (irp_unmarshall_gr(gr, argv[1]) != 0) { + printf("unmarshall failed\n"); + + } + + irp_marshall_gr(gr, &b, &len); + if (strcmp(argv[1], buffer) != 0) { + printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + if ((gr = getgrnam(argv[1])) == NULL) { + perror("getgrnam"); + exit(1); + } + + if (irp_marshall_gr(gr, &b, &len) != 0) { + printf("irp_marshall_gr failed\n"); + exit(1); + } + + printf("success: \"%s\"\n", buffer); + } + break; + } + + + case 'p': { + struct passwd *pw; + struct passwd pw1; + + if (strchr(argv[1], ':') != NULL) { + pw = &pw1; + memset(pw, 0xef, sizeof (*pw)); + if (irp_unmarshall_pw(pw, argv[1]) != 0) { + printf("unmarshall failed\n"); + exit(1); + } + + printf("User: \"%s\"\nPasswd: \"%s\"\nUid: %ld\nGid: %ld\n", + pw->pw_name, pw->pw_passwd, (long)pw->pw_uid, + (long)pw->pw_gid); + printf("Class: \"%s\"\nChange: %ld\nGecos: \"%s\"\n", + pw->pw_class, (long)pw->pw_change, pw->pw_gecos); + printf("Shell: \"%s\"\nDirectory: \"%s\"\n", + pw->pw_shell, pw->pw_dir); + + pw = getpwnam(pw->pw_name); + irp_marshall_pw(pw, &b, &len); + if (strcmp(argv[1], buffer) != 0) { + printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + if ((pw = getpwnam(argv[1])) == NULL) { + perror("getpwnam"); + exit(1); + } + + if (irp_marshall_pw(pw, &b, &len) != 0) { + printf("irp_marshall_pw failed\n"); + exit(1); + } + + printf("success: \"%s\"\n", buffer); + } + break; + } + + default: + printf("Wrong option: %c\n", option); + break; + } + +#endif + + return (0); +} + +#endif diff --git a/lib/bind/irs/irs_data.c b/lib/bind/irs/irs_data.c new file mode 100644 index 0000000000..16609a40fe --- /dev/null +++ b/lib/bind/irs/irs_data.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: irs_data.c,v 1.1 2001/03/29 06:31:50 marka Exp $"; +#endif + +#include "port_before.h" + +#ifndef __BIND_NOSTATIC + +#include + +#include +#include + +#include +#include +#include + +#ifdef DO_PTHREADS +#include +#endif + +#include + +#include "port_after.h" + +#include "irs_data.h" +#undef _res +#undef h_errno + +extern struct __res_state _res; +extern int h_errno; + +#ifdef DO_PTHREADS +static pthread_key_t key; +static int once = 0; +#else +static struct net_data *net_data; +#endif + +void +irs_destroy(void) { +#ifndef DO_PTHREADS + if (net_data != NULL) + net_data_destroy(net_data); + net_data = NULL; +#endif +} + +void +net_data_destroy(void *p) { + struct net_data *net_data = p; + + res_nclose(net_data->res); + if (net_data->gr != NULL) { + (*net_data->gr->close)(net_data->gr); + net_data->gr = NULL; + } + if (net_data->pw != NULL) { + (*net_data->pw->close)(net_data->pw); + net_data->pw = NULL; + } + if (net_data->sv != NULL) { + (*net_data->sv->close)(net_data->sv); + net_data->sv = NULL; + } + if (net_data->pr != NULL) { + (*net_data->pr->close)(net_data->pr); + net_data->pr = NULL; + } + if (net_data->ho != NULL) { + (*net_data->ho->close)(net_data->ho); + net_data->ho = NULL; + } + if (net_data->nw != NULL) { + (*net_data->nw->close)(net_data->nw); + net_data->nw = NULL; + } + if (net_data->ng != NULL) { + (*net_data->ng->close)(net_data->ng); + net_data->ng = NULL; + } + + (*net_data->irs->close)(net_data->irs); + memput(net_data, sizeof *net_data); +} + +/* applications that need a specific config file other than + * _PATH_IRS_CONF should call net_data_init directly rather than letting + * the various wrapper functions make the first call. - brister + */ + +struct net_data * +net_data_init(const char *conf_file) { +#ifdef DO_PTHREADS + static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER; + struct net_data *net_data; + + if (!once) { + pthread_mutex_lock(&keylock); + if (!once++) + pthread_key_create(&key, net_data_destroy); + pthread_mutex_unlock(&keylock); + } + net_data = pthread_getspecific(key); +#endif + + if (net_data == NULL) { + net_data = net_data_create(conf_file); + if (net_data == NULL) + return (NULL); +#ifdef DO_PTHREADS + pthread_setspecific(key, net_data); +#endif + } + + return (net_data); +} + +struct net_data * +net_data_create(const char *conf_file) { + struct net_data *net_data; + + net_data = memget(sizeof (struct net_data)); + if (net_data == NULL) + return (NULL); + memset(net_data, 0, sizeof (struct net_data)); + + if ((net_data->irs = irs_gen_acc("", conf_file)) == NULL) + return (NULL); +#ifndef DO_PTHREADS + (*net_data->irs->res_set)(net_data->irs, &_res, NULL); +#endif + + net_data->res = (*net_data->irs->res_get)(net_data->irs); + if (net_data->res == NULL) + return (NULL); + + if (res_ninit(net_data->res) == -1) + return (NULL); + + return (net_data); +} + + + +void +net_data_minimize(struct net_data *net_data) { + res_nclose(net_data->res); +} + +struct __res_state * +__res_state(void) { + /* NULL param here means use the default config file. */ + struct net_data *net_data = net_data_init(NULL); + if (net_data && net_data->res) + return (net_data->res); + + return (&_res); +} + +int * +__h_errno(void) { + /* NULL param here means use the default config file. */ + struct net_data *net_data = net_data_init(NULL); + if (net_data && net_data->res) + return (&net_data->res->res_h_errno); + return (&h_errno); +} + +void +__h_errno_set(struct __res_state *res, int err) { + + h_errno = res->res_h_errno = err; +} + +#endif /*__BIND_NOSTATIC*/ diff --git a/lib/bind/irs/irs_data.h b/lib/bind/irs/irs_data.h new file mode 100644 index 0000000000..16395559cf --- /dev/null +++ b/lib/bind/irs/irs_data.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: irs_data.h,v 1.1 2001/03/29 06:31:50 marka Exp $ + */ + +#ifndef __BIND_NOSTATIC + +#define net_data_init __net_data_init + +struct net_data { + struct irs_acc * irs; + + struct irs_gr * gr; + struct irs_pw * pw; + struct irs_sv * sv; + struct irs_pr * pr; + struct irs_ho * ho; + struct irs_nw * nw; + struct irs_ng * ng; + + struct group * gr_last; + struct passwd * pw_last; + struct servent * sv_last; + struct protoent * pr_last; + struct netent * nw_last; /* should have been ne_last */ + struct nwent * nww_last; + struct hostent * ho_last; + + unsigned int gr_stayopen :1; + unsigned int pw_stayopen :1; + unsigned int sv_stayopen :1; + unsigned int pr_stayopen :1; + unsigned int ho_stayopen :1; + unsigned int nw_stayopen :1; + + void * nw_data; + void * ho_data; + + struct __res_state * res; /* for gethostent.c */ + +}; + +extern struct net_data * net_data_init(const char *conf_file); +extern void net_data_minimize(struct net_data *); + +#endif /*__BIND_NOSTATIC*/ diff --git a/lib/bind/irs/irs_p.h b/lib/bind/irs/irs_p.h new file mode 100644 index 0000000000..a4ed450bb5 --- /dev/null +++ b/lib/bind/irs/irs_p.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: irs_p.h,v 1.1 2001/03/29 06:31:50 marka Exp $ + */ + +#ifndef _IRS_P_H_INCLUDED +#define _IRS_P_H_INCLUDED + +#include + +#include "pathnames.h" + +#define IRS_SV_MAXALIASES 35 + +struct lcl_sv { + FILE * fp; + char line[BUFSIZ+1]; + struct servent serv; + char * serv_aliases[IRS_SV_MAXALIASES]; +}; + +#define irs_nul_ng __irs_nul_ng +#define map_v4v6_address __map_v4v6_address +#define make_group_list __make_group_list +#define irs_lclsv_fnxt __irs_lclsv_fnxt + +extern void map_v4v6_address(const char *src, char *dst); +extern int make_group_list(struct irs_gr *, const char *, + gid_t, gid_t *, int *); +extern struct irs_ng * irs_nul_ng(struct irs_acc *); +extern struct servent * irs_lclsv_fnxt(struct lcl_sv *); + +#endif diff --git a/lib/bind/irs/lcl.c b/lib/bind/irs/lcl.c new file mode 100644 index 0000000000..3adc4cd94f --- /dev/null +++ b/lib/bind/irs/lcl.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: lcl.c,v 1.1 2001/03/29 06:31:50 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +/* Forward. */ + +static void lcl_close(struct irs_acc *); +static struct __res_state * lcl_res_get(struct irs_acc *); +static void lcl_res_set(struct irs_acc *, struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_acc * +irs_lcl_acc(const char *options) { + struct irs_acc *acc; + struct lcl_p *lcl; + + UNUSED(options); + + if (!(acc = memget(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(lcl = memget(sizeof *lcl))) { + errno = ENOMEM; + free(acc); + return (NULL); + } + memset(lcl, 0x5e, sizeof *lcl); + lcl->res = NULL; + lcl->free_res = NULL; + acc->private = lcl; +#ifdef WANT_IRS_GR + acc->gr_map = irs_lcl_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_lcl_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_lcl_sv; + acc->pr_map = irs_lcl_pr; + acc->ho_map = irs_lcl_ho; + acc->nw_map = irs_lcl_nw; + acc->ng_map = irs_lcl_ng; + acc->res_get = lcl_res_get; + acc->res_set = lcl_res_set; + acc->close = lcl_close; + return (acc); +} + +/* Methods */ +static struct __res_state * +lcl_res_get(struct irs_acc *this) { + struct lcl_p *lcl = (struct lcl_p *)this->private; + + if (lcl->res == NULL) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) + return (NULL); + memset(res, 0, sizeof *res); + lcl_res_set(this, res, free); + } + + if ((lcl->res->options & RES_INIT) == 0 && + res_ninit(lcl->res) < 0) + return (NULL); + + return (lcl->res); +} + +static void +lcl_res_set(struct irs_acc *this, struct __res_state *res, + void (*free_res)(void *)) { + struct lcl_p *lcl = (struct lcl_p *)this->private; + + if (lcl->res && lcl->free_res) { + res_nclose(lcl->res); + (*lcl->free_res)(lcl->res); + } + + lcl->res = res; + lcl->free_res = free_res; +} + +static void +lcl_close(struct irs_acc *this) { + struct lcl_p *lcl = (struct lcl_p *)this->private; + + if (lcl) { + if (lcl->free_res) + (*lcl->free_res)(lcl->res); + memput(lcl, sizeof *lcl); + } + memput(this, sizeof *this); +} diff --git a/lib/bind/irs/lcl_gr.c b/lib/bind/irs/lcl_gr.c new file mode 100644 index 0000000000..d70fac0b9a --- /dev/null +++ b/lib/bind/irs/lcl_gr.c @@ -0,0 +1,354 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_gr.c,v 1.1 2001/03/29 06:31:50 marka Exp $"; +/* from getgrent.c 8.2 (Berkeley) 3/21/94"; */ +/* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */ +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_gr_unneeded; +#else + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "irs_p.h" +#include "lcl_p.h" +#include "irp_p.h" + +#include "port_after.h" + + +/* Types. */ + +struct pvt { + FILE * fp; + /* + * Need space to store the entries read from the group file. + * The members list also needs space per member, and the + * strings making up the user names must be allocated + * somewhere. Rather than doing lots of small allocations, + * we keep one buffer and resize it as needed. + */ + struct group group; + size_t nmemb; /* Malloc'd max index of gr_mem[]. */ + char * membuf; + size_t membufsize; +}; + +/* Forward. */ + +static void gr_close(struct irs_gr *); +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static void gr_minimize(struct irs_gr *); + +static int grstart(struct pvt *); +static char * grnext(struct pvt *); +static struct group * grscan(struct irs_gr *, int, gid_t, const char *); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public. */ + +struct irs_gr * +irs_lcl_gr(struct irs_acc *this) { + struct irs_gr *gr; + struct pvt *pvt; + + UNUSED(this); + + if (!(gr = memget(sizeof *gr))) { + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x5e, sizeof *gr); + if (!(pvt = memget(sizeof *pvt))) { + memput(gr, sizeof *gr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + gr->private = pvt; + gr->close = gr_close; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->list = make_group_list; + gr->minimize = gr_minimize; + gr->res_get = NULL; + gr->res_set = NULL; + return (gr); +} + +/* Methods. */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) + (void)fclose(pvt->fp); + if (pvt->group.gr_mem) + free(pvt->group.gr_mem); + if (pvt->membuf) + free(pvt->membuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct group * +gr_next(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->fp && !grstart(pvt)) + return (NULL); + return (grscan(this, 0, 0, NULL)); +} + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + if (!grstart((struct pvt *)this->private)) + return (NULL); + return (grscan(this, 1, 0, name)); +} + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + if (!grstart((struct pvt *)this->private)) + return (NULL); + return (grscan(this, 1, gid, NULL)); +} + +static void +gr_rewind(struct irs_gr *this) { + (void) grstart((struct pvt *)this->private); +} + +static void +gr_minimize(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +/* Private. */ + +static int +grstart(struct pvt *pvt) { + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return (1); + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_GROUP, "r"))) + return (0); + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + fclose(pvt->fp); + return (0); + } + return (1); +} + +#define INITIAL_NMEMB 30 /* about 120 bytes */ +#define INITIAL_BUFSIZ (INITIAL_NMEMB * 8) /* about 240 bytes */ + +static char * +grnext(struct pvt *pvt) { + char *w, *e; + int ch; + + /* Make sure we have a buffer. */ + if (pvt->membuf == NULL) { + pvt->membuf = malloc(INITIAL_BUFSIZ); + if (pvt->membuf == NULL) { + enomem: + errno = ENOMEM; + return (NULL); + } + pvt->membufsize = INITIAL_BUFSIZ; + } + + /* Read until EOF or EOL. */ + w = pvt->membuf; + e = pvt->membuf + pvt->membufsize; + while ((ch = fgetc(pvt->fp)) != EOF && ch != '\n') { + /* Make sure we have room for this character and a \0. */ + if (w + 1 == e) { + size_t o = w - pvt->membuf; + size_t n = pvt->membufsize * 2; + char *t = realloc(pvt->membuf, n); + + if (t == NULL) + goto enomem; + pvt->membuf = t; + pvt->membufsize = n; + w = pvt->membuf + o; + e = pvt->membuf + pvt->membufsize; + } + /* Store it. */ + *w++ = (char)ch; + } + + /* Hitting EOF on the first character really does mean EOF. */ + if (w == pvt->membuf && ch == EOF) { + errno = ENOENT; + return (NULL); + } + + /* Last line of /etc/group need not end with \n; we don't care. */ + *w = '\0'; + return (pvt->membuf); +} + +static struct group * +grscan(struct irs_gr *this, int search, gid_t gid, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + size_t n; + char *bp, **m, *p; + + /* Read lines until we find one that matches our search criteria. */ + for (;;) { + if ((bp = grnext(pvt)) == NULL) + return (NULL); + + /* Optimize the usual case of searching for a name. */ + pvt->group.gr_name = strsep(&bp, ":"); + if (search && name != NULL && + strcmp(pvt->group.gr_name, name) != 0) + continue; + if (bp == NULL || *bp == '\0') + goto corrupt; + + /* Skip past the password field. */ + pvt->group.gr_passwd = strsep(&bp, ":"); + if (bp == NULL || *bp == '\0') + goto corrupt; + + /* Checking for a gid. */ + if ((p = strsep(&bp, ":")) == NULL) + continue; + /* + * Unlike the tests above, the test below is supposed to be + * testing 'p' and not 'bp', in case you think it's a typo. + */ + if (p == NULL || *p == '\0') { + corrupt: + /* warning: corrupted %s file!", _PATH_GROUP */ + continue; + } + pvt->group.gr_gid = atoi(p); + if (search && name == NULL && (gid_t)pvt->group.gr_gid != gid) + continue; + + /* We want this record. */ + break; + } + + /* + * Count commas to find out how many members there might be. + * Note that commas separate, so if there is one comma there + * can be two members (group:*:id:user1,user2). Add another + * to account for the NULL terminator. As above, allocate + * largest of INITIAL_NMEMB, or 2*n. + */ + n = 1; + if (bp != NULL) + for (n = 2, p = bp; (p = strpbrk(p, ", ")) != NULL; ++n) + p += strspn(p, ", "); + if (n > pvt->nmemb || pvt->group.gr_mem == NULL) { + if ((n *= 2) < INITIAL_NMEMB) + n = INITIAL_NMEMB; + if ((m = realloc(pvt->group.gr_mem, n * sizeof *m)) == NULL) + return (NULL); + pvt->group.gr_mem = m; + pvt->nmemb = n; + } + + /* Set the name pointers. */ + for (m = pvt->group.gr_mem; (p = strsep(&bp, ", ")) != NULL;) + if (p[0] != '\0') + *m++ = p; + *m = NULL; + + return (&pvt->group); +} + +#endif /* WANT_IRS_GR */ diff --git a/lib/bind/irs/lcl_ho.c b/lib/bind/irs/lcl_ho.c new file mode 100644 index 0000000000..a2d13e3350 --- /dev/null +++ b/lib/bind/irs/lcl_ho.c @@ -0,0 +1,576 @@ +/* + * Copyright (c) 1985, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* from gethostnamadr.c 8.1 (Berkeley) 6/4/93 */ +/* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_ho.c,v 1.1 2001/03/29 06:31:50 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "dns_p.h" +#include "lcl_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +/* Definitions. */ + +#define MAXALIASES 35 +#define MAXADDRS 35 +#define Max(a,b) ((a) > (b) ? (a) : (b)) + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +struct pvt { + FILE * fp; + struct hostent host; + char * h_addr_ptrs[MAXADDRS + 1]; + char * host_aliases[MAXALIASES]; + char hostbuf[8*1024]; + u_char host_addr[16]; /* IPv4 or IPv6 */ + struct __res_state *res; + void (*free_res)(void *); +}; + +typedef union { + int32_t al; + char ac; +} align; + +static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; +static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; + +/* Forward. */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); +static struct __res_state * ho_res_get(struct irs_ho *this); +static void ho_res_set(struct irs_ho *this, + struct __res_state *res, + void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +static size_t ns_namelen(const char *); +static int init(struct irs_ho *this); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public. */ + +struct irs_ho * +irs_lcl_ho(struct irs_acc *this) { + struct irs_ho *ho; + struct pvt *pvt; + + UNUSED(this); + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(ho = memget(sizeof *ho))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->res_get = ho_res_get; + ho->res_set = ho_res_set; + ho->addrinfo = ho_addrinfo; + return (ho); +} + +/* Methods. */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + if (pvt->fp) + (void) fclose(pvt->fp); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + + if (init(this) == -1) + return (NULL); + + if (pvt->res->options & RES_USE_INET6) { + hp = ho_byname2(this, name, AF_INET6); + if (hp) + return (hp); + } + return (ho_byname2(this, name, AF_INET)); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + char **hap; + size_t n; + + if (init(this) == -1) + return (NULL); + + ho_rewind(this); + n = ns_namelen(name); + while ((hp = ho_next(this)) != NULL) { + size_t nn; + + if (hp->h_addrtype != af) + continue; + nn = ns_namelen(hp->h_name); + if (strncasecmp(hp->h_name, name, Max(n, nn)) == 0) + goto found; + for (hap = hp->h_aliases; *hap; hap++) { + nn = ns_namelen(*hap); + if (strncasecmp(*hap, name, Max(n, nn)) == 0) + goto found; + } + } + found: + if (!hp) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (hp); +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + const u_char *uaddr = addr; + struct hostent *hp; + int size; + + if (init(this) == -1) + return (NULL); + + if (af == AF_INET6 && len == IN6ADDRSZ && + (!memcmp(uaddr, mapped, sizeof mapped) || + !memcmp(uaddr, tunnelled, sizeof tunnelled))) { + /* Unmap. */ + addr = (const u_char *)addr + sizeof mapped; + uaddr += sizeof mapped; + af = AF_INET; + len = INADDRSZ; + } + switch (af) { + case AF_INET: + size = INADDRSZ; + break; + case AF_INET6: + size = IN6ADDRSZ; + break; + default: + errno = EAFNOSUPPORT; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + if (size > len) { + errno = EINVAL; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + + /* + * Do the search. + */ + ho_rewind(this); + while ((hp = ho_next(this)) != NULL) { + char **hap; + + for (hap = hp->h_addr_list; *hap; hap++) { + const u_char *taddr = (const u_char *)*hap; + int taf = hp->h_addrtype; + int tlen = hp->h_length; + + if (taf == AF_INET6 && tlen == IN6ADDRSZ && + (!memcmp(taddr, mapped, sizeof mapped) || + !memcmp(taddr, tunnelled, sizeof tunnelled))) { + /* Unmap. */ + taddr += sizeof mapped; + taf = AF_INET; + tlen = INADDRSZ; + } + if (taf == af && tlen == len && + !memcmp(taddr, uaddr, tlen)) + goto found; + } + } + found: + if (!hp) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (hp); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *cp, **q, *p; + char *bufp, *ndbuf, *dbuf = NULL; + int c, af, len, bufsiz, offset; + + if (init(this) == -1) + return (NULL); + + if (!pvt->fp) + ho_rewind(this); + if (!pvt->fp) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + bufp = pvt->hostbuf; + bufsiz = sizeof pvt->hostbuf; + offset = 0; + again: + if (!(p = fgets(bufp + offset, bufsiz - offset, pvt->fp))) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + if (dbuf) + free(dbuf); + return (NULL); + } + if (!strchr(p, '\n') && !feof(pvt->fp)) { +#define GROWBUF 1024 + /* allocate space for longer line */ + if (dbuf == NULL) { + if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL) + strcpy(ndbuf, bufp); + } else + ndbuf = realloc(dbuf, bufsiz + GROWBUF); + if (ndbuf) { + dbuf = ndbuf; + bufp = dbuf; + bufsiz += GROWBUF; + offset = strlen(dbuf); + } else { + /* allocation failed; skip this long line */ + while ((c = getc(pvt->fp)) != EOF) + if (c == '\n') + break; + if (c != EOF) + ungetc(c, pvt->fp); + } + goto again; + } + + p -= offset; + offset = 0; + + if (*p == '#') + goto again; + if ((cp = strpbrk(p, "#\n")) != NULL) + *cp = '\0'; + if (!(cp = strpbrk(p, " \t"))) + goto again; + *cp++ = '\0'; + if (inet_pton(AF_INET6, p, pvt->host_addr) > 0) { + af = AF_INET6; + len = IN6ADDRSZ; + } else if (inet_aton(p, (struct in_addr *)pvt->host_addr) > 0) { + if (pvt->res->options & RES_USE_INET6) { + map_v4v6_address((char*)pvt->host_addr, + (char*)pvt->host_addr); + af = AF_INET6; + len = IN6ADDRSZ; + } else { + af = AF_INET; + len = INADDRSZ; + } + } else { + goto again; + } + pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; + pvt->h_addr_ptrs[1] = NULL; + pvt->host.h_addr_list = pvt->h_addr_ptrs; + pvt->host.h_length = len; + pvt->host.h_addrtype = af; + while (*cp == ' ' || *cp == '\t') + cp++; + pvt->host.h_name = cp; + q = pvt->host.h_aliases = pvt->host_aliases; + if ((cp = strpbrk(cp, " \t")) != NULL) + *cp++ = '\0'; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->host_aliases[MAXALIASES - 1]) + *q++ = cp; + if ((cp = strpbrk(cp, " \t")) != NULL) + *cp++ = '\0'; + } + *q = NULL; + if (dbuf) + free(dbuf); + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (&pvt->host); +} + +static void +ho_rewind(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_HOSTS, "r"))) + return; + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +ho_res_get(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + ho_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +ho_res_set(struct irs_ho *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +struct lcl_res_target { + struct lcl_res_target *next; + int family; +}; + +/* XXX */ +extern struct addrinfo *hostent2addrinfo __P((struct hostent *, + const struct addrinfo *pai)); + +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + struct lcl_res_target q, q2, *p; + struct addrinfo sentinel, *cur; + + memset(&q, 0, sizeof(q2)); + memset(&q2, 0, sizeof(q2)); + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + switch(pai->ai_family) { + case AF_UNSPEC: /* INET6 then INET4 */ + q.family = AF_INET6; + q.next = &q2; + q2.family = AF_INET; + break; + case AF_INET6: + q.family = AF_INET6; + break; + case AF_INET: + q.family = AF_INET; + break; + default: + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /* ??? */ + return(NULL); + } + + for (p = &q; p; p = p->next) { + struct addrinfo *ai; + + hp = (*this->byname2)(this, name, p->family); + if (hp == NULL) { + /* byname2 should've set an appropriate error */ + continue; + } + if ((hp->h_name == NULL) || (hp->h_name[0] == 0) || + (hp->h_addr_list[0] == NULL)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + continue; + } + + ai = hostent2addrinfo(hp, pai); + if (ai) { + cur->ai_next = ai; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + } + + if (sentinel.ai_next == NULL) + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + + return(sentinel.ai_next); +} + +/* Private. */ + +static size_t +ns_namelen(const char *s) { + int i; + + for (i = strlen(s); i > 0 && s[i-1] == '.'; i--) + (void)NULL; + return ((size_t) i); +} + +static int +init(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !ho_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} diff --git a/lib/bind/irs/lcl_ng.c b/lib/bind/irs/lcl_ng.c new file mode 100644 index 0000000000..7edc28d556 --- /dev/null +++ b/lib/bind/irs/lcl_ng.c @@ -0,0 +1,444 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: lcl_ng.c,v 1.1 2001/03/29 06:31:50 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +/* Definitions */ + +#define NG_HOST 0 /* Host name */ +#define NG_USER 1 /* User name */ +#define NG_DOM 2 /* and Domain name */ +#define LINSIZ 1024 /* Length of netgroup file line */ + +/* + * XXX Warning XXX + * This code is a hack-and-slash special. It realy needs to be + * rewritten with things like strdup, and realloc in mind. + * More reasonable data structures would not be a bad thing. + */ + +/* + * Static Variables and functions used by setnetgrent(), getnetgrent() and + * endnetgrent(). + * There are two linked lists: + * - linelist is just used by setnetgrent() to parse the net group file via. + * parse_netgrp() + * - netgrp is the list of entries for the current netgroup + */ +struct linelist { + struct linelist *l_next; /* Chain ptr. */ + int l_parsed; /* Flag for cycles */ + char * l_groupname; /* Name of netgroup */ + char * l_line; /* Netgroup entrie(s) to be parsed */ +}; + +struct ng_old_struct { + struct ng_old_struct *ng_next; /* Chain ptr */ + char * ng_str[3]; /* Field pointers, see below */ +}; + +struct pvt { + FILE *fp; + struct linelist *linehead; + struct ng_old_struct *nextgrp; + struct { + struct ng_old_struct *gr; + char *grname; + } grouphead; +}; + +/* Forward */ + +static void ng_rewind(struct irs_ng *, const char*); +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); +static int ng_test(struct irs_ng *, const char *, + const char *, const char *, + const char *); +static void ng_minimize(struct irs_ng *); + +static int parse_netgrp(struct irs_ng *, const char*); +static struct linelist *read_for_group(struct irs_ng *, const char *); +static void freelists(struct irs_ng *); + +/* Public */ + +struct irs_ng * +irs_lcl_ng(struct irs_acc *this) { + struct irs_ng *ng; + struct pvt *pvt; + + UNUSED(this); + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + if (!(pvt = memget(sizeof *pvt))) { + memput(ng, sizeof *ng); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + ng->private = pvt; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods */ + +static void +ng_close(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) + fclose(pvt->fp); + freelists(this); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +/* + * Parse the netgroup file looking for the netgroup and build the list + * of netgrp structures. Let parse_netgrp() and read_for_group() do + * most of the work. + */ +static void +ng_rewind(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL && fseek(pvt->fp, SEEK_CUR, 0L) == -1) { + fclose(pvt->fp); + pvt->fp = NULL; + } + + if (pvt->fp == NULL || pvt->grouphead.gr == NULL || + strcmp(group, pvt->grouphead.grname)) { + freelists(this); + if (pvt->fp != NULL) + fclose(pvt->fp); + pvt->fp = fopen(_PATH_NETGROUP, "r"); + if (pvt->fp != NULL) { + if (parse_netgrp(this, group)) + freelists(this); + if (!(pvt->grouphead.grname = strdup(group))) + freelists(this); + fclose(pvt->fp); + pvt->fp = NULL; + } + } + pvt->nextgrp = pvt->grouphead.gr; +} + +/* + * Get the next netgroup off the list. + */ +static int +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->nextgrp) { + *host = pvt->nextgrp->ng_str[NG_HOST]; + *user = pvt->nextgrp->ng_str[NG_USER]; + *domain = pvt->nextgrp->ng_str[NG_DOM]; + pvt->nextgrp = pvt->nextgrp->ng_next; + return (1); + } + return (0); +} + +/* + * Search for a match in a netgroup. + */ +static int +ng_test(struct irs_ng *this, const char *name, + const char *host, const char *user, const char *domain) +{ + const char *ng_host, *ng_user, *ng_domain; + + ng_rewind(this, name); + while (ng_next(this, &ng_host, &ng_user, &ng_domain)) + if ((host == NULL || ng_host == NULL || + !strcmp(host, ng_host)) && + (user == NULL || ng_user == NULL || + !strcmp(user, ng_user)) && + (domain == NULL || ng_domain == NULL || + !strcmp(domain, ng_domain))) { + freelists(this); + return (1); + } + freelists(this); + return (0); +} + +static void +ng_minimize(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +/* Private */ + +/* + * endnetgrent() - cleanup + */ +static void +freelists(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct linelist *lp, *olp; + struct ng_old_struct *gp, *ogp; + + lp = pvt->linehead; + while (lp) { + olp = lp; + lp = lp->l_next; + free(olp->l_groupname); + free(olp->l_line); + free((char *)olp); + } + pvt->linehead = NULL; + if (pvt->grouphead.grname) { + free(pvt->grouphead.grname); + pvt->grouphead.grname = NULL; + } + gp = pvt->grouphead.gr; + while (gp) { + ogp = gp; + gp = gp->ng_next; + if (ogp->ng_str[NG_HOST]) + free(ogp->ng_str[NG_HOST]); + if (ogp->ng_str[NG_USER]) + free(ogp->ng_str[NG_USER]); + if (ogp->ng_str[NG_DOM]) + free(ogp->ng_str[NG_DOM]); + free((char *)ogp); + } + pvt->grouphead.gr = NULL; +} + +/* + * Parse the netgroup file setting up the linked lists. + */ +static int +parse_netgrp(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + char *spos, *epos; + int len, strpos; + char *pos, *gpos; + struct ng_old_struct *grp; + struct linelist *lp = pvt->linehead; + + /* + * First, see if the line has already been read in. + */ + while (lp) { + if (!strcmp(group, lp->l_groupname)) + break; + lp = lp->l_next; + } + if (lp == NULL && + (lp = read_for_group(this, group)) == NULL) + return (1); + if (lp->l_parsed) { + /*fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);*/ + return (1); + } else + lp->l_parsed = 1; + pos = lp->l_line; + while (*pos != '\0') { + if (*pos == '(') { + if (!(grp = malloc(sizeof (struct ng_old_struct)))) { + freelists(this); + errno = ENOMEM; + return (1); + } + memset(grp, 0, sizeof (struct ng_old_struct)); + grp->ng_next = pvt->grouphead.gr; + pvt->grouphead.gr = grp; + pos++; + gpos = strsep(&pos, ")"); + for (strpos = 0; strpos < 3; strpos++) { + if ((spos = strsep(&gpos, ","))) { + while (*spos == ' ' || *spos == '\t') + spos++; + if ((epos = strpbrk(spos, " \t"))) { + *epos = '\0'; + len = epos - spos; + } else + len = strlen(spos); + if (len > 0) { + if(!(grp->ng_str[strpos] + = (char *) + malloc(len + 1))) { + freelists(this); + return (1); + } + memcpy(grp->ng_str[strpos], + spos, + len + 1); + } + } else + goto errout; + } + } else { + spos = strsep(&pos, ", \t"); + if (spos != NULL && parse_netgrp(this, spos)) { + freelists(this); + return (1); + } + } + if (pos == NULL) + break; + while (*pos == ' ' || *pos == ',' || *pos == '\t') + pos++; + } + return (0); + errout: + /*fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname, + spos);*/ + return (1); +} + +/* + * Read the netgroup file and save lines until the line for the netgroup + * is found. Return 1 if eof is encountered. + */ +static struct linelist * +read_for_group(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + char *pos, *spos, *linep = NULL, *olinep; + int len, olen, cont; + struct linelist *lp; + char line[LINSIZ + 1]; + + while (fgets(line, LINSIZ, pvt->fp) != NULL) { + pos = line; + if (*pos == '#') + continue; + while (*pos == ' ' || *pos == '\t') + pos++; + spos = pos; + while (*pos != ' ' && *pos != '\t' && *pos != '\n' && + *pos != '\0') + pos++; + len = pos - spos; + while (*pos == ' ' || *pos == '\t') + pos++; + if (*pos != '\n' && *pos != '\0') { + if (!(lp = malloc(sizeof (*lp)))) { + freelists(this); + return (NULL); + } + lp->l_parsed = 0; + if (!(lp->l_groupname = malloc(len + 1))) { + free(lp); + freelists(this); + return (NULL); + } + memcpy(lp->l_groupname, spos, len); + *(lp->l_groupname + len) = '\0'; + len = strlen(pos); + olen = 0; + olinep = NULL; + + /* + * Loop around handling line continuations. + */ + do { + if (*(pos + len - 1) == '\n') + len--; + if (*(pos + len - 1) == '\\') { + len--; + cont = 1; + } else + cont = 0; + if (len > 0) { + if (!(linep = malloc(olen + len + 1))){ + if (olen > 0) + free(olinep); + free(lp->l_groupname); + free(lp); + freelists(this); + errno = ENOMEM; + return (NULL); + } + if (olen > 0) { + memcpy(linep, olinep, olen); + free(olinep); + } + memcpy(linep + olen, pos, len); + olen += len; + *(linep + olen) = '\0'; + olinep = linep; + } + if (cont) { + if (fgets(line, LINSIZ, pvt->fp)) { + pos = line; + len = strlen(pos); + } else + cont = 0; + } + } while (cont); + lp->l_line = linep; + lp->l_next = pvt->linehead; + pvt->linehead = lp; + + /* + * If this is the one we wanted, we are done. + */ + if (!strcmp(lp->l_groupname, group)) + return (lp); + } + } + return (NULL); +} diff --git a/lib/bind/irs/lcl_nw.c b/lib/bind/irs/lcl_nw.c new file mode 100644 index 0000000000..d6a9710cd9 --- /dev/null +++ b/lib/bind/irs/lcl_nw.c @@ -0,0 +1,371 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_nw.c,v 1.1 2001/03/29 06:31:50 marka Exp $"; +/* from getgrent.c 8.2 (Berkeley) 3/21/94"; */ +/* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */ +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include +#include "irs_p.h" +#include "lcl_p.h" + +#define MAXALIASES 35 +#define MAXADDRSIZE 4 + +struct pvt { + FILE * fp; + char line[BUFSIZ+1]; + struct nwent net; + char * aliases[MAXALIASES]; + char addr[MAXADDRSIZE]; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void nw_close(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static struct nwent * nw_next(struct irs_nw *); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); +static struct __res_state * nw_res_get(struct irs_nw *this); +static void nw_res_set(struct irs_nw *this, + struct __res_state *res, + void (*free_res)(void *)); + +static int init(struct irs_nw *this); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public */ + +struct irs_nw * +irs_lcl_nw(struct irs_acc *this) { + struct irs_nw *nw; + struct pvt *pvt; + + UNUSED(this); + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + nw->private = pvt; + nw->close = nw_close; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->next = nw_next; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + nw->res_get = nw_res_get; + nw->res_set = nw_res_set; + return (nw); +} + +/* Methods */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + if (pvt->fp) + (void)fclose(pvt->fp); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int length, int type) { + struct nwent *p; + + if (init(this) == -1) + return(NULL); + + nw_rewind(this); + while ((p = nw_next(this)) != NULL) + if (p->n_addrtype == type && p->n_length == length) + if (bitncmp(p->n_addr, net, length) == 0) + break; + return (p); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int type) { + struct nwent *p; + char **ap; + + if (init(this) == -1) + return(NULL); + + nw_rewind(this); + while ((p = nw_next(this)) != NULL) { + if (ns_samename(p->n_name, name) == 1 && + p->n_addrtype == type) + break; + for (ap = p->n_aliases; *ap; ap++) + if ((ns_samename(*ap, name) == 1) && + (p->n_addrtype == type)) + goto found; + } + found: + return (p); +} + +static void +nw_rewind(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_NETWORKS, "r"))) + return; + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static struct nwent * +nw_next(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *ret = NULL; + char *p, *cp, **q; + char *bufp, *ndbuf, *dbuf = NULL; + int c, bufsiz, offset = 0; + + if (init(this) == -1) + return(NULL); + + if (pvt->fp == NULL) + nw_rewind(this); + if (pvt->fp == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + bufp = pvt->line; + bufsiz = sizeof(pvt->line); + + again: + p = fgets(bufp + offset, bufsiz - offset, pvt->fp); + if (p == NULL) + goto cleanup; + if (!strchr(p, '\n') && !feof(pvt->fp)) { +#define GROWBUF 1024 + /* allocate space for longer line */ + if (dbuf == NULL) { + if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL) + strcpy(ndbuf, bufp); + } else + ndbuf = realloc(dbuf, bufsiz + GROWBUF); + if (ndbuf) { + dbuf = ndbuf; + bufp = dbuf; + bufsiz += GROWBUF; + offset = strlen(dbuf); + } else { + /* allocation failed; skip this long line */ + while ((c = getc(pvt->fp)) != EOF) + if (c == '\n') + break; + if (c != EOF) + ungetc(c, pvt->fp); + } + goto again; + } + + p -= offset; + offset = 0; + + if (*p == '#') + goto again; + + cp = strpbrk(p, "#\n"); + if (cp != NULL) + *cp = '\0'; + pvt->net.n_name = p; + cp = strpbrk(p, " \t"); + if (cp == NULL) + goto again; + *cp++ = '\0'; + while (*cp == ' ' || *cp == '\t') + cp++; + p = strpbrk(cp, " \t"); + if (p != NULL) + *p++ = '\0'; + pvt->net.n_length = inet_net_pton(AF_INET, cp, pvt->addr, + sizeof pvt->addr); + if (pvt->net.n_length < 0) + goto again; + pvt->net.n_addrtype = AF_INET; + pvt->net.n_addr = pvt->addr; + q = pvt->net.n_aliases = pvt->aliases; + if (p != NULL) { + cp = p; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->aliases[MAXALIASES - 1]) + *q++ = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + } + *q = NULL; + ret = &pvt->net; + + cleanup: + if (dbuf) + free(dbuf); + + return (ret); +} + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static struct __res_state * +nw_res_get(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + nw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +nw_res_set(struct irs_nw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +static int +init(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !nw_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} diff --git a/lib/bind/irs/lcl_p.h b/lib/bind/irs/lcl_p.h new file mode 100644 index 0000000000..7da2f26e03 --- /dev/null +++ b/lib/bind/irs/lcl_p.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: lcl_p.h,v 1.1 2001/03/29 06:31:50 marka Exp $ + */ + +/* + * lcl_p.h - private include file for the local accessor functions. + */ + +#ifndef _LCL_P_H_INCLUDED +#define _LCL_P_H_INCLUDED + +/* + * Object state. + */ +struct lcl_p { + struct __res_state * res; + void (*free_res) __P((void *)); +}; + +/* + * Externs. + */ + +extern struct irs_acc * irs_lcl_acc __P((const char *)); +extern struct irs_gr * irs_lcl_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_lcl_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_lcl_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_lcl_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_lcl_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_lcl_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_lcl_ng __P((struct irs_acc *)); + +#endif /*_LCL_P_H_INCLUDED*/ diff --git a/lib/bind/irs/lcl_pr.c b/lib/bind/irs/lcl_pr.c new file mode 100644 index 0000000000..a4010a5d1e --- /dev/null +++ b/lib/bind/irs/lcl_pr.c @@ -0,0 +1,284 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_pr.c,v 1.1 2001/03/29 06:31:50 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +#ifndef _PATH_PROTOCOLS +#define _PATH_PROTOCOLS "/etc/protocols" +#endif +#define MAXALIASES 35 + +/* Types */ + +struct pvt { + FILE * fp; + char line[BUFSIZ+1]; + struct protoent proto; + char * proto_aliases[MAXALIASES]; +}; + +/* Forward */ + +static void pr_close(struct irs_pr *); +static struct protoent * pr_next(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public */ + +struct irs_pr * +irs_lcl_pr(struct irs_acc *this) { + struct irs_pr *pr; + struct pvt *pvt; + + if (!(pr = memget(sizeof *pr))) { + errno = ENOMEM; + return (NULL); + } + if (!(pvt = memget(sizeof *pvt))) { + memput(pr, sizeof *this); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pr->private = pvt; + pr->close = pr_close; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->next = pr_next; + pr->rewind = pr_rewind; + pr->minimize = pr_minimize; + pr->res_get = NULL; + pr->res_set = NULL; + return (pr); +} + +/* Methods */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) + (void) fclose(pvt->fp); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + + struct protoent *p; + char **cp; + + pr_rewind(this); + while ((p = pr_next(this))) { + if (!strcmp(p->p_name, name)) + goto found; + for (cp = p->p_aliases; *cp; cp++) + if (!strcmp(*cp, name)) + goto found; + } + found: + return (p); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int proto) { + struct protoent *p; + + pr_rewind(this); + while ((p = pr_next(this))) + if (p->p_proto == proto) + break; + return (p); +} + +static void +pr_rewind(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_PROTOCOLS, "r" ))) + return; + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static struct protoent * +pr_next(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *cp, **q; + char *bufp, *ndbuf, *dbuf = NULL; + int c, bufsiz, offset; + + if (!pvt->fp) + pr_rewind(this); + if (!pvt->fp) + return (NULL); + bufp = pvt->line; + bufsiz = BUFSIZ; + offset = 0; + again: + if ((p = fgets(bufp + offset, bufsiz - offset, pvt->fp)) == NULL) { + if (dbuf) + free(dbuf); + return (NULL); + } + if (!strchr(p, '\n') && !feof(pvt->fp)) { +#define GROWBUF 1024 + /* allocate space for longer line */ + if (dbuf == NULL) { + if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL) + strcpy(ndbuf, bufp); + } else + ndbuf = realloc(dbuf, bufsiz + GROWBUF); + if (ndbuf) { + dbuf = ndbuf; + bufp = dbuf; + bufsiz += GROWBUF; + offset = strlen(dbuf); + } else { + /* allocation failed; skip this long line */ + while ((c = getc(pvt->fp)) != EOF) + if (c == '\n') + break; + if (c != EOF) + ungetc(c, pvt->fp); + } + goto again; + } + + p -= offset; + offset = 0; + + if (*p == '#') + goto again; + cp = strpbrk(p, "#\n"); + if (cp != NULL) + *cp = '\0'; + pvt->proto.p_name = p; + cp = strpbrk(p, " \t"); + if (cp == NULL) + goto again; + *cp++ = '\0'; + while (*cp == ' ' || *cp == '\t') + cp++; + p = strpbrk(cp, " \t"); + if (p != NULL) + *p++ = '\0'; + pvt->proto.p_proto = atoi(cp); + q = pvt->proto.p_aliases = pvt->proto_aliases; + if (p != NULL) { + cp = p; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->proto_aliases[MAXALIASES - 1]) + *q++ = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + } + *q = NULL; + return (&pvt->proto); +} + +static void +pr_minimize(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} diff --git a/lib/bind/irs/lcl_pw.c b/lib/bind/irs/lcl_pw.c new file mode 100644 index 0000000000..6b63749cfd --- /dev/null +++ b/lib/bind/irs/lcl_pw.c @@ -0,0 +1,308 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_pw.c,v 1.1 2001/03/29 06:31:51 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Extern */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_pw_unneeded; +#else + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +/* + * The lookup techniques and data extraction code here must be kept + * in sync with that in `pwd_mkdb'. + */ + + +/* Types */ + +struct pvt { + struct passwd passwd; /* password structure */ + DB *pw_db; /* password database */ + int pw_keynum; /* key counter */ + int warned; + u_int max; + char * line; +}; + +/* Forward */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_next(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); + +static int initdb(struct pvt *); +static int hashpw(struct irs_pw *, DBT *); + +/* Public */ +struct irs_pw * +irs_lcl_pw(struct irs_acc *this) { + struct irs_pw *pw; + struct pvt *pvt; + + UNUSED(this); + + if (!(pw = memget(sizeof *pw))) { + errno = ENOMEM; + return (NULL); + } + memset(pw, 0x5e, sizeof *pw); + if (!(pvt = memget(sizeof *pvt))) { + free(pw); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pw->private = pvt; + pw->close = pw_close; + pw->next = pw_next; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + pw->res_get = NULL; + pw->res_set = NULL; + return (pw); +} + +/* Methods */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->pw_db) { + (void)(pvt->pw_db->close)(pvt->pw_db); + pvt->pw_db = NULL; + } + if (pvt->line) + memput(pvt->line, pvt->max); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct passwd * +pw_next(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + DBT key; + char bf[sizeof(pvt->pw_keynum) + 1]; + + if (!initdb(pvt)) + return (NULL); + + ++pvt->pw_keynum; + bf[0] = _PW_KEYBYNUM; + memcpy(bf + 1, (char *)&pvt->pw_keynum, sizeof(pvt->pw_keynum)); + key.data = (u_char *)bf; + key.size = sizeof(pvt->pw_keynum) + 1; + return (hashpw(this, &key) ? &pvt->passwd : NULL); +} + +static struct passwd * +pw_byname(struct irs_pw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + DBT key; + int len, rval; + char bf[UT_NAMESIZE + 1]; + + if (!initdb(pvt)) + return (NULL); + + bf[0] = _PW_KEYBYNAME; + len = strlen(name); + memcpy(bf + 1, name, MIN(len, UT_NAMESIZE)); + key.data = (u_char *)bf; + key.size = len + 1; + rval = hashpw(this, &key); + + return (rval ? &pvt->passwd : NULL); +} + + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + struct pvt *pvt = (struct pvt *)this->private; + DBT key; + int keyuid, rval; + char bf[sizeof(keyuid) + 1]; + + if (!initdb(pvt)) + return (NULL); + + bf[0] = _PW_KEYBYUID; + keyuid = uid; + memcpy(bf + 1, &keyuid, sizeof(keyuid)); + key.data = (u_char *)bf; + key.size = sizeof(keyuid) + 1; + rval = hashpw(this, &key); + + return (rval ? &pvt->passwd : NULL); +} + +static void +pw_rewind(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->pw_keynum = 0; +} + +static void +pw_minimize(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->pw_db != NULL) { + (void) (*pvt->pw_db->close)(pvt->pw_db); + pvt->pw_db = NULL; + } +} + +/* Private. */ + +static int +initdb(struct pvt *pvt) { + const char *p; + + if (pvt->pw_db) { + if (lseek((*pvt->pw_db->fd)(pvt->pw_db), 0L, SEEK_CUR) >= 0L) + return (1); + else + (void) (*pvt->pw_db->close)(pvt->pw_db); + } + pvt->pw_db = dbopen((p = _PATH_SMP_DB), O_RDONLY, 0, DB_HASH, NULL); + if (!pvt->pw_db) + pvt->pw_db = dbopen((p =_PATH_MP_DB), O_RDONLY, + 0, DB_HASH, NULL); + if (pvt->pw_db) + return (1); + if (!pvt->warned) { + syslog(LOG_ERR, "%s: %m", p); + pvt->warned++; + } + return (0); +} + +static int +hashpw(struct irs_pw *this, DBT *key) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *t, *l; + DBT data; + + if ((pvt->pw_db->get)(pvt->pw_db, key, &data, 0)) + return (0); + p = (char *)data.data; + if (data.size > pvt->max) { + size_t newlen = pvt->max + 1024; + char *p = memget(newlen); + if (p == NULL) { + return (0); + } + if (pvt->line != NULL) { + memcpy(p, pvt->line, pvt->max); + memput(pvt->line, pvt->max); + } + pvt->max = newlen; + pvt->line = p; + } + + /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */ + t = pvt->line; + l = pvt->line + pvt->max; +#define EXPAND(e) if ((e = t) == NULL) return (0); else \ + do if (t >= l) return (0); while ((*t++ = *p++) != '\0') +#define SCALAR(v) if (t + sizeof v >= l) return (0); else \ + (memmove(&(v), p, sizeof v), p += sizeof v) + EXPAND(pvt->passwd.pw_name); + EXPAND(pvt->passwd.pw_passwd); + SCALAR(pvt->passwd.pw_uid); + SCALAR(pvt->passwd.pw_gid); + SCALAR(pvt->passwd.pw_change); + EXPAND(pvt->passwd.pw_class); + EXPAND(pvt->passwd.pw_gecos); + EXPAND(pvt->passwd.pw_dir); + EXPAND(pvt->passwd.pw_shell); + SCALAR(pvt->passwd.pw_expire); + return (1); +} + +#endif /* WANT_IRS_PW */ diff --git a/lib/bind/irs/lcl_sv.c b/lib/bind/irs/lcl_sv.c new file mode 100644 index 0000000000..b83ce9ac09 --- /dev/null +++ b/lib/bind/irs/lcl_sv.c @@ -0,0 +1,431 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_sv.c,v 1.1 2001/03/29 06:31:51 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#include +#include +#include +#include +#include + +#ifdef IRS_LCL_SV_DB +#include +#endif +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Types */ + +struct pvt { +#ifdef IRS_LCL_SV_DB + DB * dbh; + int dbf; +#endif + struct lcl_sv sv; +}; + +/* Forward */ + +static void sv_close(struct irs_sv*); +static struct servent * sv_next(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, const char *, + const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); +/*global*/ struct servent * irs_lclsv_fnxt(struct lcl_sv *); +#ifdef IRS_LCL_SV_DB +static struct servent * sv_db_rec(struct lcl_sv *, DBT *, DBT *); +#endif + +/* Portability */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public */ + +struct irs_sv * +irs_lcl_sv(struct irs_acc *this) { + struct irs_sv *sv; + struct pvt *pvt; + + UNUSED(this); + + if ((sv = memget(sizeof *sv)) == NULL) { + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + if ((pvt = memget(sizeof *pvt)) == NULL) { + memput(sv, sizeof *sv); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + sv->private = pvt; + sv->close = sv_close; + sv->next = sv_next; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->rewind = sv_rewind; + sv->minimize = sv_minimize; + sv->res_get = NULL; + sv->res_set = NULL; +#ifdef IRS_LCL_SV_DB + pvt->dbf = R_FIRST; +#endif + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) + (*pvt->dbh->close)(pvt->dbh); +#endif + if (pvt->sv.fp) + fclose(pvt->sv.fp); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { +#ifdef IRS_LCL_SV_DB + struct pvt *pvt = (struct pvt *)this->private; +#endif + struct servent *p; + char **cp; + + sv_rewind(this); +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) { + DBT key, data; + + /* Note that (sizeof "/") == 2. */ + if ((strlen(name) + sizeof "/" + proto ? strlen(proto) : 0) + > sizeof pvt->sv.line) + goto try_local; + key.data = pvt->sv.line; + key.size = SPRINTF((pvt->sv.line, "%s/%s", name, + proto ? proto : "")) + 1; + if (proto != NULL) { + if ((*pvt->dbh->get)(pvt->dbh, &key, &data, 0) != 0) + return (NULL); + } else if ((*pvt->dbh->seq)(pvt->dbh, &key, &data, R_CURSOR) + != 0) + return (NULL); + return (sv_db_rec(&pvt->sv, &key, &data)); + } + try_local: +#endif + + while ((p = sv_next(this))) { + if (strcmp(name, p->s_name) == 0) + goto gotname; + for (cp = p->s_aliases; *cp; cp++) + if (strcmp(name, *cp) == 0) + goto gotname; + continue; + gotname: + if (proto == NULL || strcmp(p->s_proto, proto) == 0) + break; + } + return (p); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { +#ifdef IRS_LCL_SV_DB + struct pvt *pvt = (struct pvt *)this->private; +#endif + struct servent *p; + + sv_rewind(this); +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) { + DBT key, data; + u_short *ports; + + ports = (u_short *)pvt->sv.line; + ports[0] = 0; + ports[1] = port; + key.data = ports; + key.size = sizeof(u_short) * 2; + if (proto && *proto) { + strncpy((char *)ports + key.size, proto, + BUFSIZ - key.size); + key.size += strlen((char *)ports + key.size) + 1; + if ((*pvt->dbh->get)(pvt->dbh, &key, &data, 0) != 0) + return (NULL); + } else { + if ((*pvt->dbh->seq)(pvt->dbh, &key, &data, R_CURSOR) + != 0) + return (NULL); + } + return (sv_db_rec(&pvt->sv, &key, &data)); + } +#endif + while ((p = sv_next(this))) { + if (p->s_port != port) + continue; + if (proto == NULL || strcmp(p->s_proto, proto) == 0) + break; + } + return (p); +} + +static void +sv_rewind(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->sv.fp) { + if (fseek(pvt->sv.fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->sv.fp); + pvt->sv.fp = NULL; + } +#ifdef IRS_LCL_SV_DB + pvt->dbf = R_FIRST; + if (pvt->dbh != NULL) + return; + pvt->dbh = dbopen(_PATH_SERVICES_DB, O_RDONLY,O_RDONLY,DB_BTREE, NULL); + if (pvt->dbh != NULL) { + if (fcntl((*pvt->dbh->fd)(pvt->dbh), F_SETFD, 1) < 0) { + (*pvt->dbh->close)(pvt->dbh); + pvt->dbh = NULL; + } + return; + } +#endif + if ((pvt->sv.fp = fopen(_PATH_SERVICES, "r")) == NULL) + return; + if (fcntl(fileno(pvt->sv.fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->sv.fp); + pvt->sv.fp = NULL; + } +} + +static struct servent * +sv_next(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + +#ifdef IRS_LCL_SV_DB + if (pvt->dbh == NULL && pvt->sv.fp == NULL) +#else + if (pvt->sv.fp == NULL) +#endif + sv_rewind(this); + +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) { + DBT key, data; + + while ((*pvt->dbh->seq)(pvt->dbh, &key, &data, pvt->dbf) == 0){ + pvt->dbf = R_NEXT; + if (((char *)key.data)[0]) + continue; + return (sv_db_rec(&pvt->sv, &key, &data)); + } + } +#endif + + if (pvt->sv.fp == NULL) + return (NULL); + return (irs_lclsv_fnxt(&pvt->sv)); +} + +static void +sv_minimize(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) { + (*pvt->dbh->close)(pvt->dbh); + pvt->dbh = NULL; + } +#endif + if (pvt->sv.fp != NULL) { + (void)fclose(pvt->sv.fp); + pvt->sv.fp = NULL; + } +} + +/* Quasipublic. */ + +struct servent * +irs_lclsv_fnxt(struct lcl_sv *sv) { + char *p, *cp, **q; + + again: + if ((p = fgets(sv->line, BUFSIZ, sv->fp)) == NULL) + return (NULL); + if (*p == '#') + goto again; + sv->serv.s_name = p; + while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#') + ++p; + if (*p == '\0' || *p == '#' || *p == '\n') + goto again; + *p++ = '\0'; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '\0' || *p == '#' || *p == '\n') + goto again; + sv->serv.s_port = htons((u_short)strtol(p, &cp, 10)); + if (cp == p || (*cp != '/' && *cp != ',')) + goto again; + p = cp + 1; + sv->serv.s_proto = p; + + q = sv->serv.s_aliases = sv->serv_aliases; + + while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#') + ++p; + + while (*p == ' ' || *p == '\t') { + *p++ = '\0'; + while (*p == ' ' || *p == '\t') + ++p; + if (*p == '\0' || *p == '#' || *p == '\n') + break; + if (q < &sv->serv_aliases[IRS_SV_MAXALIASES - 1]) + *q++ = p; + while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#') + ++p; + } + + *p = '\0'; + *q = NULL; + return (&sv->serv); +} + +/* Private. */ + +#ifdef IRS_LCL_SV_DB +static struct servent * +sv_db_rec(struct lcl_sv *sv, DBT *key, DBT *data) { + char *p, **q; + int n; + + p = data->data; + p[data->size - 1] = '\0'; /* should be, but we depend on it */ + + if (((char *)key->data)[0] == '\0') { + if (key->size < sizeof(u_short)*2 || data->size < 2) + return (NULL); + sv->serv.s_port = ((u_short *)key->data)[1]; + n = strlen(p) + 1; + if (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/lib/bind/irs/nis.c b/lib/bind/irs/nis.c new file mode 100644 index 0000000000..e0ceccc5e1 --- /dev/null +++ b/lib/bind/irs/nis.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis.c,v 1.1 2001/03/29 06:31:51 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifdef WANT_IRS_NIS + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "nis_p.h" + +/* Forward */ + +static void nis_close(struct irs_acc *); +static struct __res_state * nis_res_get(struct irs_acc *); +static void nis_res_set(struct irs_acc *, struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_acc * +irs_nis_acc(const char *options) { + struct nis_p *nis; + struct irs_acc *acc; + char *domain; + + UNUSED(options); + + if (yp_get_default_domain(&domain) != 0) + return (NULL); + if (!(nis = memget(sizeof *nis))) { + errno = ENOMEM; + return (NULL); + } + memset(nis, 0, sizeof *nis); + if (!(acc = memget(sizeof *acc))) { + memput(nis, sizeof *nis); + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + acc->private = nis; + nis->domain = strdup(domain); +#ifdef WANT_IRS_GR + acc->gr_map = irs_nis_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_nis_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_nis_sv; + acc->pr_map = irs_nis_pr; + acc->ho_map = irs_nis_ho; + acc->nw_map = irs_nis_nw; + acc->ng_map = irs_nis_ng; + acc->res_get = nis_res_get; + acc->res_set = nis_res_set; + acc->close = nis_close; + return (acc); +} + +/* Methods */ + +static struct __res_state * +nis_res_get(struct irs_acc *this) { + struct nis_p *nis = (struct nis_p *)this->private; + + if (nis->res == NULL) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) + return (NULL); + memset(res, 0, sizeof *res); + nis_res_set(this, res, free); + } + + if ((nis->res->options & RES_INIT) == 0 && + res_ninit(nis->res) < 0) + return (NULL); + + return (nis->res); +} + +static void +nis_res_set(struct irs_acc *this, struct __res_state *res, + void (*free_res)(void *)) { + struct nis_p *nis = (struct nis_p *)this->private; + + if (nis->res && nis->free_res) { + res_nclose(nis->res); + (*nis->free_res)(nis->res); + } + + nis->res = res; + nis->free_res = free_res; +} + +static void +nis_close(struct irs_acc *this) { + struct nis_p *nis = (struct nis_p *)this->private; + + if (nis->res && nis->free_res) + (*nis->free_res)(nis->res); + free(nis->domain); + memput(nis, sizeof *nis); + memput(this, sizeof *this); +} + +#endif /*WANT_IRS_NIS*/ diff --git a/lib/bind/irs/nis_gr.c b/lib/bind/irs/nis_gr.c new file mode 100644 index 0000000000..a617fd3ee0 --- /dev/null +++ b/lib/bind/irs/nis_gr.c @@ -0,0 +1,353 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_gr.c,v 1.1 2001/03/29 06:31:51 marka Exp $"; +/* from getgrent.c 8.2 (Berkeley) 3/21/94"; */ +/* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */ +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#if !defined(WANT_IRS_GR) || !defined(WANT_IRS_NIS) +static int __bind_irs_gr_unneeded; +#else + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + /* + * Need space to store the entries read from the group file. + * The members list also needs space per member, and the + * strings making up the user names must be allocated + * somewhere. Rather than doing lots of small allocations, + * we keep one buffer and resize it as needed. + */ + struct group group; + size_t nmemb; /* Malloc'd max index of gr_mem[]. */ + char * membuf; + size_t membufsize; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char group_bygid[] = "group.bygid"; +static /*const*/ char group_byname[] = "group.byname"; + +/* Forward */ + +static void gr_close(struct irs_gr *); +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static void gr_minimize(struct irs_gr *); + +static struct group * makegroupent(struct irs_gr *); +static void nisfree(struct pvt *, enum do_what); + +/* Public */ + +struct irs_gr * +irs_nis_gr(struct irs_acc *this) { + struct irs_gr *gr; + struct pvt *pvt; + + if (!(gr = memget(sizeof *gr))) { + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x5e, sizeof *gr); + if (!(pvt = memget(sizeof *pvt))) { + memput(gr, sizeof *gr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + gr->private = pvt; + gr->close = gr_close; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->list = make_group_list; + gr->minimize = gr_minimize; + gr->res_get = NULL; + gr->res_set = NULL; + return (gr); +} + +/* Methods */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->group.gr_mem) + free(pvt->group.gr_mem); + if (pvt->membuf) + free(pvt->membuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct group * +gr_next(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct group *rval; + int r; + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, group_byname, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, group_byname, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + errno = ENOENT; + return (NULL); + } + rval = makegroupent(this); + } while (rval == NULL); + return (rval); +} + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, group_byname, name, strlen(name), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makegroupent(this)); +} + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "4294967295"]; + int r; + + nisfree(pvt, do_val); + (void) sprintf(tmp, "%u", (unsigned int)gid); + r = yp_match(pvt->nis_domain, group_bygid, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makegroupent(this)); +} + +static void +gr_rewind(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static void +gr_minimize(struct irs_gr *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static struct group * +makegroupent(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + unsigned int num_members = 0; + char *cp, **new; + u_long t; + + if (pvt->group.gr_mem) { + free(pvt->group.gr_mem); + pvt->group.gr_mem = NULL; + pvt->nmemb = 0; + } + if (pvt->membuf) + free(pvt->membuf); + pvt->membuf = pvt->curval_data; + pvt->curval_data = NULL; + + cp = pvt->membuf; + pvt->group.gr_name = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->group.gr_passwd = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + errno = -1; + t = strtoul(cp, NULL, 10); + if (errno == ERANGE) + goto cleanup; + pvt->group.gr_gid = (gid_t) t; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + cp++; + + if (*cp && cp[strlen(cp)-1] == '\n') + cp[strlen(cp)-1] = '\0'; + + /* + * Parse the members out. + */ + while (*cp) { + if (num_members+1 >= pvt->nmemb || pvt->group.gr_mem == NULL) { + pvt->nmemb += 10; + new = realloc(pvt->group.gr_mem, + pvt->nmemb * sizeof(char *)); + if (new == NULL) + goto cleanup; + pvt->group.gr_mem = new; + } + pvt->group.gr_mem[num_members++] = cp; + if (!(cp = strchr(cp, ','))) + break; + *cp++ = '\0'; + } + if (pvt->group.gr_mem == NULL) { + pvt->group.gr_mem = malloc(sizeof(char*)); + if (!pvt->group.gr_mem) + goto cleanup; + pvt->nmemb = 1; + } + pvt->group.gr_mem[num_members] = NULL; + + return (&pvt->group); + + cleanup: + if (pvt->group.gr_mem) { + free(pvt->group.gr_mem); + pvt->group.gr_mem = NULL; + pvt->nmemb = 0; + } + if (pvt->membuf) { + free(pvt->membuf); + pvt->membuf = NULL; + } + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +#endif /* WANT_IRS_GR && WANT_IRS_NIS */ diff --git a/lib/bind/irs/nis_ho.c b/lib/bind/irs/nis_ho.c new file mode 100644 index 0000000000..970412fa08 --- /dev/null +++ b/lib/bind/irs/nis_ho.c @@ -0,0 +1,461 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_ho.c,v 1.1 2001/03/29 06:31:51 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +#define MAXALIASES 35 +#define MAXADDRS 35 + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + struct hostent host; + char * h_addr_ptrs[MAXADDRS + 1]; + char * host_aliases[MAXALIASES + 1]; + char hostbuf[8*1024]; + u_char host_addr[16]; /* IPv4 or IPv6 */ + struct __res_state *res; + void (*free_res)(void *); +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; +static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; +static /*const*/ char hosts_byname[] = "hosts.byname"; +static /*const*/ char hosts_byaddr[] = "hosts.byaddr"; + +/* Forwards */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); +static struct __res_state * ho_res_get(struct irs_ho *this); +static void ho_res_set(struct irs_ho *this, + struct __res_state *res, + void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +static struct hostent * makehostent(struct irs_ho *this); +static void nisfree(struct pvt *, enum do_what); +static int init(struct irs_ho *this); + +/* Public */ + +struct irs_ho * +irs_nis_ho(struct irs_acc *this) { + struct irs_ho *ho; + struct pvt *pvt; + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(ho = memget(sizeof *ho))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->res_set = ho_res_set; + ho->res_get = ho_res_get; + ho->addrinfo = ho_addrinfo; + return (ho); +} + +/* Methods */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + nisfree(pvt, do_all); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + + if (init(this) == -1) + return (NULL); + + if (pvt->res->options & RES_USE_INET6) { + hp = ho_byname2(this, name, AF_INET6); + if (hp) + return (hp); + } + return (ho_byname2(this, name, AF_INET)); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + + UNUSED(af); + + if (init(this) == -1) + return (NULL); + + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, hosts_byname, name, + strlen(name), &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + return (makehostent(this)); +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; + const u_char *uaddr = addr; + int r; + + if (init(this) == -1) + return (NULL); + + if (af == AF_INET6 && len == IN6ADDRSZ && + (!memcmp(uaddr, mapped, sizeof mapped) || + !memcmp(uaddr, tunnelled, sizeof tunnelled))) { + /* Unmap. */ + addr = (const u_char *)addr + sizeof mapped; + uaddr += sizeof mapped; + af = AF_INET; + len = INADDRSZ; + } + if (inet_ntop(af, uaddr, tmp, sizeof tmp) == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, hosts_byaddr, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + return (makehostent(this)); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *rval; + int r; + + if (init(this) == -1) + return (NULL); + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, hosts_byaddr, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, hosts_byaddr, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + rval = makehostent(this); + } while (rval == NULL); + return (rval); +} + +static void +ho_rewind(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +ho_res_get(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + ho_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +ho_res_set(struct irs_ho *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +struct nis_res_target { + struct nis_res_target *next; + int family; +}; + +/* XXX */ +extern struct addrinfo *hostent2addrinfo __P((struct hostent *, + const struct addrinfo *pai)); + +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + struct nis_res_target q, q2, *p; + struct addrinfo sentinel, *cur; + + memset(&q, 0, sizeof(q2)); + memset(&q2, 0, sizeof(q2)); + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + switch(pai->ai_family) { + case AF_UNSPEC: /* INET6 then INET4 */ + q.family = AF_INET6; + q.next = &q2; + q2.family = AF_INET; + break; + case AF_INET6: + q.family = AF_INET6; + break; + case AF_INET: + q.family = AF_INET; + break; + default: + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /* ??? */ + return(NULL); + } + + for (p = &q; p; p = p->next) { + struct addrinfo *ai; + + hp = (*this->byname2)(this, name, p->family); + if (hp == NULL) { + /* byname2 should've set an appropriate error */ + continue; + } + if ((hp->h_name == NULL) || (hp->h_name[0] == 0) || + (hp->h_addr_list[0] == NULL)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + continue; + } + ai = hostent2addrinfo(hp, pai); + if (ai) { + cur->ai_next = ai; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + } + + if (sentinel.ai_next == NULL) + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + + return(sentinel.ai_next); +} + +/* Private */ + +static struct hostent * +makehostent(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + static const char spaces[] = " \t"; + char *cp, **q, *p; + int af, len; + + p = pvt->curval_data; + if ((cp = strpbrk(p, "#\n")) != NULL) + *cp = '\0'; + if (!(cp = strpbrk(p, spaces))) + return (NULL); + *cp++ = '\0'; + if ((pvt->res->options & RES_USE_INET6) && + inet_pton(AF_INET6, p, pvt->host_addr) > 0) { + af = AF_INET6; + len = IN6ADDRSZ; + } else if (inet_pton(AF_INET, p, pvt->host_addr) > 0) { + if (pvt->res->options & RES_USE_INET6) { + map_v4v6_address((char*)pvt->host_addr, + (char*)pvt->host_addr); + af = AF_INET6; + len = IN6ADDRSZ; + } else { + af = AF_INET; + len = INADDRSZ; + } + } else { + return (NULL); + } + pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; + pvt->h_addr_ptrs[1] = NULL; + pvt->host.h_addr_list = pvt->h_addr_ptrs; + pvt->host.h_length = len; + pvt->host.h_addrtype = af; + cp += strspn(cp, spaces); + pvt->host.h_name = cp; + q = pvt->host.h_aliases = pvt->host_aliases; + if ((cp = strpbrk(cp, spaces)) != NULL) + *cp++ = '\0'; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->host_aliases[MAXALIASES]) + *q++ = cp; + if ((cp = strpbrk(cp, spaces)) != NULL) + *cp++ = '\0'; + } + *q = NULL; + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (&pvt->host); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +static int +init(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !ho_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} +#endif /*WANT_IRS_NIS*/ diff --git a/lib/bind/irs/nis_ng.c b/lib/bind/irs/nis_ng.c new file mode 100644 index 0000000000..9b4efa9496 --- /dev/null +++ b/lib/bind/irs/nis_ng.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_ng.c,v 1.1 2001/03/29 06:31:52 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct tmpgrp { + const char * name; + const char * host; + const char * user; + const char * domain; + struct tmpgrp * next; +}; + +struct pvt { + char * nis_domain; + struct tmpgrp * tmp; + struct tmpgrp * cur; + char * tmpgroup; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char netgroup_map[] = "netgroup"; + +/* Forward */ + +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); +static int ng_test(struct irs_ng *, + const char *, const char *, + const char *, const char *); +static void ng_rewind(struct irs_ng *, const char *); +static void ng_minimize(struct irs_ng *); + +static void add_group_to_list(struct pvt *, const char *, int); +static void add_tuple_to_list(struct pvt *, const char *, char *); +static void tmpfree(struct pvt *); + +/* Public */ + +struct irs_ng * +irs_nis_ng(struct irs_acc *this) { + struct irs_ng *ng; + struct pvt *pvt; + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + if (!(pvt = memget(sizeof *pvt))) { + memput(ng, sizeof *ng); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + ng->private = pvt; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods */ + +static void +ng_close(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + tmpfree(pvt); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static int +ng_next(struct irs_ng *this, const char **host, const char **user, const char **domain) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->cur) + return (0); + *host = pvt->cur->host; + *user = pvt->cur->user; + *domain = pvt->cur->domain; + pvt->cur = pvt->cur->next; + return (1); +} + +static int +ng_test(struct irs_ng *this, const char *name, + const char *host, const char *user, const char *domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct tmpgrp *cur; + + tmpfree(pvt); + add_group_to_list(pvt, name, strlen(name)); + for (cur = pvt->tmp; cur; cur = cur->next) { + if ((!host || !cur->host || !strcmp(host, cur->host)) && + (!user || !cur->user || !strcmp(user, cur->user)) && + (!domain || !cur->domain || !strcmp(domain, cur->domain))) + break; + } + tmpfree(pvt); + return ((cur == NULL) ? 0 : 1); +} + +static void +ng_rewind(struct irs_ng *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + + /* Either hand back or free the existing list. */ + if (pvt->tmpgroup) { + if (pvt->tmp && !strcmp(pvt->tmpgroup, name)) + goto reset; + tmpfree(pvt); + } + pvt->tmpgroup = strdup(name); + add_group_to_list(pvt, name, strlen(name)); + reset: + pvt->cur = pvt->tmp; +} + +static void +ng_minimize(struct irs_ng *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static void +add_group_to_list(struct pvt *pvt, const char *name, int len) { + char *vdata, *cp, *np; + struct tmpgrp *tmp; + int vlen, r; + + /* Don't add the same group to the list more than once. */ + for (tmp = pvt->tmp; tmp; tmp = tmp->next) + if (!strcmp(tmp->name, name)) + return; + + r = yp_match(pvt->nis_domain, netgroup_map, name, len, + &vdata, &vlen); + if (r == 0) { + cp = vdata; + if (*cp && cp[strlen(cp)-1] == '\n') + cp[strlen(cp)-1] = '\0'; + for ( ; cp; cp = np) { + np = strchr(cp, ' '); + if (np) + *np++ = '\0'; + if (*cp == '(') + add_tuple_to_list(pvt, name, cp); + else + add_group_to_list(pvt, cp, strlen(cp)); + } + free(vdata); + } +} + +static void +add_tuple_to_list(struct pvt *pvt, const char *name, char *cp) { + struct tmpgrp *tmp; + char *tp, *np; + + INSIST(*cp++ == '('); + + tmp = malloc(sizeof *tmp + strlen(name) + sizeof '\0' + + strlen(cp) - sizeof ')'); + if (!tmp) + return; + memset(tmp, 0, sizeof *tmp); + tp = ((char *)tmp) + sizeof *tmp; + + /* Name */ + strcpy(tp, name); + tmp->name = tp; + tp += strlen(tp) + 1; + + /* Host */ + if (!(np = strchr(cp, ','))) + goto cleanup; + *np++ = '\0'; + strcpy(tp, cp); + tmp->host = tp; + tp += strlen(tp) + 1; + cp = np; + + /* User */ + if (!(np = strchr(cp, ','))) + goto cleanup; + *np++ = '\0'; + strcpy(tp, cp); + tmp->user = tp; + tp += strlen(tp) + 1; + cp = np; + + /* Domain */ + if (!(np = strchr(cp, ')'))) + goto cleanup; + *np++ = '\0'; + strcpy(tp, cp); + tmp->domain = tp; + + /* + * Empty string in file means wildcard, but + * NULL string in return value means wildcard. + */ + if (!*tmp->host) + tmp->host = NULL; + if (!*tmp->user) + tmp->user = NULL; + if (!*tmp->domain) + tmp->domain = NULL; + + /* Add to list (LIFO). */ + tmp->next = pvt->tmp; + pvt->tmp = tmp; + return; + + cleanup: + free(tmp); +} + +static void +tmpfree(struct pvt *pvt) { + struct tmpgrp *cur, *next; + + if (pvt->tmpgroup) { + free(pvt->tmpgroup); + pvt->tmpgroup = NULL; + } + for (cur = pvt->tmp; cur; cur = next) { + next = cur->next; + free(cur); + } + pvt->tmp = NULL; +} + +#endif /*WANT_IRS_NIS*/ diff --git a/lib/bind/irs/nis_nw.c b/lib/bind/irs/nis_nw.c new file mode 100644 index 0000000000..3485f45ce2 --- /dev/null +++ b/lib/bind/irs/nis_nw.c @@ -0,0 +1,379 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_nw.c,v 1.1 2001/03/29 06:31:52 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +#define MAXALIASES 35 +#define MAXADDRSIZE 4 + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + + struct nwent nwent; + char * nwbuf; + + char * aliases[MAXALIASES + 1]; + u_char addr[MAXADDRSIZE]; + + struct __res_state * res; + void (*free_res)(void *); +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char networks_byname[] = "networks.byname"; +static /*const*/ char networks_byaddr[] = "networks.byaddr"; + +/* Forward */ + +static void nw_close(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static struct nwent * nw_next(struct irs_nw *); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); +static struct __res_state * nw_res_get(struct irs_nw *this); +static void nw_res_set(struct irs_nw *this, + struct __res_state *res, + void (*free_res)(void *)); + +static struct nwent * makenwent(struct irs_nw *this); +static void nisfree(struct pvt *, enum do_what); +static int init(struct irs_nw *this); + +/* Public */ + +struct irs_nw * +irs_nis_nw(struct irs_acc *this) { + struct irs_nw *nw; + struct pvt *pvt; + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + nw->private = pvt; + nw->close = nw_close; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->next = nw_next; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + nw->res_get = nw_res_get; + nw->res_set = nw_res_set; + return (nw); +} + +/* Methods */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + if (pvt->nwbuf) + free(pvt->nwbuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int length, int af) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "255.255.255.255/32"], *t; + int r; + + if (init(this) == -1) + return (NULL); + + if (af != AF_INET) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + return (NULL); + } + nisfree(pvt, do_val); + /* Try it with /CIDR first. */ + if (inet_net_ntop(AF_INET, net, length, tmp, sizeof tmp) == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + r = yp_match(pvt->nis_domain, networks_byaddr, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + /* Give it a shot without the /CIDR. */ + if ((t = strchr(tmp, '/')) != NULL) { + *t = '\0'; + r = yp_match(pvt->nis_domain, networks_byaddr, + tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + } + if (r != 0) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + } + return (makenwent(this)); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + + if (init(this) == -1) + return (NULL); + + if (af != AF_INET) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + return (NULL); + } + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, networks_byname, name, + strlen(name), &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + return (makenwent(this)); +} + +static void +nw_rewind(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static struct nwent * +nw_next(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *rval; + int r; + + if (init(this) == -1) + return (NULL); + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, networks_byaddr, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, networks_byaddr, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + rval = makenwent(this); + } while (rval == NULL); + return (rval); +} + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +nw_res_get(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + nw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +nw_res_set(struct irs_nw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +/* Private */ + +static struct nwent * +makenwent(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + static const char spaces[] = " \t"; + char *t, *cp, **ap; + + if (pvt->nwbuf) + free(pvt->nwbuf); + pvt->nwbuf = pvt->curval_data; + pvt->curval_data = NULL; + + if ((cp = strpbrk(pvt->nwbuf, "#\n")) != NULL) + *cp = '\0'; + cp = pvt->nwbuf; + + /* Name */ + pvt->nwent.n_name = cp; + cp += strcspn(cp, spaces); + if (!*cp) + goto cleanup; + *cp++ = '\0'; + cp += strspn(cp, spaces); + + /* Network */ + pvt->nwent.n_addrtype = AF_INET; + t = cp + strcspn(cp, spaces); + if (*t) + *t++ = '\0'; + pvt->nwent.n_length = inet_net_pton(AF_INET, cp, + pvt->addr, sizeof pvt->addr); + if (pvt->nwent.n_length < 0) + goto cleanup; + pvt->nwent.n_addr = pvt->addr; + cp = t; + + /* Aliases */ + ap = pvt->nwent.n_aliases = pvt->aliases; + while (*cp) { + if (ap >= &pvt->aliases[MAXALIASES]) + break; + *ap++ = cp; + cp += strcspn(cp, spaces); + if (!*cp) + break; + *cp++ = '\0'; + cp += strspn(cp, spaces); + } + *ap = NULL; + + return (&pvt->nwent); + + cleanup: + if (pvt->nwbuf) { + free(pvt->nwbuf); + pvt->nwbuf = NULL; + } + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +static int +init(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !nw_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} + +#endif /*WANT_IRS_NIS*/ diff --git a/lib/bind/irs/nis_p.h b/lib/bind/irs/nis_p.h new file mode 100644 index 0000000000..6461e85ad7 --- /dev/null +++ b/lib/bind/irs/nis_p.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: nis_p.h,v 1.1 2001/03/29 06:31:52 marka Exp $ + */ + +/* + * nis_p.h - private include file for the NIS functions. + */ + +/* + * Object state. + */ +struct nis_p { + char * domain; + struct __res_state * res; + void (*free_res) __P((void *)); +}; + + +/* + * Methods. + */ + +extern struct irs_gr * irs_nis_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_nis_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_nis_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_nis_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_nis_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_nis_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_nis_ng __P((struct irs_acc *)); diff --git a/lib/bind/irs/nis_pr.c b/lib/bind/irs/nis_pr.c new file mode 100644 index 0000000000..14847b052a --- /dev/null +++ b/lib/bind/irs/nis_pr.c @@ -0,0 +1,295 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_pr.c,v 1.1 2001/03/29 06:31:52 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + struct protoent proto; + char * prbuf; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char protocols_byname[] = "protocols.byname"; +static /*const*/ char protocols_bynumber[] = "protocols.bynumber"; + +/* Forward */ + +static void pr_close(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static struct protoent * pr_next(struct irs_pr *); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); + +static struct protoent * makeprotoent(struct irs_pr *this); +static void nisfree(struct pvt *, enum do_what); + +/* Public */ + +struct irs_pr * +irs_nis_pr(struct irs_acc *this) { + struct irs_pr *pr; + struct pvt *pvt; + + if (!(pr = memget(sizeof *pr))) { + errno = ENOMEM; + return (NULL); + } + memset(pr, 0x5e, sizeof *pr); + if (!(pvt = memget(sizeof *pvt))) { + memput(pr, sizeof *pr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + pr->private = pvt; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->next = pr_next; + pr->rewind = pr_rewind; + pr->close = pr_close; + pr->minimize = pr_minimize; + pr->res_get = NULL; + pr->res_set = NULL; + return (pr); +} + +/* Methods. */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nisfree(pvt, do_all); + if (pvt->proto.p_aliases) + free(pvt->proto.p_aliases); + if (pvt->prbuf) + free(pvt->prbuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, protocols_byname, name, + strlen(name), &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makeprotoent(this)); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int num) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "-4294967295"]; + int r; + + nisfree(pvt, do_val); + (void) sprintf(tmp, "%d", num); + r = yp_match(pvt->nis_domain, protocols_bynumber, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makeprotoent(this)); +} + +static struct protoent * +pr_next(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *rval; + int r; + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, protocols_bynumber, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, protocols_bynumber, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + errno = ENOENT; + return (NULL); + } + rval = makeprotoent(this); + } while (rval == NULL); + return (rval); +} + +static void +pr_rewind(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static void +pr_minimize(struct irs_pr *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static struct protoent * +makeprotoent(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, **t; + int n, m; + + if (pvt->prbuf) + free(pvt->prbuf); + pvt->prbuf = pvt->curval_data; + pvt->curval_data = NULL; + + for (p = pvt->prbuf; *p && *p != '#';) + p++; + while (p > pvt->prbuf && isspace(p[-1])) + p--; + *p = '\0'; + + p = pvt->prbuf; + n = m = 0; + + pvt->proto.p_name = p; + while (*p && !isspace(*p)) + p++; + if (!*p) + return (NULL); + *p++ = '\0'; + + while (*p && isspace(*p)) + p++; + pvt->proto.p_proto = atoi(p); + while (*p && !isspace(*p)) + p++; + *p++ = '\0'; + + while (*p) { + if ((n + 1) >= m || !pvt->proto.p_aliases) { + m += 10; + t = realloc(pvt->proto.p_aliases, + m * sizeof(char *)); + if (!t) { + errno = ENOMEM; + goto cleanup; + } + pvt->proto.p_aliases = t; + } + pvt->proto.p_aliases[n++] = p; + while (*p && !isspace(*p)) + p++; + if (*p) + *p++ = '\0'; + } + if (!pvt->proto.p_aliases) + pvt->proto.p_aliases = malloc(sizeof(char *)); + if (!pvt->proto.p_aliases) + goto cleanup; + pvt->proto.p_aliases[n] = NULL; + return (&pvt->proto); + + cleanup: + if (pvt->proto.p_aliases) { + free(pvt->proto.p_aliases); + pvt->proto.p_aliases = NULL; + } + if (pvt->prbuf) { + free(pvt->prbuf); + pvt->prbuf = NULL; + } + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +#endif /*WANT_IRS_NIS*/ diff --git a/lib/bind/irs/nis_pw.c b/lib/bind/irs/nis_pw.c new file mode 100644 index 0000000000..730dc68207 --- /dev/null +++ b/lib/bind/irs/nis_pw.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_pw.c,v 1.1 2001/03/29 06:31:52 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#if !defined(WANT_IRS_PW) || !defined(WANT_IRS_NIS) +static int __bind_irs_pw_unneeded; +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + struct passwd passwd; + char * pwbuf; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char passwd_byname[] = "passwd.byname"; +static /*const*/ char passwd_byuid[] = "passwd.byuid"; + +/* Forward */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_next(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); + +static struct passwd * makepasswdent(struct irs_pw *); +static void nisfree(struct pvt *, enum do_what); + +/* Public */ + +struct irs_pw * +irs_nis_pw(struct irs_acc *this) { + struct irs_pw *pw; + struct pvt *pvt; + + if (!(pw = memget(sizeof *pw))) { + errno = ENOMEM; + return (NULL); + } + memset(pw, 0x5e, sizeof *pw); + if (!(pvt = memget(sizeof *pvt))) { + memput(pw, sizeof *pw); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + pw->private = pvt; + pw->close = pw_close; + pw->next = pw_next; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + pw->res_get = NULL; + pw->res_set = NULL; + return (pw); +} + +/* Methods */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->pwbuf) + free(pvt->pwbuf); + nisfree(pvt, do_all); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct passwd * +pw_next(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct passwd *rval; + int r; + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, passwd_byname, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, passwd_byname, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + errno = ENOENT; + return (NULL); + } + rval = makepasswdent(this); + } while (rval == NULL); + return (rval); +} + +static struct passwd * +pw_byname(struct irs_pw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, passwd_byname, name, strlen(name), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makepasswdent(this)); +} + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "4294967295"]; + int r; + + nisfree(pvt, do_val); + (void) sprintf(tmp, "%u", (unsigned int)uid); + r = yp_match(pvt->nis_domain, passwd_byuid, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makepasswdent(this)); +} + +static void +pw_rewind(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static void +pw_minimize(struct irs_pw *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static struct passwd * +makepasswdent(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *cp; + + memset(&pvt->passwd, 0, sizeof pvt->passwd); + if (pvt->pwbuf) + free(pvt->pwbuf); + pvt->pwbuf = pvt->curval_data; + pvt->curval_data = NULL; + + cp = pvt->pwbuf; + pvt->passwd.pw_name = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + pvt->passwd.pw_class = cp; /* Needs to point at a \0. */ + *cp++ = '\0'; + + pvt->passwd.pw_passwd = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_uid = atoi(cp); + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_gid = atoi(cp); + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_gecos = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_dir = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_shell = cp; + + if ((cp = strchr(cp, '\n')) != NULL) + *cp = '\0'; + + return (&pvt->passwd); + + cleanup: + free(pvt->pwbuf); + pvt->pwbuf = NULL; + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +#endif /* WANT_IRS_PW && WANT_IRS_NIS */ diff --git a/lib/bind/irs/nis_sv.c b/lib/bind/irs/nis_sv.c new file mode 100644 index 0000000000..799fe51ca0 --- /dev/null +++ b/lib/bind/irs/nis_sv.c @@ -0,0 +1,305 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_sv.c,v 1.1 2001/03/29 06:31:52 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + char line[BUFSIZ+1]; + struct servent serv; + char * svbuf; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char services_byname[] = "services.byname"; + +/* Forward */ + +static void sv_close(struct irs_sv*); +static struct servent * sv_next(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, const char *, + const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); + +static struct servent * makeservent(struct irs_sv *this); +static void nisfree(struct pvt *, enum do_what); + +/* Public */ + +struct irs_sv * +irs_nis_sv(struct irs_acc *this) { + struct irs_sv *sv; + struct pvt *pvt; + + if (!(sv = memget(sizeof *sv))) { + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + if (!(pvt = memget(sizeof *pvt))) { + memput(sv, sizeof *sv); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + sv->private = pvt; + sv->close = sv_close; + sv->next = sv_next; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->rewind = sv_rewind; + sv->minimize = sv_minimize; + sv->res_get = NULL; + sv->res_set = NULL; + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nisfree(pvt, do_all); + if (pvt->serv.s_aliases) + free(pvt->serv.s_aliases); + if (pvt->svbuf) + free(pvt->svbuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + struct servent *serv; + char **sap; + + sv_rewind(this); + while ((serv = sv_next(this)) != NULL) { + if (proto != NULL && strcmp(proto, serv->s_proto)) + continue; + if (!strcmp(name, serv->s_name)) + break; + for (sap = serv->s_aliases; sap && *sap; sap++) + if (!strcmp(name, *sap)) + break; + } + return (serv); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + struct servent *serv; + + sv_rewind(this); + while ((serv = sv_next(this)) != NULL) { + if (proto != NULL && strcmp(proto, serv->s_proto)) + continue; + if (serv->s_port == port) + break; + } + return (serv); +} + +static void +sv_rewind(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static struct servent * +sv_next(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *rval; + int r; + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, services_byname, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, services_byname, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + errno = ENOENT; + return (NULL); + } + rval = makeservent(this); + } while (rval == NULL); + return (rval); +} + +static void +sv_minimize(struct irs_sv *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static struct servent * +makeservent(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + static const char spaces[] = " \t"; + char *p, **t; + int n, m; + + if (pvt->svbuf) + free(pvt->svbuf); + pvt->svbuf = pvt->curval_data; + pvt->curval_data = NULL; + + if (pvt->serv.s_aliases) { + free(pvt->serv.s_aliases); + pvt->serv.s_aliases = NULL; + } + + if ((p = strpbrk(pvt->svbuf, "#\n"))) + *p = '\0'; + + p = pvt->svbuf; + + pvt->serv.s_name = p; + p += strcspn(p, spaces); + if (!*p) + goto cleanup; + *p++ = '\0'; + p += strspn(p, spaces); + + pvt->serv.s_port = htons((u_short) atoi(p)); + pvt->serv.s_proto = NULL; + + while (*p && !isspace(*p)) + if (*p++ == '/') + pvt->serv.s_proto = p; + if (!pvt->serv.s_proto) + goto cleanup; + if (*p) { + *p++ = '\0'; + p += strspn(p, spaces); + } + + n = m = 0; + while (*p) { + if ((n + 1) >= m || !pvt->serv.s_aliases) { + m += 10; + t = realloc(pvt->serv.s_aliases, m * sizeof(char *)); + if (!t) { + errno = ENOMEM; + goto cleanup; + } + pvt->serv.s_aliases = t; + } + pvt->serv.s_aliases[n++] = p; + p += strcspn(p, spaces); + if (!*p) + break; + *p++ = '\0'; + p += strspn(p, spaces); + } + if (!pvt->serv.s_aliases) + pvt->serv.s_aliases = malloc(sizeof(char *)); + if (!pvt->serv.s_aliases) + goto cleanup; + pvt->serv.s_aliases[n] = NULL; + return (&pvt->serv); + + cleanup: + if (pvt->serv.s_aliases) { + free(pvt->serv.s_aliases); + pvt->serv.s_aliases = NULL; + } + if (pvt->svbuf) { + free(pvt->svbuf); + pvt->svbuf = NULL; + } + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +#endif /*WANT_IRS_NIS*/ diff --git a/lib/bind/irs/nul_ng.c b/lib/bind/irs/nul_ng.c new file mode 100644 index 0000000000..9efc4245de --- /dev/null +++ b/lib/bind/irs/nul_ng.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nul_ng.c,v 1.1 2001/03/29 06:31:52 marka Exp $"; +#endif + +/* + * nul_ng.c - the netgroup accessor null map + */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Forward. */ + +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); +static int ng_test(struct irs_ng *, + const char *, const char *, + const char *, const char *); +static void ng_rewind(struct irs_ng *, const char *); +static void ng_minimize(struct irs_ng *); + +/* Public. */ + +struct irs_ng * +irs_nul_ng(struct irs_acc *this) { + struct irs_ng *ng; + + UNUSED(this); + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + ng->private = NULL; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods. */ + +static void +ng_close(struct irs_ng *this) { + memput(this, sizeof *this); +} + +/* ARGSUSED */ +static int +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ + UNUSED(this); + UNUSED(host); + UNUSED(user); + UNUSED(domain); + errno = ENOENT; + return (-1); +} + +static int +ng_test(struct irs_ng *this, const char *name, + const char *user, const char *host, const char *domain) +{ + UNUSED(this); + UNUSED(name); + UNUSED(user); + UNUSED(host); + UNUSED(domain); + errno = ENODEV; + return (-1); +} + +static void +ng_rewind(struct irs_ng *this, const char *netgroup) { + UNUSED(this); + UNUSED(netgroup); + /* NOOP */ +} + +static void +ng_minimize(struct irs_ng *this) { + UNUSED(this); + /* NOOP */ +} diff --git a/lib/bind/irs/pathnames.h b/lib/bind/irs/pathnames.h new file mode 100644 index 0000000000..c436545f92 --- /dev/null +++ b/lib/bind/irs/pathnames.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: pathnames.h,v 1.1 2001/03/29 06:31:52 marka Exp $ + */ + +#ifndef _PATH_IRS_CONF +#define _PATH_IRS_CONF "/etc/irs.conf" +#endif + +#ifndef _PATH_NETWORKS +#define _PATH_NETWORKS "/etc/networks" +#endif + +#ifndef _PATH_GROUP +#define _PATH_GROUP "/etc/group" +#endif + +#ifndef _PATH_NETGROUP +#define _PATH_NETGROUP "/etc/netgroup" +#endif + +#ifndef _PATH_SERVICES +#define _PATH_SERVICES "/etc/services" +#endif + +#ifdef IRS_LCL_SV_DB +#ifndef _PATH_SERVICES_DB +#define _PATH_SERVICES_DB _PATH_SERVICES ".db" +#endif +#endif + +#ifndef _PATH_HESIOD_CONF +#define _PATH_HESIOD_CONF "/etc/hesiod.conf" +#endif diff --git a/lib/bind/irs/util.c b/lib/bind/irs/util.c new file mode 100644 index 0000000000..05d90155c6 --- /dev/null +++ b/lib/bind/irs/util.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: util.c,v 1.1 2001/03/29 06:31:52 marka Exp $"; +#endif + +#include "port_before.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "port_after.h" + +#include "irs_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +void +map_v4v6_address(const char *src, char *dst) { + u_char *p = (u_char *)dst; + char tmp[NS_INADDRSZ]; + int i; + + /* Stash a temporary copy so our caller can update in place. */ + memcpy(tmp, src, NS_INADDRSZ); + /* Mark this ipv6 addr as a mapped ipv4. */ + for (i = 0; i < 10; i++) + *p++ = 0x00; + *p++ = 0xff; + *p++ = 0xff; + /* Retrieve the saved copy and we're done. */ + memcpy((void*)p, tmp, NS_INADDRSZ); +} + +int +make_group_list(struct irs_gr *this, const char *name, + gid_t basegid, gid_t *groups, int *ngroups) +{ + struct group *grp; + int i, ng; + int ret, maxgroups; + + ret = -1; + ng = 0; + maxgroups = *ngroups; + /* + * When installing primary group, duplicate it; + * the first element of groups is the effective gid + * and will be overwritten when a setgid file is executed. + */ + if (ng >= maxgroups) + goto done; + groups[ng++] = basegid; + if (ng >= maxgroups) + goto done; + groups[ng++] = basegid; + /* + * Scan the group file to find additional groups. + */ + (*this->rewind)(this); + while ((grp = (*this->next)(this)) != NULL) { + if ((gid_t)grp->gr_gid == basegid) + continue; + for (i = 0; grp->gr_mem[i]; i++) { + if (!strcmp(grp->gr_mem[i], name)) { + if (ng >= maxgroups) + goto done; + groups[ng++] = grp->gr_gid; + break; + } + } + } + ret = 0; + done: + *ngroups = ng; + return (ret); +} diff --git a/lib/bind/isc/Makefile.in b/lib/bind/isc/Makefile.in new file mode 100644 index 0000000000..31217831a9 --- /dev/null +++ b/lib/bind/isc/Makefile.in @@ -0,0 +1,16 @@ +OBJS= assertions.@O@ base64.@O@ bitncmp.@O@ ctl_clnt.@O@ ctl_p.@O@ \ + ctl_srvr.@O@ ev_connects.@O@ ev_files.@O@ ev_streams.@O@ \ + ev_timers.@O@ ev_waits.@O@ eventlib.@O@ heap.@O@ logging.@O@ \ + memcluster.@O@ movefile.@O@ tree.@O@ + +SRCS= assertions.c base64.c bitncmp.c ctl_clnt.c ctl_p.c \ + ctl_srvr.c ev_connects.c ev_files.c ev_streams.c \ + ev_timers.c ev_waits.c eventlib.c heap.c logging.c \ + memcluster.c movefile.c tree.c + +TARGETS= ${OBJS} + +CINCLUDES= -I.. -I../include +CWARNINGS= -Werror + +@BIND9_MAKE_RULES@ diff --git a/lib/bind/isc/assertions.c b/lib/bind/isc/assertions.c new file mode 100644 index 0000000000..52ad3f9b96 --- /dev/null +++ b/lib/bind/isc/assertions.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 1997,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: assertions.c,v 1.1 2001/03/29 06:31:53 marka Exp $"; +#endif + +#include "port_before.h" + +#include +#include +#include +#include + +#include + +#include "port_after.h" + +/* + * Forward. + */ + +static void default_assertion_failed(const char *, int, assertion_type, + const char *, int); + +/* + * Public. + */ + +assertion_failure_callback __assertion_failed = default_assertion_failed; + +void +set_assertion_failure_callback(assertion_failure_callback f) { + if (f == NULL) + __assertion_failed = default_assertion_failed; + else + __assertion_failed = f; +} + +const char * +assertion_type_to_text(assertion_type type) { + const char *result; + + switch (type) { + case assert_require: + result = "REQUIRE"; + break; + case assert_ensure: + result = "ENSURE"; + break; + case assert_insist: + result = "INSIST"; + break; + case assert_invariant: + result = "INVARIANT"; + break; + default: + result = NULL; + } + return (result); +} + +/* + * Private. + */ + +static void +default_assertion_failed(const char *file, int line, assertion_type type, + const char *cond, int print_errno) +{ + fprintf(stderr, "%s:%d: %s(%s)%s%s failed.\n", + file, line, assertion_type_to_text(type), cond, + (print_errno) ? ": " : "", + (print_errno) ? strerror(errno) : ""); + abort(); + /* NOTREACHED */ +} diff --git a/lib/bind/isc/assertions.mdoc b/lib/bind/isc/assertions.mdoc new file mode 100644 index 0000000000..7fa00c97f6 --- /dev/null +++ b/lib/bind/isc/assertions.mdoc @@ -0,0 +1,134 @@ +.\" $Id: assertions.mdoc,v 1.1 2001/03/29 06:31:53 marka Exp $ +.\" +.\"Copyright (c) 1997,1999 by Internet Software Consortium. +.\" +.\"Permission to use, copy, modify, and distribute this software for any +.\"purpose with or without fee is hereby granted, provided that the above +.\"copyright notice and this permission notice appear in all copies. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\"DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\"PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\"ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\"SOFTWARE. +.\" +.Dd November 17, 1997 +.Dt ASSERTIONS 3 +.Os ISC +.Sh NAME +.Nm REQUIRE , +.Nm REQUIRE_ERR , +.Nm ENSURE , +.Nm ENSURE_ERR , +.Nm INSIST , +.Nm INSIST_ERR , +.Nm INVARIANT , +.Nm INVARIANT_ERR , +.Nm set_assertion_failure_callback +.Nd assertion system +.Sh SYNOPSIS +.Fd #include +.Fo "typedef void (*assertion_failure_callback)" +.Fa "char *filename" +.Fa "int line" +.Fa "assertion_type type" +.Fa "char *condition" +.Fa "int print_errno" +.Fc +.Fn REQUIRE "int boolean_expression" +.Fn REQUIRE_ERR "int boolean_expression" +.Fn ENSURE "int boolean_expression" +.Fn ENSURE_ERR "int boolean_expression" +.Fn INSIST "int boolean_expression" +.Fn INSIST_ERR "int boolean_expression" +.Fn INVARIANT "int boolean_expression" +.Fn INVARIANT_ERR "int boolean_expression" +.Ft void +.Fn set_assertion_failure_callback "assertion_failure_callback callback" +.Ft char * +.Fn assertion_type_to_text "assertion_type type" +.Sh DESCRIPTION +The +.Fn REQUIRE , +.Fn ENSURE , +.Fn INSIST , +and +.Fn INVARIANT +macros evaluate a boolean expression, and if it is false, they invoke the +current assertion failure callback. The default callback will print a message +to +.Li stderr +describing the failure, and then cause the program to dump core. +If the +.Dq Fn _ERR +variant of the assertion is used, the callback will include +.Fn strerror "errno" +in its message. +.Pp +Each assertion type has an associated +.Li CHECK +macro. If this macro's value is +.Dq 0 +when +.Dq "" +is included, then assertions of that type will not be checked. E.g. + +.Dl #define CHECK_ENSURE 0 + +will disable checking of +.Fn ENSURE +and +.Fn ENSURE_ERR . +The macros +.Li CHECK_ALL +and +.Li CHECK_NONE +may also be used, respectively specifying that either all or none of the +assertion types should be checked. +.Pp +.Fn set_assertion_failure_callback +specifies the function to call when an assertion fails. +.Pp +When an +.li +assertion_failure_callback +is called, the +.Fa filename +and +.Fa line +arguments specify the filename and line number of the failing assertion. +The +.Fa type +is one of: +.Bd -literal -offset indent +assert_require +assert_ensure +assert_insist +assert_invariant +.Ed + +and may be used by the callback to determine the type of the failing +assertion. +.Fa condition +is the literal text of the assertion that failed. +.Fa print_errno +will be non-zero if the callback should print +.Fa strerror "errno" +as part of its output. +.Pp +.Fn assertion_type_to_text +returns a textual representation of +.Fa type . +For example, +.Fn assertion_type_to_text "assert_require" +returns the string +.Dq REQUIRE . +.Sh SEE ALSO +Bertrand Meyer, +.Sy Object-Oriented Software Construction, +2nd edition, Prentice\-Hall, 1997, ISBN 0\-13\-629155\-4, chapter 11. +.Sh AUTHOR +Bob Halley (ISC). diff --git a/lib/bind/isc/base64.c b/lib/bind/isc/base64.c new file mode 100644 index 0000000000..4683328e42 --- /dev/null +++ b/lib/bind/isc/base64.c @@ -0,0 +1,320 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: base64.c,v 1.1 2001/03/29 06:31:53 marka Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "port_after.h" + +#define Assert(Cond) if (!(Cond)) abort() + +static const char Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +int +b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { + size_t datalength = 0; + u_char input[3]; + u_char output[4]; + size_t i; + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + Assert(output[3] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (datalength); +} + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +b64_pton(src, target, targsize) + char const *src; + u_char *target; + size_t targsize; +{ + int tarindex, state, ch; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = *src++) != '\0') { + if (isspace(ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) /* A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + default: + abort(); + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace(ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace(ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} diff --git a/lib/bind/isc/bitncmp.c b/lib/bind/isc/bitncmp.c new file mode 100644 index 0000000000..5425467f55 --- /dev/null +++ b/lib/bind/isc/bitncmp.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: bitncmp.c,v 1.1 2001/03/29 06:31:53 marka Exp $"; +#endif + +#include "port_before.h" + +#include + +#include + +#include "port_after.h" + +#include + +/* + * int + * bitncmp(l, r, n) + * compare bit masks l and r, for n bits. + * return: + * -1, 1, or 0 in the libc tradition. + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0x11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), June 1996 + */ +int +bitncmp(const void *l, const void *r, int n) { + u_int lb, rb; + int x, b; + + b = n / 8; + x = memcmp(l, r, b); + if (x) + return (x); + + lb = ((const u_char *)l)[b]; + rb = ((const u_char *)r)[b]; + for (b = n % 8; b > 0; b--) { + if ((lb & 0x80) != (rb & 0x80)) { + if (lb & 0x80) + return (1); + return (-1); + } + lb <<= 1; + rb <<= 1; + } + return (0); +} diff --git a/lib/bind/isc/bitncmp.mdoc b/lib/bind/isc/bitncmp.mdoc new file mode 100644 index 0000000000..7ad37f3ab0 --- /dev/null +++ b/lib/bind/isc/bitncmp.mdoc @@ -0,0 +1,82 @@ +.\" $Id: bitncmp.mdoc,v 1.1 2001/03/29 06:31:53 marka Exp $ +.\" +.\"Copyright (c) 1996,1999 by Internet Software Consortium. +.\" +.\"Permission to use, copy, modify, and distribute this software for any +.\"purpose with or without fee is hereby granted, provided that the above +.\"copyright notice and this permission notice appear in all copies. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\"DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\"PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\"ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\"SOFTWARE. +.\" +.Dd June 1, 1996 +.Dt BITNCMP 3 +.Os BSD 4 +.Sh NAME +.Nm bitncmp +.Nd compare bit masks +.Sh SYNOPSIS +.Ft int +.Fn bitncmp "const void *l" "const void *r" "int n" +.Sh DESCRIPTION +The function +.Fn bitncmp +compares the +.Dq Fa n +most-significant bits of the two masks pointed to by +.Dq Fa l +and +.Dq Fa r , +and returns an integer less than, equal to, or greater than 0, according to +whether or not +.Dq Fa l +is lexicographically less than, equal to, or greater than +.Dq Fa r +when taken to be unsigned characters (this behaviour is just like that of +.Xr memcmp 3 ) . +.Pp +.Sy NOTE: +.Fn Bitncmp +assumes +.Sy network byte order ; +this means that the fourth octet of +.Li 192.5.5.240/28 +.Li 0x11110000 . +.Sh RETURN VALUES +.Fn Bitncmp +returns values in the manner of +.Xr memcmp 3 : +.Bd -filled -offset indent ++1 if +.Dq Fa 1 +is greater than +.Dq Fa r ; +.Pp +-1 if +.Dq Fa l +is less than +.Dq Fa r ; +and +.Pp +0 if +.Dq Fa l +is equal to +.Dq Fa r , +.Ed +.Pp +where +.Dq Fa l +and +.Dq Fa r +are both interpreted as strings of unsigned characters (through bit +.Dq Fa n .) +.Sh SEE ALSO +.Xr memcmp 3 . +.Sh AUTHOR +Paul Vixie (ISC). diff --git a/lib/bind/isc/ctl_clnt.c b/lib/bind/isc/ctl_clnt.c new file mode 100644 index 0000000000..fbc298a50d --- /dev/null +++ b/lib/bind/isc/ctl_clnt.c @@ -0,0 +1,598 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ctl_clnt.c,v 1.1 2001/03/29 06:31:53 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1998,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* Extern. */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ctl_p.h" + +#include "port_after.h" + +/* Constants. */ + + +/* Macros. */ + +#define donefunc_p(ctx) ((ctx).donefunc != NULL) +#define arpacode_p(line) (isdigit(line[0]) && isdigit(line[1]) && \ + isdigit(line[2])) +#define arpacont_p(line) (line[3] == '-') +#define arpadone_p(line) (line[3] == ' ' || line[3] == '\t' || \ + line[3] == '\r' || line[3] == '\0') + +/* Types. */ + +enum state { + initializing = 0, connecting, connected, destroyed +}; + +struct ctl_tran { + LINK(struct ctl_tran) link; + LINK(struct ctl_tran) wlink; + struct ctl_cctx * ctx; + struct ctl_buf outbuf; + ctl_clntdone donefunc; + void * uap; +}; + +struct ctl_cctx { + enum state state; + evContext ev; + int sock; + ctl_logfunc logger; + ctl_clntdone donefunc; + void * uap; + evConnID coID; + evTimerID tiID; + evFileID rdID; + evStreamID wrID; + struct ctl_buf inbuf; + struct timespec timeout; + LIST(struct ctl_tran) tran; + LIST(struct ctl_tran) wtran; +}; + +/* Forward. */ + +static struct ctl_tran *new_tran(struct ctl_cctx *, ctl_clntdone, void *, int); +static void start_write(struct ctl_cctx *); +static void destroy(struct ctl_cctx *, int); +static void error(struct ctl_cctx *); +static void new_state(struct ctl_cctx *, enum state); +static void conn_done(evContext, void *, int, + const void *, int, + const void *, int); +static void write_done(evContext, void *, int, int); +static void start_read(struct ctl_cctx *); +static void stop_read(struct ctl_cctx *); +static void readable(evContext, void *, int, int); +static void start_timer(struct ctl_cctx *); +static void stop_timer(struct ctl_cctx *); +static void touch_timer(struct ctl_cctx *); +static void timer(evContext, void *, + struct timespec, struct timespec); + +/* Private data. */ + +static const char * const state_names[] = { + "initializing", "connecting", "connected", "destroyed" +}; + +/* Public. */ + +/* + * void + * ctl_client() + * create, condition, and connect to a listener on the control port. + */ +struct ctl_cctx * +ctl_client(evContext lev, const struct sockaddr *cap, size_t cap_len, + const struct sockaddr *sap, size_t sap_len, + ctl_clntdone donefunc, void *uap, + u_int timeout, ctl_logfunc logger) +{ + static const char me[] = "ctl_client"; + static const int on = 1; + struct ctl_cctx *ctx; + + if (logger == NULL) + logger = ctl_logger; + ctx = memget(sizeof *ctx); + if (ctx == NULL) { + (*logger)(ctl_error, "%s: getmem: %s", me, strerror(errno)); + goto fatal; + } + ctx->state = initializing; + ctx->ev = lev; + ctx->logger = logger; + ctx->timeout = evConsTime(timeout, 0); + ctx->donefunc = donefunc; + ctx->uap = uap; + ctx->coID.opaque = NULL; + ctx->tiID.opaque = NULL; + ctx->rdID.opaque = NULL; + ctx->wrID.opaque = NULL; + buffer_init(ctx->inbuf); + INIT_LIST(ctx->tran); + INIT_LIST(ctx->wtran); + ctx->sock = socket(sap->sa_family, SOCK_STREAM, PF_UNSPEC); + if (ctx->sock > evHighestFD(ctx->ev)) { + ctx->sock = -1; + errno = ENOTSOCK; + } + if (ctx->sock < 0) { + (*ctx->logger)(ctl_error, "%s: socket: %s", + me, strerror(errno)); + goto fatal; + } + if (cap != NULL) { + if (setsockopt(ctx->sock, SOL_SOCKET, SO_REUSEADDR, + (const 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, (const 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; + unsigned 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; + INIT_LINK(new, link); + INIT_LINK(new, wlink); + APPEND(ctx->tran, new, link); + if (w) + APPEND(ctx->wtran, 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; + char * tmp; + + 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); + DE_CONST("\r\n", tmp); + *iovp++ = evConsIovec(tmp, 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; + + UNUSED(ev); + UNUSED(la); + UNUSED(lalen); + UNUSED(ra); + UNUSED(ralen); + + 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; + + UNUSED(lev); + UNUSED(fd); + + 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; + + UNUSED(ev); + + 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; + + UNUSED(ev); + UNUSED(due); + UNUSED(itv); + + 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/lib/bind/isc/ctl_p.c b/lib/bind/isc/ctl_p.c new file mode 100644 index 0000000000..0a51a817f1 --- /dev/null +++ b/lib/bind/isc/ctl_p.c @@ -0,0 +1,186 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ctl_p.c,v 1.1 2001/03/29 06:31:53 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1998,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* Extern. */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ctl_p.h" + +#include "port_after.h" + +/* Constants. */ + +const char * const ctl_sevnames[] = { + "debug", "warning", "error" +}; + +/* Public. */ + +/* + * ctl_logger() + * if ctl_startup()'s caller didn't specify a logger, this one + * is used. this pollutes stderr with all kinds of trash so it will + * probably never be used in real applications. + */ +void +ctl_logger(enum ctl_severity severity, const char *format, ...) { + va_list ap; + static const char me[] = "ctl_logger"; + + fprintf(stderr, "%s(%s): ", me, ctl_sevnames[severity]); + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + fputc('\n', stderr); +} + +int +ctl_bufget(struct ctl_buf *buf, ctl_logfunc logger) { + static const char me[] = "ctl_bufget"; + + REQUIRE(!allocated_p(*buf) && buf->used == 0); + buf->text = memget(MAX_LINELEN); + if (!allocated_p(*buf)) { + (*logger)(ctl_error, "%s: getmem: %s", me, strerror(errno)); + return (-1); + } + buf->used = 0; + return (0); +} + +void +ctl_bufput(struct ctl_buf *buf) { + + REQUIRE(allocated_p(*buf)); + memput(buf->text, MAX_LINELEN); + buf->text = NULL; + buf->used = 0; +} + +const char * +ctl_sa_ntop(const struct sockaddr *sa, + char *buf, size_t size, + ctl_logfunc logger) +{ + static const char me[] = "ctl_sa_ntop"; + static const char punt[] = "[0].-1"; + char tmp[INET6_ADDRSTRLEN]; + + switch (sa->sa_family) { + case AF_INET6: { + const struct sockaddr_in6 *in6 = + (const struct sockaddr_in6 *) sa; + + if (inet_ntop(in6->sin6_family, &in6->sin6_addr, tmp, sizeof tmp) + == NULL) { + (*logger)(ctl_error, "%s: inet_ntop(%u %04x): %s", + me, in6->sin6_family, + in6->sin6_port, 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(in6->sin6_port)); + return (buf); + } + case AF_INET: { + const struct sockaddr_in *in = + (const struct sockaddr_in *) sa; + + if (inet_ntop(in->sin_family, &in->sin_addr, tmp, sizeof tmp) + == NULL) { + (*logger)(ctl_error, "%s: inet_ntop(%u %04x %08x): %s", + me, in->sin_family, + in->sin_port, in->sin_addr.s_addr, + strerror(errno)); + return (punt); + } + if (strlen(tmp) + sizeof "[].65535" > size) { + (*logger)(ctl_error, "%s: buffer overflow", me); + return (punt); + } + (void) sprintf(buf, "[%s].%u", tmp, ntohs(in->sin_port)); + return (buf); + } +#ifndef NO_SOCKADDR_UN + case AF_UNIX: { + const struct sockaddr_un *un = + (const struct sockaddr_un *) sa; + unsigned int x = sizeof un->sun_path; + + if (x > size) + x = size; + strncpy(buf, un->sun_path, x - 1); + buf[x - 1] = '\0'; + return (buf); + } +#endif + default: + return (punt); + } +} + +void +ctl_sa_copy(const struct sockaddr *src, struct sockaddr *dst) { + switch (src->sa_family) { + case AF_INET6: + *((struct sockaddr_in6 *)dst) = + *((const struct sockaddr_in6 *)src); + break; + case AF_INET: + *((struct sockaddr_in *)dst) = + *((const struct sockaddr_in *)src); + break; +#ifndef NO_SOCKADDR_UN + case AF_UNIX: + *((struct sockaddr_un *)dst) = + *((const struct sockaddr_un *)src); + break; +#endif + default: + *dst = *src; + break; + } +} diff --git a/lib/bind/isc/ctl_p.h b/lib/bind/isc/ctl_p.h new file mode 100644 index 0000000000..1ebb254236 --- /dev/null +++ b/lib/bind/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/lib/bind/isc/ctl_srvr.c b/lib/bind/isc/ctl_srvr.c new file mode 100644 index 0000000000..dfa280efba --- /dev/null +++ b/lib/bind/isc/ctl_srvr.c @@ -0,0 +1,778 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ctl_srvr.c,v 1.1 2001/03/29 06:31:53 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1998,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* Extern. */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ctl_p.h" + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Macros. */ + +#define lastverb_p(verb) (verb->name == NULL || verb->func == NULL) +#define address_expr ctl_sa_ntop((struct sockaddr *)&sess->sa, \ + tmp, sizeof tmp, ctx->logger) + +/* Types. */ + +enum state { + available = 0, initializing, writing, reading, reading_data, + processing, idling, quitting, closing +}; + +union sa_un { + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif +}; + +struct ctl_sess { + LINK(struct ctl_sess) link; + struct ctl_sctx * ctx; + enum state state; + int sock; + union sa_un sa; + evFileID rdID; + evStreamID wrID; + evTimerID rdtiID; + evTimerID wrtiID; + struct ctl_buf inbuf; + struct ctl_buf outbuf; + const struct ctl_verb * verb; + u_int helpcode; + const 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, const 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 , NULL +}; + +/* 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, + (const char *)&on, sizeof on) != 0) { + (*ctx->logger)(ctl_warning, + "%s: setsockopt(REUSEADDR): %s", + me, strerror(errno)); + } + if (bind(ctx->sock, sap, sap_len) < 0) { + char tmp[MAX_NTOP]; + save_errno = errno; + (*ctx->logger)(ctl_error, "%s: bind: %s: %s", + me, ctl_sa_ntop((const struct sockaddr *)sap, + tmp, sizeof tmp, ctx->logger), + strerror(save_errno)); + close(ctx->sock); + memput(ctx, sizeof *ctx); + errno = save_errno; + return (NULL); + } + if (fcntl(ctx->sock, F_SETFD, 1) < 0) { + (*ctx->logger)(ctl_warning, "%s: fcntl: %s", me, + strerror(errno)); + } + if (evListen(lev, ctx->sock, backlog, ctl_accept, ctx, + &ctx->acID) < 0) { + save_errno = errno; + (*ctx->logger)(ctl_error, "%s: evListen(fd %d): %s", + me, (void *)ctx->sock, strerror(errno)); + close(ctx->sock); + memput(ctx, sizeof *ctx); + errno = save_errno; + return (NULL); + } + (*ctx->logger)(ctl_debug, "%s: new ctx %p, sock %d", + me, ctx, ctx->sock); + return (ctx); +} + +/* + * void + * ctl_endserver(ctx) + * if the control listener is open, close it. clean out all eventlib + * stuff. close all active sessions. + */ +void +ctl_endserver(struct ctl_sctx *ctx) { + static const char me[] = "ctl_endserver"; + struct ctl_sess *this, *next; + + (*ctx->logger)(ctl_debug, "%s: ctx %p, sock %d, acID %p, sess %p", + me, ctx, ctx->sock, ctx->acID.opaque, ctx->sess); + if (ctx->acID.opaque != NULL) { + (void)evCancelConn(ctx->ev, ctx->acID); + ctx->acID.opaque = NULL; + } + if (ctx->sock != -1) { + (void) close(ctx->sock); + ctx->sock = -1; + } + for (this = HEAD(ctx->sess); this != NULL; this = next) { + next = NEXT(this, link); + ctl_close(this); + } + memput(ctx, sizeof *ctx); +} + +/* + * If body is non-NULL then it we add a "." line after it. + * Caller must have escaped lines with leading ".". + */ +void +ctl_response(struct ctl_sess *sess, u_int code, const char *text, + u_int flags, const 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 < (int)sess->outbuf.used-2; pc++, n++) + if (!isascii(*pc) || !isprint(*pc)) + *pc = '\040'; + *iovp++ = evConsIovec(sess->outbuf.text, sess->outbuf.used); + if (body != NULL) { + char *tmp; + DE_CONST(body, tmp); + *iovp++ = evConsIovec(tmp, bodylen); + DE_CONST(".\r\n", tmp); + *iovp++ = evConsIovec(tmp, 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, + (const 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]; + + UNUSED(lev); + UNUSED(lalen); + UNUSED(ralen); + + 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((const 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++; + INIT_LINK(sess, link); + 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 (((const struct sockaddr *)rav)->sa_family == AF_UNIX) + ctl_sa_copy((const struct sockaddr *)lav, + (struct sockaddr *)&sess->sa); + else + ctl_sa_copy((const 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, + (const struct sockaddr *)rav, ctx->uctx); +} + +static void +ctl_new_state(struct ctl_sess *sess, enum state new_state, const char *reason) +{ + static const char me[] = "ctl_new_state"; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + (*ctx->logger)(ctl_debug, "%s: %s: %s -> %s (%s)", + me, address_expr, + state_names[sess->state], + state_names[new_state], reason); + sess->state = new_state; +} + +static void +ctl_close(struct ctl_sess *sess) { + static const char me[] = "ctl_close"; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + REQUIRE(sess->state == initializing || + sess->state == writing || + sess->state == reading || + sess->state == processing || + sess->state == reading_data || + sess->state == idling); + REQUIRE(sess->sock != -1); + if (sess->state == reading || sess->state == reading_data) + ctl_stop_read(sess); + else if (sess->state == writing) { + if (sess->wrID.opaque != NULL) { + (void) evCancelRW(ctx->ev, sess->wrID); + sess->wrID.opaque = NULL; + } + if (sess->wrtiID.opaque != NULL) { + (void) evClearIdleTimer(ctx->ev, sess->wrtiID); + sess->wrtiID.opaque = NULL; + } + } + ctl_new_state(sess, closing, me); + (void) close(sess->sock); + if (allocated_p(sess->inbuf)) + ctl_bufput(&sess->inbuf); + if (allocated_p(sess->outbuf)) + ctl_bufput(&sess->outbuf); + (*ctx->logger)(ctl_debug, "%s: %s: closed (fd %d)", + me, address_expr, sess->sock); + UNLINK(ctx->sess, sess, link); + memput(sess, sizeof *sess); + ctx->cur_sess--; +} + +static void +ctl_start_read(struct ctl_sess *sess) { + static const char me[] = "ctl_start_read"; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + REQUIRE(sess->state == initializing || + sess->state == writing || + sess->state == processing || + sess->state == idling); + REQUIRE(sess->rdtiID.opaque == NULL); + REQUIRE(sess->rdID.opaque == NULL); + sess->inbuf.used = 0; + if (evSetIdleTimer(ctx->ev, ctl_rdtimeout, sess, ctx->timeout, + &sess->rdtiID) < 0) + { + (*ctx->logger)(ctl_error, "%s: %s: evSetIdleTimer: %s", me, + address_expr, strerror(errno)); + ctl_close(sess); + return; + } + if (evSelectFD(ctx->ev, sess->sock, EV_READ, + ctl_readable, sess, &sess->rdID) < 0) { + (*ctx->logger)(ctl_error, "%s: %s: evSelectFD: %s", me, + address_expr, strerror(errno)); + return; + } + ctl_new_state(sess, reading, me); +} + +static void +ctl_stop_read(struct ctl_sess *sess) { + static const char me[] = "ctl_stop_read"; + struct ctl_sctx *ctx = sess->ctx; + + REQUIRE(sess->state == reading || sess->state == reading_data); + REQUIRE(sess->rdID.opaque != NULL); + (void) evDeselectFD(ctx->ev, sess->rdID); + sess->rdID.opaque = NULL; + if (sess->rdtiID.opaque != NULL) { + (void) evClearIdleTimer(ctx->ev, sess->rdtiID); + sess->rdtiID.opaque = NULL; + } + ctl_new_state(sess, idling, me); +} + +static void +ctl_readable(evContext lev, void *uap, int fd, int evmask) { + static const char me[] = "ctl_readable"; + struct ctl_sess *sess = uap; + struct ctl_sctx *ctx = sess->ctx; + char *eos, tmp[MAX_NTOP]; + ssize_t n; + + REQUIRE(sess != NULL); + REQUIRE(fd >= 0); + REQUIRE(evmask == EV_READ); + REQUIRE(sess->state == reading || sess->state == reading_data); + evTouchIdleTimer(lev, sess->rdtiID); + if (!allocated_p(sess->inbuf) && + ctl_bufget(&sess->inbuf, ctx->logger) < 0) { + (*ctx->logger)(ctl_error, "%s: %s: cant get an input buffer", + me, address_expr); + ctl_close(sess); + return; + } + n = read(sess->sock, sess->inbuf.text + sess->inbuf.used, + MAX_LINELEN - sess->inbuf.used); + if (n <= 0) { + (*ctx->logger)(ctl_debug, "%s: %s: read: %s", + me, address_expr, + (n == 0) ? "Unexpected EOF" : strerror(errno)); + ctl_close(sess); + return; + } + sess->inbuf.used += n; + eos = memchr(sess->inbuf.text, '\n', sess->inbuf.used); + if (eos != NULL && eos != sess->inbuf.text && eos[-1] == '\r') { + eos[-1] = '\0'; + if ((sess->respflags & CTL_DATA) != 0) { + INSIST(sess->verb != NULL); + (*sess->verb->func)(sess->ctx, sess, sess->verb, + sess->inbuf.text, + CTL_DATA, sess->respctx, + sess->ctx->uctx); + } else { + ctl_stop_read(sess); + ctl_docommand(sess); + } + sess->inbuf.used -= ((eos - sess->inbuf.text) + 1); + if (sess->inbuf.used == 0) + ctl_bufput(&sess->inbuf); + else + memmove(sess->inbuf.text, eos + 1, sess->inbuf.used); + return; + } + if (sess->inbuf.used == MAX_LINELEN) { + (*ctx->logger)(ctl_error, "%s: %s: line too long, closing", + me, address_expr); + ctl_close(sess); + } +} + +static void +ctl_wrtimeout(evContext lev, void *uap, + struct timespec due, + struct timespec itv) +{ + static const char me[] = "ctl_wrtimeout"; + struct ctl_sess *sess = uap; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + UNUSED(lev); + UNUSED(due); + UNUSED(itv); + + 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]; + + UNUSED(lev); + UNUSED(due); + UNUSED(itv); + + 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; + + UNUSED(lev); + UNUSED(uap); + + 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, const void *respctx, void *uctx) +{ + const struct ctl_verb *this = respctx, *next = this + 1; + + UNUSED(ctx); + UNUSED(verb); + UNUSED(text); + UNUSED(uctx); + + 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/lib/bind/isc/ev_connects.c b/lib/bind/isc/ev_connects.c new file mode 100644 index 0000000000..dbb417ed5b --- /dev/null +++ b/lib/bind/isc/ev_connects.c @@ -0,0 +1,352 @@ +/* + * Copyright (c) 1995-1999 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* ev_connects.c - implement asynch connect/accept for the eventlib + * vix 16sep96 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_connects.c,v 1.1 2001/03/29 06:31:53 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include +#include + +#include + +#include +#include +#include "eventlib_p.h" + +#include "port_after.h" + +/* Macros. */ + +#define GETXXXNAME(f, s, sa, len) ( \ + (f((s), (&sa), (&len)) >= 0) ? 0 : \ + (errno != EAFNOSUPPORT && errno != EOPNOTSUPP) ? -1 : ( \ + memset(&(sa), 0, sizeof (sa)), \ + (len) = sizeof (sa), \ + (sa).sa_family = AF_UNIX, \ + 0 \ + ) \ + ) + +/* Forward. */ + +static void listener(evContext ctx, void *uap, int fd, int evmask); +static void connector(evContext ctx, void *uap, int fd, int evmask); + +/* Public. */ + +int +evListen(evContext opaqueCtx, int fd, int maxconn, + evConnFunc func, void *uap, evConnID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evConn *new; + int mode; + + OKNEW(new); + new->flags = EV_CONN_LISTEN; + OK(mode = fcntl(fd, F_GETFL, NULL)); /* side effect: validate fd. */ + /* + * Remember the nonblocking status. We assume that either evSelectFD + * has not been done to this fd, or that if it has then the caller + * will evCancelConn before they evDeselectFD. If our assumptions + * are not met, then we might restore the old nonblocking status + * incorrectly. + */ + if ((mode & PORT_NONBLOCK) == 0) { + OK(fcntl(fd, F_SETFL, mode | PORT_NONBLOCK)); + new->flags |= EV_CONN_BLOCK; + } + OK(listen(fd, maxconn)); + if (evSelectFD(opaqueCtx, fd, EV_READ, listener, new, &new->file) < 0){ + int save = errno; + + FREE(new); + errno = save; + return (-1); + } + new->flags |= EV_CONN_SELECTED; + new->func = func; + new->uap = uap; + new->fd = fd; + if (ctx->conns != NULL) + ctx->conns->prev = new; + new->prev = NULL; + new->next = ctx->conns; + ctx->conns = new; + if (id) + id->opaque = new; + return (0); +} + +int +evConnect(evContext opaqueCtx, int fd, const void *ra, int ralen, + evConnFunc func, void *uap, evConnID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evConn *new; + + OKNEW(new); + new->flags = 0; + /* Do the select() first to get the socket into nonblocking mode. */ + if (evSelectFD(opaqueCtx, fd, EV_MASK_ALL, + connector, new, &new->file) < 0) { + int save = errno; + + FREE(new); + errno = save; + return (-1); + } + new->flags |= EV_CONN_SELECTED; + if (connect(fd, ra, ralen) < 0 && + errno != EWOULDBLOCK && + errno != EAGAIN && + errno != EINPROGRESS) { + int save = errno; + + (void) evDeselectFD(opaqueCtx, new->file); + FREE(new); + errno = save; + return (-1); + } + /* No error, or EWOULDBLOCK. select() tells when it's ready. */ + new->func = func; + new->uap = uap; + new->fd = fd; + if (ctx->conns != NULL) + ctx->conns->prev = new; + new->prev = NULL; + new->next = ctx->conns; + ctx->conns = new; + if (id) + id->opaque = new; + return (0); +} + +int +evCancelConn(evContext opaqueCtx, evConnID id) { + evContext_p *ctx = opaqueCtx.opaque; + evConn *this = id.opaque; + evAccept *acc, *nxtacc; + int mode; + + if ((this->flags & EV_CONN_SELECTED) != 0) + (void) evDeselectFD(opaqueCtx, this->file); + if ((this->flags & EV_CONN_BLOCK) != 0) { + mode = fcntl(this->fd, F_GETFL, NULL); + if (mode == -1) { + if (errno != EBADF) + return (-1); + } else + OK(fcntl(this->fd, F_SETFL, mode | PORT_NONBLOCK)); + } + + /* Unlink from ctx->conns. */ + if (this->prev != NULL) + this->prev->next = this->next; + else + ctx->conns = this->next; + if (this->next != NULL) + this->next->prev = this->prev; + + /* + * Remove `this' from the ctx->accepts list (zero or more times). + */ + for (acc = HEAD(ctx->accepts), nxtacc = NULL; + acc != NULL; + acc = nxtacc) + { + nxtacc = NEXT(acc, link); + if (acc->conn == this) { + UNLINK(ctx->accepts, acc, link); + close(acc->fd); + FREE(acc); + } + } + + /* Wrap up and get out. */ + FREE(this); + return (0); +} + +int evHold(evContext opaqueCtx, evConnID id) { + evConn *this = id.opaque; + + if ((this->flags & EV_CONN_LISTEN) == 0) { + errno = EINVAL; + return (-1); + } + if ((this->flags & EV_CONN_SELECTED) == 0) + return (0); + this->flags &= ~EV_CONN_SELECTED; + return (evDeselectFD(opaqueCtx, this->file)); +} + +int evUnhold(evContext opaqueCtx, evConnID id) { + evConn *this = id.opaque; + int ret; + + if ((this->flags & EV_CONN_LISTEN) == 0) { + errno = EINVAL; + return (-1); + } + if ((this->flags & EV_CONN_SELECTED) != 0) + return (0); + ret = evSelectFD(opaqueCtx, this->fd, EV_READ, listener, this, + &this->file); + if (ret == 0) + this->flags |= EV_CONN_SELECTED; + return (ret); +} + +int +evTryAccept(evContext opaqueCtx, evConnID id, int *sys_errno) { + evContext_p *ctx = opaqueCtx.opaque; + evConn *conn = id.opaque; + evAccept *new; + + if ((conn->flags & EV_CONN_LISTEN) == 0) { + errno = EINVAL; + return (-1); + } + OKNEW(new); + new->conn = conn; + new->ralen = sizeof new->ra; + new->fd = accept(conn->fd, &new->ra.sa, &new->ralen); + if (new->fd > ctx->highestFD) { + close(new->fd); + new->fd = -1; + new->ioErrno = ENOTSOCK; + } + if (new->fd >= 0) { + new->lalen = sizeof new->la; + if (GETXXXNAME(getsockname, new->fd, new->la.sa, new->lalen) < 0) { + new->ioErrno = errno; + (void) close(new->fd); + new->fd = -1; + } else + new->ioErrno = 0; + } else { + new->ioErrno = errno; + if (errno == EAGAIN || errno == EWOULDBLOCK) { + FREE(new); + return (-1); + } + } + INIT_LINK(new, link); + APPEND(ctx->accepts, new, link); + *sys_errno = new->ioErrno; + return (0); +} + +/* Private. */ + +static void +listener(evContext opaqueCtx, void *uap, int fd, int evmask) { + evContext_p *ctx = opaqueCtx.opaque; + evConn *conn = uap; + union { + struct sockaddr sa; + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif + } la, ra; + int new, lalen = 0, ralen; + + REQUIRE((evmask & EV_READ) != 0); + ralen = sizeof ra; + new = accept(fd, &ra.sa, &ralen); + if (new > ctx->highestFD) { + close(new); + new = -1; + errno = ENOTSOCK; + } + if (new >= 0) { + lalen = sizeof la; + if (GETXXXNAME(getsockname, new, la.sa, lalen) < 0) { + int save = errno; + + (void) close(new); + errno = save; + new = -1; + } + } else if (errno == EAGAIN || errno == EWOULDBLOCK) + return; + (*conn->func)(opaqueCtx, conn->uap, new, &la.sa, lalen, &ra.sa, ralen); +} + +static void +connector(evContext opaqueCtx, void *uap, int fd, int evmask) { + evConn *conn = uap; + union { + struct sockaddr sa; + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif + } la, ra; + int lalen, ralen; + char buf[1]; + void *conn_uap; + evConnFunc conn_func; + evConnID id; + int socket_errno = 0; + int optlen; + + UNUSED(evmask); + + lalen = sizeof la; + ralen = sizeof ra; + conn_uap = conn->uap; + conn_func = conn->func; + id.opaque = conn; +#ifdef SO_ERROR + optlen = sizeof socket_errno; + if (fd < 0 && + getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, (char *)&socket_errno, + &optlen) < 0) + socket_errno = errno; + else + errno = socket_errno; +#endif + if (evCancelConn(opaqueCtx, id) < 0 || + socket_errno || +#ifdef NETREAD_BROKEN + 0 || +#else + read(fd, buf, 0) < 0 || +#endif + GETXXXNAME(getsockname, fd, la.sa, lalen) < 0 || + GETXXXNAME(getpeername, fd, ra.sa, ralen) < 0) { + int save = errno; + + (void) close(fd); /* XXX closing caller's fd */ + errno = save; + fd = -1; + } + (*conn_func)(opaqueCtx, conn_uap, fd, &la.sa, lalen, &ra.sa, ralen); +} diff --git a/lib/bind/isc/ev_files.c b/lib/bind/isc/ev_files.c new file mode 100644 index 0000000000..a6c13eea9d --- /dev/null +++ b/lib/bind/isc/ev_files.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 1995-1999 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* ev_files.c - implement asynch file IO for the eventlib + * vix 11sep95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_files.c,v 1.1 2001/03/29 06:31:54 marka Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include +#include + +#include +#include +#include + +#include +#include "eventlib_p.h" + +#include "port_after.h" + +static evFile *FindFD(const evContext_p *ctx, int fd, int eventmask); + +int +evSelectFD(evContext opaqueCtx, + int fd, + int eventmask, + evFileFunc func, + void *uap, + evFileID *opaqueID +) { + evContext_p *ctx = opaqueCtx.opaque; + evFile *id; + int mode; + + evPrintf(ctx, 1, + "evSelectFD(ctx %#x, fd %d, mask 0x%x, func %#x, uap %#x)\n", + ctx, fd, eventmask, func, uap); + if (eventmask == 0 || (eventmask & ~EV_MASK_ALL) != 0) + ERR(EINVAL); + if (fd > ctx->highestFD) + ERR(EINVAL); + OK(mode = fcntl(fd, F_GETFL, NULL)); /* side effect: validate fd. */ + + /* + * The first time we touch a file descriptor, we need to check to see + * if the application already had it in O_NONBLOCK mode and if so, all + * of our deselect()'s have to leave it in O_NONBLOCK. If not, then + * all but our last deselect() has to leave it in O_NONBLOCK. + */ + id = FindFD(ctx, fd, EV_MASK_ALL); + if (id == NULL) { + if (mode & PORT_NONBLOCK) + FD_SET(fd, &ctx->nonblockBefore); + else { + OK(fcntl(fd, F_SETFL, mode | PORT_NONBLOCK)); + FD_CLR(fd, &ctx->nonblockBefore); + } + } + + /* + * If this descriptor is already in use, search for it again to see + * if any of the eventmask bits we want to set are already captured. + * We cannot usefully capture the same fd event more than once in the + * same context. + */ + if (id != NULL && FindFD(ctx, fd, eventmask) != NULL) + ERR(ETOOMANYREFS); + + /* Allocate and fill. */ + OKNEW(id); + id->func = func; + id->uap = uap; + id->fd = fd; + id->eventmask = eventmask; + + /* + * Insert at head. Order could be important for performance if we + * believe that evGetNext()'s accesses to the fd_sets will be more + * serial and therefore more cache-lucky if the list is ordered by + * ``fd.'' We do not believe these things, so we don't do it. + * + * The interesting sequence is where GetNext() has cached a select() + * result and the caller decides to evSelectFD() on some descriptor. + * Since GetNext() starts at the head, it can miss new entries we add + * at the head. This is not a serious problem since the event being + * evSelectFD()'d for has to occur before evSelectFD() is called for + * the file event to be considered "missed" -- a real corner case. + * Maintaining a "tail" pointer for ctx->files would fix this, but I'm + * not sure it would be ``more correct.'' + */ + if (ctx->files != NULL) + ctx->files->prev = id; + id->prev = NULL; + id->next = ctx->files; + ctx->files = id; + + /* Insert into fd table. */ + if (ctx->fdTable[fd] != NULL) + ctx->fdTable[fd]->fdprev = id; + id->fdprev = NULL; + id->fdnext = ctx->fdTable[fd]; + ctx->fdTable[fd] = id; + + /* Turn on the appropriate bits in the {rd,wr,ex}Next fd_set's. */ + if (eventmask & EV_READ) + FD_SET(fd, &ctx->rdNext); + if (eventmask & EV_WRITE) + FD_SET(fd, &ctx->wrNext); + if (eventmask & EV_EXCEPT) + FD_SET(fd, &ctx->exNext); + + /* Update fdMax. */ + if (fd > ctx->fdMax) + ctx->fdMax = fd; + + /* Remember the ID if the caller provided us a place for it. */ + if (opaqueID) + opaqueID->opaque = id; + + evPrintf(ctx, 5, + "evSelectFD(fd %d, mask 0x%x): new masks: 0x%lx 0x%lx 0x%lx\n", + fd, eventmask, + (u_long)ctx->rdNext.fds_bits[0], + (u_long)ctx->wrNext.fds_bits[0], + (u_long)ctx->exNext.fds_bits[0]); + + return (0); +} + +int +evDeselectFD(evContext opaqueCtx, evFileID opaqueID) { + evContext_p *ctx = opaqueCtx.opaque; + evFile *del = opaqueID.opaque; + evFile *cur; + int mode, eventmask; + + if (!del) { + evPrintf(ctx, 11, "evDeselectFD(NULL) ignored\n"); + errno = EINVAL; + return (-1); + } + + evPrintf(ctx, 1, "evDeselectFD(fd %d, mask 0x%x)\n", + del->fd, del->eventmask); + + /* Get the mode. Unless the file has been closed, errors are bad. */ + mode = fcntl(del->fd, F_GETFL, NULL); + if (mode == -1 && errno != EBADF) + ERR(errno); + + /* Remove from the list of files. */ + if (del->prev != NULL) + del->prev->next = del->next; + else + ctx->files = del->next; + if (del->next != NULL) + del->next->prev = del->prev; + + /* Remove from the fd table. */ + if (del->fdprev != NULL) + del->fdprev->fdnext = del->fdnext; + else + ctx->fdTable[del->fd] = del->fdnext; + if (del->fdnext != NULL) + del->fdnext->fdprev = del->fdprev; + + /* + * If the file descriptor does not appear in any other select() entry, + * and if !EV_WASNONBLOCK, and if we got no EBADF when we got the mode + * earlier, then: restore the fd to blocking status. + */ + if (!(cur = FindFD(ctx, del->fd, EV_MASK_ALL)) && + !FD_ISSET(del->fd, &ctx->nonblockBefore) && + mode != -1) { + /* + * Note that we won't return an error status to the caller if + * this fcntl() fails since (a) we've already done the work + * and (b) the caller didn't ask us anything about O_NONBLOCK. + */ + (void) fcntl(del->fd, F_SETFL, mode & ~PORT_NONBLOCK); + } + + /* + * Now find all other uses of this descriptor and OR together an event + * mask so that we don't turn off {rd,wr,ex}Next bits that some other + * file event is using. As an optimization, stop if the event mask + * fills. + */ + eventmask = 0; + for ((void)NULL; + cur != NULL && eventmask != EV_MASK_ALL; + cur = cur->next) + if (cur->fd == del->fd) + eventmask |= cur->eventmask; + + /* OK, now we know which bits we can clear out. */ + if (!(eventmask & EV_READ)) { + FD_CLR(del->fd, &ctx->rdNext); + if (FD_ISSET(del->fd, &ctx->rdLast)) { + FD_CLR(del->fd, &ctx->rdLast); + ctx->fdCount--; + } + } + if (!(eventmask & EV_WRITE)) { + FD_CLR(del->fd, &ctx->wrNext); + if (FD_ISSET(del->fd, &ctx->wrLast)) { + FD_CLR(del->fd, &ctx->wrLast); + ctx->fdCount--; + } + } + if (!(eventmask & EV_EXCEPT)) { + FD_CLR(del->fd, &ctx->exNext); + if (FD_ISSET(del->fd, &ctx->exLast)) { + FD_CLR(del->fd, &ctx->exLast); + ctx->fdCount--; + } + } + + /* If this was the maxFD, find the new one. */ + if (del->fd == ctx->fdMax) { + ctx->fdMax = -1; + for (cur = ctx->files; cur; cur = cur->next) + if (cur->fd > ctx->fdMax) + ctx->fdMax = cur->fd; + } + + /* If this was the fdNext, cycle that to the next entry. */ + if (del == ctx->fdNext) + ctx->fdNext = del->next; + + evPrintf(ctx, 5, + "evDeselectFD(fd %d, mask 0x%x): new masks: 0x%lx 0x%lx 0x%lx\n", + del->fd, eventmask, + (u_long)ctx->rdNext.fds_bits[0], + (u_long)ctx->wrNext.fds_bits[0], + (u_long)ctx->exNext.fds_bits[0]); + + /* Couldn't free it before now since we were using fields out of it. */ + FREE(del); + + return (0); +} + +static evFile * +FindFD(const evContext_p *ctx, int fd, int eventmask) { + evFile *id; + + for (id = ctx->fdTable[fd]; id != NULL; id = id->fdnext) + if (id->fd == fd && (id->eventmask & eventmask) != 0) + break; + return (id); +} diff --git a/lib/bind/isc/ev_streams.c b/lib/bind/isc/ev_streams.c new file mode 100644 index 0000000000..678be35a62 --- /dev/null +++ b/lib/bind/isc/ev_streams.c @@ -0,0 +1,306 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* ev_streams.c - implement asynch stream file IO for the eventlib + * vix 04mar96 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_streams.c,v 1.1 2001/03/29 06:31:54 marka Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include +#include + +#include + +#include +#include +#include "eventlib_p.h" + +#include "port_after.h" + +static int copyvec(evStream *str, const struct iovec *iov, int iocnt); +static void consume(evStream *str, size_t bytes); +static void done(evContext opaqueCtx, evStream *str); +static void writable(evContext opaqueCtx, void *uap, int fd, int evmask); +static void readable(evContext opaqueCtx, void *uap, int fd, int evmask); + +struct iovec +evConsIovec(void *buf, size_t cnt) { + struct iovec ret; + + memset(&ret, 0xf5, sizeof ret); + ret.iov_base = buf; + ret.iov_len = cnt; + return (ret); +} + +int +evWrite(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt, + evStreamFunc func, void *uap, evStreamID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evStream *new; + int save; + + OKNEW(new); + new->func = func; + new->uap = uap; + new->fd = fd; + new->flags = 0; + if (evSelectFD(opaqueCtx, fd, EV_WRITE, writable, new, &new->file) < 0) + goto free; + if (copyvec(new, iov, iocnt) < 0) + goto free; + new->prevDone = NULL; + new->nextDone = NULL; + if (ctx->streams != NULL) + ctx->streams->prev = new; + new->prev = NULL; + new->next = ctx->streams; + ctx->streams = new; + if (id != NULL) + id->opaque = new; + return (0); + free: + save = errno; + FREE(new); + errno = save; + return (-1); +} + +int +evRead(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt, + evStreamFunc func, void *uap, evStreamID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evStream *new; + int save; + + OKNEW(new); + new->func = func; + new->uap = uap; + new->fd = fd; + new->flags = 0; + if (evSelectFD(opaqueCtx, fd, EV_READ, readable, new, &new->file) < 0) + goto free; + if (copyvec(new, iov, iocnt) < 0) + goto free; + new->prevDone = NULL; + new->nextDone = NULL; + if (ctx->streams != NULL) + ctx->streams->prev = new; + new->prev = NULL; + new->next = ctx->streams; + ctx->streams = new; + if (id) + id->opaque = new; + return (0); + free: + save = errno; + FREE(new); + errno = save; + return (-1); +} + +int +evTimeRW(evContext opaqueCtx, evStreamID id, evTimerID timer) /*ARGSUSED*/ { + evStream *str = id.opaque; + + UNUSED(opaqueCtx); + + str->timer = timer; + str->flags |= EV_STR_TIMEROK; + return (0); +} + +int +evUntimeRW(evContext opaqueCtx, evStreamID id) /*ARGSUSED*/ { + evStream *str = id.opaque; + + UNUSED(opaqueCtx); + + str->flags &= ~EV_STR_TIMEROK; + return (0); +} + +int +evCancelRW(evContext opaqueCtx, evStreamID id) { + evContext_p *ctx = opaqueCtx.opaque; + evStream *old = id.opaque; + + /* + * The streams list is doubly threaded. First, there's ctx->streams + * that's used by evDestroy() to find and cancel all streams. Second, + * there's ctx->strDone (head) and ctx->strLast (tail) which thread + * through the potentially smaller number of "IO completed" streams, + * used in evGetNext() to avoid scanning the entire list. + */ + + /* Unlink from ctx->streams. */ + if (old->prev != NULL) + old->prev->next = old->next; + else + ctx->streams = old->next; + if (old->next != NULL) + old->next->prev = old->prev; + + /* + * If 'old' is on the ctx->strDone list, remove it. Update + * ctx->strLast if necessary. + */ + if (old->prevDone == NULL && old->nextDone == NULL) { + /* + * Either 'old' is the only item on the done list, or it's + * not on the done list. If the former, then we unlink it + * from the list. If the latter, we leave the list alone. + */ + if (ctx->strDone == old) { + ctx->strDone = NULL; + ctx->strLast = NULL; + } + } else { + if (old->prevDone != NULL) + old->prevDone->nextDone = old->nextDone; + else + ctx->strDone = old->nextDone; + if (old->nextDone != NULL) + old->nextDone->prevDone = old->prevDone; + else + ctx->strLast = old->prevDone; + } + + /* Deallocate the stream. */ + if (old->file.opaque) + evDeselectFD(opaqueCtx, old->file); + memput(old->iovOrig, sizeof (struct iovec) * old->iovOrigCount); + FREE(old); + return (0); +} + +/* Copy a scatter/gather vector and initialize a stream handler's IO. */ +static int +copyvec(evStream *str, const struct iovec *iov, int iocnt) { + int i; + + str->iovOrig = (struct iovec *)memget(sizeof(struct iovec) * iocnt); + if (str->iovOrig == NULL) { + errno = ENOMEM; + return (-1); + } + str->ioTotal = 0; + for (i = 0; i < iocnt; i++) { + str->iovOrig[i] = iov[i]; + str->ioTotal += iov[i].iov_len; + } + str->iovOrigCount = iocnt; + str->iovCur = str->iovOrig; + str->iovCurCount = str->iovOrigCount; + str->ioDone = 0; + return (0); +} + +/* Pull off or truncate lead iovec(s). */ +static void +consume(evStream *str, size_t bytes) { + while (bytes > 0) { + if (bytes < str->iovCur->iov_len) { + str->iovCur->iov_len -= bytes; + str->iovCur->iov_base = (void *) + ((u_char *)str->iovCur->iov_base + bytes); + str->ioDone += bytes; + bytes = 0; + } else { + bytes -= str->iovCur->iov_len; + str->ioDone += str->iovCur->iov_len; + str->iovCur++; + str->iovCurCount--; + } + } +} + +/* Add a stream to Done list and deselect the FD. */ +static void +done(evContext opaqueCtx, evStream *str) { + evContext_p *ctx = opaqueCtx.opaque; + + if (ctx->strLast != NULL) { + str->prevDone = ctx->strLast; + ctx->strLast->nextDone = str; + ctx->strLast = str; + } else { + INSIST(ctx->strDone == NULL); + ctx->strDone = ctx->strLast = str; + } + evDeselectFD(opaqueCtx, str->file); + str->file.opaque = NULL; + /* evDrop() will call evCancelRW() on us. */ +} + +/* Dribble out some bytes on the stream. (Called by evDispatch().) */ +static void +writable(evContext opaqueCtx, void *uap, int fd, int evmask) { + evStream *str = uap; + int bytes; + + UNUSED(evmask); + + bytes = writev(fd, str->iovCur, str->iovCurCount); + if (bytes > 0) { + if ((str->flags & EV_STR_TIMEROK) != 0) + evTouchIdleTimer(opaqueCtx, str->timer); + consume(str, bytes); + } else { + if (bytes < 0 && errno != EINTR) { + str->ioDone = -1; + str->ioErrno = errno; + } + } + if (str->ioDone == -1 || str->ioDone == str->ioTotal) + done(opaqueCtx, str); +} + +/* Scoop up some bytes from the stream. (Called by evDispatch().) */ +static void +readable(evContext opaqueCtx, void *uap, int fd, int evmask) { + evStream *str = uap; + int bytes; + + UNUSED(evmask); + + bytes = readv(fd, str->iovCur, str->iovCurCount); + if (bytes > 0) { + if ((str->flags & EV_STR_TIMEROK) != 0) + evTouchIdleTimer(opaqueCtx, str->timer); + consume(str, bytes); + } else { + if (bytes == 0) + str->ioDone = 0; + else { + if (errno != EINTR) { + str->ioDone = -1; + str->ioErrno = errno; + } + } + } + if (str->ioDone <= 0 || str->ioDone == str->ioTotal) + done(opaqueCtx, str); +} diff --git a/lib/bind/isc/ev_timers.c b/lib/bind/isc/ev_timers.c new file mode 100644 index 0000000000..ce573b287a --- /dev/null +++ b/lib/bind/isc/ev_timers.c @@ -0,0 +1,415 @@ +/* + * Copyright (c) 1995-1999 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* ev_timers.c - implement timers for the eventlib + * vix 09sep95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_timers.c,v 1.1 2001/03/29 06:31:54 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include + +#include +#include +#include "eventlib_p.h" + +#include "port_after.h" + +/* Constants. */ + +#define MILLION 1000000 +#define BILLION 1000000000 + +/* Forward. */ + +static int due_sooner(void *, void *); +static void set_index(void *, int); +static void free_timer(void *, void *); +static void print_timer(void *, void *); +static void idle_timeout(evContext, void *, struct timespec, struct timespec); + +/* Private type. */ + +typedef struct { + evTimerFunc func; + void * uap; + struct timespec lastTouched; + struct timespec max_idle; + evTimer * timer; +} idle_timer; + +/* Public. */ + +struct timespec +evConsTime(time_t sec, long nsec) { + struct timespec x; + + x.tv_sec = sec; + x.tv_nsec = nsec; + return (x); +} + +struct timespec +evAddTime(struct timespec addend1, struct timespec addend2) { + struct timespec x; + + x.tv_sec = addend1.tv_sec + addend2.tv_sec; + x.tv_nsec = addend1.tv_nsec + addend2.tv_nsec; + if (x.tv_nsec >= BILLION) { + x.tv_sec++; + x.tv_nsec -= BILLION; + } + return (x); +} + +struct timespec +evSubTime(struct timespec minuend, struct timespec subtrahend) { + struct timespec x; + + x.tv_sec = minuend.tv_sec - subtrahend.tv_sec; + if (minuend.tv_nsec >= subtrahend.tv_nsec) + x.tv_nsec = minuend.tv_nsec - subtrahend.tv_nsec; + else { + x.tv_nsec = BILLION - subtrahend.tv_nsec + minuend.tv_nsec; + x.tv_sec--; + } + return (x); +} + +int +evCmpTime(struct timespec a, struct timespec b) { + long x = a.tv_sec - b.tv_sec; + + if (x == 0L) + x = a.tv_nsec - b.tv_nsec; + return (x < 0L ? (-1) : x > 0L ? (1) : (0)); +} + +struct timespec +evNowTime() { + struct timeval now; + + if (gettimeofday(&now, NULL) < 0) + return (evConsTime(0, 0)); + return (evTimeSpec(now)); +} + +struct timespec +evLastEventTime(evContext opaqueCtx) { + evContext_p *ctx = opaqueCtx.opaque; + + return (ctx->lastEventTime); +} + +struct timespec +evTimeSpec(struct timeval tv) { + struct timespec ts; + + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + return (ts); +} + +struct timeval +evTimeVal(struct timespec ts) { + struct timeval tv; + + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000; + return (tv); +} + +int +evSetTimer(evContext opaqueCtx, + evTimerFunc func, + void *uap, + struct timespec due, + struct timespec inter, + evTimerID *opaqueID +) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *id; + + evPrintf(ctx, 1, +"evSetTimer(ctx %#x, func %#x, uap %#x, due %d.%09ld, inter %d.%09ld)\n", + ctx, func, uap, + due.tv_sec, due.tv_nsec, + inter.tv_sec, inter.tv_nsec); + + /* due={0,0} is a magic cookie meaning "now." */ + if (due.tv_sec == 0 && due.tv_nsec == 0L) + due = evNowTime(); + + /* Allocate and fill. */ + OKNEW(id); + id->func = func; + id->uap = uap; + id->due = due; + id->inter = inter; + + if (heap_insert(ctx->timers, id) < 0) + return (-1); + + /* Remember the ID if the caller provided us a place for it. */ + if (opaqueID) + opaqueID->opaque = id; + + if (ctx->debug > 7) { + evPrintf(ctx, 7, "timers after evSetTimer:\n"); + (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); + } + + return (0); +} + +int +evClearTimer(evContext opaqueCtx, evTimerID id) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *del = id.opaque; + + if (ctx->cur != NULL && + ctx->cur->type == Timer && + ctx->cur->u.timer.this == del) { + evPrintf(ctx, 8, "deferring delete of timer (executing)\n"); + /* + * Setting the interval to zero ensures that evDrop() will + * clean up the timer. + */ + del->inter = evConsTime(0, 0); + return (0); + } + + if (heap_element(ctx->timers, del->index) != del) + ERR(ENOENT); + + if (heap_delete(ctx->timers, del->index) < 0) + return (-1); + FREE(del); + + if (ctx->debug > 7) { + evPrintf(ctx, 7, "timers after evClearTimer:\n"); + (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); + } + + return (0); +} + +int +evResetTimer(evContext opaqueCtx, + evTimerID id, + evTimerFunc func, + void *uap, + struct timespec due, + struct timespec inter +) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *timer = id.opaque; + struct timespec old_due; + int result=0; + + if (heap_element(ctx->timers, timer->index) != timer) + ERR(ENOENT); + + old_due = timer->due; + + timer->func = func; + timer->uap = uap; + timer->due = due; + timer->inter = inter; + + switch (evCmpTime(due, old_due)) { + case -1: + result = heap_increased(ctx->timers, timer->index); + break; + case 0: + result = 0; + break; + case 1: + result = heap_decreased(ctx->timers, timer->index); + break; + } + + if (ctx->debug > 7) { + evPrintf(ctx, 7, "timers after evResetTimer:\n"); + (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); + } + + return (result); +} + +int +evSetIdleTimer(evContext opaqueCtx, + evTimerFunc func, + void *uap, + struct timespec max_idle, + evTimerID *opaqueID +) { + evContext_p *ctx = opaqueCtx.opaque; + idle_timer *tt; + + /* Allocate and fill. */ + OKNEW(tt); + tt->func = func; + tt->uap = uap; + tt->lastTouched = ctx->lastEventTime; + tt->max_idle = max_idle; + + if (evSetTimer(opaqueCtx, idle_timeout, tt, + evAddTime(ctx->lastEventTime, max_idle), + max_idle, opaqueID) < 0) { + FREE(tt); + return (-1); + } + + tt->timer = opaqueID->opaque; + + return (0); +} + +int +evClearIdleTimer(evContext opaqueCtx, evTimerID id) { + evTimer *del = id.opaque; + idle_timer *tt = del->uap; + + FREE(tt); + return (evClearTimer(opaqueCtx, id)); +} + +int +evResetIdleTimer(evContext opaqueCtx, + evTimerID opaqueID, + evTimerFunc func, + void *uap, + struct timespec max_idle +) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *timer = opaqueID.opaque; + idle_timer *tt = timer->uap; + + tt->func = func; + tt->uap = uap; + tt->lastTouched = ctx->lastEventTime; + tt->max_idle = max_idle; + + return (evResetTimer(opaqueCtx, opaqueID, idle_timeout, tt, + evAddTime(ctx->lastEventTime, max_idle), + max_idle)); +} + +int +evTouchIdleTimer(evContext opaqueCtx, evTimerID id) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *t = id.opaque; + idle_timer *tt = t->uap; + + tt->lastTouched = ctx->lastEventTime; + + return (0); +} + +/* Public to the rest of eventlib. */ + +heap_context +evCreateTimers(const evContext_p *ctx) { + + UNUSED(ctx); + + return (heap_new(due_sooner, set_index, 2048)); +} + +void +evDestroyTimers(const evContext_p *ctx) { + (void) heap_for_each(ctx->timers, free_timer, NULL); + (void) heap_free(ctx->timers); +} + +/* Private. */ + +static int +due_sooner(void *a, void *b) { + evTimer *a_timer, *b_timer; + + a_timer = a; + b_timer = b; + return (evCmpTime(a_timer->due, b_timer->due) < 0); +} + +static void +set_index(void *what, int index) { + evTimer *timer; + + timer = what; + timer->index = index; +} + +static void +free_timer(void *what, void *uap) { + evTimer *t = what; + + UNUSED(uap); + + FREE(t); +} + +static void +print_timer(void *what, void *uap) { + evTimer *cur = what; + evContext_p *ctx = uap; + + cur = what; + evPrintf(ctx, 7, + " func %p, uap %p, due %d.%09ld, inter %d.%09ld\n", + cur->func, cur->uap, + cur->due.tv_sec, cur->due.tv_nsec, + cur->inter.tv_sec, cur->inter.tv_nsec); +} + +static void +idle_timeout(evContext opaqueCtx, + void *uap, + struct timespec due, + struct timespec inter +) { + evContext_p *ctx = opaqueCtx.opaque; + idle_timer *this = uap; + struct timespec idle; + + UNUSED(due); + UNUSED(inter); + + idle = evSubTime(ctx->lastEventTime, this->lastTouched); + if (evCmpTime(idle, this->max_idle) >= 0) { + (this->func)(opaqueCtx, this->uap, this->timer->due, + this->max_idle); + /* + * Setting the interval to zero will cause the timer to + * be cleaned up in evDrop(). + */ + this->timer->inter = evConsTime(0, 0); + FREE(this); + } else { + /* evDrop() will reschedule the timer. */ + this->timer->inter = evSubTime(this->max_idle, idle); + } +} diff --git a/lib/bind/isc/ev_waits.c b/lib/bind/isc/ev_waits.c new file mode 100644 index 0000000000..d6b15fa6c8 --- /dev/null +++ b/lib/bind/isc/ev_waits.c @@ -0,0 +1,245 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* ev_waits.c - implement deferred function calls for the eventlib + * vix 05dec95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_waits.c,v 1.1 2001/03/29 06:31:54 marka Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include + +#include +#include +#include "eventlib_p.h" + +#include "port_after.h" + +/* Forward. */ + +static void print_waits(evContext_p *ctx); +static evWaitList * evNewWaitList(evContext_p *); +static void evFreeWaitList(evContext_p *, evWaitList *); +static evWaitList * evGetWaitList(evContext_p *, const void *, int); + + +/* Public. */ + +/* + * Enter a new wait function on the queue. + */ +int +evWaitFor(evContext opaqueCtx, const void *tag, + evWaitFunc func, void *uap, evWaitID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evWait *new; + evWaitList *wl = evGetWaitList(ctx, tag, 1); + + OKNEW(new); + new->func = func; + new->uap = uap; + new->tag = tag; + new->next = NULL; + if (wl->last != NULL) + wl->last->next = new; + else + wl->first = new; + wl->last = new; + if (id != NULL) + id->opaque = new; + if (ctx->debug >= 9) + print_waits(ctx); + return (0); +} + +/* + * Mark runnable all waiting functions having a certain tag. + */ +int +evDo(evContext opaqueCtx, const void *tag) { + evContext_p *ctx = opaqueCtx.opaque; + evWaitList *wl = evGetWaitList(ctx, tag, 0); + evWait *first; + + if (!wl) { + errno = ENOENT; + return (-1); + } + + first = wl->first; + INSIST(first != NULL); + + if (ctx->waitDone.last != NULL) + ctx->waitDone.last->next = first; + else + ctx->waitDone.first = first; + ctx->waitDone.last = wl->last; + evFreeWaitList(ctx, wl); + + return (0); +} + +/* + * Remove a waiting (or ready to run) function from the queue. + */ +int +evUnwait(evContext opaqueCtx, evWaitID id) { + evContext_p *ctx = opaqueCtx.opaque; + evWait *this, *prev; + evWaitList *wl; + int found = 0; + + this = id.opaque; + INSIST(this != NULL); + wl = evGetWaitList(ctx, this->tag, 0); + if (wl != NULL) { + for (prev = NULL, this = wl->first; + this != NULL; + prev = this, this = this->next) + if (this == (evWait *)id.opaque) { + found = 1; + if (prev != NULL) + prev->next = this->next; + else + wl->first = this->next; + if (wl->last == this) + wl->last = prev; + if (wl->first == NULL) + evFreeWaitList(ctx, wl); + break; + } + } + + if (!found) { + /* Maybe it's done */ + for (prev = NULL, this = ctx->waitDone.first; + this != NULL; + prev = this, this = this->next) + if (this == (evWait *)id.opaque) { + found = 1; + if (prev != NULL) + prev->next = this->next; + else + ctx->waitDone.first = this->next; + if (ctx->waitDone.last == this) + ctx->waitDone.last = prev; + break; + } + } + + if (!found) { + errno = ENOENT; + return (-1); + } + + FREE(this); + + if (ctx->debug >= 9) + print_waits(ctx); + + return (0); +} + +int +evDefer(evContext opaqueCtx, evWaitFunc func, void *uap) { + evContext_p *ctx = opaqueCtx.opaque; + evWait *new; + + OKNEW(new); + new->func = func; + new->uap = uap; + new->tag = NULL; + new->next = NULL; + if (ctx->waitDone.last != NULL) + ctx->waitDone.last->next = new; + else + ctx->waitDone.first = new; + ctx->waitDone.last = new; + if (ctx->debug >= 9) + print_waits(ctx); + return (0); +} + +/* Private. */ + +static void +print_waits(evContext_p *ctx) { + evWaitList *wl; + evWait *this; + + evPrintf(ctx, 9, "wait waiting:\n"); + for (wl = ctx->waitLists; wl != NULL; wl = wl->next) { + INSIST(wl->first != NULL); + evPrintf(ctx, 9, " tag %#x:", wl->first->tag); + for (this = wl->first; this != NULL; this = this->next) + evPrintf(ctx, 9, " %#x", this); + evPrintf(ctx, 9, "\n"); + } + evPrintf(ctx, 9, "wait done:"); + for (this = ctx->waitDone.first; this != NULL; this = this->next) + evPrintf(ctx, 9, " %#x", this); + evPrintf(ctx, 9, "\n"); +} + +static evWaitList * +evNewWaitList(evContext_p *ctx) { + evWaitList *new; + + NEW(new); + if (new == NULL) + return (NULL); + new->first = new->last = NULL; + new->prev = NULL; + new->next = ctx->waitLists; + if (new->next != NULL) + new->next->prev = new; + ctx->waitLists = new; + return (new); +} + +static void +evFreeWaitList(evContext_p *ctx, evWaitList *this) { + + INSIST(this != NULL); + + if (this->prev != NULL) + this->prev->next = this->next; + else + ctx->waitLists = this->next; + if (this->next != NULL) + this->next->prev = this->prev; + FREE(this); +} + +static evWaitList * +evGetWaitList(evContext_p *ctx, const void *tag, int should_create) { + evWaitList *this; + + for (this = ctx->waitLists; this != NULL; this = this->next) { + if (this->first != NULL && this->first->tag == tag) + break; + } + if (this == NULL && should_create) + this = evNewWaitList(ctx); + return (this); +} diff --git a/lib/bind/isc/eventlib.c b/lib/bind/isc/eventlib.c new file mode 100644 index 0000000000..22ea951376 --- /dev/null +++ b/lib/bind/isc/eventlib.c @@ -0,0 +1,676 @@ +/* + * Copyright (c) 1995-1999 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* eventlib.c - implement glue for the eventlib + * vix 09sep95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: eventlib.c,v 1.1 2001/03/29 06:31:54 marka Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include "eventlib_p.h" + +#include "port_after.h" + +/* Forward. */ + +#ifdef NEED_PSELECT +static int pselect(int, void *, void *, void *, + struct timespec *, + const sigset_t *); +#endif + +/* Public. */ + +int +evCreate(evContext *opaqueCtx) { + evContext_p *ctx; + + /* Make sure the memory heap is initialized. */ + if (meminit(0, 0) < 0 && errno != EEXIST) + return (-1); + + OKNEW(ctx); + + /* Global. */ + ctx->cur = NULL; + + /* Debugging. */ + ctx->debug = 0; + ctx->output = NULL; + + /* Connections. */ + ctx->conns = NULL; + INIT_LIST(ctx->accepts); + + /* Files. */ + ctx->files = NULL; + FD_ZERO(&ctx->rdNext); + FD_ZERO(&ctx->wrNext); + FD_ZERO(&ctx->exNext); + FD_ZERO(&ctx->nonblockBefore); + ctx->fdMax = -1; + ctx->fdNext = NULL; + ctx->fdCount = 0; /* Invalidate {rd,wr,ex}Last. */ + ctx->highestFD = FD_SETSIZE - 1; +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastFdCount = 0; +#endif + memset(ctx->fdTable, 0, sizeof ctx->fdTable); + + /* Streams. */ + ctx->streams = NULL; + ctx->strDone = NULL; + ctx->strLast = NULL; + + /* Timers. */ + ctx->lastEventTime = evNowTime(); +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastSelectTime = ctx->lastEventTime; +#endif + ctx->timers = evCreateTimers(ctx); + if (ctx->timers == NULL) + return (-1); + + /* Waits. */ + ctx->waitLists = NULL; + ctx->waitDone.first = ctx->waitDone.last = NULL; + ctx->waitDone.prev = ctx->waitDone.next = NULL; + + opaqueCtx->opaque = ctx; + return (0); +} + +void +evSetDebug(evContext opaqueCtx, int level, FILE *output) { + evContext_p *ctx = opaqueCtx.opaque; + + ctx->debug = level; + ctx->output = output; +} + +int +evDestroy(evContext opaqueCtx) { + evContext_p *ctx = opaqueCtx.opaque; + int revs = 424242; /* Doug Adams. */ + evWaitList *this_wl, *next_wl; + evWait *this_wait, *next_wait; + + /* Connections. */ + while (revs-- > 0 && ctx->conns != NULL) { + evConnID id; + + id.opaque = ctx->conns; + (void) evCancelConn(opaqueCtx, id); + } + INSIST(revs >= 0); + + /* Streams. */ + while (revs-- > 0 && ctx->streams != NULL) { + evStreamID id; + + id.opaque = ctx->streams; + (void) evCancelRW(opaqueCtx, id); + } + + /* Files. */ + while (revs-- > 0 && ctx->files != NULL) { + evFileID id; + + id.opaque = ctx->files; + (void) evDeselectFD(opaqueCtx, id); + } + INSIST(revs >= 0); + + /* Timers. */ + evDestroyTimers(ctx); + + /* Waits. */ + for (this_wl = ctx->waitLists; + revs-- > 0 && this_wl != NULL; + this_wl = next_wl) { + next_wl = this_wl->next; + for (this_wait = this_wl->first; + revs-- > 0 && this_wait != NULL; + this_wait = next_wait) { + next_wait = this_wait->next; + FREE(this_wait); + } + FREE(this_wl); + } + for (this_wait = ctx->waitDone.first; + revs-- > 0 && this_wait != NULL; + this_wait = next_wait) { + next_wait = this_wait->next; + FREE(this_wait); + } + + FREE(ctx); + return (0); +} + +int +evGetNext(evContext opaqueCtx, evEvent *opaqueEv, int options) { + evContext_p *ctx = opaqueCtx.opaque; + struct timespec nextTime; + evTimer *nextTimer; + evEvent_p *new; + int x, pselect_errno, timerPast; +#ifdef EVENTLIB_TIME_CHECKS + struct timespec interval; +#endif + + /* Ensure that exactly one of EV_POLL or EV_WAIT was specified. */ + x = ((options & EV_POLL) != 0) + ((options & EV_WAIT) != 0); + if (x != 1) + ERR(EINVAL); + + /* Get the time of day. We'll do this again after select() blocks. */ + ctx->lastEventTime = evNowTime(); + + again: + /* Finished accept()'s do not require a select(). */ + if (!EMPTY(ctx->accepts)) { + OKNEW(new); + new->type = Accept; + new->u.accept.this = HEAD(ctx->accepts); + UNLINK(ctx->accepts, HEAD(ctx->accepts), link); + opaqueEv->opaque = new; + return (0); + } + + /* Stream IO does not require a select(). */ + if (ctx->strDone != NULL) { + OKNEW(new); + new->type = Stream; + new->u.stream.this = ctx->strDone; + ctx->strDone = ctx->strDone->nextDone; + if (ctx->strDone == NULL) + ctx->strLast = NULL; + opaqueEv->opaque = new; + return (0); + } + + /* Waits do not require a select(). */ + if (ctx->waitDone.first != NULL) { + OKNEW(new); + new->type = Wait; + new->u.wait.this = ctx->waitDone.first; + ctx->waitDone.first = ctx->waitDone.first->next; + if (ctx->waitDone.first == NULL) + ctx->waitDone.last = NULL; + opaqueEv->opaque = new; + return (0); + } + + /* Get the status and content of the next timer. */ + if ((nextTimer = heap_element(ctx->timers, 1)) != NULL) { + nextTime = nextTimer->due; + timerPast = (evCmpTime(nextTime, ctx->lastEventTime) <= 0); + } else + timerPast = 0; /* Make gcc happy. */ + + evPrintf(ctx, 9, "evGetNext: fdCount %d\n", ctx->fdCount); + if (ctx->fdCount == 0) { + static const struct timespec NoTime = {0, 0L}; + enum { JustPoll, Block, Timer } m; + struct timespec t, *tp; + + /* Are there any events at all? */ + if ((options & EV_WAIT) != 0 && !nextTimer && ctx->fdMax == -1) + ERR(ENOENT); + + /* Figure out what select()'s timeout parameter should be. */ + if ((options & EV_POLL) != 0) { + m = JustPoll; + t = NoTime; + tp = &t; + } else if (nextTimer == NULL) { + m = Block; + /* ``t'' unused. */ + tp = NULL; + } else if (timerPast) { + m = JustPoll; + t = NoTime; + tp = &t; + } else { + m = Timer; + /* ``t'' filled in later. */ + tp = &t; + } +#ifdef EVENTLIB_TIME_CHECKS + if (ctx->debug > 0) { + interval = evSubTime(ctx->lastEventTime, + ctx->lastSelectTime); + if (interval.tv_sec > 0) + evPrintf(ctx, 1, + "time between pselect() %u.%09u count %d\n", + interval.tv_sec, interval.tv_nsec, + ctx->lastFdCount); + } +#endif + do { + /* XXX need to copy only the bits we are using. */ + ctx->rdLast = ctx->rdNext; + ctx->wrLast = ctx->wrNext; + ctx->exLast = ctx->exNext; + + if (m == Timer) { + INSIST(tp == &t); + t = evSubTime(nextTime, ctx->lastEventTime); + } + + evPrintf(ctx, 4, + "pselect(%d, 0x%lx, 0x%lx, 0x%lx, %d.%09ld)\n", + ctx->fdMax+1, + (u_long)ctx->rdLast.fds_bits[0], + (u_long)ctx->wrLast.fds_bits[0], + (u_long)ctx->exLast.fds_bits[0], + tp ? tp->tv_sec : -1, + tp ? tp->tv_nsec : -1); + + /* XXX should predict system's earliness and adjust. */ + x = pselect(ctx->fdMax+1, + &ctx->rdLast, &ctx->wrLast, &ctx->exLast, + tp, NULL); + pselect_errno = errno; + + evPrintf(ctx, 4, "select() returns %d (err: %s)\n", + x, (x == -1) ? strerror(errno) : "none"); + + /* Anything but a poll can change the time. */ + if (m != JustPoll) + ctx->lastEventTime = evNowTime(); + + /* Select() likes to finish about 10ms early. */ + } while (x == 0 && m == Timer && + evCmpTime(ctx->lastEventTime, nextTime) < 0); +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastSelectTime = ctx->lastEventTime; +#endif + if (x < 0) { + if (pselect_errno == EINTR) { + if ((options & EV_NULL) != 0) + goto again; + OKNEW(new); + new->type = Null; + /* No data. */ + opaqueEv->opaque = new; + return (0); + } + if (pselect_errno == EBADF) { + for (x = 0; x <= ctx->fdMax; x++) { + struct stat sb; + + if (FD_ISSET(x, &ctx->rdNext) == 0 && + FD_ISSET(x, &ctx->wrNext) == 0 && + FD_ISSET(x, &ctx->exNext) == 0) + continue; + if (fstat(x, &sb) == -1 && + errno == EBADF) + evPrintf(ctx, 1, "EBADF: %d\n", + x); + } + abort(); + } + ERR(pselect_errno); + } + if (x == 0 && (nextTimer == NULL || !timerPast) && + (options & EV_POLL)) + ERR(EWOULDBLOCK); + ctx->fdCount = x; +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastFdCount = x; +#endif + } + INSIST(nextTimer || ctx->fdCount); + + /* Timers go first since we'd like them to be accurate. */ + if (nextTimer && !timerPast) { + /* Has anything happened since we blocked? */ + timerPast = (evCmpTime(nextTime, ctx->lastEventTime) <= 0); + } + if (nextTimer && timerPast) { + OKNEW(new); + new->type = Timer; + new->u.timer.this = nextTimer; + opaqueEv->opaque = new; + return (0); + } + + /* No timers, so there should be a ready file descriptor. */ + x = 0; + while (ctx->fdCount > 0) { + evFile *fid; + int fd, eventmask; + + if (ctx->fdNext == NULL) { + if (++x == 2) { + /* + * Hitting the end twice means that the last + * select() found some FD's which have since + * been deselected. + * + * On some systems, the count returned by + * selects is the total number of bits in + * all masks that are set, and on others it's + * the number of fd's that have some bit set, + * and on others, it's just broken. We + * always assume that it's the number of + * bits set in all masks, because that's what + * the man page says it should do, and + * the worst that can happen is we do an + * extra select(). + */ + ctx->fdCount = 0; + break; + } + ctx->fdNext = ctx->files; + } + fid = ctx->fdNext; + ctx->fdNext = fid->next; + + fd = fid->fd; + eventmask = 0; + if (FD_ISSET(fd, &ctx->rdLast)) + eventmask |= EV_READ; + if (FD_ISSET(fd, &ctx->wrLast)) + eventmask |= EV_WRITE; + if (FD_ISSET(fd, &ctx->exLast)) + eventmask |= EV_EXCEPT; + eventmask &= fid->eventmask; + if (eventmask != 0) { + if ((eventmask & EV_READ) != 0) { + FD_CLR(fd, &ctx->rdLast); + ctx->fdCount--; + } + if ((eventmask & EV_WRITE) != 0) { + FD_CLR(fd, &ctx->wrLast); + ctx->fdCount--; + } + if ((eventmask & EV_EXCEPT) != 0) { + FD_CLR(fd, &ctx->exLast); + ctx->fdCount--; + } + OKNEW(new); + new->type = File; + new->u.file.this = fid; + new->u.file.eventmask = eventmask; + opaqueEv->opaque = new; + return (0); + } + } + if (ctx->fdCount < 0) { + /* + * select()'s count is off on a number of systems, and + * can result in fdCount < 0. + */ + evPrintf(ctx, 4, "fdCount < 0 (%d)\n", ctx->fdCount); + ctx->fdCount = 0; + } + + /* We get here if the caller deselect()'s an FD. Gag me with a goto. */ + goto again; +} + +int +evDispatch(evContext opaqueCtx, evEvent opaqueEv) { + evContext_p *ctx = opaqueCtx.opaque; + evEvent_p *ev = opaqueEv.opaque; +#ifdef EVENTLIB_TIME_CHECKS + void *func; + struct timespec start_time; + struct timespec interval; +#endif + +#ifdef EVENTLIB_TIME_CHECKS + if (ctx->debug > 0) + start_time = evNowTime(); +#endif + ctx->cur = ev; + switch (ev->type) { + case Accept: { + evAccept *this = ev->u.accept.this; + + evPrintf(ctx, 5, + "Dispatch.Accept: fd %d -> %d, func %#x, uap %#x\n", + this->conn->fd, this->fd, + this->conn->func, this->conn->uap); + errno = this->ioErrno; + (this->conn->func)(opaqueCtx, this->conn->uap, this->fd, + &this->la, this->lalen, + &this->ra, this->ralen); +#ifdef EVENTLIB_TIME_CHECKS + func = this->conn->func; +#endif + break; + } + case File: { + evFile *this = ev->u.file.this; + int eventmask = ev->u.file.eventmask; + + evPrintf(ctx, 5, + "Dispatch.File: fd %d, mask 0x%x, func %#x, uap %#x\n", + this->fd, this->eventmask, this->func, this->uap); + (this->func)(opaqueCtx, this->uap, this->fd, eventmask); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Stream: { + evStream *this = ev->u.stream.this; + + evPrintf(ctx, 5, + "Dispatch.Stream: fd %d, func %#x, uap %#x\n", + this->fd, this->func, this->uap); + errno = this->ioErrno; + (this->func)(opaqueCtx, this->uap, this->fd, this->ioDone); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Timer: { + evTimer *this = ev->u.timer.this; + + evPrintf(ctx, 5, "Dispatch.Timer: func %#x, uap %#x\n", + this->func, this->uap); + (this->func)(opaqueCtx, this->uap, this->due, this->inter); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Wait: { + evWait *this = ev->u.wait.this; + + evPrintf(ctx, 5, + "Dispatch.Wait: tag %#x, func %#x, uap %#x\n", + this->tag, this->func, this->uap); + (this->func)(opaqueCtx, this->uap, this->tag); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Null: { + /* No work. */ +#ifdef EVENTLIB_TIME_CHECKS + func = NULL; +#endif + break; + } + default: { + abort(); + } + } +#ifdef EVENTLIB_TIME_CHECKS + if (ctx->debug > 0) { + interval = evSubTime(evNowTime(), start_time); + /* + * Complain if it took longer than 50 milliseconds. + * + * We call getuid() to make an easy to find mark in a kernel + * trace. + */ + if (interval.tv_sec > 0 || interval.tv_nsec > 50000000) + evPrintf(ctx, 1, + "dispatch interval %u.%09u uid %d type %d func %p\n", + interval.tv_sec, interval.tv_nsec, + getuid(), ev->type, func); + } +#endif + ctx->cur = NULL; + evDrop(opaqueCtx, opaqueEv); + return (0); +} + +void +evDrop(evContext opaqueCtx, evEvent opaqueEv) { + evContext_p *ctx = opaqueCtx.opaque; + evEvent_p *ev = opaqueEv.opaque; + + switch (ev->type) { + case Accept: { + FREE(ev->u.accept.this); + break; + } + case File: { + /* No work. */ + break; + } + case Stream: { + evStreamID id; + + id.opaque = ev->u.stream.this; + (void) evCancelRW(opaqueCtx, id); + break; + } + case Timer: { + evTimer *this = ev->u.timer.this; + evTimerID opaque; + + /* Check to see whether the user func cleared the timer. */ + if (heap_element(ctx->timers, this->index) != this) { + evPrintf(ctx, 5, "Dispatch.Timer: timer rm'd?\n"); + break; + } + /* + * Timer is still there. Delete it if it has expired, + * otherwise set it according to its next interval. + */ + if (this->inter.tv_sec == 0 && this->inter.tv_nsec == 0L) { + opaque.opaque = this; + (void) evClearTimer(opaqueCtx, opaque); + } else { + opaque.opaque = this; + (void) evResetTimer(opaqueCtx, opaque, this->func, + this->uap, + evAddTime(ctx->lastEventTime, + this->inter), + this->inter); + } + break; + } + case Wait: { + FREE(ev->u.wait.this); + break; + } + case Null: { + /* No work. */ + break; + } + default: { + abort(); + } + } + FREE(ev); +} + +int +evMainLoop(evContext opaqueCtx) { + evEvent event; + int x; + + while ((x = evGetNext(opaqueCtx, &event, EV_WAIT)) == 0) + if ((x = evDispatch(opaqueCtx, event)) < 0) + break; + return (x); +} + +int +evHighestFD(evContext opaqueCtx) { + evContext_p *ctx = opaqueCtx.opaque; + + return (ctx->highestFD); +} + +void +evPrintf(const evContext_p *ctx, int level, const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + if (ctx->output != NULL && ctx->debug >= level) { + vfprintf(ctx->output, fmt, ap); + fflush(ctx->output); + } + va_end(ap); +} + +#ifdef NEED_PSELECT +/* XXX needs to move to the porting library. */ +static int +pselect(int nfds, void *rfds, void *wfds, void *efds, + struct timespec *tsp, + const sigset_t *sigmask) +{ + struct timeval tv, *tvp; + sigset_t sigs; + int n; + + if (tsp) { + tvp = &tv; + tv = evTimeVal(*tsp); + } else + tvp = NULL; + if (sigmask) + sigprocmask(SIG_SETMASK, sigmask, &sigs); + n = select(nfds, rfds, wfds, efds, tvp); + if (sigmask) + sigprocmask(SIG_SETMASK, &sigs, NULL); + if (tsp) + *tsp = evTimeSpec(tv); + return (n); +} +#endif diff --git a/lib/bind/isc/eventlib.mdoc b/lib/bind/isc/eventlib.mdoc new file mode 100644 index 0000000000..f3bfef3601 --- /dev/null +++ b/lib/bind/isc/eventlib.mdoc @@ -0,0 +1,854 @@ +.\" $Id: eventlib.mdoc,v 1.1 2001/03/29 06:31:54 marka Exp $ +.\" +.\"Copyright (c) 1995-1999 by Internet Software Consortium +.\" +.\"Permission to use, copy, modify, and distribute this software for any +.\"purpose with or without fee is hereby granted, provided that the above +.\"copyright notice and this permission notice appear in all copies. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\"DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\"PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\"ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\"SOFTWARE. +.\" +.Dd March 6, 1996 +.Dt EVENTLIB 3 +.Os BSD 4 +.Sh NAME +.Nm evConnFunc , +.Nm evFileFunc , +.Nm evStreamFunc , +.Nm evTimerFunc , +.Nm evWaitFunc , +.Nm evCreate , +.Nm evDestroy , +.Nm evGetNext , +.Nm evDispatch , +.Nm evDrop , +.Nm evMainLoop , +.Nm evConsTime , +.Nm evTimeSpec , +.Nm evTimeVal , +.Nm evAddTime , +.Nm evSubTime , +.Nm evCmpTime , +.Nm evNowTime , +.Nm evLastEventTime , +.Nm evSetTimer , +.Nm evResetTimer , +.Nm evClearTimer , +.Nm evSetIdleTimer , +.Nm evTouchIdleTimer , +.Nm evClearIdleTimer , +.Nm evWaitFor , +.Nm evDo , +.Nm evUnwait , +.Nm evDefer , +.Nm evSelectFD , +.Nm evDeselectFD , +.Nm evWrite , +.Nm evRead , +.Nm evCancelRW , +.Nm evTimeRW , +.Nm evUntimeRW , +.Nm evListen , +.Nm evConnect , +.Nm evCancelConn , +.Nm evHold , +.Nm evUnhold , +.Nm evTryAccept , +.Nm evConsIovec , +.Nm evSetDebug , +.Nm evPrintf , +.Nm evInitID , +.Nm evTestID +.Nd event handling library +.Sh SYNOPSIS +.Fd #include +.Ft typedef void +.Fn (*evConnFunc) "evContext ctx" "void *uap" "int fd" \ +"const void *la" "int lalen" "const void *ra" "int ralen" +.Ft typedef void +.Fn (*evTimerFunc) "evContext ctx" "void *uap" \ +"struct timespec due" "struct timespec inter" +.Ft typedef void +.Fn (*evFileFunc) "evContext ctx" "void *uap" "int fd" "int eventmask" +.Ft typedef void +.Fn (*evStreamFunc) "evContext ctx" "void *uap" "int fd" "int bytes" +.Ft typedef void +.Fn (*evWaitFunc) "evContext ctx" "void *uap" "const void *tag" +.Ft int +.Fn evCreate "evContext *ctx" +.Ft int +.Fn evDestroy "evContext ctx" +.Ft int +.Fn evGetNext "evContext ctx" "evEvent *ev" "int options" +.Ft int +.Fn evDispatch "evContext ctx" "evEvent ev" +.Ft void +.Fn evDrop "evContext ctx" "evEvent ev" +.Ft int +.Fn evMainLoop "evContext ctx" +.Ft struct timespec +.Fn evConsTime "int sec" "int usec" +.Ft struct timespec +.Fn evTimeSpec "struct timeval tv" +.Ft struct timeval +.Fn evTimeVal "struct timespec ts" +.Ft struct timespec +.Fn evAddTime "struct timespec addend1" "struct timespec addend2" +.Ft struct timespec +.Fn evSubTime "struct timespec minuend" "struct timespec subtrahend" +.Ft struct timespec +.Fn evCmpTime "struct timespec a" "struct timespec b" +.Ft struct timespec +.Fn evNowTime "void" +.Ft struct timespec +.Fn evLastEventTime "evContext opaqueCtx" +.Ft int +.Fn evSetTimer "evContext ctx" "evTimerFunc func" "void *uap" \ +"struct timespec due" "struct timespec inter" "evTimerID *id" +.Ft int +.Fn evResetTimer "evContext ctx" "evTimerID id" "evTimerFunc func" \ +"void *uap" "struct timespec due" "struct timespec inter" +.Ft int +.Fn evClearTimer "evContext ctx" "evTimerID id" +.Ft int +.Fn evSetIdleTimer "evContext opaqueCtx" "evTimerFunc func" "void *uap" \ +"struct timespec max_idle" "evTimerID *opaqueID" +.Ft int +.Fn evTouchIdleTimer "evContext opaqueCtx" "evTimerID id" +.Ft int +.Fn evResetIdleTimer "evContext opaqueCtx" "evTimerID id" "evTimerFunc func" \ +"void *uap" "struct timespec max_idle" +.Ft int +.Fn evClearIdleTimer "evContext opaqueCtx" "evTimerID id" +.Ft int +.Fn evWaitFor "evContext opaqueCtx" "const void *tag" \ +"evWaitFunc func" "void *uap" "evWaitID *id" +.Ft int +.Fn evDo "evContext opaqueCtx" "const void *tag" +.Ft int +.Fn evUnwait "evContext opaqueCtx" "evWaitID id" +.Ft int +.Fn evDefer "evContext opaqueCtx" "evWaitFunc func" "void *uap" +.Ft int +.Fn evSelectFD "evContext ctx" "int fd" "int eventmask" \ +"evFileFunc func" "void *uap" "evFileID *id" +.Ft int +.Fn evDeselectFD "evContext ctx" "evFileID id" +.Ft struct iovec +.Fn evConsIovec "void *buf" "size_t cnt" +.Ft int +.Fn evWrite "evContext ctx" "int fd" "const struct iovec *iov" "int cnt" \ +"evStreamFunc func" "void *uap" "evStreamID *id" +.Ft int +.Fn evRead "evContext ctx" "int fd" "const struct iovec *iov" "int cnt" \ +"evStreamFunc func" "void *uap" "evStreamID *id" +.Ft int +.Fn evCancelRW "evContext ctx" "evStreamID id" +.Ft int +.Fn evTimeRW "evContext opaqueCtx" "evStreamID id" "evTimerID timer" +.Ft int +.Fn evUntimeRW "evContext opaqueCtx" "evStreamID id" +.Ft int +.Fn evListen "evContext ctx" "int fd" "int maxconn" \ +"evConnFunc func" "void *uap" "evConnID *id" +.Ft int +.Fn evConnect "evContext ctx" "int fd" "void *ra" "int ralen" \ +"evConnFunc func" "void *uap" "evConnID *id" +.Ft int +.Fn evCancelConn "evContext ctx" "evConnID id" +.Ft int +.Fn evHold "evContext ctx" "evConnID id" +.Ft int +.Fn evUnhold "evContext ctx" "evConnID id" +.Ft int +.Fn evTryAccept "evContext ctx" "evConnID id" "int *sys_errno" +.Ft void +.Fn evSetDebug "evContext ctx" "int level" "FILE *output" +.Ft void +.Fn evPrintf "const evContext_p *ctx" "int level" "const char *fmt" "..." +.Ft void +.Fn evInitID "*\s-1ID\s+1" +.Ft int +.Fn evTestID "\s-1ID\s+1" +.Sh DESCRIPTION +This library provides multiple outstanding asynchronous timers and I/O +to a cooperating application. The model is similar to that of the X +Toolkit, in that events are registered with the library and the application +spends most of its time in the +.Fn evMainLoop +function. If an application already has a main loop, it can safely register +events with this library as long as it periodically calls the +.Fn evGetNext +and +.Fn evDispatch +functions. (Note that +.Fn evGetNext +has both polling and blocking modes.) +.Pp +The function +.Fn evCreate +creates an event context which is needed by all the other functions in this +library. All information used internally by this library is bound to this +context, rather than to static storage. This makes the library +.Dq thread safe, +and permits other library functions to use events without +disrupting the application's use of events. +.Pp +The function +.Fn evDestroy +destroys a context that has been created by +.Fn evCreate . +All dynamic memory bound to this context will be freed. An implicit +.Fn evTimerClear +will be done on all timers set in this event context. An implicit +.Fn evDeselectFD +will be done on all file descriptors selected in this event context. +.Pp +The function +.Fn evGetNext +potentially waits for and then retrieves the next asynchronous event, +placing it in the object of the +.Fa ev +pointer argument. The following +.Fa options +are available: +.Fa EV_POLL , +meaning that +.Fn evGetNext +should not block, but rather return +.Dq Fa -1 +with +.Fa errno +set to +.Fa EWOULDBLOCK +if no events have occurred; +.Fa EV_WAIT , +which tells +.Fn evGetNext +to block internally until the next event occurs; and +.Fa EV_NULL , +which tells +.Fn evGetNext +that it should return a special +.Dq no-op +event, which is ignored by +.Fn evDispatch +but handled correctly by +.Fn evDrop . +.Fa EV_NULL +can be necessary to the correct functioning of a caller\-written equivilent to +.Fn evMainLoop , +wherein perterbations caused by external system events must be polled for, and +the default behaviour of internally ignoring such events is undesirable. +Note that +.Fa EV_POLL +and +.Fa EV_WAIT +are mutually exclusive. +.Pp +The function +.Fn evDispatch +dispatches an event retrieved by +.Fn evGetNext . +This usually involves calling the function that was associated with the event +when the event was registered with +.Fn evSetTimer , +.Fn evResetTimer , +or +.Fn evSelectFD . +All events retrieved by +.Fn evGetNext +must be given over to +.Fn evDispatch +at some point, since there is some dynamic memory associated with each event. +.Pp +The function +.Fn evDrop +deallocates dynamic memory that has been allocated by +.Fn evGetNext . +Calling +.Fn evDispatch +has the side effect of calling +.Fn evDrop , +but if you are going to drop the event rather than dispatch it, you will have +to call +.Fn evDrop +directly. +.Pp +The function +.Fn evMainLoop +is just: +.Bd -literal -offset indent +while ((x = evGetNext(opaqueCtx, &event, EV_WAIT)) == 0) + if ((x = evDispatch(opaqueCtx, event)) < 0) + break; +return (x); +.Ed +.Pp +In other words, get events and dispatch them until an error occurs. One such +error would be that all the events under this context become unregistered; in +that event, there will be nothing to wait for and +.Fn evGetNext +becomes an undefined operation. +.Pp +The function +.Fn evConsTime +is a constructor for +.Dq Fa struct timespec +which allows these structures to be created and then passed as arguments to +other functions without the use of temporary variables. (If C had inline +constructors, there would be no need for this function.) +.Pp +The functions +.Fn evTimeSpec +and +.Fn evTimeVal +are utilities which allow the caller to convert a +.Dq Fa struct timeval +to a +.Dq Fa struct timespec +(the function of +.Fn evTimeSpec ) +or vice versa (the function of +.Fn evTimeVal ) . +Note that the name of the function indicates the type of the return value. +.Pp +The function +.Fn evAddTime +adds two +.Dq Fa struct timespec +values and returns the result as a +.Dq Fa struct timespec. +.Pp +The function +.Fn evSubTime +subtracts its second +.Dq Fa struct timespec +argument from its first +.Dq Fa struct timespec +argument and returns the result as a +.Dq Fa struct timespec. +.Pp +The function +.Fn evCmpTime +compares its two +.Dq Fa struct timespec +arguments and returns an +.Dq Fa int +that is less than zero if the first argument specifies an earlier time than +the second, or more than zero if the first argument specifies a later time +than the second, or equal to zero if both arguments specify the same time. +.Pp +The function +.Fn evNowTime +returns a +.Dq Fa struct timespec +which either describes the current time (using +.Xr gettimeofday 2 ) , +if successful, or has its fields set to zero, if there is an error. +(In the latter case, the caller can check +.Va errno , +since it will be set by +.Xr gettimeofday 2 . ) +.Pp +The function +.Fn evLastEventTime +returns the +.Dq Fa struct timespec +which describes the last time that certain events happened to the +event context indicated by +.Fa opaqueCtx . +This value is updated by +.Fn evCreate +and +.Fn evGetNext +(upon entry and after +.Xr select 2 +returns); it is routinely compared with other times in the internal handling +of, e.g., timers. +.Pp +The function +.Fn evSetTimer +registers a timer event, which will be delivered as a function call to the +function specified by the +.Fa func +argument. The event will be delivered at absolute time +.Fa due , +and then if time +.Fa inter +is not equal to +.Dq Fa evConsTime(0,0) , +subsequently at intervals equal to time +.Fa inter . +As a special case, specifying a +.Fa due +argument equal to +.Dq Fa evConsTime(0,0) +means +.Dq due immediately. +The +.Fa opaqueID +argument, if specified as a value other than +.Fa NULL , +will be used to store the resulting +.Dq timer \s-1ID\s+1 , +useful as an argument to +.Fn evClearTimer . +Note that in a +.Dq one\-shot +timer (which has an +.Fa inter +argument equal to +.Dq Fa evConsTime(0,0) +.\" putting the ) after the Dq Fa arg did not work well. --vix +) the user function +.Fa func +should deallocate any dynamic memory that is uniquely bound to the +.Fa uap , +since no handles to this memory will exist within the event library +after a one\-shot timer has been delivered. +.Pp +The function +.Fn evResetTimer +resets the values of the timer specified by +.Fa id +to the given arguments. The arguments are the same as in the description of +.Fn evSetTimer +above. +.Pp +The function +.Fn evClearTimer +will unregister the timer event specified by +.Fa id . +Note that if the +.Fa uap +specified in the corresponding +.Fn evSetTimer +call is uniquely bound to any dynamic memory, then that dynamic memory should +be freed by the caller before the handle is lost. After a call to +.Fn evClearTimer , +no handles to this +.Fa uap +will exist within the event library. +.Pp +The function +.Fn evSetIdleTimer +is similar to (and built on) +.Fn evSetTimer ; +it registers an idle timer event which provides for the function call to +.Fa func +to occur. However, for an +.Em idle +timer, the call will occur after at least +.Dq Fa max_idle +time has passed since the time the idle timer was +.Dq last touched ; +originally, this is set to the time returned by +.Fn evLastEventTime +(described above) for the event context specified by +.Fa opaqueCtx . +This is a +.Dq one\-shot +timer, but the time at which the +.Fa func +is actually called can be changed by recourse to +.Fn evTouchIdleTimer +(described below). The pointer to the underlying +.Dq timer \s-1ID\s+1 +is returned in +.Fa opaqueID , +if it is +.No non- Ns Dv NULL . +.Pp +The +.Fn evTouchIdleTimer +function updates the idle timer associated with +.Fa id , +setting its idea of the time it was last accessed to the value returned by +.Fn evLastEventTime +(described above) for the event context specified by +.Fa opaqueCtx . +This means that the idle timer will expire after at least +.Fa max_idle +time has passed since this (possibly new) time, providing a caller mechanism +for resetting the call to the +.Fa func +associated with the idle timer. (See the description of +.Fn evSetIdleTimer , +above, for information about +.Fa func +and +.Fa max_idle . ) +.Pp +The +.Fn evResetIdleTimer +function reschedules a timer and resets the callback function and its argument. +Note that resetting a timer also ``touches'' it. +.Pp +The +.Fn evClearIdleTimer +function unregisters the idle timer associated with +.Fa id . +See the discussion under +.Fn evClearTimer , +above, for information regarding caller handling of the +.Fa uap +associated with the corresponding +.Fn evSetIdleTimer +call. +.Pp +The function +.Fn evWaitFor +places the function +.Fa func +on the given event context's wait queue with the associated (possibly +.Dv NULL ) +.Dq Fa tag ; +if +.Fa id +is +.No non- Ns Dv NULL , +then it will contain the +.Dq wait \s-1ID\s+1 +associated with the created queue element. +.Pp +The function +.Fn evDo +marks +.Em all +of the +.Dq waiting +functions in the given event context's wait queue with the associated (possibly +.Dv NULL ) +.Dq Fa tag +as runnable. This places these functions in a +.Dq done +queue which will be read by +.Fn evGetNext . +.Pp +The function +.Fn evUnwait +will search for the +.Dq wait \s-1ID\s+1 +.Fa id +in the wait queue of the given event context; if an element with the given +.Fa id +is not found, then the +.Dq done +queue of that context is searched. If found, the queue element is removed +from the appropriate list. +.Pp +The function +.Fn evDefer +causes a function (specified as +.Fa func , +with argument +.Fa uap ) +to be dispatched at some later time. Note that the +.Fa tag +argument to +.Fa func +will always be +.Fa NULL +when dispatched. +.Pp +The function +.Fn evSelectFD +registers a file I/O event for the file descriptor specified by +.Fa fd . +Bits in the +.Fa eventmask +argument are named +.Fa EV_READ , +.Fa EV_WRITE , +and +.Fa EV_EXCEPT . +At least one of these bits must be specified. If the +.Fa id +argument is not equal to +.Fa NULL , +it will be used to store a unique ``file event \s-1ID\s+1'' for this event, +which is useful in subsequent calls to +.Fn evDeselectFD . +A file descriptor will be made nonblocking using the +.Fa O_NONBLOCK +flag with +.Xr fcntl 2 +on its first concurrent registration via +.Fn evSelectFD . +An +.Fn evSelectFD +remains in effect until cancelled via +.Fn evDeselectFD . +.Pp +The function +.Fn evDeselectFD +unregisters the ``file event'' specified by the +.Fa id +argument. If the corresponding +.Fa uap +uniquely points to dynamic memory, that memory should be freed before its +handle is lost, since after a call to +.Fn evDeselectFD , +no handles to this event's +.Fa uap +will remain within the event library. A file descriptor will be taken out of +nonblocking mode (see +.Fa O_NONBLOCK +and +.Xr fcntl 2 ) +when its last event registration is removed via +.Fn evDeselectFD , +if it was in blocking mode before the first registration via +.Fn evSelectFD . +.Pp +The function +.Fn evConsIovec +is a constructor for a single +.Ft struct iovec +structure, which is useful for +.Fn evWrite +and +.Fn evRead . +.Pp +The functions +.Fn evWrite +and +.Fn evRead +start asynchronous stream I/O operations on file descriptor +.Fa fd . +The data to be written or read is in the scatter/gather descriptor specified by +.Fa iov +and +.Fa cnt . +The supplied function +.Fa func +will be called with argument +.Fa uap +when the I/O operation is complete. If +.Fa id +is not +.Fa NULL , +it will be filled a with the stream event identifier suitable for use with +.Fn evCancelRW . +.Pp +The function +.Fn evCancelRW +extinguishes an outstanding +.Fn evWrite +or +.Fn evRead +call. System I/O calls cannot always be cancelled, but you are guaranteed +that the +.Fa func +function supplied to +.Fn evWrite +or +.Fn evRead +will not be called after a call to +.Fn evCancelRW . +Care should be taken not to deallocate or otherwise reuse the space pointed +to by the segment descriptors in +.Fa iov +unless the underlying file descriptor is closed first. +.Pp +The function +.Fn evTimeRW +sets the stream associated with the given stream \s-1ID\s+1 +.Dq Fa id +to have the idle timer associated with the timer \s-1ID\s+1 +.Dq Fa timer . +.Pp +The function +.Fn evUntimeRW +says that the stream associated with the given stream \s-1ID\s+1 +.Dq Fa id +should ignore its idle timer, if present. +.Pp +The functions +.Fn evListen , +.Fn evConnect , +and +.Fn evCancelConn +can be used to manage asynchronous incoming and outgoing socket connections. +Sockets to be used with these functions should first be created with +.Xr socket 2 +and given a local name with +.Xr bind 2 . +It is extremely unlikely that the same socket will ever be +useful for both incoming and outgoing connections. The +.Fa id +argument to +.Fn evListen +and +.Fn evConnect +is either +.Fa NULL +or the address of a +.Ft evFileID +variable which can then be used in a subsequent call to +.Fn evCancelConn . +.Pp +After a call to +.Fn evListen , +each incoming connection arriving on +.Fa fd +will cause +.Fa func +to be called with +.Fa uap +as one of its arguments. +.Fn evConnect +initiates an outgoing connection on +.Fa fd +to destination address +.Fa ra +(whose length is +.Fa ralen ). +When the connection is complete, +.Fa func +will be called with +.Fa uap +as one of its arguments. The argument +.Fa fd +to +.Fn (*func)() +will be +.Fa -1 +if an error occurred that prevented this connection from completing +successfully. In this case +.Fn errno +will have been set and the socket described by +.Fa fd +will have been closed. The +.Fn evCancelConn +function will prevent delivery of all pending and subsequent +events for the outstanding connection. The +.Fn evHold +function will suspend the acceptance of new connections on the listener +specified by +.Fa id . +Connections will be queued by the protocol stack up to the system's limit. The +.Fn evUnhold +function will reverse the effects of +.Fn evHold , +allowing incoming connections to be delivered for listener +.Fa id . +The +.Fn evTryAccept +function will poll the listener specified by +.Fa id , +accepting a new connection if one is available, and queuing a connection event +for later retrieval by +.Fn evGetNext . +If the connection event queued is an accept error(), sys_errno will contain +the error code; otherwise it will be zero. All connection events queued by +.Fn evTryAccept +will be delivered by +.Fn evGetNext +before a new select is done on the listener. +.Pp +The function +.Fn evSetDebug +sets the debugging +.Fa level +and diagnostic +.Fa output +file handle for an event context. Greater numeric levels will +result in more verbose output being sent to the output FILE during program +execution. +.Pp +The function +.Fn evPrintf +prints a message with the format +.Dq Fa fmt +and the following arguments (if any), on the output stream associated +with the event context pointed to by +.Fa ctx . +The message is output if the event context's debug level is greater than +or equal to the indicated +.Fa level . +.Pp +The function +.Fn evInitID +will initialize an opaque +.Dq evConn \s-1ID\s+1 , +.Dq evFile \s-1ID\s+1 , +.Dq evStream \s-1ID\s+1 , +.Dq evTimer \s-1ID\s+1 , +.Dq evWait \s-1ID\s+1 , +.Dq evContext , +or +.Dq evEvent , +which is passed by reference. +.Pp +The function +.Fn evTestID +will examine an opaque \s-1ID\s+1 and return +.Dq TRUE +only if it is not in its initialized state. +.Sh RETURN VALUES +All the functions whose return type is +.Dq Fa int +use the standard convention of returning zero (0) to indicate success, or +returning +.Dq Fa -1 +and setting +.Fa errno +to indicate failure. +.Sh FILE +.Pa heap.h , +which is in the +.Pa src/lib/isc +directory of the current +.Sy BIND +distribution. +.Sh ERRORS +The possible values for +.Fa errno +when one of the +.Dq Fa int +functions in this library returns +.Dq Fa -1 +include those of the Standard C Library and also: +.Bl -tag -width EWOULDBLOCKAA +.It Bq Er EINVAL +Some function argument has an unreasonable value. +.It Bq Er EINVAL +The specified file descriptor has an integer value greater than the default +.Fa FD_SETSIZE , +meaning that the application's limit is higher than the library's. +.It Bq Er ENOENT +The specified +.Dq event \s-1ID\s+1 +does not exist. +.It Bq Er EWOULDBLOCK +No events have occurred and the +.Fa EV_POLL +option was specified. +.It Bq Er EBADF +The specified signal was unblocked outside the library. +.El +.Sh SEE ALSO +.Xr gettimeofday 2 , +.Xr select 2 , +.Xr fcntl 3 , +.Xr malloc 3 , +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr readv 3 , +.Xr writev 3 . +.Sh BUGS +This huge man page needs to be broken up into a handful of smaller ones. +.Sh HISTORY +The +.Nm eventlib +library was designed by Paul Vixie with excellent advice from his friends +and with tips 'o the cap to the X Consortium and the implementors of DEC SRC +Modula-3. diff --git a/lib/bind/isc/eventlib_p.h b/lib/bind/isc/eventlib_p.h new file mode 100644 index 0000000000..e70eb7bda7 --- /dev/null +++ b/lib/bind/isc/eventlib_p.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 1995-1999 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* eventlib_p.h - private interfaces for eventlib + * vix 09sep95 [initial] + * + * $Id: eventlib_p.h,v 1.1 2001/03/29 06:31:54 marka Exp $ + */ + +#ifndef _EVENTLIB_P_H +#define _EVENTLIB_P_H + +#include +#include +#include +#include +#include + +#define EVENTLIB_DEBUG 1 + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define EV_MASK_ALL (EV_READ | EV_WRITE | EV_EXCEPT) +#define ERR(e) return (errno = (e), -1) +#define OK(x) if ((x) < 0) ERR(errno); else (void)NULL + +#define NEW(p) if (((p) = memget(sizeof *(p))) != NULL) \ + FILL(p); \ + else \ + (void)NULL; +#define OKNEW(p) if (!((p) = memget(sizeof *(p)))) { \ + errno = ENOMEM; \ + return (-1); \ + } else \ + FILL(p) +#define FREE(p) memput((p), sizeof *(p)) + +#if EVENTLIB_DEBUG +#define FILL(p) memset((p), 0xF5, sizeof *(p)) +#else +#define FILL(p) +#endif + +typedef struct evConn { + evConnFunc func; + void * uap; + int fd; + int flags; +#define EV_CONN_LISTEN 0x0001 /* Connection is a listener. */ +#define EV_CONN_SELECTED 0x0002 /* evSelectFD(conn->file). */ +#define EV_CONN_BLOCK 0x0004 /* Listener fd was blocking. */ + evFileID file; + struct evConn * prev; + struct evConn * next; +} evConn; + +typedef struct evAccept { + int fd; + union { + struct sockaddr sa; + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif + } la; + int lalen; + union { + struct sockaddr sa; + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif + } ra; + int ralen; + int ioErrno; + evConn * conn; + LINK(struct evAccept) link; +} evAccept; + +typedef struct evFile { + evFileFunc func; + void * uap; + int fd; + int eventmask; + int preemptive; + struct evFile * prev; + struct evFile * next; + struct evFile * fdprev; + struct evFile * fdnext; +} evFile; + +typedef struct evStream { + evStreamFunc func; + void * uap; + evFileID file; + evTimerID timer; + int flags; +#define EV_STR_TIMEROK 0x0001 /* IFF timer valid. */ + int fd; + struct iovec * iovOrig; + int iovOrigCount; + struct iovec * iovCur; + int iovCurCount; + int ioTotal; + int ioDone; + int ioErrno; + struct evStream *prevDone, *nextDone; + struct evStream *prev, *next; +} evStream; + +typedef struct evTimer { + evTimerFunc func; + void * uap; + struct timespec due, inter; + int index; +} evTimer; + +typedef struct evWait { + evWaitFunc func; + void * uap; + const void * tag; + struct evWait * next; +} evWait; + +typedef struct evWaitList { + evWait * first; + evWait * last; + struct evWaitList * prev; + struct evWaitList * next; +} evWaitList; + +typedef struct evEvent_p { + enum { Accept, File, Stream, Timer, Wait, Free, Null } type; + union { + struct { evAccept *this; } accept; + struct { evFile *this; int eventmask; } file; + struct { evStream *this; } stream; + struct { evTimer *this; } timer; + struct { evWait *this; } wait; + struct { struct evEvent_p *next; } free; + struct { const void *placeholder; } null; + } u; +} evEvent_p; + +typedef struct { + /* Global. */ + const evEvent_p *cur; + /* Debugging. */ + int debug; + FILE *output; + /* Connections. */ + evConn *conns; + LIST(evAccept) accepts; + /* Files. */ + evFile *files, *fdNext; + fd_set rdLast, rdNext; + fd_set wrLast, wrNext; + fd_set exLast, exNext; + fd_set nonblockBefore; + int fdMax, fdCount, highestFD; + evFile *fdTable[FD_SETSIZE]; +#ifdef EVENTLIB_TIME_CHECKS + struct timespec lastSelectTime; + int lastFdCount; +#endif + /* Streams. */ + evStream *streams; + evStream *strDone, *strLast; + /* Timers. */ + struct timespec lastEventTime; + heap_context timers; + /* Waits. */ + evWaitList *waitLists; + evWaitList waitDone; +} evContext_p; + +/* eventlib.c */ +#define evPrintf __evPrintf +void evPrintf(const evContext_p *ctx, int level, const char *fmt, ...); + +/* ev_timers.c */ +#define evCreateTimers __evCreateTimers +heap_context evCreateTimers(const evContext_p *); +#define evDestroyTimers __evDestroyTimers +void evDestroyTimers(const evContext_p *); + +/* ev_waits.c */ +#define evFreeWait __evFreeWait +evWait *evFreeWait(evContext_p *ctx, evWait *old); + +#endif /*_EVENTLIB_P_H*/ diff --git a/lib/bind/isc/heap.c b/lib/bind/isc/heap.c new file mode 100644 index 0000000000..69f98dadd3 --- /dev/null +++ b/lib/bind/isc/heap.c @@ -0,0 +1,221 @@ +/* + * Copyright (c) 1997,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Heap implementation of priority queues adapted from the following: + * + * _Introduction to Algorithms_, Cormen, Leiserson, and Rivest, + * MIT Press / McGraw Hill, 1990, ISBN 0-262-03141-8, chapter 7. + * + * _Algorithms_, Second Edition, Sedgewick, Addison-Wesley, 1988, + * ISBN 0-201-06673-4, chapter 11. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: heap.c,v 1.1 2001/03/29 06:31:55 marka Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include +#include +#include + +#include "port_after.h" + +#include + +/* + * Note: to make heap_parent and heap_left easy to compute, the first + * element of the heap array is not used; i.e. heap subscripts are 1-based, + * not 0-based. + */ +#define heap_parent(i) ((i) >> 1) +#define heap_left(i) ((i) << 1) + +#define ARRAY_SIZE_INCREMENT 512 + +heap_context +heap_new(heap_higher_priority_func higher_priority, heap_index_func index, + int array_size_increment) { + heap_context ctx; + + ctx = (heap_context)malloc(sizeof (struct heap_context)); + if (ctx == NULL || higher_priority == NULL) + return (NULL); + ctx->array_size = 0; + if (array_size_increment == 0) + ctx->array_size_increment = ARRAY_SIZE_INCREMENT; + else + ctx->array_size_increment = array_size_increment; + ctx->heap_size = 0; + ctx->heap = NULL; + ctx->higher_priority = higher_priority; + ctx->index = index; + return (ctx); +} + +int +heap_free(heap_context ctx) { + if (ctx == NULL) { + errno = EINVAL; + return (-1); + } + + if (ctx->heap != NULL) + free(ctx->heap); + free(ctx); + + return (0); +} + +static int +heap_resize(heap_context ctx) { + void **new_heap; + + ctx->array_size += ctx->array_size_increment; + new_heap = (void **)realloc(ctx->heap, + (ctx->array_size) * (sizeof (void *))); + if (new_heap == NULL) { + errno = ENOMEM; + return (-1); + } + ctx->heap = new_heap; + return (0); +} + +static void +float_up(heap_context ctx, int i, void *elt) { + int p; + + for ( p = heap_parent(i); + i > 1 && ctx->higher_priority(elt, ctx->heap[p]); + i = p, p = heap_parent(i) ) { + ctx->heap[i] = ctx->heap[p]; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); + } + ctx->heap[i] = elt; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); +} + +static void +sink_down(heap_context ctx, int i, void *elt) { + int j, size, half_size; + + size = ctx->heap_size; + half_size = size / 2; + while (i <= half_size) { + /* find smallest of the (at most) two children */ + j = heap_left(i); + if (j < size && ctx->higher_priority(ctx->heap[j+1], + ctx->heap[j])) + j++; + if (ctx->higher_priority(elt, ctx->heap[j])) + break; + ctx->heap[i] = ctx->heap[j]; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); + i = j; + } + ctx->heap[i] = elt; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); +} + +int +heap_insert(heap_context ctx, void *elt) { + int i; + + if (ctx == NULL || elt == NULL) { + errno = EINVAL; + return (-1); + } + + i = ++ctx->heap_size; + if (ctx->heap_size >= ctx->array_size && heap_resize(ctx) < 0) + return (-1); + + float_up(ctx, i, elt); + + return (0); +} + +int +heap_delete(heap_context ctx, int i) { + void *elt; + + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (-1); + } + + elt = ctx->heap[ctx->heap_size]; + if (--ctx->heap_size > 0) + sink_down(ctx, i, elt); + + return (0); +} + +int +heap_increased(heap_context ctx, int i) { + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (-1); + } + + float_up(ctx, i, ctx->heap[i]); + + return (0); +} + +int +heap_decreased(heap_context ctx, int i) { + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (-1); + } + + sink_down(ctx, i, ctx->heap[i]); + + return (0); +} + +void * +heap_element(heap_context ctx, int i) { + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (NULL); + } + + return (ctx->heap[i]); +} + +int +heap_for_each(heap_context ctx, heap_for_each_func action, void *uap) { + int i; + + if (ctx == NULL || action == NULL) { + errno = EINVAL; + return (-1); + } + + for (i = 1; i <= ctx->heap_size; i++) + (action)(ctx->heap[i], uap); + return (0); +} diff --git a/lib/bind/isc/heap.mdoc b/lib/bind/isc/heap.mdoc new file mode 100644 index 0000000000..cd1596a510 --- /dev/null +++ b/lib/bind/isc/heap.mdoc @@ -0,0 +1,368 @@ +.\" $Id: heap.mdoc,v 1.1 2001/03/29 06:31:55 marka Exp $ +.\" +.\"Copyright (c) 1997,1999 by Internet Software Consortium. +.\" +.\"Permission to use, copy, modify, and distribute this software for any +.\"purpose with or without fee is hereby granted, provided that the above +.\"copyright notice and this permission notice appear in all copies. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\"DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\"PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\"ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\"SOFTWARE. +.\" +.Dd Jan 1, 1997 +.\"Os OPERATING_SYSTEM [version/release] +.Os BSD 4 +.Dt HEAP @SYSCALL_EXT@ +.Sh NAME +.Nm heap_new , +.Nm heap_free , +.Nm heap_insert , +.Nm heap_delete , +.Nm heap_increased , +.Nm heap_decreased , +.Nm heap_element , +.Nm heap_for_each +.Nd heap implementation of priority queues +.Sh SYNOPSIS +.Fd #include \&"heap.h\&" +.Ft heap_context +.Fn heap_new "heap_higher_priority_func higher_priority" \ +"heap_index_func index" "int array_size_increment" +.Ft int +.Fn heap_free "heap_context ctx" +.Ft int +.Fn heap_insert "heap_context ctx" "void *elt" +.Ft int +.Fn heap_delete "heap_context ctx" "int i" +.Ft int +.Fn heap_increased "heap_context ctx" "int i" +.Ft int +.Fn heap_decreased "heap_context ctx" "int i" +.Ft void * +.Fn heap_element "heap_context ctx" "int i" +.Ft int +.Fn heap_for_each "heap_context ctx" "heap_for_each_func action" "void *uap" +.Sh DESCRIPTION +These functions implement heap\-based priority queues. The user defines a +priority scheme, and provides a function for comparison of the priority +of heap elements +.Po see the description of the +.Ft heap_higher_priority_func +function pointer, below +.Pc . +.Pp +Each of the functions depends upon the +.Ft heap_context +type, which is a pointer to a +.Ft struct heap_context +.Pq see Pa heap.h No for more information . +.Pp +The +.Pa heap.h +header file also defines the following set of function +function pointers: +.Bd -literal -offset indent +typedef int (*heap_higher_priority_func)(void *, void *); +typedef void (*heap_index_func)(void *, int); +typedef void (*heap_for_each_func)(void *, void *); +.Ed +.Pp +These are pointers to user-defined functions. +The +.Ft heap_higher_priority_func +type is a pointer to a function which compares two +different heap (queue) elements and returns an +.Ft int +which answers the question, "Does the first queue element +have a higher priority than the second?" In other words, +a function pointer of this type +.Em must +return a number greater than zero +if the element indicated by the first argument is of a higher priority than +that indicated by the second element, and zero otherwise. +.Pp +The other two function pointers are documented in the descriptions +of +.Fn heap_new +.Pq Va heap_index_func +and +.Fn heap_for_each +.Pq Va heap_for_each_func , +below. +.Pp +The function +.Fn heap_new +initializes a +.Ft struct heap_context +and returns a pointer to it. The +.Fa higher_priority +function pointer +.Em must +be +.No non\- Ns Dv NULL . +As explained above, this refers to a +function supplied by the user which compares the priority of two different +queue or heap elements; see above for more information. +The second argument, +.Fa index , +is a pointer to a user-defined function whose arguments are +a heap element and its index in the heap. +.Fa Index +is intended to provide the user a means of knowing the internal index +of an element in the heap while maintaining the opacity of the implementation; +since the user has to know the actual indexes of heap elements in order to use, +e.g., +.Fn heap_delete +or +.Fn heap_element , +the user +.Fa index +function could store the index in the heap element, itself. If +.Fa index +is +.No non\- Ns Dv NULL , +then it is called +.Em whenever +the index of an element changes, allowing the user to stay up\-to\-date +with index changes. +The last argument, +.Fa array_size_increment +will be used, as its name suggests, by +.Xr malloc 3 +or +.Xr realloc 3 +to increment the array which implements the heap; if zero, a default value +will be used. +.Pp +The +.Fn heap_free +function frees the given +.Ft heap_context +argument +.Pq Fa ctx , +which also frees the entire +.Nm heap , +if it is +.No non\- Ns Dv NULL . +The argument +.Fa ctx +should be +.No non\- Ns Dv NULL . +.Pp +The +.Fn heap_insert +function is used to insert the new heap element +.Fa elt +into the appropriate place (priority\-wise) in the +.Ft heap +indicated by +.Fa ctx +.Po a pointer to a +.Ft heap_context +.Pc . +If +.No non\- Ns Dv NULL , +the user-defined +.Ft higher_priority +function pointer associated with the indicated +.Nm heap +is used to determine that +.Dq appropriate place ; +the highest\-priority elements are at the front of the queue (top of +the heap). +(See the description of +.Fn heap_new , +above, for more information.) +.Pp +The function +.Fn heap_delete +is used to delete the +.Fa i\- Ns th +element of the queue (heap), and fixing up the queue (heap) from that +element onward via the priority as determined by the user function +pointed to by +.Ft higher_priority +function pointer +.Pq see description of Fn heap_new, No above . +.Pp +.Fn heap_increased +.Pp +.Fn heap_decreased +.Pp +The +.Fn heap_element +function returns the +.Fa i\- Ns th +element of the queue/heap indicated by +.Fa ctx , +if possible. +.Pp +The +.Fn heap_for_each +function provides a mechanism for the user to increment through the entire +queue (heap) and perform some +.Fa action +upon each of the queue elements. This +.Fa action +is pointer to a user\-defined function with two arguments, the first of +which should be interpreted by the user's function as a heap element. The +second value passed to the user function is just the +.Fa uap +argument to +.Fn heap_for_each ; +this allows the user to specify additional arguments, if necessary, to +the function pointed to by +.Fa action . +.\" The following requests should be uncommented and +.\" used where appropriate. This next request is +.\" for sections 2 and 3 function return values only. +.Sh RETURN VALUES +.Bl -tag -width "heap_decreased()" +.It Fn heap_new +.Dv NULL +if unable to +.Xr malloc 3 +a +.Ft struct heap_context +or if the +.Fa higher_priority +function pointer is +.Dv NULL; +otherwise, a valid +.Ft heap_context +.Ns . +.It Fn heap_free +-1 if +.Fa ctx +is +.Dv NULL +(with +.Va errno +set to +.Dv EINVAL ) ; +otherwise, 0. +.It Fn heap_insert +-1 +if either +.Fa ctx +or +.Fa elt +is +.Dv NULL , +or if an attempt to +.Xr malloc 3 +or +.Xr realloc 3 +the heap array fails (with +.Va errno +set to +.Dv EINVAL +or +.Dv ENOMEM , +respectively). +Otherwise, 0. +.It Fn heap_delete +-1 if +.Fa ctx +is +.Dv NULL +or +.Fa i +is out\-of\-range (with +.Va errno +set to +.Dv EINVAL ) ; +0 otherwise. +.It Fn heap_increased +As for +.Fn heap_delete . +.It Fn heap_decreased +As for +.Fn heap_delete . +.It Fn heap_element +NULL if +.Fa ctx +is +.Dv NULL +or +.Fa i +out\-of-bounds (with +.Va errno +set to +.Dv EINVAL ) ; +otherwise, a pointer to the +.Fa i\- Ns th +queue element. +.It Fn heap_for_each +-1 if either +.Fa ctx +or +.Fa action +is +.Dv NULL +(with +.Va errno +set to +.Dv EINVAL ) ; +0 otherwise. +.El +.\" This next request is for sections 1, 6, 7 & 8 only +.\" .Sh ENVIRONMENT +.Sh FILES +.Bl -tag -width "heap.h000" +.It Pa heap.h + heap library header file +.El +.\" .Sh EXAMPLES +.\" This next request is for sections 1, 6, 7 & 8 only +.\" (command return values (to shell) and +.\" fprintf/stderr type diagnostics) +.Sh DIAGNOSTICS +Please refer to +.Sx RETURN VALUES . +.\" The next request is for sections 2 and 3 error +.\" and signal handling only. +.Sh ERRORS +The variable +.Va errno +is set by +.Fn heap_free , +.Fn heap_insert , +.Fn heap_delete , +.Fn heap_increased , +and +.Fn heap_decreased +under the conditions of invalid input +.Pq Dv EINVAL +or lack of memory +.Pq Dv ENOMEM ; +please refer to +.Sx RETURN VALUES . +.Sh SEE ALSO +.Xr malloc 3 , +.Xr realloc 3 . +.Pp +Cormen, Leiserson, and Rivest, +.Sy Introduction to Algorithms, +MIT Press / McGraw Hill, 1990, ISBN 0\-262\-03141\-8, chapter 7. +.Pp +Sedgewick, +.Sy Algorithms, +2nd ed'n, Addison\-Wesley, 1988, ISBN 0\-201\-06673\-4, chapter 11. +.\" .Sh STANDARDS +.\" .Sh HISTORY +.Sh AUTHORS +The +.Nm heap +library was implemented by Bob Halley (halley@vix.com) of Vixie Enterprises, +Inc., for the Internet Software consortium, and was adapted from +the two books listed in the +.Sx SEE ALSO +section, above. +.\" .Sh BUGS diff --git a/lib/bind/isc/logging.c b/lib/bind/isc/logging.c new file mode 100644 index 0000000000..468bb58d2f --- /dev/null +++ b/lib/bind/isc/logging.c @@ -0,0 +1,702 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: logging.c,v 1.1 2001/03/29 06:31:55 marka Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef VSPRINTF_CHAR +# define VSPRINTF(x) strlen(vsprintf/**/x) +#else +# define VSPRINTF(x) ((size_t)vsprintf x) +#endif + +#include "logging_p.h" + +static const int syslog_priority[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE, + LOG_WARNING, LOG_ERR, LOG_CRIT }; + +static const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + +static const char *level_text[] = { + "info: ", "notice: ", "warning: ", "error: ", "critical: " +}; + +static void +version_rename(log_channel chan) { + unsigned int ver; + char old_name[PATH_MAX+1]; + char new_name[PATH_MAX+1]; + + ver = chan->out.file.versions; + if (ver < 1) + return; + if (ver > LOG_MAX_VERSIONS) + ver = LOG_MAX_VERSIONS; + /* + * Need to have room for '.nn' (XXX assumes LOG_MAX_VERSIONS < 100) + */ + if (strlen(chan->out.file.name) > (PATH_MAX-3)) + return; + for (ver--; ver > 0; ver--) { + sprintf(old_name, "%s.%d", chan->out.file.name, ver-1); + sprintf(new_name, "%s.%d", chan->out.file.name, ver); + (void)isc_movefile(old_name, new_name); + } + sprintf(new_name, "%s.0", chan->out.file.name); + (void)isc_movefile(chan->out.file.name, new_name); +} + +FILE * +log_open_stream(log_channel chan) { + FILE *stream; + int fd, flags; + struct stat sb; + int regular; + + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (NULL); + } + + /* + * Don't open already open streams + */ + if (chan->out.file.stream != NULL) + return (chan->out.file.stream); + + if (stat(chan->out.file.name, &sb) < 0) { + if (errno != ENOENT) { + syslog(LOG_ERR, + "log_open_stream: stat of %s failed: %s", + chan->out.file.name, strerror(errno)); + chan->flags |= LOG_CHANNEL_BROKEN; + return (NULL); + } + regular = 1; + } else + regular = (sb.st_mode & S_IFREG); + + if (chan->out.file.versions) { + if (!regular) { + syslog(LOG_ERR, + "log_open_stream: want versions but %s isn't a regular file", + chan->out.file.name); + chan->flags |= LOG_CHANNEL_BROKEN; + errno = EINVAL; + return (NULL); + } + } + + flags = O_WRONLY|O_CREAT|O_APPEND; + + if ((chan->flags & LOG_TRUNCATE) != 0) { + if (regular) { + (void)unlink(chan->out.file.name); + flags |= O_EXCL; + } else { + syslog(LOG_ERR, + "log_open_stream: want truncation but %s isn't a regular file", + chan->out.file.name); + chan->flags |= LOG_CHANNEL_BROKEN; + errno = EINVAL; + return (NULL); + } + } + + fd = open(chan->out.file.name, flags, + S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); + if (fd < 0) { + syslog(LOG_ERR, "log_open_stream: open(%s) failed: %s", + chan->out.file.name, strerror(errno)); + chan->flags |= LOG_CHANNEL_BROKEN; + return (NULL); + } + stream = fdopen(fd, "a"); + if (stream == NULL) { + syslog(LOG_ERR, "log_open_stream: fdopen() failed"); + chan->flags |= LOG_CHANNEL_BROKEN; + return (NULL); + } + (void) fchown(fd, chan->out.file.owner, chan->out.file.group); + + chan->out.file.stream = stream; + return (stream); +} + +int +log_close_stream(log_channel chan) { + FILE *stream; + + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (0); + } + stream = chan->out.file.stream; + chan->out.file.stream = NULL; + if (stream != NULL && fclose(stream) == EOF) + return (-1); + return (0); +} + +FILE * +log_get_stream(log_channel chan) { + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (NULL); + } + return (chan->out.file.stream); +} + +char * +log_get_filename(log_channel chan) { + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (NULL); + } + return (chan->out.file.name); +} + +int +log_check_channel(log_context lc, int level, log_channel chan) { + int debugging, chan_level; + + REQUIRE(lc != NULL); + + debugging = ((lc->flags & LOG_OPTION_DEBUG) != 0); + + /* + * If not debugging, short circuit debugging messages very early. + */ + if (level > 0 && !debugging) + return (0); + + if ((chan->flags & (LOG_CHANNEL_BROKEN|LOG_CHANNEL_OFF)) != 0) + return (0); + + /* Some channels only log when debugging is on. */ + if ((chan->flags & LOG_REQUIRE_DEBUG) && !debugging) + return (0); + + /* Some channels use the global level. */ + if ((chan->flags & LOG_USE_CONTEXT_LEVEL) != 0) { + chan_level = lc->level; + } else + chan_level = chan->level; + + if (level > chan_level) + return (0); + + return (1); +} + +int +log_check(log_context lc, int category, int level) { + log_channel_list lcl; + int debugging; + + REQUIRE(lc != NULL); + + debugging = ((lc->flags & LOG_OPTION_DEBUG) != 0); + + /* + * If not debugging, short circuit debugging messages very early. + */ + if (level > 0 && !debugging) + return (0); + + if (category < 0 || category > lc->num_categories) + category = 0; /* use default */ + lcl = lc->categories[category]; + if (lcl == NULL) { + category = 0; + lcl = lc->categories[0]; + } + + for ( /* nothing */; lcl != NULL; lcl = lcl->next) { + if (log_check_channel(lc, level, lcl->channel)) + return (1); + } + return (0); +} + +void +log_vwrite(log_context lc, int category, int level, const char *format, + va_list args) { + log_channel_list lcl; + int pri, debugging, did_vsprintf = 0; + int original_category; + FILE *stream; + log_channel chan; + struct timeval tv; + struct tm *local_tm; + const char *category_name; + const char *level_str; + char time_buf[256]; + char level_buf[256]; + + REQUIRE(lc != NULL); + + debugging = (lc->flags & LOG_OPTION_DEBUG); + + /* + * If not debugging, short circuit debugging messages very early. + */ + if (level > 0 && !debugging) + return; + + if (category < 0 || category > lc->num_categories) + category = 0; /* use default */ + original_category = category; + lcl = lc->categories[category]; + if (lcl == NULL) { + category = 0; + lcl = lc->categories[0]; + } + + /* + * Get the current time and format it. + */ + time_buf[0]='\0'; + if (gettimeofday(&tv, NULL) < 0) { + syslog(LOG_INFO, "gettimeofday failed in log_vwrite()"); + } else { +#ifdef HAVE_TIME_R + localtime_r((time_t *)&tv.tv_sec, &local_tm); +#else + local_tm = localtime((time_t *)&tv.tv_sec); +#endif + if (local_tm != NULL) { + sprintf(time_buf, "%02d-%s-%4d %02d:%02d:%02d.%03ld ", + local_tm->tm_mday, months[local_tm->tm_mon], + local_tm->tm_year+1900, local_tm->tm_hour, + local_tm->tm_min, local_tm->tm_sec, + (long)tv.tv_usec/1000); + } + } + + /* + * Make a string representation of the current category and level + */ + + if (lc->category_names != NULL && + lc->category_names[original_category] != NULL) + category_name = lc->category_names[original_category]; + else + category_name = ""; + + if (level >= log_critical) { + if (level >= 0) { + sprintf(level_buf, "debug %d: ", level); + level_str = level_buf; + } else + level_str = level_text[-level-1]; + } else { + sprintf(level_buf, "level %d: ", level); + level_str = level_buf; + } + + /* + * Write the message to channels. + */ + for ( /* nothing */; lcl != NULL; lcl = lcl->next) { + chan = lcl->channel; + + if (!log_check_channel(lc, level, chan)) + continue; + + if (!did_vsprintf) { + if (VSPRINTF((lc->buffer, format, args)) > + LOG_BUFFER_SIZE) { + syslog(LOG_CRIT, + "memory overrun in log_vwrite()"); + exit(1); + } + did_vsprintf = 1; + } + + switch (chan->type) { + case log_syslog: + if (level >= log_critical) + pri = (level >= 0) ? 0 : -level; + else + pri = -log_critical; + syslog(chan->out.facility|syslog_priority[pri], + "%s%s%s%s", + (chan->flags & LOG_TIMESTAMP) ? time_buf : "", + (chan->flags & LOG_PRINT_CATEGORY) ? + category_name : "", + (chan->flags & LOG_PRINT_LEVEL) ? + level_str : "", + lc->buffer); + break; + case log_file: + stream = chan->out.file.stream; + if (stream == NULL) { + stream = log_open_stream(chan); + if (stream == NULL) + break; + } + if (chan->out.file.max_size != ULONG_MAX) { + long pos; + + pos = ftell(stream); + if (pos >= 0 && + (unsigned long)pos > + chan->out.file.max_size) { + /* + * try to roll over the log files, + * ignoring all all return codes + * except the open (we don't want + * to write any more anyway) + */ + log_close_stream(chan); + version_rename(chan); + stream = log_open_stream(chan); + if (stream == NULL) + break; + } + } + fprintf(stream, "%s%s%s%s\n", + (chan->flags & LOG_TIMESTAMP) ? time_buf : "", + (chan->flags & LOG_PRINT_CATEGORY) ? + category_name : "", + (chan->flags & LOG_PRINT_LEVEL) ? + level_str : "", + lc->buffer); + fflush(stream); + break; + case log_null: + break; + default: + syslog(LOG_ERR, + "unknown channel type in log_vwrite()"); + } + } +} + +void +log_write(log_context lc, int category, int level, const char *format, ...) { + va_list args; + + va_start(args, format); + log_vwrite(lc, category, level, format, args); + va_end(args); +} + +/* + * Functions to create, set, or destroy contexts + */ + +int +log_new_context(int num_categories, char **category_names, log_context *lc) { + log_context nlc; + + nlc = memget(sizeof (struct log_context)); + if (nlc == NULL) { + errno = ENOMEM; + return (-1); + } + nlc->num_categories = num_categories; + nlc->category_names = category_names; + nlc->categories = memget(num_categories * sizeof (log_channel_list)); + if (nlc->categories == NULL) { + memput(nlc, sizeof (struct log_context)); + errno = ENOMEM; + return (-1); + } + memset(nlc->categories, '\0', + num_categories * sizeof (log_channel_list)); + nlc->flags = 0U; + nlc->level = 0; + *lc = nlc; + return (0); +} + +void +log_free_context(log_context lc) { + log_channel_list lcl, lcl_next; + log_channel chan; + int i; + + REQUIRE(lc != NULL); + + for (i = 0; i < lc->num_categories; i++) + for (lcl = lc->categories[i]; lcl != NULL; lcl = lcl_next) { + lcl_next = lcl->next; + chan = lcl->channel; + (void)log_free_channel(chan); + memput(lcl, sizeof (struct log_channel_list)); + } + memput(lc->categories, + lc->num_categories * sizeof (log_channel_list)); + memput(lc, sizeof (struct log_context)); +} + +int +log_add_channel(log_context lc, int category, log_channel chan) { + log_channel_list lcl; + + if (lc == NULL || category < 0 || category >= lc->num_categories) { + errno = EINVAL; + return (-1); + } + + lcl = memget(sizeof (struct log_channel_list)); + if (lcl == NULL) { + errno = ENOMEM; + return(-1); + } + lcl->channel = chan; + lcl->next = lc->categories[category]; + lc->categories[category] = lcl; + chan->references++; + return (0); +} + +int +log_remove_channel(log_context lc, int category, log_channel chan) { + log_channel_list lcl, prev_lcl, next_lcl; + int found = 0; + + if (lc == NULL || category < 0 || category >= lc->num_categories) { + errno = EINVAL; + return (-1); + } + + for (prev_lcl = NULL, lcl = lc->categories[category]; + lcl != NULL; + lcl = next_lcl) { + next_lcl = lcl->next; + if (lcl->channel == chan) { + log_free_channel(chan); + if (prev_lcl != NULL) + prev_lcl->next = next_lcl; + else + lc->categories[category] = next_lcl; + memput(lcl, sizeof (struct log_channel_list)); + /* + * We just set found instead of returning because + * the channel might be on the list more than once. + */ + found = 1; + } else + prev_lcl = lcl; + } + if (!found) { + errno = ENOENT; + return (-1); + } + return (0); +} + +int +log_option(log_context lc, int option, int value) { + if (lc == NULL) { + errno = EINVAL; + return (-1); + } + switch (option) { + case LOG_OPTION_DEBUG: + if (value) + lc->flags |= option; + else + lc->flags &= ~option; + break; + case LOG_OPTION_LEVEL: + lc->level = value; + break; + default: + errno = EINVAL; + return (-1); + } + return (0); +} + +int +log_category_is_active(log_context lc, int category) { + if (lc == NULL) { + errno = EINVAL; + return (-1); + } + if (category >= 0 && category < lc->num_categories && + lc->categories[category] != NULL) + return (1); + return (0); +} + +log_channel +log_new_syslog_channel(unsigned int flags, int level, int facility) { + log_channel chan; + + chan = memget(sizeof (struct log_channel)); + if (chan == NULL) { + errno = ENOMEM; + return (NULL); + } + chan->type = log_syslog; + chan->flags = flags; + chan->level = level; + chan->out.facility = facility; + chan->references = 0; + return (chan); +} + +log_channel +log_new_file_channel(unsigned int flags, int level, + char *name, FILE *stream, unsigned int versions, + unsigned long max_size) { + log_channel chan; + + chan = memget(sizeof (struct log_channel)); + if (chan == NULL) { + errno = ENOMEM; + return (NULL); + } + chan->type = log_file; + chan->flags = flags; + chan->level = level; + if (name != NULL) { + size_t len; + + len = strlen(name); + /* + * Quantize length to a multiple of 256. There's space for the + * NUL, since if len is a multiple of 256, the size chosen will + * be the next multiple. + */ + chan->out.file.name_size = ((len / 256) + 1) * 256; + chan->out.file.name = memget(chan->out.file.name_size); + if (chan->out.file.name == NULL) { + memput(chan, sizeof (struct log_channel)); + errno = ENOMEM; + return (NULL); + } + /* This is safe. */ + strcpy(chan->out.file.name, name); + } else { + chan->out.file.name_size = 0; + chan->out.file.name = NULL; + } + chan->out.file.stream = stream; + chan->out.file.versions = versions; + chan->out.file.max_size = max_size; + chan->out.file.owner = getuid(); + chan->out.file.group = getgid(); + chan->references = 0; + return (chan); +} + +int +log_set_file_owner(log_channel chan, uid_t owner, gid_t group) { + if (chan->type != log_file) { + errno = EBADF; + return (-1); + } + chan->out.file.owner = owner; + chan->out.file.group = group; + return (0); +} + +log_channel +log_new_null_channel() { + log_channel chan; + + chan = memget(sizeof (struct log_channel)); + if (chan == NULL) { + errno = ENOMEM; + return (NULL); + } + chan->type = log_null; + chan->flags = LOG_CHANNEL_OFF; + chan->level = log_info; + chan->references = 0; + return (chan); +} + +int +log_inc_references(log_channel chan) { + if (chan == NULL) { + errno = EINVAL; + return (-1); + } + chan->references++; + return (0); +} + +int +log_dec_references(log_channel chan) { + if (chan == NULL || chan->references <= 0) { + errno = EINVAL; + return (-1); + } + chan->references--; + return (0); +} + +log_channel_type +log_get_channel_type(log_channel chan) { + REQUIRE(chan != NULL); + + return (chan->type); +} + +int +log_free_channel(log_channel chan) { + if (chan == NULL || chan->references <= 0) { + errno = EINVAL; + return (-1); + } + chan->references--; + if (chan->references == 0) { + if (chan->type == log_file) { + if ((chan->flags & LOG_CLOSE_STREAM) && + chan->out.file.stream != NULL) + (void)fclose(chan->out.file.stream); + if (chan->out.file.name != NULL) + memput(chan->out.file.name, + chan->out.file.name_size); + } + memput(chan, sizeof (struct log_channel)); + } + return (0); +} diff --git a/lib/bind/isc/logging.mdoc b/lib/bind/isc/logging.mdoc new file mode 100644 index 0000000000..0b7dae1ce9 --- /dev/null +++ b/lib/bind/isc/logging.mdoc @@ -0,0 +1,1052 @@ +.\" $Id: logging.mdoc,v 1.1 2001/03/29 06:31:55 marka Exp $ +.\" +.\"Copyright (c) 1995-1999 by Internet Software Consortium +.\" +.\"Permission to use, copy, modify, and distribute this software for any +.\"purpose with or without fee is hereby granted, provided that the above +.\"copyright notice and this permission notice appear in all copies. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\"DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\"PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\"ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\"SOFTWARE. +.\" +.\" The following six UNCOMMENTED lines are required. +.Dd January 1, 1996 +.\"Os OPERATING_SYSTEM [version/release] +.Os BSD 4 +.\"Dt DOCUMENT_TITLE [section number] [volume] +.Dt LOGGING @SYSCALL_EXT@ +.Sh NAME +.Nm log_open_stream , +.Nm log_close_stream , +.Nm log_get_stream , +.Nm log_get_filename , +.Nm log_vwrite , +.Nm log_write , +.Nm log_new_context , +.Nm log_free_context , +.Nm log_add_channel , +.Nm log_remove_channel , +.Nm log_option , +.Nm log_category_is_active , +.Nm log_new_syslog_channel , +.Nm log_new_file_channel , +.Nm log_set_file_owner , +.Nm log_new_null_channel , +.Nm log_inc_references , +.Nm log_dec_references , +.Nm log_free_channel +.Nd logging system +.Sh SYNOPSIS +.Fd #include +.Ft FILE * +.Fn log_open_stream "log_channel chan" +.Ft int +.Fn log_close_stream "log_channel chan" +.Ft FILE * +.Fn log_get_stream "log_channel chan" +.Ft char * +.Fn log_get_filename "log_channel chan" +.Ft void +.Fn log_vwrite "log_context lc" "int category" "int level" \ + "const char *format" va_list args" +.Ft void +.Fn log_write "log_context lc" "int category" "int level" \ + "const char *format" "..." +.Ft int +.Fn log_check_channel "log_context lc" "int level" "log_channel chan" +.Ft int +.Fn log_check "log_context lc" "int category" "int level" +.Ft int +.Fn log_new_context "int num_categories" "char **category_names" \ + "log_context *lc" +.Ft void +.Fn log_free_context "log_context lc" +.Ft int +.Fn log_add_channel "log_context lc" "int category" "log_channel chan" +.Ft int +.Fn log_remove_channel "log_context lc" "int category" "log_channel chan" +.Ft int +.Fn log_option "log_context lc" "int option" "int value" +.Ft int +.Fn log_category_is_active "log_context lc" "int category" +.Ft log_channel +.Fn log_new_syslog_channel "unsigned int flags" "int level" "int facility" +.Ft log_channel +.Fn log_new_file_channel "unsigned int flags" "int level" \ + "char *name" "FILE *stream" "unsigned int versions" \ + "unsigned long max_size" +.Ft int +.Fn log_set_file_owner "log_channel chan" "uid_t owner" "gid_t group" +.Ft log_channel +.Fn log_new_null_channel "void" +.Ft int +.Fn log_inc_references "log_channel chan" +.Ft int +.Fn log_dec_references "log_channel chan" +.Ft int +.Fn log_free_channel "log_channel chan" +.Sh DESCRIPTION +The +.Sy ISC +.Nm logging library +is flexible logging system which is based upon a set of concepts: +.Nm logging channels , +.Nm categories , +and +.Nm logging contexts . +.Pp +The basic building block is the +.Dq Nm logging channel , +which includes a +.Nm priority +(logging level), which type of logging is to occur, and other +flags and information associated with technical aspects of the logging. +The set of priorities which are supported is shown below, in the section +.Sx Message Priorities . +A priority sets a threshold for message logging; a logging channel will +.Em only +log those messages which are +.Em at least as important +as its priority indicates. (The fact that +.Dq more important +means +.Dq more negative , +under the current scheme, is an implementation detail; if a channel has +a priority of +.Dv log_error , +then it will +.Em not +log messages with the +.Dv log_warning +priority, but it +.Em will +log messages with the +.Dv log_error +or +.Dv log_critical +priority.) +.Pp +The +.Nm logging channel +also has an indication of the type of logging performed. Currently, +the supported +.Nm logging types +include (see also +.Sx Logging Types , +below): +.Bl -tag -width "log_syslog" -compact -offset indent +.It Dv log_syslog +for +.Xr syslog 3 Ns -style +logging +.It Dv log_file +for use of a file +.It Dv log_null +for +.Em no +logging +.El +A new logging channel is created by calling either +.Fn log_new_syslog_channel , +.Fn log_new_file_channel , +or +.Fn log_new_null_channel , +respectively. +When a channel is no longer to be used, it can be freed using +.Fn log_free_channel . +.Pp +Both +.Dv log_syslog +and +.Dv log_file +channel types can include more information; for instance, a +.Dv log_syslog Ns -type +channel allows the specification of a +.Xr syslog 3 Ns -style +.Dq facility , +and a +.Dv log_file Ns -type +channels allows the caller to set a maximum file size and number +of versions. (See +.Fn log_new_syslog_channel +or +.Fn log_new_file_channel , +below.) +Additionally, once a logging channel of type +.Dv log_file +is defined, the functions +.Fn log_open_stream +and +.Fn log_close_stream +can open or close the stream associated with the logging channel's logging +filename. The +.Fn log_get_stream +and +.Fn log_get_filename +functions return the stream or filename, respectively, of such a logging +channel. Also unique to logging channels of type +.Dv log_file +is the +.Fn log_set_file_owner +function, which tells the logging system what user and group ought to own +newly created files (which is only effective if the caller is privileged.) +.Pp +Callers provide +.Dq Nm categories , +determining both the number of such categories and any (optional) names. +Categories are like array indexes in C; if the caller declares +.Dq Va n +categories, then they are considered to run from 0 to +.Va n-1 ; +with this scheme, a category number would be invalid if it were negative or +greater than/equal to +.Va n . +Each category can have its own list of +.Nm logging channels +associated with it; we say that such a channel is +.Dq in +the particular category. +.Sy NOTE: +Individual logging channels can appear in more than one category. +.Pp +A +.Dq Nm logging context +is the set of all +.Nm logging channels +associated with the context's +.Nm categories; +thus, a particular +.Nm category +scheme is associated with a particular +.Nm logging context. +.Sy NOTE: +A logging channel may appear in more than one logging context, and in +multiple categories within each logging context. +.Pp +Use +.Fn log_add_channel +and +.Fn log_remove_channel +to add or remove a logging channel to some category in a logging context. +To see if a given category in a logging context is being used, use the +Boolean test +.Fn log_category_is_active . +.Pp +A +.Nm logging context +can also have a +.Nm priority +(logging level) +and various flags associated with the whole context; in order to alter the +flags or change the priority of a context, use +.Fn log_option . +.Ss Message Priorities +Currently, five +.Nm priorities +(logging levels) are supported (they can also be found in the header file): +.Bd -literal -offset indent +#define log_critical (-5) +#define log_error (-4) +#define log_warning (-3) +#define log_notice (-2) +#define log_info (-1) +.Ed +.Pp +In the current implementation, logging messages which have a level greater +than 0 are considered to be debugging messages. +.Ss Logging Types +The three different +.Nm logging types +currently supported are different values of the enumerated type +.Ft log_output_type +(these are also listed in the header file): +.Bd -literal -offset indent +typedef enum { log_syslog, log_file, log_null } log_output_type; +.Ed +.Ss Logging Channel Flags +There are several flags which can be set on a logging channel; the flags +and their meanings are as follows (they are also found in the header file): +.Bl -tag -width "LOG_USE_CONTEXT_LEVEL " -offset indent +.It Dv LOG_CHANNEL_BROKEN +This is set only when some portion of +.Fn log_open_stream +fails: +.Xr open 2 +or +.Xr fdopen 3 +fail; +.Xr stat 2 +fails in a +.Dq bad +way; versioning or truncation is requested on a non-normal file. +.It Dv LOG_CHANNEL_OFF +This is set for channels opened by +.Fn log_new_null_channel . +.It Dv LOG_CLOSE_STREAM +If this flag is set, then +.Fn log_free_channel +will free a +.No non- Dv NULL +stream of a logging channel which is being +.Xr free 3 Ns -d +(if the logging channel is of type +.Dv log_file , +of course). +.It Dv LOG_PRINT_CATEGORY +If set, +.Fn log_vwrite +will insert the category name, if available, into logging messages which are +logged to channels of type +.Dv log_syslog +or +.Dv log_file . +.It Dv LOG_PRINT_LEVEL +If set, +.Fn log_vwrite +will insert a string identifying the message priority level into the +information logged to channels of type +.Dv log_syslog +or +.Dv log_file . +.It Dv LOG_REQUIRE_DEBUG +Only log debugging messages (i.e., those with a priority greater than zero). +.It Dv LOG_TIMESTAMP +If set, +.Fn log_vwrite +will insert a timestamp into logging messages which are logged to channels of +type +.Dv log_syslog +or +.Dv log_file . +.It Dv LOG_TRUNCATE +Truncate logging file when re-opened ( +.Fn log_open_stream +will +.Xr unlink 2 +the file and then +.Xr open 2 +a new file of the same name with the +.Dv O_EXCL +bit set). +.It Dv LOG_USE_CONTEXT_LEVEL +Use the logging context's priority or logging level, rather than the logging +channel's own priority. This can be useful for those channels which are +included in multiple logging contexts. +.El +.Ss FUNCTION DESCRIPTIONS +The function +.Fn log_open_stream +is for use with channels which log to a file; i.e., logging channels with a +.Va type +field set to +.Dq Dv log_file . +If the logging channel pointed to by +.Dq Fa chan +is valid, it attempts to open (and return) the stream associated with that +channel. If the stream is already opened, then it is returned; otherwise, +.Xr stat 2 +is used to test the filename for the stream. +.Pp +At this point, if the logging file is supposed to have different +.Va versions +(i.e., incremented version numbers; higher numbers indicate older versions +of the logging file). If so, then any existing versions are +.Xr rename 2 Ns -d +to have one version-number higher than previously, and the +.Dq current +filename for the stream is set to the +.Dq \&.0 +form of the name. Next, if the logging file is supposed to be truncated +(i.e., the +.Dv LOG_TRUNCATE +bit of the +.Va flags +field of the logging channel structure is set), then any file with the +.Dq current +filename for the stream is +.X4 unlink 2 Ns -d . +.Sy NOTE: +If the logging file is +.Em not +a regular file, and either of the above operations (version numbering +or truncation) is supposed to take place, a +.Dv NULL +file pointer is returned. +.Pp +Finally, the filename associated with the logging channel is +.Xr open 2 Ns -d +using the appropriate flags and a mode which sets the read/write permissions +for the user, group, and others. The file descriptor returned by +.Xr open 2 +is then passed to +.Xr fopen 3 , +with the append mode set, and the stream returned by this call is stored +in the +.Fa chan +structure and returned. +.Pp +If +.Fn log_open_stream +fails at any point, then the +.Dv LOG_CHANNEL_BROKEN +bit of the +.Va flags +field of the logging channel pointed to by +.Fa chan +is set, a +.Dv NULL +is returned, and +.Va errno +contains pertinent information. +.Pp +The +.Fn log_close_stream +function closes the stream associated with the logging channel pointed to by +.Dq Fa chan +(if +.Fa chan +is valid and the stream exists and can be closed properly by +.Xr fclose 3 ) . +The stream is set to +.Dv NULL +even if the call to +.Xr fclose 3 +fails. +.Pp +The function +.Fn log_get_stream +returns the stream associated with the logging channel pointed to by +.Dq Fa chan , +if it is +.No non- Ns Dv NULL +and specifies a logging channel which has a +.Dv FILE * +or stream associated with it. +.Pp +The +.Fn log_get_filename +function returns the name of the file associated with the logging channel +pointed to by +.Dq Fa chan , +if it is +.No non- Ns Dv NULL +and specifies a logging channel which has a file associated with it. +.Pp +The +.Fn log_vwrite +function performs the actual logging of a message to the various logging +channels of a logging context +.Fa lc . +The message consists of an +.Xr fprint 3 Ns -style +.Fa format +and its associated +.Fa args +(if any); it will be written to all logging channels in the given +.Fa category +which have a priority set to +.Fa level +or any +.Em less important +priority value. If the +.Fa category +is not valid or has no logging channels, then the category defaults to 0. +.Pp +There are a number of conditions under which a call to +.Fn log_vwrite +will not result in actually logging the message: if there is no logging channel +at even the default category (0), or if a given channel is either +.Dq broken +or +.Dq off +(i.e., its flags have +.Dv LOG_CHANNEL_BROKEN +or +.Dv LOG_CHANNEL_OFF +set, respectively), or if the logging channel channel is of type +.Dv log_null . +Additionally, if the logging channel's flag has +.Dv LOG_REQUIRE_DEBUG +set and the message is not a debugging message (i.e., has a level greater +than 0), then it will not be logged. +Finally, if the message's priority is less important than the +channel's logging level (the priority threshold), will not be logged. +.Sy NOTE: +If a logging channel's flag has +.Dv LOG_USE_CONTEXT_LEVEL +set, it will use the logging context's priority, rather than its own. +.Pp +If all of these hurdles are passed, then only +.Dv log_syslog +and +.Dv log_file +channels actually can have logging. For channels which use +.Xr syslog 3 , +the channel's +.Xr syslog 3 +facility is used in conjunction with a potentially modified form of the +message's priority level, since +.Xr syslog 3 +has its own system of priorities +.Pq Pa /usr/include/syslog.h . +All debug messages (priority >= 0) are mapped to +.Xr syslog 3 Ns 's +.Dv LOG_DEBUG +priority, all messages +.Dq more important +than +.Dv log_critical +are mapped to +.Dv LOG_CRIT , +and the priorities corresponding to the ones listed in the section +.Sx Message Priorities +are given the obvious corresponding +.Xr syslog 3 +priority. +.Pp +For +.Dv log_file +type logging channels, if the file size is greater than the maximum file +size, then no logging occurs. (The same thing happens if a +.Dv NULL +stream is encountered and +.Fn log_open_stream +fails to open the channel's stream.) +.Pp +For both logging to normal files and logging via +.Xr syslog 3 , +the value of the flags +.Dv LOG_TIMESTAMP , +.Dv LOG_PRINT_CATEGORY , +and +.Dv LOG_PRINT_LEVEL +are used in determining whether or not these items are included in the logged +information. +.Pp +The +.Fn log_write +function is merely a front-end to a call to +.Fn log_vwrite ; +see the description of that function, above, for more information. +.Pp +.Fn log_check +and +.Fn log_check_channel +are used to see if a contemplated logging call will actually generate any +output, which is useful when creating a log message involves non-trivial +work. +.Fn log_check +will return non-zero if a call to +.Fn log_vwrite +with the given +.Fa category +and +.Fa level +would generate output on any channels, and zero otherwise. +.Fn log_check_channel +will return non-zero if writing to the +.Fa chan +at the given +.Fa level +would generate output. +.Pp +The function +.Fn log_new_context +creates a new +.Nm logging context , +and stores this in the +.Dq Va opaque +field of the argument +.Dq Fa lc , +and opaque structure used internally. This new +.Nm context +will include the +.Dq Fa num_categories +and +.Dq Fa category_names +which are supplied; the latter can be +.Dv NULL . +.Sy NOTE: +Since +.Dq Fa category_names +is used directly, it +.Em must not +be freed by the caller, if it is +.No non- Ns Dv NULL . +The initial logging flags and priority are both set to zero. +.Pp +The +.Fn log_free_context +function is used to free the opaque structure +.Dq Va lc.opaque +and its components. +.Sy NOTE: +The +.Dq Va opaque +field of +.Dq Fa lc +.Em must +be +.No non- Ns Dv NULL . +For each of the various +.Dq categories +(indicated by the +.Dq Va num_categories +which were in the corresponding call to +.Fn log_new_context ) +associated with the given +.Nm logging context , +.Em all +of the +.Nm logging channels +are +.Xr free 3 Ns -d . +The opaque structure itself is then +.Xr free 3 Ns -d , +and +.Dq Va lc.opaque +is set to +.Dv NULL . +.Pp +.Sy NOTE: +The function +.Fn log_free_context +does +.Em not +free the memory associated with +.Fa category_names , +since the logging library did not allocate the memory for it, originally; +it was supplied in the call to +.Fn log_new_context . +.Pp +The function +.Fn log_add_channel +adds the +.Nm logging channel +.Dq Fa chan +to the list of logging channels in the given +.Fa category +of the +.Nm logging context +.Dq Fa lc . +No checking is performed to see whether or not +.Fa chan +is already present in the given +.Fa category , +so multiple instances in a single +.Fa category +can occur (but see +.Fn log_remove_channel , +below). +.Pp +The +.Fn log_remove_channel +function +removes +.Em all +occurrences of the +.Nm logging channel +.Dq Fa chan +from the list of logging channels in the given +.Fa category +of the +.Nm logging context +.Dq Fa lc . +It also attempts to free the channel by calling +.Fn log_free_channel +(see its description, below). +.Pp +The +.Fn log_option +function is used to change the +.Fa option +of the indicated logging context +.Fa lc +to the given +.Fa value . +The +.Fa option +can be either +.Dv LOG_OPTION_LEVEL +or +.Dv LOG_OPTION_DEBUG ; +in the first case, the log context's debugging level is reset to the +indicated level. If the +.Fa option +is +.Dv LOG_OPTION_DEBUG , +then a non-zero +.Fa value +results in setting the debug flag of the logging context, while a zero +.Fa value +means that the debug flag is reset. +.Pp +The +.Fn log_category_is_active +test returns a 1 if the given +.Fa category +of the indicated logging context +.Fa lc +has at least one logging channel, and 0, otherwise. +.Pp +The functions +.Fn log_new_syslog_channel , +.Fn log_new_file_channel , +and +.Fn log_new_null_channel +create a new channel of the type specified (thus, the difference in arguments); +the +.Dq Va type +field of the new +.Dq Ft struct log_channel +is always set to the appropriate value. +.Pp +The +.Fn log_new_syslog_channel +function +.Xr malloc 3 Ns -s +a new +.Ft struct log_channel +of +.Va type +.Dv log_syslog , +i.e., a logging channel which will use +.Xr syslog 3 . +The new structure is filled out with the +.Dq Fa flags , +.Dq Fa level , +and +.Dq Fa facility +which are given; the +.Va references +field is initialized to zero. +See +.Sx Logging Channel Flags +and +.Sx Message Priorities , +above, or the header file for information about acceptable values for +.Dq Fa flags , +and +.Dq Fa level . +The +.Dq Fa facility . +can be any valid +.Xr syslog 3 +facility; see the appropriate system header file or manpage for more +information. +.Pp +.Ft log_channel +.Fn log_new_file_channel "unsigned int flags" "int level" \ + "char *name" "FILE *stream" "unsigned int versions" \ + "unsigned long max_size" +.Pp +.Fn log_new_null_channel +.Pp +The functions +.Fn log_inc_references +and +.Fn log_dec_references +increment or decrements, respectively, the +.Va references +field of the logging channel pointed to by +.Dq Fa chan , +if it is a valid channel (and if the +.Va references +field is strictly positive, in the case of +.Fn log_dec_references ) . +These functions are meant to track changes in the number of different clients +which refer to the given logging channel. +.Pp +The +.Fn log_free_channel +function frees the +field of the logging channel pointed to by +.Dq Fa chan +if there are no more outstanding references to it. If the channel uses a file, +the stream is +.Xr fclose 3 Ns -d +(if the +.Dv LOG_CLOSE_STREAM +flag is set), and the filename, if +.No non- Ns Dv NULL , +is +.Xr free 3 Ns -d +before +.Dq Fa chan +is +.Xr free 3 Ns -d . +.Pp +.\" The following requests should be uncommented and +.\" used where appropriate. This next request is +.\" for sections 2 and 3 function return values only. +.Sh RETURN VALUES +.\" This next request is for sections 1, 6, 7 & 8 only +.Bl -tag -width "log_category_is_active()" +.It Fn log_open_stream +.Dv NULL +is returned under any of several error conditions: +a) if +.Dq Fa chan +is either +.Dv NULL +or a +.No non- Ns Dv log_file +channel +.Pq Va errno No is set to Dv EINVAL ; +b) if either versioning or truncation is requested for a non-normal file +.Pq Va errno No is set to Dv EINVAL ; +c) if any of +.Xr stat 2 , +.Xr open 2 , +or +.Xr fdopen 3 +fails +.Po Va errno +is set by the call which failed +.Pc . +If some value other than +.Dv NULL +is returned, then it is a valid logging stream (either newly-opened or +already-open). +.It Fn log_close_stream +-1 if the stream associated with +.Dq Fa chan +is +.No non- Ns Dv NULL +and the call to +.Xr fclose 3 +fails. +0 if successful or the logging channel pointed to by +.Dq Fa chan +is invalid (i.e., +.Dv NULL +or not a logging channel which has uses a file); in the latter case, +.Va errno +is set to +.Dv EINVAL . +.It Fn log_get_stream +.Dv NULL +under the same conditions as those under which +.Fn log_close_stream , +above, returns 0 (including the setting of +.Va errno ) . +Otherwise, the stream associated with the logging channel is returned. +.It Fn log_get_filename +.Dv NULL +under the same conditions as those under which +.Fn log_close_stream , +above, returns 0 (including the setting of +.Va errno ) . +Otherwise, the name of the file associated with the logging channel is +returned. +.It Fn log_new_context +-1 if +.Xr malloc 3 +fails +.Pq with Va errno No set to Dv ENOMEM . +Otherwise, 0, with +.Dq Va lc->opaque +containing the new structures and information. +.It Fn log_add_channel +-1 if +a) either +.Dq Va lc.opaque +is +.Dv NULL +or +.Fa category +is invalid (negative or greater than or equal to +.Va lcp->num_categories ), with +.Va errno +set to +.Dv EINVAL ; +b) +.Xr malloc 3 +fails +.Pq with Va errno No set to Dv ENOMEM . +Otherwise, 0. +.It Fn log_remove_channel +-1 if +a) either +.Dq Va lc.opaque +is +.Dv NULL +or +.Fa category +is invalid, as under failure condition a) for +.Fn log_add_channel , +above, including the setting of +.Va errno ; +b) no channel numbered +.Fa chan +is found in the logging context indicated by +.Fa lc +.Pq with Va errno No set to Dv ENOENT . +Otherwise, 0. +.It Fn log_option +-1 if +a) +.Dq Va lc.opaque +is +.Dv NULL , +b) +.Fa option +specifies an unknown logging option ; +in either case, +.Va errno +is set to +.Dv EINVAL . +Otherwise, 0. +.It Fn log_category_is_active +-1 if +.Dq Va lc.opaque +is +.Dv NULL +.Pq with Va errno No set to Dv EINVAL ; +1 if the +.Fa category +number is valid and there are logging channels in this +.Fa category +within the indicated logging context; 0 if the +.Fa category +number is invalid or there are no logging channels in this +.Fa category +within the indicated logging context. +.It Fn log_new_syslog_channel +.Dv NULL +if +.Xr malloc 3 +fails +.Pq with Va errno No set to ENOMEM ; +otherwise, a valid +.Dv log_syslog Ns -type +.Ft log_channel . +.It Fn log_new_file_channel +.Dv NULL +if +.Xr malloc 3 +fails +.Pq with Va errno No set to ENOMEM ; +otherwise, a valid +.Dv log_file Ns -type +.Ft log_channel . +.It Fn log_new_null_channel +.Dv NULL +if +.Xr malloc 3 +fails +.Pq with Va errno No set to ENOMEM ; +otherwise, a valid +.Dv log_null Ns -type +.Ft log_channel . +.It Fn log_inc_references +-1 if +.Dq Fa chan +is +.Dv NULL +.Pq with Va errno set to Dv EINVAL . +Otherwise, 0. +.It Fn log_dec_references +-1 if +.Dq Fa chan +is +.Dv NULL +or its +.Va references +field is already <= 0 +.Pq with Va errno set to Dv EINVAL . +Otherwise, 0. +.It Fn log_free_channel +-1 under the same conditions as +.Fn log_dec_references , +above, including the setting of +.Va errno ; +0 otherwise. +.El +.\" .Sh ENVIRONMENT +.Sh FILES +.Bl -tag -width "isc/logging.h" +.It Pa isc/logging.h +include file for logging library +.It Pa syslog.h +.Xr syslog 3 Ns -style +priorities +.El +.\" .Sh EXAMPLES +.\" This next request is for sections 1, 6, 7 & 8 only +.\" (command return values (to shell) and +.\" fprintf/stderr type diagnostics) +.\" .Sh DIAGNOSTICS +.\" The next request is for sections 2 and 3 error +.\" and signal handling only. +.Sh ERRORS +This table shows which functions can return the indicated error in the +.Va errno +variable; see the +.Sx RETURN VALUES +section, above, for more information. +.Bl -tag -width "(any0other0value)0" +.It Dv EINVAL +.Fn log_open_stream , +.Fn log_close_stream , +.Fn log_get_stream , +.Fn log_get_filename , +.Fn log_add_channel , +.Fn log_remove_channel , +.Fn log_option , +.Fn log_category_is_active , +.Fn log_inc_references , +.Fn log_dec_references , +.Fn log_free_channel . +.It Dv ENOENT +.Fn log_remove_channel . +.It Dv ENOMEM +.Fn log_new_context , +.Fn log_add_channel , +.Fn log_new_syslog_channel , +.Fn log_new_file_channel , +.Fn log_new_null_channel . +.It (any other value) +returned via a pass-through of an error code from +.Xr stat 2 , +.Xr open 2 , +or +.Xr fdopen 3 , +which can occur in +.Fn log_open_stream +and functions which call it +.Pq currently, only Fn log_vwrite . +.El +.Pp +Additionally, +.Fn log_vwrite +and +.Fn log_free_context +will fail via +.Fn assert +if +.Dq Va lc.opaque +is +.Dv NULL . +The function +.Fn log_vwrite +can also exit with a critical error logged via +.Xr syslog 3 +indicating a memory overrun +.Sh SEE ALSO +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr syslog 3 . +The HTML documentation includes a file, +.Pa logging.html , +which has more information about this logging system. +.\" .Sh STANDARDS +.\" .Sh HISTORY +.Sh AUTHORS +Bob Halley...TODO +.\" .Sh BUGS diff --git a/lib/bind/isc/logging_p.h b/lib/bind/isc/logging_p.h new file mode 100644 index 0000000000..875da0e0f4 --- /dev/null +++ b/lib/bind/isc/logging_p.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef LOGGING_P_H +#define LOGGING_P_H + +typedef struct log_file_desc { + char *name; + size_t name_size; + FILE *stream; + unsigned int versions; + unsigned long max_size; + uid_t owner; + gid_t group; +} log_file_desc; + +typedef union log_output { + int facility; + log_file_desc file; +} log_output; + +struct log_channel { + int level; /* don't log messages > level */ + log_channel_type type; + log_output out; + unsigned int flags; + int references; +}; + +typedef struct log_channel_list { + log_channel channel; + struct log_channel_list *next; +} *log_channel_list; + +#define LOG_BUFFER_SIZE 20480 + +struct log_context { + int num_categories; + char **category_names; + log_channel_list *categories; + int flags; + int level; + char buffer[LOG_BUFFER_SIZE]; +}; + +#endif /* !LOGGING_P_H */ diff --git a/lib/bind/isc/memcluster.c b/lib/bind/isc/memcluster.c new file mode 100644 index 0000000000..323a384bd0 --- /dev/null +++ b/lib/bind/isc/memcluster.c @@ -0,0 +1,532 @@ +/* + * Copyright (c) 1997,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + + +/* When this symbol is defined allocations via memget are made slightly + bigger and some debugging info stuck before and after the region given + back to the caller. */ +/* #define DEBUGGING_MEMCLUSTER */ +#define MEMCLUSTER_ATEND + + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: memcluster.c,v 1.1 2001/03/29 06:31:55 marka Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "port_after.h" + +#ifdef MEMCLUSTER_RECORD +#ifndef DEBUGGING_MEMCLUSTER +#define DEBUGGING_MEMCLUSTER +#endif +#endif + +#define DEF_MAX_SIZE 1100 +#define DEF_MEM_TARGET 4096 + +typedef u_int32_t fence_t; + +typedef struct { + void * next; +#if defined(DEBUGGING_MEMCLUSTER) +#if defined(MEMCLUSTER_RECORD) + const char * file; + int line; +#endif + int size; + fence_t fencepost; +#endif +} memcluster_element; + +#define SMALL_SIZE_LIMIT sizeof(memcluster_element) +#define P_SIZE sizeof(void *) +#define FRONT_FENCEPOST 0xfebafeba +#define BACK_FENCEPOST 0xabefabef +#define FENCEPOST_SIZE 4 + +#ifndef MEMCLUSTER_LITTLE_MALLOC +#define MEMCLUSTER_BIG_MALLOC 1 +#define NUM_BASIC_BLOCKS 64 +#endif + +struct stats { + u_long gets; + u_long totalgets; + u_long blocks; + u_long freefrags; +}; + +/* Private data. */ + +static size_t max_size; +static size_t mem_target; +static size_t mem_target_half; +static size_t mem_target_fudge; +static memcluster_element ** freelists; +#ifdef MEMCLUSTER_RECORD +static memcluster_element ** activelists; +#endif +#ifdef MEMCLUSTER_BIG_MALLOC +static memcluster_element * basic_blocks; +#endif +static struct stats * stats; + +/* Forward. */ + +static size_t quantize(size_t); +#if defined(DEBUGGING_MEMCLUSTER) +static void check(unsigned char *, int, size_t); +#endif + +/* Public. */ + +int +meminit(size_t init_max_size, size_t target_size) { + +#if defined(DEBUGGING_MEMCLUSTER) + INSIST(sizeof(fence_t) == FENCEPOST_SIZE); +#endif + if (freelists != NULL) { + errno = EEXIST; + return (-1); + } + if (init_max_size == 0) + max_size = DEF_MAX_SIZE; + else + max_size = init_max_size; + if (target_size == 0) + mem_target = DEF_MEM_TARGET; + else + mem_target = target_size; + mem_target_half = mem_target / 2; + mem_target_fudge = mem_target + mem_target / 4; + freelists = malloc(max_size * sizeof (memcluster_element *)); + stats = malloc((max_size+1) * sizeof (struct stats)); + if (freelists == NULL || stats == NULL) { + errno = ENOMEM; + return (-1); + } + memset(freelists, 0, + max_size * sizeof (memcluster_element *)); + memset(stats, 0, (max_size + 1) * sizeof (struct stats)); +#ifdef MEMCLUSTER_RECORD + activelists = malloc((max_size + 1) * sizeof (memcluster_element *)); + if (activelists == NULL) { + errno = ENOMEM; + return (-1); + } + memset(activelists, 0, + (max_size + 1) * sizeof (memcluster_element *)); +#endif +#ifdef MEMCLUSTER_BIG_MALLOC + basic_blocks = NULL; +#endif + return (0); +} + +void * +__memget(size_t size) { + return (__memget_record(size, NULL, 0)); +} + +void * +__memget_record(size_t size, const char *file, int line) { + size_t new_size = quantize(size); +#if defined(DEBUGGING_MEMCLUSTER) + memcluster_element *e; + char *p; + fence_t fp = BACK_FENCEPOST; +#endif + void *ret; + +#if !defined(MEMCLUSTER_RECORD) + UNUSED(file); + UNUSED(line); +#endif + if (freelists == NULL) + if (meminit(0, 0) == -1) + return (NULL); + if (size == 0) { + errno = EINVAL; + return (NULL); + } + if (size >= max_size || new_size >= max_size) { + /* memget() was called on something beyond our upper limit. */ + stats[max_size].gets++; + stats[max_size].totalgets++; +#if defined(DEBUGGING_MEMCLUSTER) + e = malloc(new_size); + if (e == NULL) { + errno = ENOMEM; + return (NULL); + } + e->next = NULL; + e->size = size; +#ifdef MEMCLUSTER_RECORD + e->file = file; + e->line = line; + e->next = activelists[max_size]; + activelists[max_size] = e; +#endif + e->fencepost = FRONT_FENCEPOST; + p = (char *)e + sizeof *e + size; + memcpy(p, &fp, sizeof fp); + return ((char *)e + sizeof *e); +#else + return (malloc(size)); +#endif + } + + /* + * If there are no blocks in the free list for this size, get a chunk + * of memory and then break it up into "new_size"-sized blocks, adding + * them to the free list. + */ + if (freelists[new_size] == NULL) { + int i, frags; + size_t total_size; + void *new; + char *curr, *next; + +#ifdef MEMCLUSTER_BIG_MALLOC + if (basic_blocks == NULL) { + new = malloc(NUM_BASIC_BLOCKS * mem_target); + if (new == NULL) { + errno = ENOMEM; + return (NULL); + } + curr = new; + next = curr + mem_target; + for (i = 0; i < (NUM_BASIC_BLOCKS - 1); i++) { + ((memcluster_element *)curr)->next = next; + curr = next; + next += mem_target; + } + /* + * curr is now pointing at the last block in the + * array. + */ + ((memcluster_element *)curr)->next = NULL; + basic_blocks = new; + } + total_size = mem_target; + new = basic_blocks; + basic_blocks = basic_blocks->next; +#else + if (new_size > mem_target_half) + total_size = mem_target_fudge; + else + total_size = mem_target; + new = malloc(total_size); + if (new == NULL) { + errno = ENOMEM; + return (NULL); + } +#endif + frags = total_size / new_size; + stats[new_size].blocks++; + stats[new_size].freefrags += frags; + /* Set up a linked-list of blocks of size "new_size". */ + curr = new; + next = curr + new_size; + for (i = 0; i < (frags - 1); i++) { +#if defined (DEBUGGING_MEMCLUSTER) + memset(curr, 0xa5, new_size); +#endif + ((memcluster_element *)curr)->next = next; + curr = next; + next += new_size; + } + /* curr is now pointing at the last block in the array. */ +#if defined (DEBUGGING_MEMCLUSTER) + memset(curr, 0xa5, new_size); +#endif + ((memcluster_element *)curr)->next = freelists[new_size]; + freelists[new_size] = new; + } + + /* The free list uses the "rounded-up" size "new_size". */ +#if defined (DEBUGGING_MEMCLUSTER) + e = freelists[new_size]; + ret = (char *)e + sizeof *e; + /* + * Check to see if this buffer has been written to while on free list. + */ + check(ret, 0xa5, new_size - sizeof *e); + /* + * Mark memory we are returning. + */ + memset(ret, 0xe5, size); +#else + ret = freelists[new_size]; +#endif + freelists[new_size] = freelists[new_size]->next; +#if defined(DEBUGGING_MEMCLUSTER) + e->next = NULL; + e->size = size; + e->fencepost = FRONT_FENCEPOST; +#ifdef MEMCLUSTER_RECORD + e->file = file; + e->line = line; + e->next = activelists[size]; + activelists[size] = e; +#endif + p = (char *)e + sizeof *e + size; + memcpy(p, &fp, sizeof fp); +#endif + + /* + * The stats[] uses the _actual_ "size" requested by the + * caller, with the caveat (in the code above) that "size" >= the + * max. size (max_size) ends up getting recorded as a call to + * max_size. + */ + stats[size].gets++; + stats[size].totalgets++; + stats[new_size].freefrags--; +#if defined(DEBUGGING_MEMCLUSTER) + return ((char *)e + sizeof *e); +#else + return (ret); +#endif +} + +/* + * This is a call from an external caller, + * so we want to count this as a user "put". + */ +void +__memput(void *mem, size_t size) { + __memput_record(mem, size, NULL, 0); +} + +void +__memput_record(void *mem, size_t size, const char *file, int line) { + size_t new_size = quantize(size); +#if defined (DEBUGGING_MEMCLUSTER) + memcluster_element *e; +#ifdef MEMCLUSTER_RECORD + memcluster_element *prev, *el; +#endif + int fp; + char *p; +#endif + +#if !defined (MEMCLUSTER_RECORD) + UNUSED(file); + UNUSED(line); +#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 +#ifdef MEMCLUSTER_ATEND + e->next = NULL; + el = freelists[new_size]; + while (el != NULL && el->next != NULL) + el = el->next; + if (el) + el->next = e; + else + freelists[new_size] = e; +#else + e->next = freelists[new_size]; + freelists[new_size] = (void *)e; +#endif +#else + ((memcluster_element *)mem)->next = freelists[new_size]; + freelists[new_size] = (memcluster_element *)mem; +#endif + + /* + * The stats[] uses the _actual_ "size" requested by the + * caller, with the caveat (in the code above) that "size" >= the + * max. size (max_size) ends up getting recorded as a call to + * max_size. + */ + INSIST(stats[size].gets != 0); + stats[size].gets--; + stats[new_size].freefrags++; +} + +void * +__memget_debug(size_t size, const char *file, int line) { + void *ptr; + ptr = __memget_record(size, file, line); + fprintf(stderr, "%s:%d: memget(%lu) -> %p\n", file, line, + (u_long)size, ptr); + return (ptr); +} + +void +__memput_debug(void *ptr, size_t size, const char *file, int line) { + fprintf(stderr, "%s:%d: memput(%p, %lu)\n", file, line, ptr, + (u_long)size); + __memput_record(ptr, size, file, line); +} + +/* + * Print the stats[] on the stream "out" with suitable formatting. + */ +void +memstats(FILE *out) { + size_t i; +#ifdef MEMCLUSTER_RECORD + memcluster_element *e; +#endif + + if (freelists == NULL) + return; + for (i = 1; i <= max_size; i++) { + const struct stats *s = &stats[i]; + + if (s->totalgets == 0 && s->gets == 0) + continue; + fprintf(out, "%s%5d: %11lu gets, %11lu rem", + (i == max_size) ? ">=" : " ", + i, s->totalgets, s->gets); + if (s->blocks != 0) + fprintf(out, " (%lu bl, %lu ff)", + s->blocks, s->freefrags); + fputc('\n', out); + } +#ifdef MEMCLUSTER_RECORD + fprintf(out, "Active Memory:\n"); + for (i = 1; i <= max_size; i++) { + if ((e = activelists[i]) != NULL) + while (e != NULL) { + fprintf(out, "%s:%d %#p:%d\n", + e->file != NULL ? e->file : + "", e->line, + (char *)e + sizeof *e, e->size); + e = e->next; + } + } +#endif +} + +/* Private. */ + +/* + * Round up size to a multiple of sizeof(void *). This guarantees that a + * block is at least sizeof void *, and that we won't violate alignment + * restrictions, both of which are needed to make lists of blocks. + */ +static size_t +quantize(size_t size) { + int remainder; + /* + * If there is no remainder for the integer division of + * + * (rightsize/P_SIZE) + * + * then we already have a good size; if not, then we need + * to round up the result in order to get a size big + * enough to satisfy the request _and_ aligned on P_SIZE boundaries. + */ + remainder = size % P_SIZE; + if (remainder != 0) + size += P_SIZE - remainder; +#if defined(DEBUGGING_MEMCLUSTER) + return (size + SMALL_SIZE_LIMIT + sizeof (int)); +#else + return (size); +#endif +} + +#if defined(DEBUGGING_MEMCLUSTER) +static void +check(unsigned char *a, int value, size_t len) { + int i; + for (i = 0; i < len; i++) + INSIST(a[i] == value); +} +#endif diff --git a/lib/bind/isc/memcluster.mdoc b/lib/bind/isc/memcluster.mdoc new file mode 100644 index 0000000000..5425650b33 --- /dev/null +++ b/lib/bind/isc/memcluster.mdoc @@ -0,0 +1,375 @@ +.\" $Id: memcluster.mdoc,v 1.1 2001/03/29 06:31:55 marka Exp $ +.\" +.\"Copyright (c) 1995-1999 by Internet Software Consortium +.\" +.\"Permission to use, copy, modify, and distribute this software for any +.\"purpose with or without fee is hereby granted, provided that the above +.\"copyright notice and this permission notice appear in all copies. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\"DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\"PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\"ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\"SOFTWARE. +.\" +.\" The following six UNCOMMENTED lines are required. +.Dd Month day, year +.\"Os OPERATING_SYSTEM [version/release] +.Os BSD 4 +.\"Dt DOCUMENT_TITLE [section number] [volume] +.Dt memcluster 3 +.Sh NAME +.Nm meminit , +.Nm memget , +.Nm memput , +.Nm memstats +.Nd memory allocation/deallocation system +.Sh SYNOPSIS +.Fd #include \& +.Ft void * +.Fn memget "size_t size" +.Ft void +.Fn memput "void *mem" "size_t size" +.Ft void +.Fn memstats "FILE *out" +.Sh DESCRIPTION +These functions access a memory management system which allows callers to not +fragment memory to the extent which can ordinarily occur through many random +calls to +.Xr malloc 3 . +Instead, +.Fn memget +gets a large contiguous chunk of blocks of the requested +.Fa size +and parcels out these blocks as requested. The symmetric call is +.Fn memput , +which callers use to return a piece of memory obtained from +.Fn memget . +Statistics about memory usage are returned by +.Fn memstats , +which prints a report on the stream +.Fa out . +.Ss INTERNALS +Internally, linked lists of free memory blocks are stored in an array. +The size of this array is determined by the value +.Dv MEM_FREECOUNT , +currently set to 1100. In general, for any requested blocksize +.Dq Fa size , +any free blocks will be stored on the linked list at that index. +No free lists are managed for blocks greater than or equal to +.Dv MEM_FREECOUNT +bytes; instead, calls to +.Xr malloc 3 +or +.Xr free 3 +are made, directly. +.Pp +Since the blocks are actually stored as linked lists, they must at least +be large enough to hold a pointer to the next block. This size, which is +.Dv SMALL_SIZE_LIMIT , +is currently defined as +.Bd -literal -offset indent +#define SMALL_SIZE_LIMIT sizeof(struct { void *next; }) +.Ed +.Pp +Both +.Fn memget +and +.Fn memput +enforce this limit; for example, any call to +.Fn memget +requesting a block smaller than +.Dv SMALL_SIZE_LIMIT +bytes will actually be considered to be of size +.Dv SMALL_SIZE_LIMIT +internally. (Such a caller request will be logged for +.Fn memstats +purposes using the caller-requested +.Fa size ; +see the discussion of +.Fn memstats , +below, for more information.) +.Pp +Additionally, the requested +.Fa size +will be adjusted so that when a large +.Xr malloc 3 Ns No -d +chunk of memory is broken up into a linked list, the blocks will all fall on +the correct memory alignment boundaries. Thus, one can conceptualize a call +which mentions +.Fa size +as resulting in a +.Fa new_size +which is used internally. +.Pp +In order to more efficiently allocate memory, there is a +.Dq target +size for calls to +.Xr malloc 3 . +It is given by the pre-defined value +.Dv MEM_TARGET , +which is currently 4096 bytes. +For any requested block +.Fa size , +enough memory is +.Xr malloc 3 Ns No -d +in order to fill up a block of about +.Dv MEM_TARGET +bytes. +.No [ Ns Sy NOTE : +For allocations larger than +.Dv MEM_TARGET Ns No /2 +bytes, there is a +.Dq fudge factor +introduced which boosts the target size by 25% of +.Dv MEM_TARGET . +This means that enough memory for two blocks +will actually be allocated for any +.Fa size +such that +.Pq Dv MEM_TARGET Ns No / 3 +.No < Fa size No < +.Pq Dv MEM_TARGET Ns No *5/8 , +provided that the value of +.Dv MEM_FREECOUNT +is at least as large as the upper limit shown above.] +.Pp +.Ss FUNCTION DESCRIPTIONS +.Pp +The function +.Fn memget +returns a pointer to a block of memory of at least the requested +.Fa size . +After adjusting +.Fa size +to the value +.Va new_size +as mentioned above in the +.Sx INTERNALS +subsection, the internal array of free lists is checked. +If there is no block of the needed +.Va new_size , +then +.Fn memget +will +.Xr malloc 3 +a chunk of memory which is as many times as +.Va new_size +will fit into the target size. This memory is then turned into a linked list +of +.Va new_size Ns No -sized +blocks which are given out as requested; the last such block is the first one +returned by +.Fn memget . +If the requested +.Fa size +is zero or negative, then +.Dv NULL +is returned and +.Va errno +is set to +.Dv EINVAL ; +if +.Fa size +is larger than or equal to the pre-defined maximum size +.Dv MEM_FREECOUNT , +then only a single block of exactly +.Fa size +will be +.Xr malloc 3 Ns No -d +and returned. +.Pp +The +.Fn memput +call is used to return memory once the caller is finished with it. +After adjusting +.Fa size +the the value +.Va new_size +as mentioned in the +.Sx INTERNALS +subsection, above, the block is placed at the head of the free list of +.Va new_size Ns No -sized blocks. +If the given +.Fa size +is zero or negative, then +.Va errno +is set to +.Dv EINVAL , +as for +.Fn memget . +If +.Fa size +is larger than or equal to the pre-defined maximum size +.Dv MEM_FREECOUNT , +then the block is immediately +.Xr free 3 Ns No -d . +.Pp +.Sy NOTE : +It is important that callers give +.Fn memput +.Em only +blocks of memory which were previously obtained from +.Fn memget +if the block is +.Em actually +less than +.Dv SMALL_SIZE_LIMIT +bytes in size. Since all blocks will be added to a free list, any block +which is not at least +.Dv SMALL_SIZE_LIMIT +bytes long will not be able to hold a pointer to the next block in the +free list. +.Pp +The +.Fn memstats +function will summarize the number of calls to +.Fn memget +and +.Fn memput +for any block size from 1 byte up to +.Pq Dv MEM_FREECOUNT No - 1 +bytes, followed by a single line for any calls using a +.Fa size +greater than or equal to +.Dv MEM_FREECOUNT ; +a brief header with shell-style comment lines prefaces the report and +explains the information. The +.Dv FILE +pointer +.Fa out +identifies the stream which is used for this report. Currently, +.Fn memstat +reports the number of calls to +.Fn memget +and +.Fn memput +using the caller-supplied value +.Fa size ; +the percentage of outstanding blocks of a given size (i.e., the percentage +by which calls to +.Fn memget +exceed +.Fn memput ) +are also reported on the line for blocks of the given +.Fa size . +However, the percent of blocks used is computed using the number of +blocks allocated according to the internal parameter +.Va new_size ; +it is the percentage of blocks used to those available at a given +.Va new_size , +and is computed using the +.Em total +number of caller +.Dq gets +for any caller +.Fa size Ns No -s +which map to the internally-computed +.Va new_size . +Keep in mind that +.Va new_size +is generally +.Em not +equal to +.Fa size , +which has these implications: +.Bl -enum -offset -indent means that, for +.It +For +.Fa size +smaller than +.Dv SMALL_SIZE_LIMIT , +.Fn memstat +.Em will +show statistics for caller requests under +.Fa size , +but "percent used" information about such blocks will be reported under +.Dv SMALL_SIZE_LIMIT Ns No -sized +blocks. +.It +As a general case of point 1, internal statistics are reported on the the +line corresponding to +.Va new_size , +so that, for a given caller-supplied +.Fa size , +the associated internal information will appear on that line or on the next +line which shows "percent used" information. +.El +.Pp +.Sy NOTE : +If the caller returns blocks of a given +.Fa size +and requests others of +.Fa size Ns No -s +which map to the same internal +.Va new_size , +it is possible for +.Fn memstats +to report usage of greater than 100% for blocks of size +.Va new_size . +This should be viewed as A Good Thing. +.Sh RETURN VALUES +The function +.Fn memget +returns a +.No non- Ns Dv NULL +pointer to a block of memory of the requested +.Fa size . +It returns +.Dv NULL +if either the +.Fa size +is invalid (less than or equal to zero) or a +.Xr malloc 3 +of a new block of memory fails. In the former case, +.Va errno +is set to +.Dv EINVAL ; +in the latter, it is set to +.Dv ENOMEM . +.Pp +Neither +.Fn memput +nor +.Fn memstats +return a value. +.\" This next request is for sections 1, 6, 7 & 8 only +.\" .Sh ENVIRONMENT +.\" .Sh FILES +.\" .Sh EXAMPLES +.\" This next request is for sections 1, 6, 7 & 8 only +.\" (command return values (to shell) and +.\" fprintf/stderr type diagnostics) +.\" .Sh DIAGNOSTICS +.\" The next request is for sections 2 and 3 error +.\" and signal handling only. +.Sh ERRORS +.Va errno +is set as follows: +.Bl -tag -width "ENOMEM " -offset indent +.It Dv EINVAL +set by both +.Fn memget +and +.Fn memput +if the +.Fa size +is zero or negative +.It Dv ENOMEM +set by +.Fn memget +if a call to +.Xr malloc 3 +fails +.El +.Sh SEE ALSO +.Xr free 3 , +.Xr malloc 3 . +.\" .Sh STANDARDS +.\" .Sh HISTORY +.Sh AUTHORS +Steven J. Richardson and Paul Vixie, Vixie Enterprises. +.\" .Sh BUGS diff --git a/lib/bind/isc/movefile.c b/lib/bind/isc/movefile.c new file mode 100644 index 0000000000..1b64b6cb18 --- /dev/null +++ b/lib/bind/isc/movefile.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2000 by Internet Software Consortium, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + + +#include +#include +#include +#include +#ifndef HAVE_MOVEFILE +/* + * rename() is lame (can't overwrite an existing file) on some systems. + * use movefile() instead, and let lame OS ports do what they need to. + */ + +int +isc_movefile(const char *oldname, const char *newname) { + return (rename(oldname, newname)); +} +#else + static int os_port_has_isc_movefile = 1; +#endif diff --git a/lib/bind/isc/tree.c b/lib/bind/isc/tree.c new file mode 100644 index 0000000000..ea4753dc9a --- /dev/null +++ b/lib/bind/isc/tree.c @@ -0,0 +1,532 @@ +#ifndef LINT +static const char rcsid[] = "$Id: tree.c,v 1.1 2001/03/29 06:31:55 marka Exp $"; +#endif + +/* + * tree - balanced binary tree library + * + * vix 05apr94 [removed vixie.h dependencies; cleaned up formatting, names] + * vix 22jan93 [revisited; uses RCS, ANSI, POSIX; has bug fixes] + * vix 23jun86 [added delete uar to add for replaced nodes] + * vix 20jun86 [added tree_delete per wirth a+ds (mod2 v.) p. 224] + * vix 06feb86 [added tree_mung()] + * vix 02feb86 [added tree balancing from wirth "a+ds=p" p. 220-221] + * vix 14dec85 [written] + */ + +/* + * This program text was created by Paul Vixie using examples from the book: + * "Algorithms & Data Structures," Niklaus Wirth, Prentice-Hall, 1986, ISBN + * 0-13-022005-1. Any errors in the conversion from Modula-2 to C are Paul + * Vixie's. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/*#define DEBUG "tree"*/ + +#include "port_before.h" + +#include +#include + +#include "port_after.h" + +#include +#include + +#ifdef DEBUG +static int debugDepth = 0; +static char *debugFuncs[256]; +# define ENTER(proc) { \ + debugFuncs[debugDepth] = proc; \ + fprintf(stderr, "ENTER(%d:%s.%s)\n", \ + debugDepth, DEBUG, \ + debugFuncs[debugDepth]); \ + debugDepth++; \ + } +# define RET(value) { \ + debugDepth--; \ + fprintf(stderr, "RET(%d:%s.%s)\n", \ + debugDepth, DEBUG, \ + debugFuncs[debugDepth]); \ + return (value); \ + } +# define RETV { \ + debugDepth--; \ + fprintf(stderr, "RETV(%d:%s.%s)\n", \ + debugDepth, DEBUG, \ + debugFuncs[debugDepth]); \ + return; \ + } +# define MSG(msg) fprintf(stderr, "MSG(%s)\n", msg); +#else +# define ENTER(proc) ; +# define RET(value) return (value); +# define RETV return; +# define MSG(msg) ; +#endif + +#ifndef TRUE +# define TRUE 1 +# define FALSE 0 +#endif + +static tree * sprout(tree **, tree_t, int *, int (*)(), void (*)()); +static int delete(tree **, int (*)(), tree_t, void (*)(), int *, int *); +static void del(tree **, int *, tree **, void (*)(), int *); +static void bal_L(tree **, int *); +static void bal_R(tree **, int *); + +void +tree_init(tree **ppr_tree) { + ENTER("tree_init") + *ppr_tree = NULL; + RETV +} + +tree_t +tree_srch(tree **ppr_tree, int (*pfi_compare)(), tree_t p_user) { + ENTER("tree_srch") + + if (*ppr_tree) { + int i_comp = (*pfi_compare)(p_user, (**ppr_tree).data); + + if (i_comp > 0) + RET(tree_srch(&(**ppr_tree).right, + pfi_compare, + p_user)) + + if (i_comp < 0) + RET(tree_srch(&(**ppr_tree).left, + pfi_compare, + p_user)) + + /* not higher, not lower... this must be the one. + */ + RET((**ppr_tree).data) + } + + /* grounded. NOT found. + */ + RET(NULL) +} + +tree_t +tree_add(tree **ppr_tree, int (*pfi_compare)(), + tree_t p_user, void (*pfv_uar)()) +{ + int i_balance = FALSE; + + ENTER("tree_add") + if (!sprout(ppr_tree, p_user, &i_balance, pfi_compare, pfv_uar)) + RET(NULL) + RET(p_user) +} + +int +tree_delete(tree **ppr_p, int (*pfi_compare)(), + tree_t p_user, void (*pfv_uar)()) +{ + int i_balance = FALSE, i_uar_called = FALSE; + + ENTER("tree_delete"); + RET(delete(ppr_p, pfi_compare, p_user, pfv_uar, + &i_balance, &i_uar_called)) +} + +int +tree_trav(tree **ppr_tree, int (*pfi_uar)()) { + ENTER("tree_trav") + + if (!*ppr_tree) + RET(TRUE) + + if (!tree_trav(&(**ppr_tree).left, pfi_uar)) + RET(FALSE) + if (!(*pfi_uar)((**ppr_tree).data)) + RET(FALSE) + if (!tree_trav(&(**ppr_tree).right, pfi_uar)) + RET(FALSE) + RET(TRUE) +} + +void +tree_mung(tree **ppr_tree, void (*pfv_uar)()) { + ENTER("tree_mung") + if (*ppr_tree) { + tree_mung(&(**ppr_tree).left, pfv_uar); + tree_mung(&(**ppr_tree).right, pfv_uar); + if (pfv_uar) + (*pfv_uar)((**ppr_tree).data); + memput(*ppr_tree, sizeof(tree)); + *ppr_tree = NULL; + } + RETV +} + +static tree * +sprout(tree **ppr, tree_t p_data, int *pi_balance, + int (*pfi_compare)(), void (*pfv_delete)()) +{ + tree *p1, *p2, *sub; + int cmp; + + ENTER("sprout") + + /* are we grounded? if so, add the node "here" and set the rebalance + * flag, then exit. + */ + if (!*ppr) { + MSG("grounded. adding new node, setting h=true") + *ppr = (tree *) memget(sizeof(tree)); + if (*ppr) { + (*ppr)->left = NULL; + (*ppr)->right = NULL; + (*ppr)->bal = 0; + (*ppr)->data = p_data; + *pi_balance = TRUE; + } + RET(*ppr); + } + + /* compare the data using routine passed by caller. + */ + cmp = (*pfi_compare)(p_data, (*ppr)->data); + + /* if LESS, prepare to move to the left. + */ + if (cmp < 0) { + MSG("LESS. sprouting left.") + sub = sprout(&(*ppr)->left, p_data, pi_balance, + pfi_compare, pfv_delete); + if (sub && *pi_balance) { /* left branch has grown */ + MSG("LESS: left branch has grown") + switch ((*ppr)->bal) { + case 1: + /* right branch WAS longer; bal is ok now */ + MSG("LESS: case 1.. bal restored implicitly") + (*ppr)->bal = 0; + *pi_balance = FALSE; + break; + case 0: + /* balance WAS okay; now left branch longer */ + MSG("LESS: case 0.. balnce bad but still ok") + (*ppr)->bal = -1; + break; + case -1: + /* left branch was already too long. rebal */ + MSG("LESS: case -1: rebalancing") + p1 = (*ppr)->left; + if (p1->bal == -1) { /* LL */ + MSG("LESS: single LL") + (*ppr)->left = p1->right; + p1->right = *ppr; + (*ppr)->bal = 0; + *ppr = p1; + } else { /* double LR */ + MSG("LESS: double LR") + + p2 = p1->right; + p1->right = p2->left; + p2->left = p1; + + (*ppr)->left = p2->right; + p2->right = *ppr; + + if (p2->bal == -1) + (*ppr)->bal = 1; + else + (*ppr)->bal = 0; + + if (p2->bal == 1) + p1->bal = -1; + else + p1->bal = 0; + *ppr = p2; + } /*else*/ + (*ppr)->bal = 0; + *pi_balance = FALSE; + } /*switch*/ + } /*if*/ + RET(sub) + } /*if*/ + + /* if MORE, prepare to move to the right. + */ + if (cmp > 0) { + MSG("MORE: sprouting to the right") + sub = sprout(&(*ppr)->right, p_data, pi_balance, + pfi_compare, pfv_delete); + if (sub && *pi_balance) { + MSG("MORE: right branch has grown") + + switch ((*ppr)->bal) { + case -1: + MSG("MORE: balance was off, fixed implicitly") + (*ppr)->bal = 0; + *pi_balance = FALSE; + break; + case 0: + MSG("MORE: balance was okay, now off but ok") + (*ppr)->bal = 1; + break; + case 1: + MSG("MORE: balance was off, need to rebalance") + p1 = (*ppr)->right; + if (p1->bal == 1) { /* RR */ + MSG("MORE: single RR") + (*ppr)->right = p1->left; + p1->left = *ppr; + (*ppr)->bal = 0; + *ppr = p1; + } else { /* double RL */ + MSG("MORE: double RL") + + p2 = p1->left; + p1->left = p2->right; + p2->right = p1; + + (*ppr)->right = p2->left; + p2->left = *ppr; + + if (p2->bal == 1) + (*ppr)->bal = -1; + else + (*ppr)->bal = 0; + + if (p2->bal == -1) + p1->bal = 1; + else + p1->bal = 0; + + *ppr = p2; + } /*else*/ + (*ppr)->bal = 0; + *pi_balance = FALSE; + } /*switch*/ + } /*if*/ + RET(sub) + } /*if*/ + + /* not less, not more: this is the same key! replace... + */ + MSG("FOUND: Replacing data value") + *pi_balance = FALSE; + if (pfv_delete) + (*pfv_delete)((*ppr)->data); + (*ppr)->data = p_data; + RET(*ppr) +} + +static int +delete(tree **ppr_p, int (*pfi_compare)(), tree_t p_user, + void (*pfv_uar)(), int *pi_balance, int *pi_uar_called) +{ + tree *pr_q; + int i_comp, i_ret; + + ENTER("delete") + + if (*ppr_p == NULL) { + MSG("key not in tree") + RET(FALSE) + } + + i_comp = (*pfi_compare)((*ppr_p)->data, p_user); + if (i_comp > 0) { + MSG("too high - scan left") + i_ret = delete(&(*ppr_p)->left, pfi_compare, p_user, pfv_uar, + pi_balance, pi_uar_called); + if (*pi_balance) + bal_L(ppr_p, pi_balance); + } else if (i_comp < 0) { + MSG("too low - scan right") + i_ret = delete(&(*ppr_p)->right, pfi_compare, p_user, pfv_uar, + pi_balance, pi_uar_called); + if (*pi_balance) + bal_R(ppr_p, pi_balance); + } else { + MSG("equal") + pr_q = *ppr_p; + if (pr_q->right == NULL) { + MSG("right subtree null") + *ppr_p = pr_q->left; + *pi_balance = TRUE; + } else if (pr_q->left == NULL) { + MSG("right subtree non-null, left subtree null") + *ppr_p = pr_q->right; + *pi_balance = TRUE; + } else { + MSG("neither subtree null") + del(&pr_q->left, pi_balance, &pr_q, + pfv_uar, pi_uar_called); + if (*pi_balance) + bal_L(ppr_p, pi_balance); + } + if (!*pi_uar_called && pfv_uar) + (*pfv_uar)(pr_q->data); + /* Thanks to wuth@castrov.cuc.ab.ca for the following stmt. */ + memput(pr_q, sizeof(tree)); + i_ret = TRUE; + } + RET(i_ret) +} + +static void +del(tree **ppr_r, int *pi_balance, tree **ppr_q, + void (*pfv_uar)(), int *pi_uar_called) +{ + ENTER("del") + + if ((*ppr_r)->right != NULL) { + del(&(*ppr_r)->right, pi_balance, ppr_q, + pfv_uar, pi_uar_called); + if (*pi_balance) + bal_R(ppr_r, pi_balance); + } else { + if (pfv_uar) + (*pfv_uar)((*ppr_q)->data); + *pi_uar_called = TRUE; + (*ppr_q)->data = (*ppr_r)->data; + *ppr_q = *ppr_r; + *ppr_r = (*ppr_r)->left; + *pi_balance = TRUE; + } + + RETV +} + +static void +bal_L(tree **ppr_p, int *pi_balance) { + tree *p1, *p2; + int b1, b2; + + ENTER("bal_L") + MSG("left branch has shrunk") + + switch ((*ppr_p)->bal) { + case -1: + MSG("was imbalanced, fixed implicitly") + (*ppr_p)->bal = 0; + break; + case 0: + MSG("was okay, is now one off") + (*ppr_p)->bal = 1; + *pi_balance = FALSE; + break; + case 1: + MSG("was already off, this is too much") + p1 = (*ppr_p)->right; + b1 = p1->bal; + if (b1 >= 0) { + MSG("single RR") + (*ppr_p)->right = p1->left; + p1->left = *ppr_p; + if (b1 == 0) { + MSG("b1 == 0") + (*ppr_p)->bal = 1; + p1->bal = -1; + *pi_balance = FALSE; + } else { + MSG("b1 != 0") + (*ppr_p)->bal = 0; + p1->bal = 0; + } + *ppr_p = p1; + } else { + MSG("double RL") + p2 = p1->left; + b2 = p2->bal; + p1->left = p2->right; + p2->right = p1; + (*ppr_p)->right = p2->left; + p2->left = *ppr_p; + if (b2 == 1) + (*ppr_p)->bal = -1; + else + (*ppr_p)->bal = 0; + if (b2 == -1) + p1->bal = 1; + else + p1->bal = 0; + *ppr_p = p2; + p2->bal = 0; + } + } + RETV +} + +static void +bal_R(tree **ppr_p, int *pi_balance) { + tree *p1, *p2; + int b1, b2; + + ENTER("bal_R") + MSG("right branch has shrunk") + switch ((*ppr_p)->bal) { + case 1: + MSG("was imbalanced, fixed implicitly") + (*ppr_p)->bal = 0; + break; + case 0: + MSG("was okay, is now one off") + (*ppr_p)->bal = -1; + *pi_balance = FALSE; + break; + case -1: + MSG("was already off, this is too much") + p1 = (*ppr_p)->left; + b1 = p1->bal; + if (b1 <= 0) { + MSG("single LL") + (*ppr_p)->left = p1->right; + p1->right = *ppr_p; + if (b1 == 0) { + MSG("b1 == 0") + (*ppr_p)->bal = -1; + p1->bal = 1; + *pi_balance = FALSE; + } else { + MSG("b1 != 0") + (*ppr_p)->bal = 0; + p1->bal = 0; + } + *ppr_p = p1; + } else { + MSG("double LR") + p2 = p1->right; + b2 = p2->bal; + p1->right = p2->left; + p2->left = p1; + (*ppr_p)->left = p2->right; + p2->right = *ppr_p; + if (b2 == -1) + (*ppr_p)->bal = 1; + else + (*ppr_p)->bal = 0; + if (b2 == 1) + p1->bal = -1; + else + p1->bal = 0; + *ppr_p = p2; + p2->bal = 0; + } + } + RETV +} diff --git a/lib/bind/isc/tree.mdoc b/lib/bind/isc/tree.mdoc new file mode 100644 index 0000000000..02d452f788 --- /dev/null +++ b/lib/bind/isc/tree.mdoc @@ -0,0 +1,154 @@ +.\" $Id: tree.mdoc,v 1.1 2001/03/29 06:31:55 marka Exp $ +.\" +.\"Copyright (c) 1995-1999 by Internet Software Consortium +.\" +.\"Permission to use, copy, modify, and distribute this software for any +.\"purpose with or without fee is hereby granted, provided that the above +.\"copyright notice and this permission notice appear in all copies. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\"DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\"PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\"ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\"SOFTWARE. +.\" +.Dd April 5, 1994 +.Dt TREE 3 +.Os BSD 4 +.Sh NAME +.Nm tree_init , +.Nm tree_mung , +.Nm tree_srch , +.Nm tree_add , +.Nm tree_delete , +.Nm tree_trav +.Nd balanced binary tree routines +.Sh SYNOPSIS +.Ft void +.Fn tree_init "void **tree" +.Ft void * +.Fn tree_srch "void **tree" "int (*compare)()" "void *data" +.Ft void +.Fn tree_add(tree, compare, data, del_uar) "void **tree" "int (*compare)()" \ +"void *data" "void (*del_uar)()" +.Ft int +.Fn tree_delete(tree, compare, data, del_uar) "void **tree" "int (*compare)()" \ +"void *data" "void (*del_uar)()" +.Ft int +.Fn tree_trav(tree, trav_uar) "void **tree" "int (*trav_uar)()" +.Ft void +.Fn tree_mung(tree, del_uar) "void **tree" "void (*del_uar)()" +.Sh DESCRIPTION +These functions create and manipulate a balanced binary (AVL) tree. Each node +of the tree contains the expected left & right subtree pointers, a short int +balance indicator, and a pointer to the user data. On a 32 bit system, this +means an overhead of 4+4+2+4 bytes per node (or, on a RISC or otherwise +alignment constrained system with implied padding, 4+4+4+4 bytes per node). +There is no key data type enforced by this package; a caller supplied +compare routine is used to compare user data blocks. +.Pp +Balanced binary trees are very fast on searches and replacements, but have a +moderately high cost for additions and deletions. If your application does a +lot more searches and replacements than it does additions and deletions, the +balanced (AVL) binary tree is a good choice for a data structure. +.Pp +.Fn Tree_init +creates an empty tree and binds it to +.Dq Fa tree +(which for this and all other routines in this package should be declared as +a pointer to void or int, and passed by reference), which can then be used by +other routines in this package. Note that more than one +.Dq Fa tree +variable can exist at once; thus multiple trees can be manipulated +simultaneously. +.Pp +.Fn Tree_srch +searches a tree for a specific node and returns either +.Fa NULL +if no node was found, or the value of the user data pointer if the node +was found. +.Fn compare +is the address of a function to compare two user data blocks. This routine +should work much the way +.Xr strcmp 3 +does; in fact, +.Xr strcmp +could be used if the user data was a \s-2NUL\s+2 terminated string. +.Dq Fa Data +is the address of a user data block to be used by +.Fn compare +as the search criteria. The tree is searched for a node where +.Fn compare +returns 0. +.Pp +.Fn Tree_add +inserts or replaces a node in the specified tree. The tree specified by +.Dq Fa tree +is searched as in +.Fn tree_srch, +and if a node is found to match +.Dq Fa data, +then the +.Fn del_uar +function, if non\-\s-2NULL\s+2, is called with the address of the user data +block for the node (this routine should deallocate any dynamic memory which +is referenced exclusively by the node); the user data pointer for the node +is then replaced by the value of +.Dq Fa data. +If no node is found to match, a new node is added (which may or may not +cause a transparent rebalance operation), with a user data pointer equal to +.Dq Fa data. +A rebalance may or may not occur, depending on where the node is added +and what the rest of the tree looks like. +.Fn Tree_add +will return the +.Dq Fa data +pointer unless catastrophe occurs in which case it will return \s-2NULL\s+2. +.Pp +.Fn Tree_delete +deletes a node from +.Dq Fa tree. +A rebalance may or may not occur, depending on where the node is removed from +and what the rest of the tree looks like. +.Fn Tree_delete +returns TRUE if a node was deleted, FALSE otherwise. +.Pp +.Fn Tree_trav +traverses all of +.Dq Fa tree, +calling +.Fn trav_uar +with the address of each user data block. If +.Fn trav_uar +returns FALSE at any time, +.Fn tree_trav +will immediately return FALSE to its caller. Otherwise all nodes will be +reached and +.Fn tree_trav +will return TRUE. +.Pp +.Fn Tree_mung +deletes every node in +.Dq Fa tree, +calling +.Fn del_uar +(if it is not \s-2NULL\s+2) with the user data address from each node (see +.Fn tree_add +and +.Fn tree_delete +above). The tree is left in the same state that +.Fn tree_init +leaves it in \- i.e., empty. +.Sh BUGS +Should have a way for the caller to specify application-specific +.Xr malloc +and +.Xr free +functions to be used internally when allocating meta data. +.Sh AUTHOR +Paul Vixie, converted and augumented from Modula\-2 examples in +.Dq Algorithms & Data Structures , +Niklaus Wirth, Prentice\-Hall, ISBN 0\-13\-022005\-1. diff --git a/lib/bind/make/includes.in b/lib/bind/make/includes.in new file mode 100644 index 0000000000..d471656246 --- /dev/null +++ b/lib/bind/make/includes.in @@ -0,0 +1,44 @@ +# Copyright (C) 1999-2001 Internet Software Consortium. +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM +# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +# INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +# FROM LOSS OF USE, DATA OR PROFITS, WHETHER 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: includes.in,v 1.1 2001/03/29 06:31:55 marka Exp $ + +# Search for machine-generated header files in the build tree, +# and for normal headers in the source tree (${top_srcdir}). +# We only need to look in OS-specific subdirectories for the +# latter case, because there are no machine-generated OS-specific +# headers. + +ISC_INCLUDES = @BIND9_ISC_BUILDINCLUDE@ \ + -I${top_srcdir}/lib/isc \ + -I${top_srcdir}/lib/isc/include \ + -I${top_srcdir}/lib/isc/unix/include \ + -I${top_srcdir}/lib/isc/@ISC_THREAD_DIR@/include + +ISCCFG_INCLUDES = @BIND9_ISCCFG_BUILDINCLUDE@ \ + -I${top_srcdir}/lib/isccfg/include + +DNS_INCLUDES = @BIND9_DNS_BUILDINCLUDE@ \ + -I${top_srcdir}/lib/dns/include \ + -I${top_srcdir}/lib/dns/sec/dst/include + +OMAPI_INCLUDES = @BIND9_OMAPI_BUILDINCLUDE@ \ + -I${top_srcdir}/lib/omapi/include + +LWRES_INCLUDES = @BIND9_LWRES_BUILDINCLUDE@ \ + -I${top_srcdir}/lib/lwres/include + +TEST_INCLUDES = \ + -I${top_srcdir}/lib/tests/include diff --git a/lib/bind/make/mkdep.in b/lib/bind/make/mkdep.in new file mode 100644 index 0000000000..60aea6fc6c --- /dev/null +++ b/lib/bind/make/mkdep.in @@ -0,0 +1,147 @@ +#!/bin/sh - + +## ++Copyright++ 1987 +## - +## Copyright (c) 1987 Regents of the University of California. +## All rights reserved. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## 2. Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. +## 3. All advertising materials mentioning features or use of this software +## must display the following acknowledgement: +## This product includes software developed by the University of +## California, Berkeley and its contributors. +## 4. Neither the name of the University nor the names of its contributors +## may be used to endorse or promote products derived from this software +## without specific prior written permission. +## THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +## ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +## SUCH DAMAGE. +## - +## Portions Copyright (c) 1993 by Digital Equipment Corporation. +## +## Permission to use, copy, modify, and distribute this software for any +## purpose with or without fee is hereby granted, provided that the above +## copyright notice and this permission notice appear in all copies, and that +## the name of Digital Equipment Corporation not be used in advertising or +## publicity pertaining to distribution of the document or software without +## specific, written prior permission. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL +## WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT +## CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +## DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +## PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +## SOFTWARE. +## - +## --Copyright-- + +# +# @(#)mkdep.sh 5.12 (Berkeley) 6/30/88 +# + +MAKE=Makefile # default makefile name is "Makefile" + +while : + do case "$1" in + # -f allows you to select a makefile name + -f) + MAKE=$2 + shift; shift ;; + + # the -p flag produces "program: program.c" style dependencies + # so .o's don't get produced + -p) + SED='s;\.o;;' + shift ;; + *) + break ;; + esac +done + +if [ $# = 0 ] ; then + echo 'usage: mkdep [-p] [-f makefile] [flags] file ...' + exit 1 +fi + +if [ ! -w $MAKE ]; then + echo "mkdep: no writeable file \"$MAKE\"" + exit 1 +fi + +TMP=mkdep$$ + +trap 'rm -f $TMP ; exit 1' 1 2 3 13 15 + +cp $MAKE ${MAKE}.bak + +sed -e '/DO NOT DELETE THIS LINE/,$d' < $MAKE > $TMP + +cat << _EOF_ >> $TMP +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. + +_EOF_ + +# If your compiler doesn't have -M, add it. If you can't, the next two +# lines will try and replace the "cc -M". The real problem is that this +# hack can't deal with anything that requires a search path, and doesn't +# even try for anything using bracket (<>) syntax. +# +# egrep '^#include[ ]*".*"' /dev/null $* | +# sed -e 's/:[^"]*"\([^"]*\)".*/: \1/' -e 's/\.c/.o/' | + +MKDEPPROG="@MKDEPPROG@" +if [ X"${MKDEPPROG}" != X ]; then + @SHELL@ -c "${MKDEPPROG} $*" +else + @MKDEPCC@ @MKDEPCFLAGS@ $* | + sed " + s; \./; ;g + $SED" | + awk '{ + if ($1 != prev) { + if (rec != "") + print rec; + rec = $0; + prev = $1; + } + else { + if (length(rec $2) > 78) { + print rec; + rec = $0; + } + else + rec = rec " " $2 + } + } + END { + print rec + }' >> $TMP +fi + +cat << _EOF_ >> $TMP + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY +_EOF_ + +# copy to preserve permissions +cp $TMP $MAKE +rm -f ${MAKE}.bak $TMP +exit 0 diff --git a/lib/bind/make/rules.in b/lib/bind/make/rules.in new file mode 100644 index 0000000000..fca8c7263d --- /dev/null +++ b/lib/bind/make/rules.in @@ -0,0 +1,172 @@ +# Copyright (C) 1998-2001 Internet Software Consortium. +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM +# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +# INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +# FROM LOSS OF USE, DATA OR PROFITS, WHETHER 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: rules.in,v 1.1 2001/03/29 06:31:56 marka Exp $ + +### +### Common Makefile rules for BIND 9. +### + +### +### Paths +### +### Note: paths that vary by Makefile MUST NOT be listed +### here, or they won't get expanded correctly. + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +sbindir = @sbindir@ +includedir = @includedir@ +libdir = @libdir@ +sysconfdir = @sysconfdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ + +DESTDIR = + +@SET_MAKE@ + +top_builddir = @BIND9_TOP_BUILDDIR@ + +### +### All +### +### Makefile may define: +### TARGETS + +all: subdirs ${TARGETS} + +### +### Subdirectories +### +### Makefile may define: +### SUBDIRS + +ALL_SUBDIRS = ${SUBDIRS} nulldir + +# +# We use a single-colon rule so that additional dependencies of +# subdirectories can be specified after the inclusion of this file. +# The "depend" target is treated the same way. +# +subdirs: + @for i in ${ALL_SUBDIRS}; do \ + if [ "$$i" != "nulldir" -a -d $$i ]; then \ + echo "making all in `pwd`/$$i"; \ + (cd $$i; ${MAKE} ${MAKEDEFS} all) || exit 1; \ + fi \ + done + +install clean distclean:: + @for i in ${ALL_SUBDIRS}; do \ + if [ "$$i" != "nulldir" -a -d $$i ]; then \ + echo "making $@ in `pwd`/$$i"; \ + (cd $$i; ${MAKE} ${MAKEDEFS} $@) || exit 1; \ + fi \ + done + +### +### C Programs +### +### Makefile must define +### CC +### Makefile may define +### CFLAGS +### CINCLUDES +### CDEFINES +### CWARNINGS +### User may define externally +### EXT_CFLAGS + +CC = @CC@ +CFLAGS = @CFLAGS@ +STD_CINCLUDES = @STD_CINCLUDES@ +STD_CDEFINES = @STD_CDEFINES@ +STD_CWARNINGS = @STD_CWARNINGS@ + +.SUFFIXES: +.SUFFIXES: .c .@O@ + +ALWAYS_INCLUDES = -I${top_builddir} +ALWAYS_DEFINES = @ALWAYS_DEFINES@ +ALWAYS_WARNINGS = + +ALL_CPPFLAGS = \ + ${ALWAYS_INCLUDES} ${CINCLUDES} ${STD_CINCLUDES} \ + ${ALWAYS_DEFINES} ${CDEFINES} ${STD_CDEFINES} + +ALL_CFLAGS = ${EXT_CFLAGS} ${CFLAGS} \ + ${ALL_CPPFLAGS} \ + ${ALWAYS_WARNINGS} ${STD_CWARNINGS} ${CWARNINGS} + +.c.@O@: + ${LIBTOOL} ${CC} ${ALL_CFLAGS} -c $< + +SHELL = @SHELL@ +LIBTOOL = @LIBTOOL@ +PURIFY = @PURIFY@ + +MKDEP = ${SHELL} ${top_builddir}/make/mkdep + +cleandir: distclean + +clean distclean:: + rm -f *.@O@ *.lo *.la core *.core + rm -rf .libs + +distclean:: + rm -f Makefile + +depend: + @for i in ${ALL_SUBDIRS}; do \ + if [ "$$i" != "nulldir" -a -d $$i ]; then \ + echo "making depend in `pwd`/$$i"; \ + (cd $$i; ${MAKE} ${MAKEDEFS} $@) || exit 1; \ + fi \ + done + @if [ X"${SRCS}" != X -a X"${PSRCS}" != X ] ; then \ + echo ${MKDEP} ${ALL_CPPFLAGS} ${SRCS}; \ + ${MKDEP} ${ALL_CPPFLAGS} ${SRCS}; \ + echo ${MKDEP} -ap ${ALL_CPPFLAGS} ${PSRCS}; \ + ${MKDEP} -ap ${ALL_CPPFLAGS} ${PSRCS}; \ + ${DEPENDEXTRA} \ + elif [ X"${SRCS}" != X ] ; then \ + echo ${MKDEP} ${ALL_CPPFLAGS} ${SRCS}; \ + ${MKDEP} ${ALL_CPPFLAGS} ${SRCS}; \ + ${DEPENDEXTRA} \ + elif [ X"${PSRCS}" != X ] ; then \ + echo ${MKDEP} ${ALL_CPPFLAGS} ${PSRCS}; \ + ${MKDEP} -p ${ALL_CPPFLAGS} ${PSRCS}; \ + ${DEPENDEXTRA} \ + fi + +FORCE: + +### +### Libraries +### + +AR = @AR@ +ARFLAGS = @ARFLAGS@ +RANLIB = @RANLIB@ + +### +### Installation +### + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ diff --git a/lib/bind/nameser/Makefile.in b/lib/bind/nameser/Makefile.in new file mode 100644 index 0000000000..5f836e2935 --- /dev/null +++ b/lib/bind/nameser/Makefile.in @@ -0,0 +1,12 @@ +OBJS= ns_date.@O@ ns_name.@O@ ns_netint.@O@ ns_parse.@O@ ns_print.@O@ \ + ns_samedomain.@O@ ns_sign.@O@ ns_ttl.@O@ ns_verify.@O@ + +SRCS= ns_date.c ns_name.c ns_netint.c ns_parse.c ns_print.c \ + ns_samedomain.c ns_sign.c ns_ttl.c ns_verify.c + +TARGETS= ${OBJS} + +CINCLUDES= -I.. -I../include +CWARNINGS= -Werror + +@BIND9_MAKE_RULES@ diff --git a/lib/bind/nameser/ns_date.c b/lib/bind/nameser/ns_date.c new file mode 100644 index 0000000000..486f70abda --- /dev/null +++ b/lib/bind/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.1 2001/03/29 06:31:56 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include + +#include +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Forward. */ + +static int datepart(const char *, int, int, int, int *); + +/* Public. */ + +/* Convert a date in ASCII into the number of seconds since + 1 January 1970 (GMT assumed). Format is yyyymmddhhmmss, all + digits required, no spaces allowed. */ + +u_int32_t +ns_datetosecs(const char *cp, int *errp) { + struct tm time; + u_int32_t result; + int mdays, i; + static const int days_per_month[12] = + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + if (strlen(cp) != 14) { + *errp = 1; + return (0); + } + *errp = 0; + + memset(&time, 0, sizeof time); + time.tm_year = datepart(cp + 0, 4, 1990, 9999, errp) - 1900; + time.tm_mon = datepart(cp + 4, 2, 01, 12, errp) - 1; + time.tm_mday = datepart(cp + 6, 2, 01, 31, errp); + time.tm_hour = datepart(cp + 8, 2, 00, 23, errp); + time.tm_min = datepart(cp + 10, 2, 00, 59, errp); + time.tm_sec = datepart(cp + 12, 2, 00, 59, errp); + if (*errp) /* Any parse errors? */ + return (0); + + /* + * OK, now because timegm() is not available in all environments, + * we will do it by hand. Roll up sleeves, curse the gods, begin! + */ + +#define SECS_PER_DAY ((u_int32_t)24*60*60) +#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) + + result = time.tm_sec; /* Seconds */ + result += time.tm_min * 60; /* Minutes */ + result += time.tm_hour * (60*60); /* Hours */ + result += (time.tm_mday - 1) * SECS_PER_DAY; /* Days */ + + /* Months are trickier. Look without leaping, then leap */ + mdays = 0; + for (i = 0; i < time.tm_mon; i++) + mdays += days_per_month[i]; + result += mdays * SECS_PER_DAY; /* Months */ + if (time.tm_mon > 1 && isleap(1900+time.tm_year)) + result += SECS_PER_DAY; /* Add leapday for this year */ + + /* First figure years without leapdays, then add them in. */ + /* The loop is slow, FIXME, but simple and accurate. */ + result += (time.tm_year - 70) * (SECS_PER_DAY*365); /* Years */ + for (i = 70; i < time.tm_year; i++) + if (isleap(1900+i)) + result += SECS_PER_DAY; /* Add leapday for prev year */ + + return (result); +} + +/* Private. */ + +/* + * Parse part of a date. Set error flag if any error. + * Don't reset the flag if there is no error. + */ +static int +datepart(const char *buf, int size, int min, int max, int *errp) { + int result = 0; + int i; + + for (i = 0; i < size; i++) { + if (!isdigit(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/lib/bind/nameser/ns_name.c b/lib/bind/nameser/ns_name.c new file mode 100644 index 0000000000..1bed101870 --- /dev/null +++ b/lib/bind/nameser/ns_name.c @@ -0,0 +1,934 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_name.c,v 1.1 2001/03/29 06:31:56 marka Exp $"; +#endif + +#include "port_before.h" + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +#define NS_TYPE_ELT 0x40 /* EDNS0 extended label type */ +#define DNS_LABELTYPE_BITSTRING 0x41 + +/* Data. */ + +static const char digits[] = "0123456789"; + +static const char digitvalue[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/ + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/ + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/ +}; + +/* Forward. */ + +static int special(int); +static int printable(int); +static int dn_find(const u_char *, const u_char *, + const u_char * const *, + const u_char * const *); +static int encode_bitsring(const char **, const char *, + char **, char **, const char *); +static int labellen(const u_char *); +static int decode_bitstring(const char **, char *, const char *); + +/* Public. */ + +/* + * ns_name_ntop(src, dst, dstsiz) + * Convert an encoded domain name to printable ascii as per RFC1035. + * return: + * Number of bytes written to buffer, or -1 (with errno set) + * notes: + * The root is returned as "." + * All other domains are returned in non absolute form + */ +int +ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) +{ + const u_char *cp; + char *dn, *eom; + u_char c; + u_int n; + int l; + + cp = src; + dn = dst; + eom = dst + dstsiz; + + while ((n = *cp++) != 0) { + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* Some kind of compression pointer. */ + errno = EMSGSIZE; + return (-1); + } + if (dn != dst) { + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '.'; + } + if ((l = labellen(cp - 1)) < 0) { + errno = EMSGSIZE; /* XXX */ + return(-1); + } + if (dn + l >= eom) { + errno = EMSGSIZE; + return (-1); + } + if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) { + int m; + + if (n != DNS_LABELTYPE_BITSTRING) { + /* XXX: labellen should reject this case */ + errno = EINVAL; + return(-1); + } + if ((m = decode_bitstring((const char **)&cp, dn, eom)) < 0) + { + errno = EMSGSIZE; + return(-1); + } + dn += m; + continue; + } + for ((void)NULL; l > 0; l--) { + c = *cp++; + if (special(c)) { + if (dn + 1 >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '\\'; + *dn++ = (char)c; + } else if (!printable(c)) { + if (dn + 3 >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '\\'; + *dn++ = digits[c / 100]; + *dn++ = digits[(c % 100) / 10]; + *dn++ = digits[c % 10]; + } else { + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = (char)c; + } + } + } + if (dn == dst) { + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '.'; + } + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '\0'; + return (dn - dst); +} + +/* + * ns_name_pton(src, dst, dstsiz) + * Convert a ascii string into an encoded domain name as per RFC1035. + * return: + * -1 if it fails + * 1 if string was fully qualified + * 0 is string was not fully qualified + * notes: + * Enforces label and domain length limits. + */ + +int +ns_name_pton(const char *src, u_char *dst, size_t dstsiz) +{ + u_char *label, *bp, *eom; + int c, n, escaped, e = 0; + char *cp; + + escaped = 0; + bp = dst; + eom = dst + dstsiz; + label = bp++; + + while ((c = *src++) != 0) { + if (escaped) { + if (c == '[') { /* start a bit string label */ + if ((cp = strchr(src, ']')) == NULL) { + errno = EINVAL; /* ??? */ + return(-1); + } + if ((e = encode_bitsring(&src, + cp + 2, + (char **)&label, + (char **)&bp, + (const char *)eom)) + != 0) { + errno = e; + return(-1); + } + escaped = 0; + label = bp++; + if ((c = *src++) == 0) + goto done; + else if (c != '.') { + errno = EINVAL; + return(-1); + } + continue; + } + else if ((cp = strchr(digits, c)) != NULL) { + n = (cp - digits) * 100; + if ((c = *src++) == 0 || + (cp = strchr(digits, c)) == NULL) { + errno = EMSGSIZE; + return (-1); + } + n += (cp - digits) * 10; + if ((c = *src++) == 0 || + (cp = strchr(digits, c)) == NULL) { + errno = EMSGSIZE; + return (-1); + } + n += (cp - digits); + if (n > 255) { + errno = EMSGSIZE; + return (-1); + } + c = n; + } + escaped = 0; + } else if (c == '\\') { + escaped = 1; + continue; + } else if (c == '.') { + c = (bp - label - 1); + if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ + errno = EMSGSIZE; + return (-1); + } + if (label >= eom) { + errno = EMSGSIZE; + return (-1); + } + *label = c; + /* Fully qualified ? */ + if (*src == '\0') { + if (c != 0) { + if (bp >= eom) { + errno = EMSGSIZE; + return (-1); + } + *bp++ = '\0'; + } + if ((bp - dst) > MAXCDNAME) { + errno = EMSGSIZE; + return (-1); + } + return (1); + } + if (c == 0 || *src == '.') { + errno = EMSGSIZE; + return (-1); + } + label = bp++; + continue; + } + if (bp >= eom) { + errno = EMSGSIZE; + return (-1); + } + *bp++ = (u_char)c; + } + c = (bp - label - 1); + if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ + errno = EMSGSIZE; + return (-1); + } + done: + if (label >= eom) { + errno = EMSGSIZE; + return (-1); + } + *label = c; + if (c != 0) { + if (bp >= eom) { + errno = EMSGSIZE; + return (-1); + } + *bp++ = 0; + } + if ((bp - dst) > MAXCDNAME) { /* src too big */ + errno = EMSGSIZE; + return (-1); + } + return (0); +} + +/* + * ns_name_ntol(src, dst, dstsiz) + * Convert a network strings labels into all lowercase. + * return: + * Number of bytes written to buffer, or -1 (with errno set) + * notes: + * Enforces label and domain length limits. + */ + +int +ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) +{ + const u_char *cp; + u_char *dn, *eom; + u_char c; + u_int n; + int l; + + cp = src; + dn = dst; + eom = dst + dstsiz; + + while ((n = *cp++) != 0) { + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* Some kind of compression pointer. */ + errno = EMSGSIZE; + return (-1); + } + *dn++ = n; + if ((l = labellen(cp - 1)) < 0) { + errno = EMSGSIZE; + return (-1); + } + if (dn + l >= eom) { + errno = EMSGSIZE; + return (-1); + } + for ((void)NULL; l > 0; l--) { + c = *cp++; + if (isupper(c)) + *dn++ = tolower(c); + else + *dn++ = c; + } + } + *dn++ = '\0'; + return (dn - dst); +} + +/* + * ns_name_unpack(msg, eom, src, dst, dstsiz) + * Unpack a domain name from a message, source may be compressed. + * return: + * -1 if it fails, or consumed octets if it succeeds. + */ +int +ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, + u_char *dst, size_t dstsiz) +{ + const u_char *srcp, *dstlim; + u_char *dstp; + int n, len, checked, l; + + len = -1; + checked = 0; + dstp = dst; + srcp = src; + dstlim = dst + dstsiz; + if (srcp < msg || srcp >= eom) { + errno = EMSGSIZE; + return (-1); + } + /* Fetch next label in domain name. */ + while ((n = *srcp++) != 0) { + /* Check for indirection. */ + switch (n & NS_CMPRSFLGS) { + case 0: + case NS_TYPE_ELT: + /* Limit checks. */ + if ((l = labellen(srcp - 1)) < 0) { + errno = EMSGSIZE; + return(-1); + } + if (dstp + l + 1 >= dstlim || srcp + l >= eom) { + errno = EMSGSIZE; + return (-1); + } + checked += l + 1; + *dstp++ = n; + memcpy(dstp, srcp, l); + dstp += l; + srcp += l; + break; + + case NS_CMPRSFLGS: + if (srcp >= eom) { + errno = EMSGSIZE; + return (-1); + } + if (len < 0) + len = srcp - src + 1; + srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); + if (srcp < msg || srcp >= eom) { /* Out of range. */ + errno = EMSGSIZE; + return (-1); + } + checked += 2; + /* + * Check for loops in the compressed name; + * if we've looked at the whole message, + * there must be a loop. + */ + if (checked >= eom - msg) { + errno = EMSGSIZE; + return (-1); + } + break; + + default: + errno = EMSGSIZE; + return (-1); /* flag error */ + } + } + *dstp = '\0'; + if (len < 0) + len = srcp - src; + return (len); +} + +/* + * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr) + * Pack domain name 'domain' into 'comp_dn'. + * return: + * Size of the compressed name, or -1. + * notes: + * 'dnptrs' is an array of pointers to previous compressed names. + * dnptrs[0] is a pointer to the beginning of the message. The array + * ends with NULL. + * 'lastdnptr' is a pointer to the end of the array pointed to + * by 'dnptrs'. + * Side effects: + * The list of pointers in dnptrs is updated for labels inserted into + * the message as we compress the name. If 'dnptr' is NULL, we don't + * try to compress names. If 'lastdnptr' is NULL, we don't update the + * list. + */ +int +ns_name_pack(const u_char *src, u_char *dst, int dstsiz, + const u_char **dnptrs, const u_char **lastdnptr) +{ + u_char *dstp; + const u_char **cpp, **lpp, *eob, *msg; + const u_char *srcp; + int n, l, first = 1; + + srcp = src; + dstp = dst; + eob = dstp + dstsiz; + lpp = cpp = NULL; + if (dnptrs != NULL) { + if ((msg = *dnptrs++) != NULL) { + for (cpp = dnptrs; *cpp != NULL; cpp++) + (void)NULL; + lpp = cpp; /* end of list to search */ + } + } else + msg = NULL; + + /* make sure the domain we are about to add is legal */ + l = 0; + do { + int l0; + + n = *srcp; + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + errno = EMSGSIZE; + return (-1); + } + if ((l0 = labellen(srcp)) < 0) { + errno = EINVAL; + return(-1); + } + l += l0 + 1; + if (l > MAXCDNAME) { + errno = EMSGSIZE; + return (-1); + } + srcp += l0 + 1; + } while (n != 0); + + /* from here on we need to reset compression pointer array on error */ + srcp = src; + do { + /* Look to see if we can use pointers. */ + n = *srcp; + if (n != 0 && msg != NULL) { + l = dn_find(srcp, msg, (const u_char * const *)dnptrs, + (const u_char * const *)lpp); + if (l >= 0) { + if (dstp + 1 >= eob) { + goto cleanup; + } + *dstp++ = (l >> 8) | NS_CMPRSFLGS; + *dstp++ = l % 256; + return (dstp - dst); + } + /* Not found, save it. */ + if (lastdnptr != NULL && cpp < lastdnptr - 1 && + (dstp - msg) < 0x4000 && first) { + *cpp++ = dstp; + *cpp = NULL; + first = 0; + } + } + /* copy label to buffer */ + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* Should not happen. */ + goto cleanup; + } + n = labellen(srcp); + if (dstp + 1 + n >= eob) { + goto cleanup; + } + memcpy(dstp, srcp, n + 1); + srcp += n + 1; + dstp += n + 1; + } while (n != 0); + + if (dstp > eob) { +cleanup: + if (msg != NULL) + *lpp = NULL; + errno = EMSGSIZE; + return (-1); + } + return (dstp - dst); +} + +/* + * ns_name_uncompress(msg, eom, src, dst, dstsiz) + * Expand compressed domain name to presentation format. + * return: + * Number of bytes read out of `src', or -1 (with errno set). + * note: + * Root domain returns as "." not "". + */ +int +ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src, + char *dst, size_t dstsiz) +{ + u_char tmp[NS_MAXCDNAME]; + int n; + + if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) + return (-1); + if (ns_name_ntop(tmp, dst, dstsiz) == -1) + return (-1); + return (n); +} + +/* + * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr) + * Compress a domain name into wire format, using compression pointers. + * return: + * Number of bytes consumed in `dst' or -1 (with errno set). + * notes: + * 'dnptrs' is an array of pointers to previous compressed names. + * dnptrs[0] is a pointer to the beginning of the message. + * The list ends with NULL. 'lastdnptr' is a pointer to the end of the + * array pointed to by 'dnptrs'. Side effect is to update the list of + * pointers for labels inserted into the message as we compress the name. + * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' + * is NULL, we don't update the list. + */ +int +ns_name_compress(const char *src, u_char *dst, size_t dstsiz, + const u_char **dnptrs, const u_char **lastdnptr) +{ + u_char tmp[NS_MAXCDNAME]; + + if (ns_name_pton(src, tmp, sizeof tmp) == -1) + return (-1); + return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr)); +} + +/* + * Reset dnptrs so that there are no active references to pointers at or + * after src. + */ +void +ns_name_rollback(const u_char *src, const u_char **dnptrs, + const u_char **lastdnptr) +{ + while (dnptrs < lastdnptr && *dnptrs != NULL) { + if (*dnptrs >= src) { + *dnptrs = NULL; + break; + } + dnptrs++; + } +} + +/* + * ns_name_skip(ptrptr, eom) + * Advance *ptrptr to skip over the compressed name it points at. + * return: + * 0 on success, -1 (with errno set) on failure. + */ +int +ns_name_skip(const u_char **ptrptr, const u_char *eom) +{ + const u_char *cp; + u_int n; + int l; + + cp = *ptrptr; + while (cp < eom && (n = *cp++) != 0) { + /* Check for indirection. */ + switch (n & NS_CMPRSFLGS) { + case 0: /* normal case, n == len */ + cp += n; + continue; + case NS_TYPE_ELT: /* EDNS0 extended label */ + if ((l = labellen(cp - 1)) < 0) { + errno = EMSGSIZE; /* XXX */ + return(-1); + } + cp += l; + continue; + case NS_CMPRSFLGS: /* indirection */ + cp++; + break; + default: /* illegal type */ + errno = EMSGSIZE; + return (-1); + } + break; + } + if (cp > eom) { + errno = EMSGSIZE; + return (-1); + } + *ptrptr = cp; + return (0); +} + +/* Private. */ + +/* + * special(ch) + * Thinking in noninternationalized USASCII (per the DNS spec), + * is this characted special ("in need of quoting") ? + * return: + * boolean. + */ +static int +special(int ch) { + switch (ch) { + case 0x22: /* '"' */ + case 0x2E: /* '.' */ + case 0x3B: /* ';' */ + case 0x5C: /* '\\' */ + /* Special modifiers in zone files. */ + case 0x40: /* '@' */ + case 0x24: /* '$' */ + return (1); + default: + return (0); + } +} + +/* + * printable(ch) + * Thinking in noninternationalized USASCII (per the DNS spec), + * is this character visible and not a space when printed ? + * return: + * boolean. + */ +static int +printable(int ch) { + return (ch > 0x20 && ch < 0x7f); +} + +/* + * Thinking in noninternationalized USASCII (per the DNS spec), + * convert this character to lower case if it's upper case. + */ +static int +mklower(int ch) { + if (ch >= 0x41 && ch <= 0x5A) + return (ch + 0x20); + return (ch); +} + +/* + * dn_find(domain, msg, dnptrs, lastdnptr) + * Search for the counted-label name in an array of compressed names. + * return: + * offset from msg if found, or -1. + * notes: + * dnptrs is the pointer to the first name on the list, + * not the pointer to the start of the message. + */ +static int +dn_find(const u_char *domain, const u_char *msg, + const u_char * const *dnptrs, + const u_char * const *lastdnptr) +{ + const u_char *dn, *cp, *sp; + const u_char * const *cpp; + u_int n; + + for (cpp = dnptrs; cpp < lastdnptr; cpp++) { + sp = *cpp; + /* + * terminate search on: + * root label + * compression pointer + * unusable offset + */ + while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 && + (sp - msg) < 0x4000) { + dn = domain; + cp = sp; + while ((n = *cp++) != 0) { + /* + * check for indirection + */ + switch (n & NS_CMPRSFLGS) { + case 0: /* normal case, n == len */ + n = labellen(cp - 1); /* XXX */ + + if (n != *dn++) + goto next; + + for ((void)NULL; n > 0; n--) + if (mklower(*dn++) != + mklower(*cp++)) + goto next; + /* Is next root for both ? */ + if (*dn == '\0' && *cp == '\0') + return (sp - msg); + if (*dn) + continue; + goto next; + case NS_CMPRSFLGS: /* indirection */ + cp = msg + (((n & 0x3f) << 8) | *cp); + break; + + default: /* illegal type */ + errno = EMSGSIZE; + return (-1); + } + } + } + next: ; + sp += *sp + 1; + } + errno = ENOENT; + return (-1); +} + +static int +decode_bitstring(const char **cpp, char *dn, const char *eom) +{ + const char *cp = *cpp; + char *beg = dn, tc; + int b, blen, plen; + + if ((blen = (*cp & 0xff)) == 0) + blen = 256; + plen = (blen + 3) / 4; + plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1); + if (dn + plen >= eom) + return(-1); + + cp++; + dn += sprintf(dn, "\\[x"); + for (b = blen; b > 7; b -= 8, cp++) + dn += sprintf(dn, "%02x", *cp & 0xff); + if (b > 4) { + tc = *cp++; + dn += sprintf(dn, "%02x", tc & (0xff << (8 - b))); + } else if (b > 0) { + tc = *cp++; + dn += sprintf(dn, "%1x", ((tc >> 4) & 0x0f) & (0x0f << (4 - b))); + } + dn += sprintf(dn, "/%d]", blen); + + *cpp = cp; + return(dn - beg); +} + +static int +encode_bitsring(const char **bp, const char *end, char **labelp, + char ** dst, const char *eom) +{ + int afterslash = 0; + const char *cp = *bp; + char *tp, c; + const char *beg_blen; + char *end_blen = NULL; + int value = 0, count = 0, tbcount = 0, blen = 0; + + beg_blen = end_blen = NULL; + + /* a bitstring must contain at least 2 characters */ + if (end - cp < 2) + return(EINVAL); + + /* XXX: currently, only hex strings are supported */ + if (*cp++ != 'x') + return(EINVAL); + if (!isxdigit((*cp) & 0xff)) /* reject '\[x/BLEN]' */ + return(EINVAL); + + for (tp = *dst + 1; cp < end && tp < eom; cp++) { + switch((c = *cp)) { + case ']': /* end of the bitstring */ + if (afterslash) { + if (beg_blen == NULL) + return(EINVAL); + blen = (int)strtol(beg_blen, &end_blen, 10); + if (*end_blen != ']') + return(EINVAL); + } + if (count) + *tp++ = ((value << 4) & 0xff); + cp++; /* skip ']' */ + goto done; + case '/': + afterslash = 1; + break; + default: + if (afterslash) { + if (!isdigit(c)) + return(EINVAL); + if (beg_blen == NULL) { + + if (c == '0') { + /* blen never begings with 0 */ + return(EINVAL); + } + beg_blen = cp; + } + } else { + if (!isxdigit(c)) + return(EINVAL); + value <<= 4; + value += digitvalue[(int)c]; + count += 4; + tbcount += 4; + if (tbcount > 256) + return(EINVAL); + if (count == 8) { + *tp++ = value; + count = 0; + } + } + break; + } + } + done: + if (cp >= end || tp >= eom) + return(EMSGSIZE); + + /* + * bit length validation: + * If a is present, the number of digits in the + * MUST be just sufficient to contain the number of bits specified + * by the . If there are insignificant bits in a final + * hexadecimal or octal digit, they MUST be zero. + * RFC 2673, Section 3.2. + */ + if (blen > 0) { + int traillen; + + if (((blen + 3) & ~3) != tbcount) + return(EINVAL); + traillen = tbcount - blen; /* between 0 and 3 */ + if (((value << (8 - traillen)) & 0xff) != 0) + return(EINVAL); + } + else + blen = tbcount; + if (blen == 256) + blen = 0; + + /* encode the type and the significant bit fields */ + **labelp = DNS_LABELTYPE_BITSTRING; + **dst = blen; + + *bp = cp; + *dst = tp; + + return(0); +} + +static int +labellen(const u_char *lp) +{ + int bitlen; + u_char l = *lp; + + if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* should be avoided by the caller */ + return(-1); + } + + if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) { + if (l == DNS_LABELTYPE_BITSTRING) { + if ((bitlen = *(lp + 1)) == 0) + bitlen = 256; + return((bitlen + 7 ) / 8 + 1); + } + return(-1); /* unknwon ELT */ + } + return(l); +} diff --git a/lib/bind/nameser/ns_netint.c b/lib/bind/nameser/ns_netint.c new file mode 100644 index 0000000000..509ae86e41 --- /dev/null +++ b/lib/bind/nameser/ns_netint.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_netint.c,v 1.1 2001/03/29 06:31:56 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include + +#include "port_after.h" + +/* Public. */ + +u_int +ns_get16(const u_char *src) { + u_int dst; + + NS_GET16(dst, src); + return (dst); +} + +u_long +ns_get32(const u_char *src) { + u_long dst; + + NS_GET32(dst, src); + return (dst); +} + +void +ns_put16(u_int src, u_char *dst) { + NS_PUT16(src, dst); +} + +void +ns_put32(u_long src, u_char *dst) { + NS_PUT32(src, dst); +} diff --git a/lib/bind/nameser/ns_parse.c b/lib/bind/nameser/ns_parse.c new file mode 100644 index 0000000000..6b08ee1cf1 --- /dev/null +++ b/lib/bind/nameser/ns_parse.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_parse.c,v 1.1 2001/03/29 06:31:57 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include + +#include +#include + +#include +#include +#include + +#include "port_after.h" + +/* Forward. */ + +static void setsection(ns_msg *msg, ns_sect sect); + +/* Macros. */ + +#define RETERR(err) do { errno = (err); return (-1); } while (0) + +/* Public. */ + +/* These need to be in the same order as the nres.h:ns_flag enum. */ +struct _ns_flagdata _ns_flagdata[16] = { + { 0x8000, 15 }, /* qr. */ + { 0x7800, 11 }, /* opcode. */ + { 0x0400, 10 }, /* aa. */ + { 0x0200, 9 }, /* tc. */ + { 0x0100, 8 }, /* rd. */ + { 0x0080, 7 }, /* ra. */ + { 0x0040, 6 }, /* z. */ + { 0x0020, 5 }, /* ad. */ + { 0x0010, 4 }, /* cd. */ + { 0x000f, 0 }, /* rcode. */ + { 0x0000, 0 }, /* expansion (1/6). */ + { 0x0000, 0 }, /* expansion (2/6). */ + { 0x0000, 0 }, /* expansion (3/6). */ + { 0x0000, 0 }, /* expansion (4/6). */ + { 0x0000, 0 }, /* expansion (5/6). */ + { 0x0000, 0 }, /* expansion (6/6). */ +}; + +int ns_msg_getflag(ns_msg handle, int flag) { + return(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift); +} + +int +ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) { + const u_char *optr = ptr; + + for ((void)NULL; count > 0; count--) { + int b, rdlength; + + b = dn_skipname(ptr, eom); + if (b < 0) + RETERR(EMSGSIZE); + ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/; + if (section != ns_s_qd) { + if (ptr + NS_INT32SZ + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + ptr += NS_INT32SZ/*TTL*/; + NS_GET16(rdlength, ptr); + ptr += rdlength/*RData*/; + } + } + if (ptr > eom) + RETERR(EMSGSIZE); + return (ptr - optr); +} + +int +ns_initparse(const u_char *msg, int msglen, ns_msg *handle) { + const u_char *eom = msg + msglen; + int i; + + memset(handle, 0x5e, sizeof *handle); + handle->_msg = msg; + handle->_eom = eom; + if (msg + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + NS_GET16(handle->_id, msg); + if (msg + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + NS_GET16(handle->_flags, msg); + for (i = 0; i < ns_s_max; i++) { + if (msg + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + NS_GET16(handle->_counts[i], msg); + } + for (i = 0; i < ns_s_max; i++) + if (handle->_counts[i] == 0) + handle->_sections[i] = NULL; + else { + int b = ns_skiprr(msg, eom, (ns_sect)i, + handle->_counts[i]); + + if (b < 0) + return (-1); + handle->_sections[i] = msg; + msg += b; + } + if (msg != eom) + RETERR(EMSGSIZE); + setsection(handle, ns_s_max); + return (0); +} + +int +ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) { + int b; + + /* Make section right. */ + if (section >= ns_s_max) + RETERR(ENODEV); + if (section != handle->_sect) + setsection(handle, section); + + /* Make rrnum right. */ + if (rrnum == -1) + rrnum = handle->_rrnum; + if (rrnum < 0 || rrnum >= handle->_counts[(int)section]) + RETERR(ENODEV); + if (rrnum < handle->_rrnum) + setsection(handle, section); + if (rrnum > handle->_rrnum) { + b = ns_skiprr(handle->_ptr, handle->_eom, section, + rrnum - handle->_rrnum); + + if (b < 0) + return (-1); + handle->_ptr += b; + handle->_rrnum = rrnum; + } + + /* Do the parse. */ + b = dn_expand(handle->_msg, handle->_eom, + handle->_ptr, rr->name, NS_MAXDNAME); + if (b < 0) + return (-1); + handle->_ptr += b; + if (handle->_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom) + RETERR(EMSGSIZE); + NS_GET16(rr->type, handle->_ptr); + NS_GET16(rr->rr_class, handle->_ptr); + if (section == ns_s_qd) { + rr->ttl = 0; + rr->rdlength = 0; + rr->rdata = NULL; + } else { + if (handle->_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom) + RETERR(EMSGSIZE); + NS_GET32(rr->ttl, handle->_ptr); + NS_GET16(rr->rdlength, handle->_ptr); + if (handle->_ptr + rr->rdlength > handle->_eom) + RETERR(EMSGSIZE); + rr->rdata = handle->_ptr; + handle->_ptr += rr->rdlength; + } + if (++handle->_rrnum > handle->_counts[(int)section]) + setsection(handle, (ns_sect)((int)section + 1)); + + /* All done. */ + return (0); +} + +/* Private. */ + +static void +setsection(ns_msg *msg, ns_sect sect) { + msg->_sect = sect; + if (sect == ns_s_max) { + msg->_rrnum = -1; + msg->_ptr = NULL; + } else { + msg->_rrnum = 0; + msg->_ptr = msg->_sections[(int)sect]; + } +} diff --git a/lib/bind/nameser/ns_print.c b/lib/bind/nameser/ns_print.c new file mode 100644 index 0000000000..c78bf5c5ae --- /dev/null +++ b/lib/bind/nameser/ns_print.c @@ -0,0 +1,901 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_print.c,v 1.1 2001/03/29 06:31:57 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Forward. */ + +static size_t prune_origin(const char *name, const char *origin); +static int charstr(const u_char *rdata, const u_char *edata, + char **buf, size_t *buflen); +static int addname(const u_char *msg, size_t msglen, + const u_char **p, const char *origin, + char **buf, size_t *buflen); +static void addlen(size_t len, char **buf, size_t *buflen); +static int addstr(const char *src, size_t len, + char **buf, size_t *buflen); +static int addtab(size_t len, size_t target, int spaced, + char **buf, size_t *buflen); + +/* Proto. */ + +u_int16_t dst_s_dns_key_id(const u_char *, const int); + +/* Macros. */ + +#define T(x) \ + do { \ + if ((x) < 0) \ + return (-1); \ + } while (0) + +/* Public. */ + +/* + * int + * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen) + * Convert an RR to presentation format. + * return: + * Number of characters written to buf, or -1 (check errno). + */ +int +ns_sprintrr(const ns_msg *handle, const ns_rr *rr, + const char *name_ctx, const char *origin, + char *buf, size_t buflen) +{ + int n; + + n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle), + ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr), + ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr), + name_ctx, origin, buf, buflen); + return (n); +} + +/* + * int + * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen, + * name_ctx, origin, buf, buflen) + * Convert the fields of an RR into presentation format. + * return: + * Number of characters written to buf, or -1 (check errno). + */ +int +ns_sprintrrf(const u_char *msg, size_t msglen, + const char *name, ns_class class, ns_type type, + u_long ttl, const u_char *rdata, size_t rdlen, + const char *name_ctx, const char *origin, + char *buf, size_t buflen) +{ + const char *obuf = buf; + const u_char *edata = rdata + rdlen; + int spaced = 0; + + const char *comment; + char tmp[100]; + int len, x; + + /* + * Owner. + */ + if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) { + T(addstr("\t\t\t", 3, &buf, &buflen)); + } else { + len = prune_origin(name, origin); + if (*name == '\0') { + goto root; + } else if (len == 0) { + T(addstr("@\t\t\t", 4, &buf, &buflen)); + } else { + T(addstr(name, len, &buf, &buflen)); + /* Origin not used or not root, and no trailing dot? */ + if (((origin == NULL || origin[0] == '\0') || + (origin[0] != '.' && origin[1] != '\0' && + name[len] == '\0')) && name[len - 1] != '.') { + root: + T(addstr(".", 1, &buf, &buflen)); + len++; + } + T(spaced = addtab(len, 24, spaced, &buf, &buflen)); + } + } + + /* + * TTL, Class, Type. + */ + T(x = ns_format_ttl(ttl, buf, buflen)); + addlen(x, &buf, &buflen); + len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type))); + T(addstr(tmp, len, &buf, &buflen)); + if (rdlen == 0) + return (buf - obuf); + T(spaced = addtab(x + len, 16, spaced, &buf, &buflen)); + + /* + * RData. + */ + switch (type) { + case ns_t_a: + if (rdlen != NS_INADDRSZ) + goto formerr; + (void) inet_ntop(AF_INET, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + break; + + case ns_t_cname: + case ns_t_mb: + case ns_t_mg: + case ns_t_mr: + case ns_t_ns: + case ns_t_ptr: + case ns_t_dname: + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + + case ns_t_hinfo: + case ns_t_isdn: + /* First word. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + + /* Second word, optional in ISDN records. */ + if (type == ns_t_isdn && rdata == edata) + break; + + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + break; + + case ns_t_soa: { + u_long t; + + /* Server name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Administrator name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" (\n", 3, &buf, &buflen)); + spaced = 0; + + if ((edata - rdata) != 5*NS_INT32SZ) + goto formerr; + + /* Serial number. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + len = SPRINTF((tmp, "%lu", t)); + T(addstr(tmp, len, &buf, &buflen)); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; serial\n", 9, &buf, &buflen)); + spaced = 0; + + /* Refresh interval. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; refresh\n", 10, &buf, &buflen)); + spaced = 0; + + /* Retry interval. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; retry\n", 8, &buf, &buflen)); + spaced = 0; + + /* Expiry. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; expiry\n", 9, &buf, &buflen)); + spaced = 0; + + /* Minimum TTL. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(addstr(" )", 2, &buf, &buflen)); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; minimum\n", 10, &buf, &buflen)); + + break; + } + + case ns_t_mx: + case ns_t_afsdb: + case ns_t_rt: { + u_int t; + + if (rdlen < NS_INT16SZ) + goto formerr; + + /* Priority. */ + t = ns_get16(rdata); + rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", t)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Target. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + } + + case ns_t_px: { + u_int t; + + if (rdlen < NS_INT16SZ) + goto formerr; + + /* Priority. */ + t = ns_get16(rdata); + rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", t)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Name1. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Name2. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + } + + case ns_t_x25: + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + break; + + case ns_t_txt: + while (rdata < edata) { + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + if (rdata < edata) + T(addstr(" ", 1, &buf, &buflen)); + } + break; + + case ns_t_nsap: { + char t[255*3]; + + (void) inet_nsap_ntoa(rdlen, rdata, t); + T(addstr(t, strlen(t), &buf, &buflen)); + break; + } + + case ns_t_aaaa: + if (rdlen != NS_IN6ADDRSZ) + goto formerr; + (void) inet_ntop(AF_INET6, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + break; + + case ns_t_loc: { + char t[255]; + + /* XXX protocol format checking? */ + (void) loc_ntoa(rdata, t); + T(addstr(t, strlen(t), &buf, &buflen)); + break; + } + + case ns_t_naptr: { + u_int order, preference; + char t[50]; + + if (rdlen < 2*NS_INT16SZ) + goto formerr; + + /* Order, Precedence. */ + order = ns_get16(rdata); rdata += NS_INT16SZ; + preference = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((t, "%u %u ", order, preference)); + T(addstr(t, len, &buf, &buflen)); + + /* Flags. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Service. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Regexp. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len < 0) + return (-1); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Server. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + } + + case ns_t_srv: { + u_int priority, weight, port; + char t[50]; + + if (rdlen < NS_INT16SZ*3) + goto formerr; + + /* Priority, Weight, Port. */ + priority = ns_get16(rdata); rdata += NS_INT16SZ; + weight = ns_get16(rdata); rdata += NS_INT16SZ; + port = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((t, "%u %u %u ", priority, weight, port)); + T(addstr(t, len, &buf, &buflen)); + + /* Server. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + } + + case ns_t_minfo: + case ns_t_rp: + /* Name1. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Name2. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + + case ns_t_wks: { + int n, lcnt; + + if (rdlen < NS_INT32SZ + 1) + goto formerr; + + /* Address. */ + (void) inet_ntop(AF_INET, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + rdata += NS_INADDRSZ; + + /* Protocol. */ + len = SPRINTF((tmp, " %u ( ", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + rdata += NS_INT8SZ; + + /* Bit map. */ + n = 0; + lcnt = 0; + while (rdata < edata) { + u_int c = *rdata++; + do { + if (c & 0200) { + if (lcnt == 0) { + T(addstr("\n\t\t\t\t", 5, + &buf, &buflen)); + lcnt = 10; + spaced = 0; + } + len = SPRINTF((tmp, "%d ", n)); + T(addstr(tmp, len, &buf, &buflen)); + lcnt--; + } + c <<= 1; + } while (++n & 07); + } + T(addstr(")", 1, &buf, &buflen)); + + break; + } + + case ns_t_key: { + char base64_key[NS_MD5RSA_MAX_BASE64]; + u_int keyflags, protocol, algorithm, key_id; + const char *leader; + int n; + + if (rdlen < NS_INT16SZ + NS_INT8SZ + NS_INT8SZ) + goto formerr; + + /* Key flags, Protocol, Algorithm. */ + key_id = dst_s_dns_key_id(rdata, edata-rdata); + keyflags = ns_get16(rdata); rdata += NS_INT16SZ; + protocol = *rdata++; + algorithm = *rdata++; + len = SPRINTF((tmp, "0x%04x %u %u", + keyflags, protocol, algorithm)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Public key data. */ + len = b64_ntop(rdata, edata - rdata, + base64_key, sizeof base64_key); + if (len < 0) + goto formerr; + if (len > 15) { + T(addstr(" (", 2, &buf, &buflen)); + leader = "\n\t\t"; + spaced = 0; + } else + leader = " "; + for (n = 0; n < len; n += 48) { + T(addstr(leader, strlen(leader), &buf, &buflen)); + T(addstr(base64_key + n, MIN(len - n, 48), + &buf, &buflen)); + } + if (len > 15) + T(addstr(" )", 2, &buf, &buflen)); + n = SPRINTF((tmp, " ; key_tag= %u", key_id)); + T(addstr(tmp, n, &buf, &buflen)); + + break; + } + + case ns_t_sig: { + char base64_key[NS_MD5RSA_MAX_BASE64]; + u_int type, algorithm, labels, footprint; + const char *leader; + u_long t; + int n; + + if (rdlen < 22) + goto formerr; + + /* Type covered, Algorithm, Label count, Original TTL. */ + type = ns_get16(rdata); rdata += NS_INT16SZ; + algorithm = *rdata++; + labels = *rdata++; + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s %d %d %lu ", + p_type(type), algorithm, labels, t)); + T(addstr(tmp, len, &buf, &buflen)); + if (labels > (u_int)dn_count_labels(name)) + goto formerr; + + /* Signature expiry. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Time signed. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Signature Footprint. */ + footprint = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", footprint)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Signer's name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + /* Signature. */ + len = b64_ntop(rdata, edata - rdata, + base64_key, sizeof base64_key); + if (len > 15) { + T(addstr(" (", 2, &buf, &buflen)); + leader = "\n\t\t"; + spaced = 0; + } else + leader = " "; + if (len < 0) + goto formerr; + for (n = 0; n < len; n += 48) { + T(addstr(leader, strlen(leader), &buf, &buflen)); + T(addstr(base64_key + n, MIN(len - n, 48), + &buf, &buflen)); + } + if (len > 15) + T(addstr(" )", 2, &buf, &buflen)); + break; + } + + case ns_t_nxt: { + int n, c; + + /* Next domain name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + /* Type bit map. */ + n = edata - rdata; + for (c = 0; c < n*8; c++) + if (NS_NXT_BIT_ISSET(c, rdata)) { + len = SPRINTF((tmp, " %s", p_type(c))); + T(addstr(tmp, len, &buf, &buflen)); + } + break; + } + + case ns_t_cert: { + u_int c_type, key_tag, alg; + int n; + unsigned int siz; + char base64_cert[8192], tmp[40]; + const char *leader; + + c_type = ns_get16(rdata); rdata += NS_INT16SZ; + key_tag = ns_get16(rdata); rdata += NS_INT16SZ; + alg = (u_int) *rdata++; + + len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg)); + T(addstr(tmp, len, &buf, &buflen)); + siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ + if (siz > sizeof(base64_cert) * 3/4) { + const char *str = "record too long to print"; + T(addstr(str, strlen(str), &buf, &buflen)); + } + else { + len = b64_ntop(rdata, edata-rdata, base64_cert, siz); + + if (len < 0) + goto formerr; + else if (len > 15) { + T(addstr(" (", 2, &buf, &buflen)); + leader = "\n\t\t"; + spaced = 0; + } + else + leader = " "; + + for (n = 0; n < len; n += 48) { + T(addstr(leader, strlen(leader), + &buf, &buflen)); + T(addstr(base64_cert + n, MIN(len - n, 48), + &buf, &buflen)); + } + if (len > 15) + T(addstr(" )", 2, &buf, &buflen)); + } + break; + } + + case ns_t_tkey: { + /* KJD - need to complete this */ + u_long t; + int mode, err, keysize; + + /* Algorithm name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Inception. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Experation. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Mode , Error, Key Size. */ + /* Priority, Weight, Port. */ + mode = ns_get16(rdata); rdata += NS_INT16SZ; + err = ns_get16(rdata); rdata += NS_INT16SZ; + keysize = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize)); + T(addstr(tmp, len, &buf, &buflen)); + + /* needs to dump key, print otherdata length & other data */ + break; + } + case ns_t_tsig: { + /* BEW - need to complete this */ + int n; + + T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + rdata += 8; /* time */ + n = ns_get16(rdata); rdata += INT16SZ; + rdata += n; /* sig */ + n = ns_get16(rdata); rdata += INT16SZ; /* original id */ + sprintf(buf, "%d", ns_get16(rdata)); + rdata += INT16SZ; + addlen(strlen(buf), &buf, &buflen); + break; + } + + case ns_t_a6: { + struct in6_addr a; + int pbyte, pbit; + + /* prefix length */ + if (rdlen == 0) goto formerr; + len = SPRINTF((tmp, "%d ", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + pbit = *rdata; + if (pbit > 128) goto formerr; + pbyte = (pbit & ~7) / 8; + rdata++; + + /* address suffix: provided only when prefix len != 128 */ + if (pbit < 128) { + if (rdata + pbyte >= edata) goto formerr; + memset(&a, 0, sizeof(a)); + memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte); + (void) inet_ntop(AF_INET6, &a, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + rdata += sizeof(a) - pbyte; + } + + /* prefix name: provided only when prefix len > 0 */ + if (pbit == 0) + break; + if (rdata >= edata) goto formerr; + T(addstr(" ", 1, &buf, &buflen)); + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + } + + case ns_t_opt: { + len = SPRINTF((tmp, "%u bytes", class)); + T(addstr(tmp, len, &buf, &buflen)); + break; + } + + default: + comment = "unknown RR type"; + goto hexify; + } + return (buf - obuf); + formerr: + comment = "RR format error"; + hexify: { + int n, m; + char *p; + + len = SPRINTF((tmp, "\\#(\t\t; %s", comment)); + T(addstr(tmp, len, &buf, &buflen)); + while (rdata < edata) { + p = tmp; + p += SPRINTF((p, "\n\t")); + spaced = 0; + n = MIN(16, edata - rdata); + for (m = 0; m < n; m++) + p += SPRINTF((p, "%02x ", rdata[m])); + T(addstr(tmp, p - tmp, &buf, &buflen)); + if (n < 16) { + T(addstr(")", 1, &buf, &buflen)); + T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen)); + } + p = tmp; + p += SPRINTF((p, "; ")); + for (m = 0; m < n; m++) + *p++ = (isascii(rdata[m]) && isprint(rdata[m])) + ? rdata[m] + : '.'; + T(addstr(tmp, p - tmp, &buf, &buflen)); + rdata += n; + } + return (buf - obuf); + } +} + +/* Private. */ + +/* + * size_t + * prune_origin(name, origin) + * Find out if the name is at or under the current origin. + * return: + * Number of characters in name before start of origin, + * or length of name if origin does not match. + * notes: + * This function should share code with samedomain(). + */ +static size_t +prune_origin(const char *name, const char *origin) { + const char *oname = name; + + while (*name != '\0') { + if (origin != NULL && ns_samename(name, origin) == 1) + return (name - oname - (name > oname)); + while (*name != '\0') { + if (*name == '\\') { + name++; + /* XXX need to handle \nnn form. */ + if (*name == '\0') + break; + } else if (*name == '.') { + name++; + break; + } + name++; + } + } + return (name - oname); +} + +/* + * int + * charstr(rdata, edata, buf, buflen) + * Format a into the presentation buffer. + * return: + * Number of rdata octets consumed + * 0 for protocol format error + * -1 for output buffer error + * side effects: + * buffer is advanced on success. + */ +static int +charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) { + const u_char *odata = rdata; + size_t save_buflen = *buflen; + char *save_buf = *buf; + + if (addstr("\"", 1, buf, buflen) < 0) + goto enospc; + if (rdata < edata) { + int n = *rdata; + + if (rdata + 1 + n <= edata) { + rdata++; + while (n-- > 0) { + if (strchr("\n\"\\", *rdata) != NULL) + if (addstr("\\", 1, buf, buflen) < 0) + goto enospc; + if (addstr((const char *)rdata, 1, + buf, buflen) < 0) + goto enospc; + rdata++; + } + } + } + if (addstr("\"", 1, buf, buflen) < 0) + goto enospc; + return (rdata - odata); + enospc: + errno = ENOSPC; + *buf = save_buf; + *buflen = save_buflen; + return (-1); +} + +static int +addname(const u_char *msg, size_t msglen, + const u_char **pp, const char *origin, + char **buf, size_t *buflen) +{ + size_t newlen, save_buflen = *buflen; + char *save_buf = *buf; + int n; + + n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen); + if (n < 0) + goto enospc; /* Guess. */ + newlen = prune_origin(*buf, origin); + if (**buf == '\0') { + goto root; + } else if (newlen == 0) { + /* Use "@" instead of name. */ + if (newlen + 2 > *buflen) + goto enospc; /* No room for "@\0". */ + (*buf)[newlen++] = '@'; + (*buf)[newlen] = '\0'; + } else { + if (((origin == NULL || origin[0] == '\0') || + (origin[0] != '.' && origin[1] != '\0' && + (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') { + /* No trailing dot. */ + root: + if (newlen + 2 > *buflen) + goto enospc; /* No room for ".\0". */ + (*buf)[newlen++] = '.'; + (*buf)[newlen] = '\0'; + } + } + *pp += n; + addlen(newlen, buf, buflen); + **buf = '\0'; + return (newlen); + enospc: + errno = ENOSPC; + *buf = save_buf; + *buflen = save_buflen; + return (-1); +} + +static void +addlen(size_t len, char **buf, size_t *buflen) { + INSIST(len <= *buflen); + *buf += len; + *buflen -= len; +} + +static int +addstr(const char *src, size_t len, char **buf, size_t *buflen) { + if (len >= *buflen) { + errno = ENOSPC; + return (-1); + } + memcpy(*buf, src, len); + addlen(len, buf, buflen); + **buf = '\0'; + return (0); +} + +static int +addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { + size_t save_buflen = *buflen; + char *save_buf = *buf; + int t; + + if (spaced || len >= target - 1) { + T(addstr(" ", 2, buf, buflen)); + spaced = 1; + } else { + for (t = (target - len - 1) / 8; t >= 0; t--) + if (addstr("\t", 1, buf, buflen) < 0) { + *buflen = save_buflen; + *buf = save_buf; + return (-1); + } + spaced = 0; + } + return (spaced); +} diff --git a/lib/bind/nameser/ns_samedomain.c b/lib/bind/nameser/ns_samedomain.c new file mode 100644 index 0000000000..54735b2b57 --- /dev/null +++ b/lib/bind/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 1.1 2001/03/29 06:31:57 marka Exp $"; +#endif + +#include "port_before.h" + +#include +#include +#include +#include + +#include "port_after.h" + +/* + * int + * ns_samedomain(a, b) + * Check whether a name belongs to a domain. + * Inputs: + * a - the domain whose ancestory is being verified + * b - the potential ancestor we're checking against + * Return: + * boolean - is a at or below b? + * Notes: + * Trailing dots are first removed from name and domain. + * Always compare complete subdomains, not only whether the + * domain name is the trailing string of the given name. + * + * "host.foobar.top" lies in "foobar.top" and in "top" and in "" + * but NOT in "bar.top" + */ + +int +ns_samedomain(const char *a, const char *b) { + size_t la, lb; + int diff, i, escaped; + const char *cp; + + la = strlen(a); + lb = strlen(b); + + /* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */ + if (la != 0 && a[la - 1] == '.') { + escaped = 0; + /* Note this loop doesn't get executed if la==1. */ + for (i = la - 2; i >= 0; i--) + if (a[i] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else + break; + if (!escaped) + la--; + } + + /* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */ + if (lb != 0 && b[lb - 1] == '.') { + escaped = 0; + /* note this loop doesn't get executed if lb==1 */ + for (i = lb - 2; i >= 0; i--) + if (b[i] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else + break; + if (!escaped) + lb--; + } + + /* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */ + if (lb == 0) + return (1); + + /* 'b' longer than 'a' means 'a' can't be in 'b'. */ + if (lb > la) + return (0); + + /* 'a' and 'b' being equal at this point indicates sameness. */ + if (lb == la) + return (strncasecmp(a, b, lb) == 0); + + /* Ok, we know la > lb. */ + + diff = la - lb; + + /* + * If 'a' is only 1 character longer than 'b', then it can't be + * a subdomain of 'b' (because of the need for the '.' label + * separator). + */ + if (diff < 2) + return (0); + + /* + * If the character before the last 'lb' characters of 'b' + * isn't '.', then it can't be a match (this lets us avoid + * having "foobar.com" match "bar.com"). + */ + if (a[diff - 1] != '.') + return (0); + + /* + * We're not sure about that '.', however. It could be escaped + * and thus not a really a label separator. + */ + escaped = 0; + for (i = diff - 2; i >= 0; i--) + if (a[i] == '\\') + if (escaped) + escaped = 0; + else + escaped = 1; + else + break; + if (escaped) + return (0); + + /* Now compare aligned trailing substring. */ + cp = a + diff; + return (strncasecmp(cp, b, lb) == 0); +} + +/* + * int + * ns_subdomain(a, b) + * is "a" a subdomain of "b"? + */ +int +ns_subdomain(const char *a, const char *b) { + return (ns_samename(a, b) != 1 && ns_samedomain(a, b)); +} + +/* + * int + * ns_makecanon(src, dst, dstsize) + * make a canonical copy of domain name "src" + * notes: + * foo -> foo. + * foo. -> foo. + * foo.. -> foo. + * foo\. -> foo\.. + * foo\\. -> foo\\. + */ + +int +ns_makecanon(const char *src, char *dst, size_t dstsize) { + size_t n = strlen(src); + + if (n + sizeof "." > dstsize) { + errno = EMSGSIZE; + return (-1); + } + strcpy(dst, src); + while (n > 0 && dst[n - 1] == '.') /* Ends in "." */ + if (n > 1 && dst[n - 2] == '\\' && /* Ends in "\." */ + (n < 2 || dst[n - 3] != '\\')) /* But not "\\." */ + break; + else + dst[--n] = '\0'; + dst[n++] = '.'; + dst[n] = '\0'; + return (0); +} + +/* + * int + * ns_samename(a, b) + * determine whether domain name "a" is the same as domain name "b" + * return: + * -1 on error + * 0 if names differ + * 1 if names are the same + */ + +int +ns_samename(const char *a, const char *b) { + char ta[NS_MAXDNAME], tb[NS_MAXDNAME]; + + if (ns_makecanon(a, ta, sizeof ta) < 0 || + ns_makecanon(b, tb, sizeof tb) < 0) + return (-1); + if (strcasecmp(ta, tb) == 0) + return (1); + else + return (0); +} diff --git a/lib/bind/nameser/ns_sign.c b/lib/bind/nameser/ns_sign.c new file mode 100644 index 0000000000..2675444dcf --- /dev/null +++ b/lib/bind/nameser/ns_sign.c @@ -0,0 +1,349 @@ +/* + * 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 1.1 2001/03/29 06:31:57 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "port_after.h" + +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eob) { \ + errno = EMSGSIZE; \ + return(NS_TSIG_ERROR_NO_SPACE); \ + } \ + } while (0) + +/* ns_sign + * Parameters: + * msg message to be sent + * msglen input - length of message + * output - length of signed message + * msgsize length of buffer containing message + * error value to put in the error field + * key tsig key used for signing + * querysig (response), the signature in the query + * querysiglen (response), the length of the signature in the query + * sig a buffer to hold the generated signature + * siglen input - length of signature buffer + * output - length of signature + * + * Errors: + * - bad input data (-1) + * - bad key / sign failed (-BADKEY) + * - not enough space (NS_TSIG_ERROR_NO_SPACE) + */ +int +ns_sign(u_char *msg, int *msglen, int msgsize, int error, void *k, + const u_char *querysig, int querysiglen, u_char *sig, int *siglen, + time_t in_timesigned) +{ + 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 > (int)sizeof(state->sig)) + return (-1); + memcpy(state->sig, querysig, querysiglen); + state->siglen = querysiglen; + return (0); +} + +int +ns_sign_tcp(u_char *msg, int *msglen, int msgsize, int error, + ns_tcp_tsig_state *state, int done) +{ + 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/lib/bind/nameser/ns_ttl.c b/lib/bind/nameser/ns_ttl.c new file mode 100644 index 0000000000..9c24cd8a2c --- /dev/null +++ b/lib/bind/nameser/ns_ttl.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_ttl.c,v 1.1 2001/03/29 06:31:57 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include + +#include +#include +#include +#include + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Forward. */ + +static int fmt1(int t, char s, char **buf, size_t *buflen); + +/* Macros. */ + +#define T(x) if ((x) < 0) return (-1); else (void)NULL + +/* Public. */ + +int +ns_format_ttl(u_long src, char *dst, size_t dstlen) { + char *odst = dst; + int secs, mins, hours, days, weeks, x; + char *p; + + secs = src % 60; src /= 60; + mins = src % 60; src /= 60; + hours = src % 24; src /= 24; + days = src % 7; src /= 7; + weeks = src; src = 0; + + x = 0; + if (weeks) { + T(fmt1(weeks, 'W', &dst, &dstlen)); + x++; + } + if (days) { + T(fmt1(days, 'D', &dst, &dstlen)); + x++; + } + if (hours) { + T(fmt1(hours, 'H', &dst, &dstlen)); + x++; + } + if (mins) { + T(fmt1(mins, 'M', &dst, &dstlen)); + x++; + } + if (secs || !(weeks || days || hours || mins)) { + T(fmt1(secs, 'S', &dst, &dstlen)); + x++; + } + + if (x > 1) { + int ch; + + for (p = odst; (ch = *p) != '\0'; p++) + if (isascii(ch) && isupper(ch)) + *p = tolower(ch); + } + + return (dst - odst); +} + +int +ns_parse_ttl(const char *src, u_long *dst) { + u_long ttl, tmp; + int ch, digits, dirty; + + ttl = 0; + tmp = 0; + digits = 0; + dirty = 0; + while ((ch = *src++) != '\0') { + if (!isascii(ch) || !isprint(ch)) + goto einval; + if (isdigit(ch)) { + tmp *= 10; + tmp += (ch - '0'); + digits++; + continue; + } + if (digits == 0) + goto einval; + if (islower(ch)) + ch = toupper(ch); + switch (ch) { + case 'W': tmp *= 7; + case 'D': tmp *= 24; + case 'H': tmp *= 60; + case 'M': tmp *= 60; + case 'S': break; + default: goto einval; + } + ttl += tmp; + tmp = 0; + digits = 0; + dirty = 1; + } + if (digits > 0) { + if (dirty) + goto einval; + else + ttl += tmp; + } + *dst = ttl; + return (0); + + einval: + errno = EINVAL; + return (-1); +} + +/* Private. */ + +static int +fmt1(int t, char s, char **buf, size_t *buflen) { + char tmp[50]; + size_t len; + + len = SPRINTF((tmp, "%d%c", t, s)); + if (len + 1 > *buflen) + return (-1); + strcpy(*buf, tmp); + *buf += len; + *buflen -= len; + return (0); +} diff --git a/lib/bind/nameser/ns_verify.c b/lib/bind/nameser/ns_verify.c new file mode 100644 index 0000000000..919ed1e351 --- /dev/null +++ b/lib/bind/nameser/ns_verify.c @@ -0,0 +1,480 @@ +/* + * Copyright (c) 1999 by Internet Software Consortium, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_verify.c,v 1.1 2001/03/29 06:31:58 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "port_after.h" + +/* Private. */ + +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eom) { \ + return (NS_TSIG_ERROR_FORMERR); \ + } \ + } while (0) + +/* Public. */ + +u_char * +ns_find_tsig(u_char *msg, u_char *eom) { + HEADER *hp = (HEADER *)msg; + int n, type; + u_char *cp = msg, *start; + + if (msg == NULL || eom == NULL || msg > eom) + return (NULL); + + if (cp + HFIXEDSZ >= eom) + return (NULL); + + if (hp->arcount == 0) + return (NULL); + + cp += HFIXEDSZ; + + n = ns_skiprr(cp, eom, ns_s_qd, ntohs(hp->qdcount)); + if (n < 0) + return (NULL); + cp += n; + + n = ns_skiprr(cp, eom, ns_s_an, ntohs(hp->ancount)); + if (n < 0) + return (NULL); + cp += n; + + n = ns_skiprr(cp, eom, ns_s_ns, ntohs(hp->nscount)); + if (n < 0) + return (NULL); + cp += n; + + n = ns_skiprr(cp, eom, ns_s_ar, ntohs(hp->arcount) - 1); + if (n < 0) + return (NULL); + cp += n; + + start = cp; + n = dn_skipname(cp, eom); + if (n < 0) + return (NULL); + cp += n; + if (cp + INT16SZ >= eom) + return (NULL); + + GETSHORT(type, cp); + if (type != ns_t_tsig) + return (NULL); + return (start); +} + +/* ns_verify + * Parameters: + * statp res stuff + * msg received message + * msglen length of message + * key tsig key used for verifying. + * querysig (response), the signature in the query + * querysiglen (response), the length of the signature in the query + * sig (query), a buffer to hold the signature + * siglen (query), input - length of signature buffer + * output - length of signature + * + * Errors: + * - bad input (-1) + * - invalid dns message (NS_TSIG_ERROR_FORMERR) + * - TSIG is not present (NS_TSIG_ERROR_NO_TSIG) + * - key doesn't match (-ns_r_badkey) + * - TSIG verification fails with BADKEY (-ns_r_badkey) + * - TSIG verification fails with BADSIG (-ns_r_badsig) + * - TSIG verification fails with BADTIME (-ns_r_badtime) + * - TSIG verification succeeds, error set to BAKEY (ns_r_badkey) + * - TSIG verification succeeds, error set to BADSIG (ns_r_badsig) + * - TSIG verification succeeds, error set to BADTIME (ns_r_badtime) + */ +int +ns_verify(u_char *msg, int *msglen, void *k, + const u_char *querysig, int querysiglen, u_char *sig, int *siglen, + time_t *timesigned, int nostrip) +{ + HEADER *hp = (HEADER *)msg; + DST_KEY *key = (DST_KEY *)k; + u_char *cp = msg, *eom; + char name[MAXDNAME], alg[MAXDNAME]; + u_char *recstart, *rdatastart; + u_char *sigstart, *otherstart; + int n; + int error; + u_int16_t type, length; + u_int16_t fudge, sigfieldlen, id, otherfieldlen; + + dst_init(); + if (msg == NULL || msglen == NULL || *msglen < 0) + return (-1); + + eom = msg + *msglen; + + recstart = ns_find_tsig(msg, eom); + if (recstart == NULL) + return (NS_TSIG_ERROR_NO_TSIG); + + cp = recstart; + + /* Read the key name. */ + n = dn_expand(msg, eom, cp, name, MAXDNAME); + if (n < 0) + return (NS_TSIG_ERROR_FORMERR); + cp += n; + + /* Read the type. */ + BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ); + GETSHORT(type, cp); + if (type != ns_t_tsig) + return (NS_TSIG_ERROR_NO_TSIG); + + /* Skip the class and TTL, save the length. */ + cp += INT16SZ + INT32SZ; + GETSHORT(length, cp); + if (eom - cp != length) + return (NS_TSIG_ERROR_FORMERR); + + /* Read the algorithm name. */ + rdatastart = cp; + n = dn_expand(msg, eom, cp, alg, MAXDNAME); + if (n < 0) + return (NS_TSIG_ERROR_FORMERR); + if (ns_samename(alg, NS_TSIG_ALG_HMAC_MD5) != 1) + return (-ns_r_badkey); + cp += n; + + /* Read the time signed and fudge. */ + BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); + cp += INT16SZ; + GETLONG((*timesigned), cp); + GETSHORT(fudge, cp); + + /* Read the signature. */ + BOUNDS_CHECK(cp, INT16SZ); + GETSHORT(sigfieldlen, cp); + BOUNDS_CHECK(cp, sigfieldlen); + sigstart = cp; + cp += sigfieldlen; + + /* Read the original id and error. */ + BOUNDS_CHECK(cp, 2*INT16SZ); + GETSHORT(id, cp); + GETSHORT(error, cp); + + /* Parse the other data. */ + BOUNDS_CHECK(cp, INT16SZ); + GETSHORT(otherfieldlen, cp); + BOUNDS_CHECK(cp, otherfieldlen); + otherstart = cp; + cp += otherfieldlen; + + if (cp != eom) + return (NS_TSIG_ERROR_FORMERR); + + /* Verify that the key used is OK. */ + if (key != NULL) { + if (key->dk_alg != KEY_HMAC_MD5) + return (-ns_r_badkey); + if (error != ns_r_badsig && error != ns_r_badkey) { + if (ns_samename(key->dk_key_name, name) != 1) + return (-ns_r_badkey); + } + } + + hp->arcount = htons(ntohs(hp->arcount) - 1); + + /* + * Do the verification. + */ + + if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) { + void *ctx; + u_char buf[MAXDNAME]; + u_char buf2[MAXDNAME]; + + /* Digest the query signature, if this is a response. */ + dst_verify_data(SIG_MODE_INIT, key, &ctx, NULL, 0, NULL, 0); + if (querysiglen > 0 && querysig != NULL) { + u_int16_t len_n = htons(querysiglen); + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + (u_char *)&len_n, INT16SZ, NULL, 0); + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + querysig, querysiglen, NULL, 0); + } + + /* Digest the message. */ + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, msg, recstart - msg, + NULL, 0); + + /* Digest the key name. */ + n = ns_name_pton(name, buf2, sizeof(buf2)); + if (n < 0) + return (-1); + n = ns_name_ntol(buf2, buf, sizeof(buf)); + if (n < 0) + return (-1); + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); + + /* Digest the class and TTL. */ + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + recstart + dn_skipname(recstart, eom) + INT16SZ, + INT16SZ + INT32SZ, NULL, 0); + + /* Digest the algorithm. */ + n = ns_name_pton(alg, buf2, sizeof(buf2)); + if (n < 0) + return (-1); + n = ns_name_ntol(buf2, buf, sizeof(buf)); + if (n < 0) + return (-1); + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); + + /* Digest the time signed and fudge. */ + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + rdatastart + dn_skipname(rdatastart, eom), + INT16SZ + INT32SZ + INT16SZ, NULL, 0); + + /* Digest the error and other data. */ + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + otherstart - INT16SZ - INT16SZ, + otherfieldlen + INT16SZ + INT16SZ, NULL, 0); + + n = dst_verify_data(SIG_MODE_FINAL, key, &ctx, NULL, 0, + sigstart, sigfieldlen); + + if (n < 0) + return (-ns_r_badsig); + + if (sig != NULL && siglen != NULL) { + if (*siglen < sigfieldlen) + return (NS_TSIG_ERROR_NO_SPACE); + memcpy(sig, sigstart, sigfieldlen); + *siglen = sigfieldlen; + } + } else { + if (sigfieldlen > 0) + return (NS_TSIG_ERROR_FORMERR); + if (sig != NULL && siglen != NULL) + *siglen = 0; + } + + /* Reset the counter, since we still need to check for badtime. */ + hp->arcount = htons(ntohs(hp->arcount) + 1); + + /* Verify the time. */ + if (abs((*timesigned) - time(NULL)) > fudge) + return (-ns_r_badtime); + + if (nostrip == 0) { + *msglen = recstart - msg; + hp->arcount = htons(ntohs(hp->arcount) - 1); + } + + if (error != NOERROR) + return (error); + + return (0); +} + +int +ns_verify_tcp_init(void *k, const u_char *querysig, int querysiglen, + ns_tcp_tsig_state *state) +{ + dst_init(); + if (state == NULL || k == NULL || querysig == NULL || querysiglen < 0) + return (-1); + state->counter = -1; + state->key = k; + if (state->key->dk_alg != KEY_HMAC_MD5) + return (-ns_r_badkey); + if (querysiglen > (int)sizeof(state->sig)) + return (-1); + memcpy(state->sig, querysig, querysiglen); + state->siglen = querysiglen; + return (0); +} + +int +ns_verify_tcp(u_char *msg, int *msglen, ns_tcp_tsig_state *state, + int required) +{ + HEADER *hp = (HEADER *)msg; + u_char *recstart, *rdatastart, *sigstart; + unsigned int sigfieldlen, otherfieldlen; + u_char *cp, *eom = msg + *msglen, *cp2; + char name[MAXDNAME], alg[MAXDNAME]; + u_char buf[MAXDNAME]; + int n, type, length, fudge, id, error; + time_t timesigned; + + if (msg == NULL || msglen == NULL || state == NULL) + return (-1); + + state->counter++; + if (state->counter == 0) + return (ns_verify(msg, msglen, state->key, + state->sig, state->siglen, + state->sig, &state->siglen, ×igned, 0)); + + if (state->siglen > 0) { + u_int16_t siglen_n = htons(state->siglen); + + dst_verify_data(SIG_MODE_INIT, state->key, &state->ctx, + NULL, 0, NULL, 0); + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + (u_char *)&siglen_n, INT16SZ, NULL, 0); + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + state->sig, state->siglen, NULL, 0); + state->siglen = 0; + } + + cp = recstart = ns_find_tsig(msg, eom); + + if (recstart == NULL) { + if (required) + return (NS_TSIG_ERROR_NO_TSIG); + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + msg, *msglen, NULL, 0); + return (0); + } + + hp->arcount = htons(ntohs(hp->arcount) - 1); + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + msg, recstart - msg, NULL, 0); + + /* Read the key name. */ + n = dn_expand(msg, eom, cp, name, MAXDNAME); + if (n < 0) + return (NS_TSIG_ERROR_FORMERR); + cp += n; + + /* Read the type. */ + BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ); + GETSHORT(type, cp); + if (type != ns_t_tsig) + return (NS_TSIG_ERROR_NO_TSIG); + + /* Skip the class and TTL, save the length. */ + cp += INT16SZ + INT32SZ; + GETSHORT(length, cp); + if (eom - cp != length) + return (NS_TSIG_ERROR_FORMERR); + + /* Read the algorithm name. */ + rdatastart = cp; + n = dn_expand(msg, eom, cp, alg, MAXDNAME); + if (n < 0) + return (NS_TSIG_ERROR_FORMERR); + if (ns_samename(alg, NS_TSIG_ALG_HMAC_MD5) != 1) + return (-ns_r_badkey); + cp += n; + + /* Verify that the key used is OK. */ + if ((ns_samename(state->key->dk_key_name, name) != 1 || + state->key->dk_alg != KEY_HMAC_MD5)) + return (-ns_r_badkey); + + /* Read the time signed and fudge. */ + BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); + cp += INT16SZ; + GETLONG(timesigned, cp); + GETSHORT(fudge, cp); + + /* Read the signature. */ + BOUNDS_CHECK(cp, INT16SZ); + GETSHORT(sigfieldlen, cp); + BOUNDS_CHECK(cp, sigfieldlen); + sigstart = cp; + cp += sigfieldlen; + + /* Read the original id and error. */ + BOUNDS_CHECK(cp, 2*INT16SZ); + GETSHORT(id, cp); + GETSHORT(error, cp); + + /* Parse the other data. */ + BOUNDS_CHECK(cp, INT16SZ); + GETSHORT(otherfieldlen, cp); + BOUNDS_CHECK(cp, otherfieldlen); + cp += otherfieldlen; + + if (cp != eom) + return (NS_TSIG_ERROR_FORMERR); + + /* + * Do the verification. + */ + + /* Digest the time signed and fudge. */ + cp2 = buf; + PUTSHORT(0, cp2); /* Top 16 bits of time. */ + PUTLONG(timesigned, cp2); + PUTSHORT(NS_TSIG_FUDGE, cp2); + + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + buf, cp2 - buf, NULL, 0); + + n = dst_verify_data(SIG_MODE_FINAL, state->key, &state->ctx, NULL, 0, + sigstart, sigfieldlen); + if (n < 0) + return (-ns_r_badsig); + + if (sigfieldlen > sizeof(state->sig)) + return (NS_TSIG_ERROR_NO_SPACE); + + memcpy(state->sig, sigstart, sigfieldlen); + state->siglen = sigfieldlen; + + /* Verify the time. */ + if (abs(timesigned - time(NULL)) > fudge) + return (-ns_r_badtime); + + *msglen = recstart - msg; + + if (error != NOERROR) + return (error); + + return (0); +} diff --git a/lib/bind/port_after.h.in b/lib/bind/port_after.h.in new file mode 100644 index 0000000000..c6925363f7 --- /dev/null +++ b/lib/bind/port_after.h.in @@ -0,0 +1,11 @@ +#ifndef port_after_h +#define port_after_h + +@NEED_PSELECT@ +@HAVE_SA_LEN@ +@HAVE_MINIMUM_IFREQ@ + +/* XXX sunos and cygwin needs O_NDELAY */ +#define PORT_NONBLOCK O_NONBLOCK + +#endif diff --git a/lib/bind/port_before.h.in b/lib/bind/port_before.h.in new file mode 100644 index 0000000000..6210c7c316 --- /dev/null +++ b/lib/bind/port_before.h.in @@ -0,0 +1,110 @@ +#ifndef port_before_h +#define port_before_h + +@WANT_IRS_GR@ +@WANT_IRS_NIS@ +@WANT_IRS_PW@ + +#define gettimeofday isc__gettimeofday + +@DO_PTHREADS@ +@GETGROUPLIST_ARGS@ +@GETNETBYADDR_ADDR_T@ + +@NET_R_ARGS@ +@NET_R_BAD@ +@NET_R_COPY@ +@NET_R_COPY_ARGS@ +@NET_R_END_RESULT@ +@NET_R_END_RETURN@ +@NET_R_ENT_ARGS@ +@NET_R_OK@ +@NET_R_RETURN@ +@NET_R_SET_RESULT@ +@NET_R_SET_RETURN@ + +@GROUP_R_RETURN@ +@GROUP_R_SET_RETURN@ +@GROUP_R_SET_RESULT@ +@GROUP_R_END_RETURN@ +@GROUP_R_END_RESULT@ +@GROUP_R_ARGS@ +@GROUP_R_ENT_ARGS@ +@GROUP_R_OK@ +@GROUP_R_BAD@ + +@HOST_R_ARGS@ +@HOST_R_BAD@ +@HOST_R_COPY@ +@HOST_R_COPY_ARGS@ +@HOST_R_END_RESULT@ +@HOST_R_END_RETURN@ +@HOST_R_ENT_ARGS@ +@HOST_R_ERRNO@ +@HOST_R_OK@ +@HOST_R_RETURN@ +@HOST_R_SET_RESULT@ +@HOST_R_SET_RETURN@ + + +@SETPWENT_VOID@ + +@NGR_R_ARGS@ +@NGR_R_BAD@ +@NGR_R_COPY@ +@NGR_R_COPY_ARGS@ +@NGR_R_END_RESULT@ +@NGR_R_END_RETURN@ +@NGR_R_ENT_ARGS@ +@NGR_R_OK@ +@NGR_R_RETURN@ +@NGR_R_SET_RESULT@ +@NGR_R_SET_RETURN@ + +@PROTO_R_ARGS@ +@PROTO_R_BAD@ +@PROTO_R_COPY@ +@PROTO_R_COPY_ARGS@ +@PROTO_R_END_RESULT@ +@PROTO_R_END_RETURN@ +@PROTO_R_ENT_ARGS@ +@PROTO_R_OK@ +@PROTO_R_RETURN@ +@PROTO_R_SET_RESULT@ +@PROTO_R_SET_RETURN@ + +@PASS_R_ARGS@ +@PASS_R_BAD@ +@PASS_R_COPY@ +@PASS_R_COPY_ARGS@ +@PASS_R_END_RESULT@ +@PASS_R_END_RETURN@ +@PASS_R_ENT_ARGS@ +@PASS_R_OK@ +@PASS_R_RETURN@ +@PASS_R_SET_RESULT@ +@PASS_R_SET_RETURN@ + +@SERV_R_ARGS@ +@SERV_R_BAD@ +@SERV_R_COPY@ +@SERV_R_COPY_ARGS@ +@SERV_R_END_RESULT@ +@SERV_R_END_RETURN@ +@SERV_R_ENT_ARGS@ +@SERV_R_OK@ +@SERV_R_RETURN@ +@SERV_R_SET_RESULT@ +@SERV_R_SET_RETURN@ + + +#define DE_CONST(konst, var) \ + do { \ + union { const void *k; void *v; } _u; \ + _u.k = konst; \ + var = _u.v; \ + } while (0) + +#define UNUSED(x) (x) = (x) + +#endif diff --git a/lib/bind/prand_conf.c b/lib/bind/prand_conf.c new file mode 100644 index 0000000000..5cd5152ff9 --- /dev/null +++ b/lib/bind/prand_conf.c @@ -0,0 +1,219 @@ +/* $Id: prand_conf.c,v 1.1 2001/03/29 06:30:30 marka Exp $ + * + * Portions Copyright (c) 1995-1998 by TIS Labs at Network Assoociates Inc. + * Portions Copyright (c) 1998-1998 by TIS Labs @ Network Associates Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND NETWORK ASSOCIATES + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + * + * program to find where system commands reside + * and what directores are avialable for inspection + * this information is stored in the file prand_conf.h in current directory + * + * function my_find get variable number of arguments + * the first argument is the name of the command + * all remaining arguments are list of directories to search for the command in + * this function returns the path to the command + */ + +#include +#include +#include +#include +#include +#include + +#define LINE_MAX 256 + +static int +my_find(const char *cmd, const char **dir) +{ + unsigned int curr = 0, c_len, i; + char cmd_line[LINE_MAX]; + + memset(cmd_line, 0, sizeof(cmd_line)); + c_len = strlen(cmd); + for (i = 0; dir[i]; i++) { + curr = strlen(dir[i]); + if (curr + c_len < sizeof(cmd_line)-3) { + sprintf(cmd_line, "%s%s",dir[i], cmd); + if (access(cmd_line, X_OK) == 0) + return (i); + memset(cmd_line, 0, c_len + curr + 2); + } + } + return (0); +} + +/* + * function to simulate the ` ` operator in perl return the number + * of bytes read from the pipe + */ +static int +pipe_run(char *cmd_line) +{ + FILE *pd; + char scratch[LINE_MAX]; + int ex, no_bytes = 0, no = 1; + + pd = popen(cmd_line, "r"); + for (; (pd != NULL) && (no > 0); no_bytes += no) + no = fread(scratch, sizeof(char), sizeof(scratch), pd); + ex = pclose(pd); + return (no_bytes); +} + +/* + * function that executes a command with certain flags and checks that the + * output is at least certain length + * First parameter the command + * Second parameter is ther flags + * third parameter is the number of bytes required + * output is 1 if the command works 0 if not + * This function writes to the include file if + */ +static int +ex(FILE *fd, const char *path, const char *cmd, const char *arg, + int lower_bound) +{ + char line[LINE_MAX]; + + if (strlen(path) + strlen(cmd) + strlen(arg) < sizeof(line)-7) { + memset(line, 0, sizeof(line)); + sprintf(line, "%s%s %s 2>&1", path, cmd, arg); + if (pipe_run(line) > lower_bound) { + fprintf(fd,"\t\"%s\",\n", line); + return (1); + } + } + return (0); +} + +int +main() +{ + extern int errno; + FILE *fd; + int res, vm, i; + int ps, arp, net, dig, cmd; +/* + * set up list of directories where each command may be found in + */ + const char *arp_path[] = {"/usr/sbin", "/sbin", "/usr/etc/", "/etc/", + "/usr/bin/", NULL}; + const char *ps_path[] = {"/usr/bin", "/bin/", NULL}; + const char *net_path[] = {"/usr/ucb/", "/usr/bin/", "/usr/etc/", + "/usr/sbin/", "/bin/", NULL}; + const char *dig_path[] = {"/usr/bin/", "/usr/local/bin/", NULL}; + const char **df_path = ps_path; + const char *uptime_path[] = {"/usr/ucb/", "/usr/bin/", "/usr/bsd/", NULL}; + const char *iostat_path[] = { "/usr/bin/", "/bin/", "/usr/sbin/", NULL}; + const char *vmstat_path[] = {"/usr/ucb/", "/usr/bin/", "/usr/sbin/", NULL}; + const char *vm_stat_path[] = {"/usr/ucb/", "/usr/bin/", NULL}; + const char **w_path = uptime_path; + +/* find which directories exist */ + const char *dirs[] = {"/tmp", "/usr/tmp", "/var/tmp", ".", "/", + "/var/spool", "/usr/spool", + "/usr/adm", "/var/adm", "/dev", + "/usr/mail", "/var/spool/mail", "/var/mail", + "/home", "/usr/home", NULL}; + + const char *files[] = {"/proc/stat", "/proc/rtc", "/proc/meminfo", + "/proc/interrupts", "/proc/self/status", + "/proc/self/maps", "/proc/curproc/status", + "/proc/curproc/map", + "/var/log/messages", "/var/log/wtmp", + "/var/log/lastlog", "/var/adm/messages", + "/var/adm/wtmp", "/var/adm/lastlog", NULL}; + + struct stat st; + time_t tim; +/* main program: */ + + if ((fd = fopen("prand_conf.h", "w")) == NULL) { + perror("Failed creating file prand_conf.h"); + exit(errno); + } + + fprintf(fd, "#ifndef _PRAND_CMD_H_\n#define _PRAND_CMD_H_\n\n"); + + fprintf(fd, "static const char *cmds[] = {\n"); + + if ((ps = my_find("ps", ps_path)) >= 0) + res = ex(fd, ps_path[ps], "ps","-axlw", 460) || + ex(fd, ps_path[ps], "ps", "-ef", 300) || + ex(fd, ps_path[ps], "ps", "-ale", 300); + + if ((arp = my_find("arp", arp_path)) >= 0) + res = ex(fd, arp_path[arp], "arp", "-n -a", 40); + + if ((net = my_find("netstat", net_path)) >= 0) + res = ex(fd, net_path[net], "netstat", "-an", 1000); + if ((cmd = my_find("df", df_path)) >= 0) + res = ex(fd, df_path[cmd], "df", "", 40); + + if ((dig = my_find("dig", dig_path)) >= 0) + res = ex(fd, dig_path[dig], "dig", "com. soa +ti=1 +retry=0", + 100); + if ((cmd = my_find("uptime", uptime_path)) >= 0) + res = ex(fd, uptime_path[cmd], "uptime", "", 40); + if ((cmd = my_find("printenv", uptime_path)) >= 0) + res = ex(fd, uptime_path[cmd], "printenv", "", 400); + if (net >= 0) + res = ex(fd, net_path[net], "netstat", "-s", 1000); + + if (dig >= 0) + res = ex(fd, net_path[net], "dig", ". soa +ti=1 +retry=0",100); + if ((cmd = my_find("iostat", iostat_path)) >= 0) + res = ex(fd, iostat_path[cmd], "iostat", "", 100); + + vm = 0; + if ((cmd = my_find("vmstat", vmstat_path))) + vm = ex(fd, vmstat_path[cmd], "vmstat", "", 200); + if (vm ==0 && ((cmd = my_find("vm_stat", vm_stat_path)) >= 0)) + vm = ex(fd, vm_stat_path[cmd], "vm_stat", "", 200); + if ((cmd = my_find("w", w_path))) + res = ex(fd, w_path[cmd], "w", "", 100); + fprintf(fd,"\tNULL\n};\n\n"); + + fprintf(fd, "static const char *dirs[] = {\n"); + + for (i=0; dirs[i]; i++) { + if (lstat(dirs[i], &st) == 0) + if (S_ISDIR(st.st_mode)) + fprintf(fd,"\t\"%s\",\n", dirs[i]); + } + fprintf(fd,"\tNULL\n};\n\n"); + + + fprintf(fd, "static const char *files[] = {\n"); + tim = time(NULL); + for (i=0; files[i]; i++) { + if (lstat(files[i],&st) == 0) + if (S_ISREG(st.st_mode) && + (tim - st.st_mtime) < 84600) + fprintf(fd,"\t\"%s\",\n", files[i]); + } + fprintf (fd, "\tNULL\n};\n"); + + if ((stat("/dev/random", &st) == 0)) + if (S_ISCHR(st.st_mode)) + fprintf(fd, "\n#ifndef HAVE_DEV_RANDOM\n%s%s", + "# define HAVE_DEV_RANDOM 1\n", + "#endif /* HAVE_DEV_RANDOM */\n\n"); + + fprintf(fd, "\n#endif /* _PRAND_CMD_H_ */\n"); + fclose(fd); + exit (0); +} diff --git a/lib/bind/resolv/Makefile.in b/lib/bind/resolv/Makefile.in new file mode 100644 index 0000000000..3d4d6a5c16 --- /dev/null +++ b/lib/bind/resolv/Makefile.in @@ -0,0 +1,14 @@ +OBJS= herror.@O@ res_comp.@O@ res_data.@O@ res_debug.@O@ \ + res_findzonecut.@O@ res_init.@O@ res_mkquery.@O@ res_mkupdate.@O@ \ + res_query.@O@ res_send.@O@ res_sendsigned.@O@ res_update.@O@ + +SRCS= herror.c res_comp.c res_data.c res_debug.c \ + res_findzonecut.c res_init.c res_mkquery.c res_mkupdate.c \ + res_query.c res_send.c res_sendsigned.c res_update.c + +TARGETS= ${OBJS} + +CINCLUDES= -I.. -I../include +CWARNINGS= + +@BIND9_MAKE_RULES@ diff --git a/lib/bind/resolv/herror.c b/lib/bind/resolv/herror.c new file mode 100644 index 0000000000..e7e060d9d5 --- /dev/null +++ b/lib/bind/resolv/herror.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: herror.c,v 1.1 2001/03/29 06:31:58 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "port_after.h" +#undef h_errno + +const char *h_errlist[] = { + "Resolver Error 0 (no error)", + "Unknown host", /* 1 HOST_NOT_FOUND */ + "Host name lookup failure", /* 2 TRY_AGAIN */ + "Unknown server error", /* 3 NO_RECOVERY */ + "No address associated with name", /* 4 NO_ADDRESS */ +}; +int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] }; + +int h_errno; + +/* + * herror -- + * print the error indicated by the h_errno value. + */ +void +herror(const char *s) { + struct iovec iov[4], *v = iov; + extern int * __h_errno(); + char *t; + + if (s != NULL && *s != '\0') { + DE_CONST(s, t); + v->iov_base = t; + v->iov_len = strlen(t); + v++; + DE_CONST(": ", t); + v->iov_base = t; + v->iov_len = 2; + v++; + } + DE_CONST(hstrerror(*__h_errno()), t); + v->iov_base = t; + v->iov_len = strlen(v->iov_base); + v++; + DE_CONST("\n", t); + v->iov_base = t; + v->iov_len = 1; + writev(STDERR_FILENO, iov, (v - iov) + 1); +} + +/* + * hstrerror -- + * return the string associated with a given "host" errno value. + */ +const char * +hstrerror(int err) { + if (err < 0) + return ("Resolver internal error"); + else if (err < h_nerr) + return (h_errlist[err]); + return ("Unknown resolver error"); +} diff --git a/lib/bind/resolv/res_comp.c b/lib/bind/resolv/res_comp.c new file mode 100644 index 0000000000..cb86b3f5bb --- /dev/null +++ b/lib/bind/resolv/res_comp.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: res_comp.c,v 1.1 2001/03/29 06:31:58 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "port_after.h" + +/* + * Expand compressed domain name 'comp_dn' to full domain name. + * 'msg' is a pointer to the begining of the message, + * 'eomorig' points to the first location after the message, + * 'exp_dn' is a pointer to a buffer of size 'length' for the result. + * Return size of compressed name or -1 if there was an error. + */ +int +dn_expand(const u_char *msg, const u_char *eom, const u_char *src, + char *dst, int dstsiz) +{ + int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz); + + if (n > 0 && dst[0] == '.') + dst[0] = '\0'; + return (n); +} + +/* + * Pack domain name 'exp_dn' in presentation form into 'comp_dn'. + * Return the size of the compressed name or -1. + * 'length' is the size of the array pointed to by 'comp_dn'. + */ +int +dn_comp(const char *src, u_char *dst, int dstsiz, + u_char **dnptrs, u_char **lastdnptr) +{ + return (ns_name_compress(src, dst, (size_t)dstsiz, + (const u_char **)dnptrs, + (const u_char **)lastdnptr)); +} + +/* + * Skip over a compressed domain name. Return the size or -1. + */ +int +dn_skipname(const u_char *ptr, const u_char *eom) { + const u_char *saveptr = ptr; + + if (ns_name_skip(&ptr, eom) == -1) + return (-1); + return (ptr - saveptr); +} + +/* + * Verify that a domain name uses an acceptable character set. + */ + +/* + * Note the conspicuous absence of ctype macros in these definitions. On + * non-ASCII hosts, we can't depend on string literals or ctype macros to + * tell us anything about network-format data. The rest of the BIND system + * is not careful about this, but for some reason, we're doing it right here. + */ +#define PERIOD 0x2e +#define hyphenchar(c) ((c) == 0x2d) +#define bslashchar(c) ((c) == 0x5c) +#define periodchar(c) ((c) == PERIOD) +#define asterchar(c) ((c) == 0x2a) +#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \ + || ((c) >= 0x61 && (c) <= 0x7a)) +#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) + +#define borderchar(c) (alphachar(c) || digitchar(c)) +#define middlechar(c) (borderchar(c) || hyphenchar(c)) +#define domainchar(c) ((c) > 0x20 && (c) < 0x7f) + +int +res_hnok(const char *dn) { + int ppch = '\0', pch = PERIOD, ch = *dn++; + + while (ch != '\0') { + int nch = *dn++; + + if (periodchar(ch)) { + (void)NULL; + } else if (periodchar(pch)) { + if (!borderchar(ch)) + return (0); + } else if (periodchar(nch) || nch == '\0') { + if (!borderchar(ch)) + return (0); + } else { + if (!middlechar(ch)) + return (0); + } + ppch = pch, pch = ch, ch = nch; + } + return (1); +} + +/* + * hostname-like (A, MX, WKS) owners can have "*" as their first label + * but must otherwise be as a host name. + */ +int +res_ownok(const char *dn) { + if (asterchar(dn[0])) { + if (periodchar(dn[1])) + return (res_hnok(dn+2)); + if (dn[1] == '\0') + return (1); + } + return (res_hnok(dn)); +} + +/* + * SOA RNAMEs and RP RNAMEs can have any printable character in their first + * label, but the rest of the name has to look like a host name. + */ +int +res_mailok(const char *dn) { + int ch, escaped = 0; + + /* "." is a valid missing representation */ + if (*dn == '\0') + return (1); + + /* otherwise