summaryrefslogtreecommitdiff
path: root/usr/src/lib/libresolv2
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libresolv2
downloadillumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libresolv2')
-rw-r--r--usr/src/lib/libresolv2/Makefile114
-rw-r--r--usr/src/lib/libresolv2/Makefile.com177
-rw-r--r--usr/src/lib/libresolv2/amd64/Makefile19
-rw-r--r--usr/src/lib/libresolv2/client.xml98
-rw-r--r--usr/src/lib/libresolv2/common/bsd/daemon.c86
-rw-r--r--usr/src/lib/libresolv2/common/bsd/ftruncate.c70
-rw-r--r--usr/src/lib/libresolv2/common/bsd/gettimeofday.c35
-rw-r--r--usr/src/lib/libresolv2/common/bsd/mktemp.c162
-rw-r--r--usr/src/lib/libresolv2/common/bsd/putenv.c33
-rw-r--r--usr/src/lib/libresolv2/common/bsd/readv.c46
-rw-r--r--usr/src/lib/libresolv2/common/bsd/setenv.c157
-rw-r--r--usr/src/lib/libresolv2/common/bsd/setitimer.c35
-rw-r--r--usr/src/lib/libresolv2/common/bsd/strcasecmp.c130
-rw-r--r--usr/src/lib/libresolv2/common/bsd/strdup.c26
-rw-r--r--usr/src/lib/libresolv2/common/bsd/strerror.c97
-rw-r--r--usr/src/lib/libresolv2/common/bsd/strpbrk.c76
-rw-r--r--usr/src/lib/libresolv2/common/bsd/strsep.c93
-rw-r--r--usr/src/lib/libresolv2/common/bsd/strtoul.c125
-rw-r--r--usr/src/lib/libresolv2/common/bsd/utimes.c47
-rw-r--r--usr/src/lib/libresolv2/common/bsd/writev.c95
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bits.c366
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bn.c138
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bn.h228
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bn00.c76
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bn16.c956
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bn16.h100
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bn32.c956
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bn32.h100
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bn68000.c69
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bn8086.c69
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bninit16.c63
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bninit32.c63
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bnsize00.h83
-rw-r--r--usr/src/lib/libresolv2/common/cylink/c_asm.h140
-rw-r--r--usr/src/lib/libresolv2/common/cylink/cencrint.h262
-rw-r--r--usr/src/lib/libresolv2/common/cylink/ctk_endian.h219
-rw-r--r--usr/src/lib/libresolv2/common/cylink/ctk_prime.c442
-rw-r--r--usr/src/lib/libresolv2/common/cylink/cylink.h89
-rw-r--r--usr/src/lib/libresolv2/common/cylink/dss.c1209
-rw-r--r--usr/src/lib/libresolv2/common/cylink/dssnum.h731
-rw-r--r--usr/src/lib/libresolv2/common/cylink/kludge.h165
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn.h193
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn00.c73
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn16.c3651
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn16.h188
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn32.c3650
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn32.h188
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn68000.c507
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn68000.h82
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn68020.c356
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn68020.h77
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn80386.h176
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn8086.h120
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbnmem.c202
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbnmem.h109
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbnppc.c365
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbnppc.h105
-rw-r--r--usr/src/lib/libresolv2/common/cylink/legal.c52
-rw-r--r--usr/src/lib/libresolv2/common/cylink/legal.h54
-rw-r--r--usr/src/lib/libresolv2/common/cylink/math.c1158
-rw-r--r--usr/src/lib/libresolv2/common/cylink/ppcasm.h582
-rw-r--r--usr/src/lib/libresolv2/common/cylink/rand.c340
-rw-r--r--usr/src/lib/libresolv2/common/cylink/sha.c706
-rw-r--r--usr/src/lib/libresolv2/common/cylink/sha.h162
-rw-r--r--usr/src/lib/libresolv2/common/cylink/sizetest.c58
-rw-r--r--usr/src/lib/libresolv2/common/cylink/swap.c218
-rw-r--r--usr/src/lib/libresolv2/common/cylink/toolkit.h399
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/README.copyright51
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahcbcpad.c183
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahcbcpad.h44
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahchdig.c139
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahchdig.h39
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahchencr.c275
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahchencr.h81
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahchgen.c225
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahchgen.h51
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahchrand.c137
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahchrand.h38
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahdigest.c100
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahdigest.h55
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahencryp.c178
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahencryp.h92
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahgen.c99
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahgen.h54
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahrandom.c106
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahrandom.h54
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahrsaenc.c251
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahrsaenc.h75
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahrsaepr.c108
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahrsaepr.h27
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahrsaepu.c121
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ahrsaepu.h27
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/aichdig.c45
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/aichdig.h24
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/aichenc8.c42
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/aichenc8.h26
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/aichencn.c26
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/aichencn.h24
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/aichencr.c40
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/aichencr.h24
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/aichgen.c40
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/aichgen.h24
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/aichrand.c45
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/aichrand.h24
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/aimd5.c34
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/aimd5ran.c34
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ainfotyp.c39
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ainfotyp.h46
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ainull.c35
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ainull.h17
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/airsaepr.c54
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/airsaepu.c54
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/airsakgn.c69
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/airsaprv.c34
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/airsapub.c34
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/algae.h73
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/algchoic.c176
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/algchoic.h118
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/algobj.c130
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/algobj.h26
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/amcrte.c126
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/amdigest.h26
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/amencdec.h28
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/amgen.h26
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ammd5.c109
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ammd5r.c86
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/amrandom.h24
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/amrkg.c90
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/amrsae.c124
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/atypes.h67
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/balg.c124
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/balg.h123
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/balgmeth.h25
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bgclrbit.c37
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bgmdmpyx.c35
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bgmdsqx.c33
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bgmodexp.c141
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bgpegcd.c87
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/big2exp.c34
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigabs.c31
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigacc.c43
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigarith.c147
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigcmp.c43
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigconst.c35
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/biginv.c112
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/biglen.c37
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigmath.h78
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigmaxes.h54
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigmodx.c34
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigmpy.c45
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigpdiv.c168
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigpmpy.c34
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigpmpyh.c39
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigpmpyl.c39
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigpsq.c51
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigqrx.c94
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigsmod.c37
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigtocan.c69
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigu.c30
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bigunexp.c107
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/binfocsh.c72
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/binfocsh.h40
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bkey.c110
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bkey.h39
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bmempool.c280
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bmempool.h60
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/bsafe2.h201
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/btypechk.h32
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/cantobig.c66
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/crt2.c237
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/crt2.h57
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/digest.c76
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/digrand.c97
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/digrand.h60
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/encrypt.c156
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/generate.c87
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/global.h70
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/intbits.c41
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/intitem.c63
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/intitem.h18
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/keyobj.c122
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/keyobj.h23
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ki8byte.c79
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/ki8byte.h16
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/kifulprv.c160
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/kifulprv.h19
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/kiitem.c53
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/kiitem.h16
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/kinfotyp.c35
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/kinfotyp.h64
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/kipkcrpr.c109
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/kipkcrpr.h20
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/kirsacrt.c110
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/kirsapub.c89
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/kirsapub.h20
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/md5.h51
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/md5rand.c78
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/md5rand.h43
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/prime.c173
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/prime.h33
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/random.c67
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/rsa.c218
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/rsa.h51
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/rsakeygn.c251
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/rsakeygn.h61
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/seccbcd.c155
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/seccbce.c106
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/secrcbc.h43
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/surrendr.c33
-rw-r--r--usr/src/lib/libresolv2/common/dnssafe/surrendr.h29
-rw-r--r--usr/src/lib/libresolv2/common/dst/bsafe_link.c1128
-rw-r--r--usr/src/lib/libresolv2/common/dst/cylink_link.c677
-rw-r--r--usr/src/lib/libresolv2/common/dst/dst_api.c1100
-rw-r--r--usr/src/lib/libresolv2/common/dst/dst_internal.h175
-rw-r--r--usr/src/lib/libresolv2/common/dst/eay_dss_link.c637
-rw-r--r--usr/src/lib/libresolv2/common/dst/hmac_link.c510
-rw-r--r--usr/src/lib/libresolv2/common/dst/prandom.c860
-rw-r--r--usr/src/lib/libresolv2/common/dst/rsaref_link.c768
-rw-r--r--usr/src/lib/libresolv2/common/dst/support.c465
-rw-r--r--usr/src/lib/libresolv2/common/inet/inet_addr.c79
-rw-r--r--usr/src/lib/libresolv2/common/inet/inet_cidr_ntop.c266
-rw-r--r--usr/src/lib/libresolv2/common/inet/inet_cidr_pton.c282
-rw-r--r--usr/src/lib/libresolv2/common/inet/inet_data.c51
-rw-r--r--usr/src/lib/libresolv2/common/inet/inet_lnaof.c77
-rw-r--r--usr/src/lib/libresolv2/common/inet/inet_makeaddr.c87
-rw-r--r--usr/src/lib/libresolv2/common/inet/inet_net_ntop.c284
-rw-r--r--usr/src/lib/libresolv2/common/inet/inet_net_pton.c406
-rw-r--r--usr/src/lib/libresolv2/common/inet/inet_neta.c94
-rw-r--r--usr/src/lib/libresolv2/common/inet/inet_netof.c77
-rw-r--r--usr/src/lib/libresolv2/common/inet/inet_network.c129
-rw-r--r--usr/src/lib/libresolv2/common/inet/inet_ntoa.c71
-rw-r--r--usr/src/lib/libresolv2/common/inet/inet_ntop.c212
-rw-r--r--usr/src/lib/libresolv2/common/inet/inet_pton.c231
-rw-r--r--usr/src/lib/libresolv2/common/inet/nsap_addr.c119
-rw-r--r--usr/src/lib/libresolv2/common/irs/dns.c160
-rw-r--r--usr/src/lib/libresolv2/common/irs/dns_gr.c301
-rw-r--r--usr/src/lib/libresolv2/common/irs/dns_ho.c1163
-rw-r--r--usr/src/lib/libresolv2/common/irs/dns_nw.c601
-rw-r--r--usr/src/lib/libresolv2/common/irs/dns_p.h58
-rw-r--r--usr/src/lib/libresolv2/common/irs/dns_pr.c273
-rw-r--r--usr/src/lib/libresolv2/common/irs/dns_pw.c238
-rw-r--r--usr/src/lib/libresolv2/common/irs/dns_sv.c305
-rw-r--r--usr/src/lib/libresolv2/common/irs/gai_strerror.c93
-rw-r--r--usr/src/lib/libresolv2/common/irs/gen.c457
-rw-r--r--usr/src/lib/libresolv2/common/irs/gen_gr.c489
-rw-r--r--usr/src/lib/libresolv2/common/irs/gen_ho.c398
-rw-r--r--usr/src/lib/libresolv2/common/irs/gen_ng.c179
-rw-r--r--usr/src/lib/libresolv2/common/irs/gen_nw.c269
-rw-r--r--usr/src/lib/libresolv2/common/irs/gen_p.h120
-rw-r--r--usr/src/lib/libresolv2/common/irs/gen_pr.c233
-rw-r--r--usr/src/lib/libresolv2/common/irs/gen_pw.c240
-rw-r--r--usr/src/lib/libresolv2/common/irs/gen_sv.c234
-rw-r--r--usr/src/lib/libresolv2/common/irs/getaddrinfo.c1307
-rw-r--r--usr/src/lib/libresolv2/common/irs/getgrent.c230
-rw-r--r--usr/src/lib/libresolv2/common/irs/getgrent_r.c237
-rw-r--r--usr/src/lib/libresolv2/common/irs/gethostent.c1091
-rw-r--r--usr/src/lib/libresolv2/common/irs/gethostent_r.c271
-rw-r--r--usr/src/lib/libresolv2/common/irs/getnameinfo.c341
-rw-r--r--usr/src/lib/libresolv2/common/irs/getnetent.c370
-rw-r--r--usr/src/lib/libresolv2/common/irs/getnetent_r.c234
-rw-r--r--usr/src/lib/libresolv2/common/irs/getnetgrent.c191
-rw-r--r--usr/src/lib/libresolv2/common/irs/getnetgrent_r.c172
-rw-r--r--usr/src/lib/libresolv2/common/irs/getprotoent.c197
-rw-r--r--usr/src/lib/libresolv2/common/irs/getprotoent_r.c223
-rw-r--r--usr/src/lib/libresolv2/common/irs/getpwent.c206
-rw-r--r--usr/src/lib/libresolv2/common/irs/getpwent_r.c283
-rw-r--r--usr/src/lib/libresolv2/common/irs/getservent.c200
-rw-r--r--usr/src/lib/libresolv2/common/irs/getservent_r.c244
-rw-r--r--usr/src/lib/libresolv2/common/irs/hesiod.c535
-rw-r--r--usr/src/lib/libresolv2/common/irs/hesiod_p.h55
-rw-r--r--usr/src/lib/libresolv2/common/irs/irp.c599
-rw-r--r--usr/src/lib/libresolv2/common/irs/irp_gr.c415
-rw-r--r--usr/src/lib/libresolv2/common/irs/irp_ho.c436
-rw-r--r--usr/src/lib/libresolv2/common/irs/irp_ng.c279
-rw-r--r--usr/src/lib/libresolv2/common/irs/irp_nw.c382
-rw-r--r--usr/src/lib/libresolv2/common/irs/irp_p.h66
-rw-r--r--usr/src/lib/libresolv2/common/irs/irp_pr.c360
-rw-r--r--usr/src/lib/libresolv2/common/irs/irp_pw.c365
-rw-r--r--usr/src/lib/libresolv2/common/irs/irp_sv.c376
-rw-r--r--usr/src/lib/libresolv2/common/irs/irpmarshall.c2351
-rw-r--r--usr/src/lib/libresolv2/common/irs/irs_data.c221
-rw-r--r--usr/src/lib/libresolv2/common/irs/irs_data.h74
-rw-r--r--usr/src/lib/libresolv2/common/irs/irs_p.h56
-rw-r--r--usr/src/lib/libresolv2/common/irs/lcl.c147
-rw-r--r--usr/src/lib/libresolv2/common/irs/lcl_gr.c361
-rw-r--r--usr/src/lib/libresolv2/common/irs/lcl_ho.c629
-rw-r--r--usr/src/lib/libresolv2/common/irs/lcl_ng.c451
-rw-r--r--usr/src/lib/libresolv2/common/irs/lcl_nw.c378
-rw-r--r--usr/src/lib/libresolv2/common/irs/lcl_p.h57
-rw-r--r--usr/src/lib/libresolv2/common/irs/lcl_pr.c291
-rw-r--r--usr/src/lib/libresolv2/common/irs/lcl_pw.c315
-rw-r--r--usr/src/lib/libresolv2/common/irs/lcl_sv.c438
-rw-r--r--usr/src/lib/libresolv2/common/irs/nis.c158
-rw-r--r--usr/src/lib/libresolv2/common/irs/nis_gr.c360
-rw-r--r--usr/src/lib/libresolv2/common/irs/nis_ho.c537
-rw-r--r--usr/src/lib/libresolv2/common/irs/nis_ng.c306
-rw-r--r--usr/src/lib/libresolv2/common/irs/nis_nw.c388
-rw-r--r--usr/src/lib/libresolv2/common/irs/nis_p.h53
-rw-r--r--usr/src/lib/libresolv2/common/irs/nis_pr.c304
-rw-r--r--usr/src/lib/libresolv2/common/irs/nis_pw.c294
-rw-r--r--usr/src/lib/libresolv2/common/irs/nis_sv.c312
-rw-r--r--usr/src/lib/libresolv2/common/irs/nul_ng.c133
-rw-r--r--usr/src/lib/libresolv2/common/irs/pathnames.h57
-rw-r--r--usr/src/lib/libresolv2/common/irs/util.c113
-rw-r--r--usr/src/lib/libresolv2/common/isc/assertions.c98
-rw-r--r--usr/src/lib/libresolv2/common/isc/base64.c333
-rw-r--r--usr/src/lib/libresolv2/common/isc/bitncmp.c73
-rw-r--r--usr/src/lib/libresolv2/common/isc/ctl_clnt.c609
-rw-r--r--usr/src/lib/libresolv2/common/isc/ctl_p.c193
-rw-r--r--usr/src/lib/libresolv2/common/isc/ctl_p.h33
-rw-r--r--usr/src/lib/libresolv2/common/isc/ctl_srvr.c787
-rw-r--r--usr/src/lib/libresolv2/common/isc/ev_connects.c372
-rw-r--r--usr/src/lib/libresolv2/common/isc/ev_files.c303
-rw-r--r--usr/src/lib/libresolv2/common/isc/ev_streams.c312
-rw-r--r--usr/src/lib/libresolv2/common/isc/ev_timers.c422
-rw-r--r--usr/src/lib/libresolv2/common/isc/ev_waits.c252
-rw-r--r--usr/src/lib/libresolv2/common/isc/eventlib.c899
-rw-r--r--usr/src/lib/libresolv2/common/isc/eventlib_p.h281
-rw-r--r--usr/src/lib/libresolv2/common/isc/heap.c228
-rw-r--r--usr/src/lib/libresolv2/common/isc/hex.c123
-rw-r--r--usr/src/lib/libresolv2/common/isc/logging.c727
-rw-r--r--usr/src/lib/libresolv2/common/isc/logging_p.h67
-rw-r--r--usr/src/lib/libresolv2/common/isc/memcluster.c588
-rw-r--r--usr/src/lib/libresolv2/common/isc/tree.c543
-rw-r--r--usr/src/lib/libresolv2/common/llib-lresolv59
-rw-r--r--usr/src/lib/libresolv2/common/mapfile-vers15
-rw-r--r--usr/src/lib/libresolv2/common/nameser/ns_date.c135
-rw-r--r--usr/src/lib/libresolv2/common/nameser/ns_name.c970
-rw-r--r--usr/src/lib/libresolv2/common/nameser/ns_netint.c63
-rw-r--r--usr/src/lib/libresolv2/common/nameser/ns_parse.c214
-rw-r--r--usr/src/lib/libresolv2/common/nameser/ns_print.c913
-rw-r--r--usr/src/lib/libresolv2/common/nameser/ns_samedomain.c213
-rw-r--r--usr/src/lib/libresolv2/common/nameser/ns_sign.c387
-rw-r--r--usr/src/lib/libresolv2/common/nameser/ns_ttl.c166
-rw-r--r--usr/src/lib/libresolv2/common/nameser/ns_verify.c487
-rw-r--r--usr/src/lib/libresolv2/common/resolv/herror.c132
-rw-r--r--usr/src/lib/libresolv2/common/resolv/res_comp.c284
-rw-r--r--usr/src/lib/libresolv2/common/resolv/res_data.c306
-rw-r--r--usr/src/lib/libresolv2/common/resolv/res_debug.c1222
-rw-r--r--usr/src/lib/libresolv2/common/resolv/res_debug.h41
-rw-r--r--usr/src/lib/libresolv2/common/resolv/res_findzonecut.c729
-rw-r--r--usr/src/lib/libresolv2/common/resolv/res_init.c897
-rw-r--r--usr/src/lib/libresolv2/common/resolv/res_mkquery.c359
-rw-r--r--usr/src/lib/libresolv2/common/resolv/res_mkupdate.c1165
-rw-r--r--usr/src/lib/libresolv2/common/resolv/res_mkupdate.h31
-rw-r--r--usr/src/lib/libresolv2/common/resolv/res_private.h27
-rw-r--r--usr/src/lib/libresolv2/common/resolv/res_query.c464
-rw-r--r--usr/src/lib/libresolv2/common/resolv/res_send.c1087
-rw-r--r--usr/src/lib/libresolv2/common/resolv/res_sendsigned.c148
-rw-r--r--usr/src/lib/libresolv2/common/resolv/res_update.c219
-rw-r--r--usr/src/lib/libresolv2/common/sunw/sunw_dst_init.c100
-rw-r--r--usr/src/lib/libresolv2/common/sunw/sunw_irs_init.c75
-rw-r--r--usr/src/lib/libresolv2/common/sunw/sunw_irs_nis_acc.c25
-rw-r--r--usr/src/lib/libresolv2/common/sunw/sunw_mtctxres.c220
-rw-r--r--usr/src/lib/libresolv2/common/sunw/sunw_updrec.c202
-rw-r--r--usr/src/lib/libresolv2/cylink/Makefile62
-rw-r--r--usr/src/lib/libresolv2/cylink/Makefile.com69
-rw-r--r--usr/src/lib/libresolv2/cylink/amd64/Makefile15
-rw-r--r--usr/src/lib/libresolv2/cylink/i386/Makefile12
-rw-r--r--usr/src/lib/libresolv2/cylink/sparc/Makefile12
-rw-r--r--usr/src/lib/libresolv2/cylink/sparcv9/Makefile13
-rw-r--r--usr/src/lib/libresolv2/cylink/spec/Makefile8
-rw-r--r--usr/src/lib/libresolv2/cylink/spec/Makefile.targ12
-rw-r--r--usr/src/lib/libresolv2/cylink/spec/amd64/Makefile26
-rw-r--r--usr/src/lib/libresolv2/cylink/spec/cylink.spec11
-rw-r--r--usr/src/lib/libresolv2/cylink/spec/i386/Makefile26
-rw-r--r--usr/src/lib/libresolv2/cylink/spec/sparc/Makefile26
-rw-r--r--usr/src/lib/libresolv2/cylink/spec/sparcv9/Makefile27
-rw-r--r--usr/src/lib/libresolv2/cylink/spec/versions19
-rw-r--r--usr/src/lib/libresolv2/dnssafe/Makefile62
-rw-r--r--usr/src/lib/libresolv2/dnssafe/Makefile.com88
-rw-r--r--usr/src/lib/libresolv2/dnssafe/amd64/Makefile15
-rw-r--r--usr/src/lib/libresolv2/dnssafe/i386/Makefile12
-rw-r--r--usr/src/lib/libresolv2/dnssafe/sparc/Makefile12
-rw-r--r--usr/src/lib/libresolv2/dnssafe/sparcv9/Makefile13
-rw-r--r--usr/src/lib/libresolv2/dnssafe/spec/Makefile8
-rw-r--r--usr/src/lib/libresolv2/dnssafe/spec/Makefile.targ12
-rw-r--r--usr/src/lib/libresolv2/dnssafe/spec/amd64/Makefile26
-rw-r--r--usr/src/lib/libresolv2/dnssafe/spec/dnssafe.spec23
-rw-r--r--usr/src/lib/libresolv2/dnssafe/spec/i386/Makefile26
-rw-r--r--usr/src/lib/libresolv2/dnssafe/spec/sparc/Makefile26
-rw-r--r--usr/src/lib/libresolv2/dnssafe/spec/sparcv9/Makefile27
-rw-r--r--usr/src/lib/libresolv2/dnssafe/spec/versions19
-rw-r--r--usr/src/lib/libresolv2/i386/Makefile17
-rw-r--r--usr/src/lib/libresolv2/include/Makefile41
-rw-r--r--usr/src/lib/libresolv2/include/conf/sunoptions.h63
-rw-r--r--usr/src/lib/libresolv2/include/err.h62
-rw-r--r--usr/src/lib/libresolv2/include/fd_setsize.h18
-rw-r--r--usr/src/lib/libresolv2/include/hesiod.h47
-rw-r--r--usr/src/lib/libresolv2/include/inet_private.h31
-rw-r--r--usr/src/lib/libresolv2/include/irp.h112
-rw-r--r--usr/src/lib/libresolv2/include/irs.h383
-rw-r--r--usr/src/lib/libresolv2/include/isc/assertions.h129
-rw-r--r--usr/src/lib/libresolv2/include/isc/ctl.h116
-rw-r--r--usr/src/lib/libresolv2/include/isc/dst.h193
-rw-r--r--usr/src/lib/libresolv2/include/isc/eventlib.h209
-rw-r--r--usr/src/lib/libresolv2/include/isc/heap.h54
-rw-r--r--usr/src/lib/libresolv2/include/isc/irpmarshall.h123
-rw-r--r--usr/src/lib/libresolv2/include/isc/list.h119
-rw-r--r--usr/src/lib/libresolv2/include/isc/logging.h118
-rw-r--r--usr/src/lib/libresolv2/include/isc/memcluster.h56
-rw-r--r--usr/src/lib/libresolv2/include/isc/misc.h44
-rw-r--r--usr/src/lib/libresolv2/include/isc/tree.h66
-rw-r--r--usr/src/lib/libresolv2/include/make_os_version34
-rw-r--r--usr/src/lib/libresolv2/include/netdb_private.h41
-rw-r--r--usr/src/lib/libresolv2/include/netgroup.h26
-rw-r--r--usr/src/lib/libresolv2/include/paths.h9
-rw-r--r--usr/src/lib/libresolv2/include/port_after.h294
-rw-r--r--usr/src/lib/libresolv2/include/port_before.h159
-rw-r--r--usr/src/lib/libresolv2/include/prand_conf.h45
-rw-r--r--usr/src/lib/libresolv2/include/probe_ipv673
-rw-r--r--usr/src/lib/libresolv2/include/res_update.h104
-rw-r--r--usr/src/lib/libresolv2/include/resolv_mt.h69
-rw-r--r--usr/src/lib/libresolv2/include/sunw_dst_init.h27
-rw-r--r--usr/src/lib/libresolv2/include/sunw_irs_init.h21
-rw-r--r--usr/src/lib/libresolv2/include/synonyms.h564
-rw-r--r--usr/src/lib/libresolv2/include/sys/bitypes.h46
-rw-r--r--usr/src/lib/libresolv2/include/sys/cdefs.h151
-rw-r--r--usr/src/lib/libresolv2/irs/Makefile62
-rw-r--r--usr/src/lib/libresolv2/irs/Makefile.com70
-rw-r--r--usr/src/lib/libresolv2/irs/amd64/Makefile15
-rw-r--r--usr/src/lib/libresolv2/irs/i386/Makefile12
-rw-r--r--usr/src/lib/libresolv2/irs/sparc/Makefile12
-rw-r--r--usr/src/lib/libresolv2/irs/sparcv9/Makefile13
-rw-r--r--usr/src/lib/libresolv2/irs/spec/Makefile8
-rw-r--r--usr/src/lib/libresolv2/irs/spec/Makefile.targ12
-rw-r--r--usr/src/lib/libresolv2/irs/spec/amd64/Makefile26
-rw-r--r--usr/src/lib/libresolv2/irs/spec/i386/Makefile26
-rw-r--r--usr/src/lib/libresolv2/irs/spec/irs.spec15
-rw-r--r--usr/src/lib/libresolv2/irs/spec/sparc/Makefile26
-rw-r--r--usr/src/lib/libresolv2/irs/spec/sparcv9/Makefile27
-rw-r--r--usr/src/lib/libresolv2/irs/spec/versions19
-rw-r--r--usr/src/lib/libresolv2/req.flg9
-rw-r--r--usr/src/lib/libresolv2/sparc/Makefile17
-rw-r--r--usr/src/lib/libresolv2/sparcv9/Makefile27
-rw-r--r--usr/src/lib/libresolv2/spec/Makefile8
-rw-r--r--usr/src/lib/libresolv2/spec/Makefile.targ12
-rw-r--r--usr/src/lib/libresolv2/spec/amd64/Makefile23
-rw-r--r--usr/src/lib/libresolv2/spec/i386/Makefile23
-rw-r--r--usr/src/lib/libresolv2/spec/resolv2.spec1096
-rw-r--r--usr/src/lib/libresolv2/spec/sparc/Makefile23
-rw-r--r--usr/src/lib/libresolv2/spec/sparcv9/Makefile24
-rw-r--r--usr/src/lib/libresolv2/spec/versions35
443 files changed, 90498 insertions, 0 deletions
diff --git a/usr/src/lib/libresolv2/Makefile b/usr/src/lib/libresolv2/Makefile
new file mode 100644
index 0000000000..cfb4e5d6d9
--- /dev/null
+++ b/usr/src/lib/libresolv2/Makefile
@@ -0,0 +1,114 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/Makefile
+#
+
+include ../../Makefile.master
+include ../Makefile.lib
+
+MANIFEST= client.xml
+MANIFESTDIR= $(ROOT)/var/svc/manifest/network/dns
+ROOTMANIFEST= $(MANIFEST:%=$(MANIFESTDIR)/%)
+
+$(ROOTMANIFEST) := FILEMODE = 444
+$(ROOTMANIFEST) := OWNER = root
+$(ROOTMANIFEST) := GROUP = bin
+
+CHKMANIFEST= $(MANIFEST:%.xml=%.xmlchk)
+
+SUBDIRS= include spec $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+SUBDIRS += .WAIT irs
+
+# EXPORT DELETE START
+# CRYPT DELETE START
+SUBDIRS += cylink dnssafe
+# CRYPT DELETE END
+# EXPORT DELETE END
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+lint := TARGET= lint
+_msg := TARGET= _msg
+
+LIBRARY= libresolv.a
+TEXT_DOMAIN= SUNW_OST_OSLIB
+XGETFLAGS= -a
+POFILE= $(LIBRARY:.a=.po)
+POFILES= generic.po
+
+SED= sed
+GREP= grep
+CP= cp
+
+.KEEP_STATE:
+
+all clean clobber lint: $(SUBDIRS)
+
+install: $(SUBDIRS) $(ROOTMANIFEST)
+
+$(ROOTMANIFEST): $(MANIFESTDIR)
+
+$(MANIFESTDIR):
+ $(INS.dir)
+
+$(MANIFESTDIR)/%: %
+ $(INS.file)
+
+# install rule for install_h target
+$(ROOTHDRDIR)/%: %
+ $(INS.file)
+
+install_h: $(ROOTHDRS)
+
+check: $(CHECKHDRS) $(CHKMANIFEST)
+
+# EXPORT DELETE START
+# CRYPT DELETE START
+# Special targets to clean up the source tree for export distribution
+# Warning: These target change the source tree
+EXPORT_SRC:
+ $(RM) Makefile+
+ $(SED) -e "/^# EXPORT DELETE START/,/^# EXPORT DELETE END/d" \
+ < Makefile > Makefile+
+ $(MV) Makefile+ Makefile
+ $(CHMOD) 444 Makefile
+ /usr/bin/find cylink dnssafe common/cylink common/dnssafe \
+ -name SCCS -prune -o -type f -exec $(RM) {} \;
+
+CRYPT_SRC:
+ $(RM) Makefile+
+ $(SED) -e "/^# CRYPT DELETE START/,/^# CRYPT DELETE END/d" \
+ < Makefile > Makefile+
+ $(MV) Makefile+ Makefile
+ $(CHMOD) 444 Makefile
+ /usr/bin/find cylink dnssafe common/cylink common/dnssafe \
+ -name SCCS -prune -o -type f -exec $(RM) {} \;
+
+# CRYPT DELETE END
+# EXPORT DELETE END
+
+_msg: $(MSGDOMAIN) $(POFILE)
+ $(RM) $(MSGDOMAIN)/$(POFILE)
+ $(CP) $(POFILE) $(MSGDOMAIN)
+
+$(POFILE): $(POFILES)
+ $(RM) $@
+ $(CAT) $(POFILES) > $@
+
+$(POFILES):
+ $(RM) messages.po
+ $(XGETTEXT) $(XGETFLAGS) *.[ch]* */*.[ch]*
+ $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@
+ $(RM) messages.po
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET); echo
+
+FRC:
diff --git a/usr/src/lib/libresolv2/Makefile.com b/usr/src/lib/libresolv2/Makefile.com
new file mode 100644
index 0000000000..e2a59c440f
--- /dev/null
+++ b/usr/src/lib/libresolv2/Makefile.com
@@ -0,0 +1,177 @@
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/Makefile.com
+#
+
+LIBRARY= libresolv.a
+VERS= .2
+
+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
+
+DSTOBJS= dst_api.o prandom.o support.o
+
+DSTLINKOBJS= bsafe_link.o cylink_link.o eay_dss_link.o hmac_link.o \
+ rsaref_link.o
+
+INETOBJS= inet_net_pton.o inet_ntop.o \
+ inet_neta.o inet_pton.o inet_lnaof.o inet_netof.o \
+ nsap_addr.o inet_makeaddr.o inet_network.o \
+ inet_net_ntop.o inet_ntoa.o inet_cidr_ntop.o \
+ inet_cidr_pton.o inet_data.o
+
+IRSOBJS= dns.o gen_ho.o getnetgrent.o lcl_ng.o \
+ nis_nw.o dns_gr.o gen_ng.o getprotoent.o \
+ lcl_nw.o nis_pr.o dns_ho.o gen_nw.o \
+ getpwent.o lcl_pr.o nis_pw.o dns_nw.o \
+ gen_pr.o getservent.o lcl_pw.o nis_sv.o \
+ dns_pr.o gen_pw.o hesiod.o lcl_sv.o \
+ nul_ng.o dns_pw.o gen_sv.o irs_data.o \
+ nis.o util.o dns_sv.o getgrent.o \
+ lcl.o nis_gr.o gen.o gethostent.o \
+ lcl_gr.o nis_ho.o gen_gr.o getnetent.o \
+ lcl_ho.o nis_ng.o getpwent_r.o \
+ getservent_r.o gai_strerror.o getgrent_r.o \
+ gethostent_r.o getnetent_r.o getnetgrent_r.o \
+ getprotoent_r.o getnameinfo.o irp.o irpmarshall.o \
+ irp_ho.o irp_nw.o irp_pr.o irp_sv.o \
+ irp_gr.o irp_ng.o irp_pw.o
+
+IRSRESOBJS= dns.o gen_ho.o lcl_ng.o dns_gr.o \
+ gen_ng.o lcl_nw.o dns_ho.o gen_nw.o \
+ lcl_pr.o dns_nw.o gen_pr.o lcl_pw.o \
+ dns_pr.o gen_pw.o hesiod.o lcl_sv.o \
+ nul_ng.o dns_pw.o gen_sv.o irs_data.o \
+ util.o dns_sv.o lcl.o gen.o \
+ gethostent.o lcl_gr.o gen_gr.o lcl_ho.o \
+ gethostent_r.o getaddrinfo.o
+
+IRSDYNOBJS= nis_nw.o nis_pr.o nis_pw.o nis_sv.o \
+ nis.o nis_gr.o nis_ho.o nis_ng.o \
+ irp.o irpmarshall.o irp_ho.o irp_nw.o \
+ irp_pr.o irp_sv.o irp_gr.o irp_ng.o \
+ irp_pw.o getnetent.o getpwent_r.o getgrent_r.o \
+ getservent_r.o getnetent_r.o getnetgrent_r.o getgrent.o \
+ getnetgrent.o getprotoent.o getpwent.o getservent.o \
+ getprotoent_r.o getnameinfo.o gai_strerror.o
+
+ISCOBJS= base64.o ev_files.o ev_waits.o logging.o \
+ bitncmp.o ev_streams.o eventlib.o tree.o \
+ ev_connects.o ev_timers.o heap.o assertions.o \
+ memcluster.o ctl_p.o ctl_clnt.o ctl_srvr.o \
+ hex.o
+
+NAMESEROBJS= ns_name.o ns_netint.o ns_parse.o ns_print.o \
+ ns_ttl.o ns_sign.o ns_verify.o ns_date.o \
+ ns_samedomain.o
+
+RESOLVOBJS= herror.o res_debug.o res_data.o res_comp.o \
+ res_init.o res_mkquery.o res_mkupdate.o res_query.o \
+ res_send.o res_update.o res_sendsigned.o \
+ res_findzonecut.o
+
+SUNWOBJS= sunw_mtctxres.o sunw_dst_init.o sunw_irs_init.o sunw_updrec.o
+
+OBJECTS= $(BSDOBJS) $(DSTOBJS) $(INETOBJS) $(IRSRESOBJS) $(ISCOBJS) \
+ $(NAMESEROBJS) $(RESOLVOBJS) $(SUNWOBJS)
+
+# include library definitions
+include ../../Makefile.lib
+
+# install this library in the root filesystem
+include ../../Makefile.rootfs
+
+MAPFILE= $(MAPDIR)/mapfile
+MAPFILES= $(MAPFILE) ../common/mapfile-vers
+MAPOPTS= $(MAPFILES:%=-M%)
+
+SRCS= $(BSDOBJS:%.o=../common/bsd/%.c) \
+ $(DSTOBJS:%.o=../common/dst/%.c) \
+ $(INETOBJS:%.o=../common/inet/%.c) \
+ $(IRSRESOBJS:%.o=../common/irs/%.c) \
+ $(ISCOBJS:%.o=../common/isc/%.c) \
+ $(NAMESEROBJS:%.o=../common/nameser/%.c) \
+ $(RESOLVOBJS:%.o=../common/resolv/%.c) \
+ $(SUNWOBJS:%.o=../common/sunw/%.c)
+
+LIBS = $(DYNLIB) $(LINTLIB)
+
+$(LINTLIB):= SRCS = ../common/llib-lresolv
+
+# Local Libresolv definitions
+SOLCOMPAT = -Dgethostbyname=res_gethostbyname \
+ -Dgethostbyaddr=res_gethostbyaddr -Dgetnetbyname=res_getnetbyname \
+ -Dgethostbyname2=res_gethostbyname2\
+ -Dgetnetbyaddr=res_getnetbyaddr -Dsethostent=res_sethostent \
+ -Dendhostent=res_endhostent -Dgethostent=res_gethostent \
+ -Dsetnetent=res_setnetent -Dendnetent=res_endnetent \
+ -Dgetnetent=res_getnetent -Dsocket=_socket \
+ -Dgetipnodebyname=res_getipnodebyname \
+ -Dgetipnodebyaddr=res_getipnodebyaddr \
+ -Dfreehostent=res_freehostent \
+ -Dgetaddrinfo=res_getaddrinfo \
+ -Dfreeaddrinfo=res_freeaddrinfo
+
+CRYPTFLAGS= -DCYLINK_DSS -DHMAC_MD5 -DUSE_MD5 -DDNSSAFE
+
+LOCFLAGS += $(CRYPTFLAGS)
+LOCFLAGS += -D_SYS_STREAM_H -D_REENTRANT -DSVR4 -DSUNW_OPTIONS \
+ $(SOLCOMPAT) -I../include
+
+CPPFLAGS += $(LOCFLAGS)
+DYNFLAGS += $(MAPOPTS) $(ZNODELETE)
+LDLIBS += -lsocket -lnsl -lc
+
+.KEEP_STATE:
+
+lint: lintcheck
+
+$(DYNLIB): $(MAPFILES)
+
+$(MAPFILE):
+ @cd $(MAPDIR); $(MAKE) mapfile
+
+# include library targets
+include ../../Makefile.targ
+
+pics/%.o: ../common/bsd/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+pics/%.o: ../common/dst/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+pics/%.o: ../common/inet/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+pics/%.o: ../common/irs/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+pics/%.o: ../common/isc/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+pics/%.o: ../common/nameser/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+pics/%.o: ../common/resolv/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+pics/%.o: ../common/sunw/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+# install rule for lint library target
+$(ROOTLINTDIR)/%: ../common/%
+ $(INS.file)
diff --git a/usr/src/lib/libresolv2/amd64/Makefile b/usr/src/lib/libresolv2/amd64/Makefile
new file mode 100644
index 0000000000..682f635c8c
--- /dev/null
+++ b/usr/src/lib/libresolv2/amd64/Makefile
@@ -0,0 +1,19 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+MAPDIR= ../spec/amd64
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+LIBS = $(DYNLIB) $(LINTLIB)
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/libresolv2/client.xml b/usr/src/lib/libresolv2/client.xml
new file mode 100644
index 0000000000..e077e4f8fb
--- /dev/null
+++ b/usr/src/lib/libresolv2/client.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+ Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ Use is subject to license terms.
+
+ ident "%Z%%M% %I% %E% SMI"
+
+ NOTE: This service manifest is not editable; its contents will
+ be overwritten by package or patch operations, including
+ operating system upgrade. Make customizations in a different
+ file.
+-->
+
+<service_bundle type='manifest' name='SUNWcsr:dns-client'>
+
+<service
+ name='network/dns/client'
+ type='service'
+ version='1'>
+
+ <create_default_instance enabled='false' />
+
+ <single_instance />
+
+ <dependency
+ name='usr'
+ grouping='require_all'
+ restart_on='none'
+ type='service'>
+ <service_fmri value='svc:/system/filesystem/minimal' />
+ </dependency>
+
+ <!--
+ Wait for potential DHCP modification of resolv.conf.
+ -->
+ <dependency
+ name='net'
+ grouping='require_all'
+ restart_on='none'
+ type='service'>
+ <service_fmri value='svc:/network/service' />
+ </dependency>
+
+ <dependency
+ name='config_data'
+ grouping='require_all'
+ restart_on='none'
+ type='path'>
+ <service_fmri
+ value='file://localhost/etc/resolv.conf' />
+ </dependency>
+
+ <dependency
+ name='loopback'
+ grouping='require_any'
+ restart_on='error'
+ type='service'>
+ <service_fmri value='svc:/network/loopback' />
+ </dependency>
+
+ <dependency
+ name='network'
+ grouping='optional_all'
+ restart_on='error'
+ type='service'>
+ <service_fmri value='svc:/milestone/network' />
+ </dependency>
+
+ <exec_method
+ type='method'
+ name='start'
+ exec=':true'
+ timeout_seconds='10' />
+
+ <exec_method
+ type='method'
+ name='stop'
+ exec=':true'
+ timeout_seconds='10' />
+
+ <stability value='Unstable' />
+
+ <template>
+ <common_name>
+ <loctext xml:lang='C'>
+ DNS resolver
+ </loctext>
+ </common_name>
+ <documentation>
+ <manpage title='resolver' section='3RESOLV'
+ manpath='/usr/share/man' />
+ </documentation>
+ </template>
+
+</service>
+
+</service_bundle>
diff --git a/usr/src/lib/libresolv2/common/bsd/daemon.c b/usr/src/lib/libresolv2/common/bsd/daemon.c
new file mode 100644
index 0000000000..aeb4f2c083
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/bsd/daemon.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#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 8.2 1999/10/13 16:39:20 vixie 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+
+#include <fcntl.h>
+#include <paths.h>
+#include <unistd.h>
+
+#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/usr/src/lib/libresolv2/common/bsd/ftruncate.c b/usr/src/lib/libresolv2/common/bsd/ftruncate.c
new file mode 100644
index 0000000000..98b953b312
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/bsd/ftruncate.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef LINT
+static const char rcsid[] = "$Id: ftruncate.c,v 8.4 1999/10/13 16:39:21 vixie Exp $";
+#endif
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * 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 <stdio.h>
+#ifdef _XOPEN_SOURCE
+#undef _XOPEN_SOURCE
+#endif
+#ifdef _POSIX_SOURCE
+#undef _POSIX_SOURCE
+#endif
+
+#include <fcntl.h>
+
+#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/usr/src/lib/libresolv2/common/bsd/gettimeofday.c b/usr/src/lib/libresolv2/common/bsd/gettimeofday.c
new file mode 100644
index 0000000000..68b5ca39a0
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/bsd/gettimeofday.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef LINT
+static const char rcsid[] = "$Id: gettimeofday.c,v 8.4 1999/10/13 16:39:21 vixie Exp $";
+#endif
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+#include "port_after.h"
+
+#if !defined(NEED_GETTIMEOFDAY)
+int __bindcompat_gettimeofday;
+#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/usr/src/lib/libresolv2/common/bsd/mktemp.c b/usr/src/lib/libresolv2/common/bsd/mktemp.c
new file mode 100644
index 0000000000..b29ae93d51
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/bsd/mktemp.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#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 8.4 1999/10/13 16:39:21 vixie 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.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#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/usr/src/lib/libresolv2/common/bsd/putenv.c b/usr/src/lib/libresolv2/common/bsd/putenv.c
new file mode 100644
index 0000000000..08ef44463e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/bsd/putenv.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef LINT
+static const char rcsid[] = "$Id: putenv.c,v 8.4 1999/10/13 16:39:21 vixie Exp $";
+#endif
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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/usr/src/lib/libresolv2/common/bsd/readv.c b/usr/src/lib/libresolv2/common/bsd/readv.c
new file mode 100644
index 0000000000..5852e2e20a
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/bsd/readv.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef LINT
+static const char rcsid[] = "$Id: readv.c,v 8.2 1999/10/13 16:39:21 vixie Exp $";
+#endif
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#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/usr/src/lib/libresolv2/common/bsd/setenv.c b/usr/src/lib/libresolv2/common/bsd/setenv.c
new file mode 100644
index 0000000000..963d0e6e1b
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/bsd/setenv.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setenv.c 8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$Id: setenv.c,v 8.4 1997/04/24 22:00:38 vixie 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.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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/usr/src/lib/libresolv2/common/bsd/setitimer.c b/usr/src/lib/libresolv2/common/bsd/setitimer.c
new file mode 100644
index 0000000000..a0185c9c1d
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/bsd/setitimer.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef LINT
+static const char rcsid[] = "$Id: setitimer.c,v 8.4 1999/10/13 16:39:21 vixie Exp $";
+#endif
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+
+#include <sys/time.h>
+
+#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/usr/src/lib/libresolv2/common/bsd/strcasecmp.c b/usr/src/lib/libresolv2/common/bsd/strcasecmp.c
new file mode 100644
index 0000000000..69e71760f0
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/bsd/strcasecmp.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#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 8.5 1999/10/13 16:39:21 vixie 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.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/cdefs.h>
+
+#include <string.h>
+
+#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/usr/src/lib/libresolv2/common/bsd/strdup.c b/usr/src/lib/libresolv2/common/bsd/strdup.c
new file mode 100644
index 0000000000..d92ed9e91d
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/bsd/strdup.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+
+#include <stdlib.h>
+
+#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/usr/src/lib/libresolv2/common/bsd/strerror.c b/usr/src/lib/libresolv2/common/bsd/strerror.c
new file mode 100644
index 0000000000..4d650edfc1
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/bsd/strerror.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#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 8.7 2001/08/28 11:48:10 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <string.h>
+
+#include "port_after.h"
+
+#ifndef NEED_STRERROR
+int __strerror_unneeded__;
+#else
+
+#ifdef USE_SYSERROR_LIST
+extern int sys_nerr;
+extern char *sys_errlist[];
+#endif
+
+const char *
+isc_strerror(int num) {
+#define UPREFIX "Unknown error: "
+ static char ebuf[40] = UPREFIX; /* 64-bit number + slop */
+ u_int errnum;
+ char *p, *t;
+ const char *ret;
+ char tmp[40];
+
+ errnum = num; /* convert to unsigned */
+#ifdef USE_SYSERROR_LIST
+ if (errnum < sys_nerr)
+ return (sys_errlist[errnum]);
+#else
+#undef strerror
+ ret = strerror(num); /* call strerror() in libc */
+ if (ret != NULL)
+ return(ret);
+#endif
+
+ /* 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/usr/src/lib/libresolv2/common/bsd/strpbrk.c b/usr/src/lib/libresolv2/common/bsd/strpbrk.c
new file mode 100644
index 0000000000..d001f28d31
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/bsd/strpbrk.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#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 8.4 1999/10/13 16:39:21 vixie 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.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <sys/cdefs.h>
+
+#include <string.h>
+
+#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/usr/src/lib/libresolv2/common/bsd/strsep.c b/usr/src/lib/libresolv2/common/bsd/strsep.c
new file mode 100644
index 0000000000..bbbdf3bc75
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/bsd/strsep.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#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 8.5 1996/11/18 09:09:04 vixie 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+#include <sys/cdefs.h>
+#include <string.h>
+#include <stdio.h>
+#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/usr/src/lib/libresolv2/common/bsd/strtoul.c b/usr/src/lib/libresolv2/common/bsd/strtoul.c
new file mode 100644
index 0000000000..41e23c1124
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/bsd/strtoul.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2003 by Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#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 8.5 2002/07/06 02:35:04 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.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#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 = *(unsigned char *)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 = *(unsigned char*)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/usr/src/lib/libresolv2/common/bsd/utimes.c b/usr/src/lib/libresolv2/common/bsd/utimes.c
new file mode 100644
index 0000000000..8a461ddbd0
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/bsd/utimes.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <utime.h>
+
+#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/usr/src/lib/libresolv2/common/bsd/writev.c b/usr/src/lib/libresolv2/common/bsd/writev.c
new file mode 100644
index 0000000000..e3a97a0c39
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/bsd/writev.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2003 by Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef LINT
+static const char rcsid[] = "$Id: writev.c,v 8.6 2003/04/30 05:21:18 marka Exp $";
+#endif
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#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;
+
+ memset(&mesg, 0, sizeof(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/usr/src/lib/libresolv2/common/cylink/bits.c b/usr/src/lib/libresolv2/common/cylink/bits.c
new file mode 100644
index 0000000000..21cadf7a50
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bits.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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:
+*
+*
+****************************************************************************/
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/****************************************************************************
+* INCLUDE FILES
+****************************************************************************/
+/* bn files */
+#include "port_before.h"
+#include <sys/types.h>
+#include "bn.h"
+/* system files */
+#ifdef VXD
+#include <vtoolsc.h>
+#else
+#include <stdlib.h>
+#include <string.h>
+#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/usr/src/lib/libresolv2/common/cylink/bn.c b/usr/src/lib/libresolv2/common/cylink/bn.c
new file mode 100644
index 0000000000..8825e1dba6
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bn.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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/usr/src/lib/libresolv2/common/cylink/bn.h b/usr/src/lib/libresolv2/common/cylink/bn.h
new file mode 100644
index 0000000000..9246388117
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bn.h
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+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/usr/src/lib/libresolv2/common/cylink/bn00.c b/usr/src/lib/libresolv2/common/cylink/bn00.c
new file mode 100644
index 0000000000..affc76dc64
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bn00.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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/usr/src/lib/libresolv2/common/cylink/bn16.c b/usr/src/lib/libresolv2/common/cylink/bn16.c
new file mode 100644
index 0000000000..3afa8f4751
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bn16.c
@@ -0,0 +1,956 @@
+/*
+ * Copyright (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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 <assert.h>
+#else
+#define assert(x) (void)0
+#endif
+
+#if !NO_STRING_H
+#include <string.h> /* for memmove() in bnMakeOdd */
+#elif HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#if NEED_MEMORY_H
+#include <memory.h>
+#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 <port_after.h>
+
+/* 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 a<b, a == b or a>b.
+ * 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 a<b, a == b or a>b.
+ * 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/usr/src/lib/libresolv2/common/cylink/bn16.h b/usr/src/lib/libresolv2/common/cylink/bn16.h
new file mode 100644
index 0000000000..8f8402534e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bn16.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+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/usr/src/lib/libresolv2/common/cylink/bn32.c b/usr/src/lib/libresolv2/common/cylink/bn32.c
new file mode 100644
index 0000000000..449cb90567
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bn32.c
@@ -0,0 +1,956 @@
+/*
+ * Copyright (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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 <assert.h>
+#else
+#define assert(x) (void)0
+#endif
+
+#if !NO_STRING_H
+#include <string.h> /* for memmove() in bnMakeOdd */
+#elif HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#if NEED_MEMORY_H
+#include <memory.h>
+#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 <port_after.h>
+
+/* 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 a<b, a == b or a>b.
+ * 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 a<b, a == b or a>b.
+ * 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/usr/src/lib/libresolv2/common/cylink/bn32.h b/usr/src/lib/libresolv2/common/cylink/bn32.h
new file mode 100644
index 0000000000..d6bdc189f6
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bn32.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+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/usr/src/lib/libresolv2/common/cylink/bn68000.c b/usr/src/lib/libresolv2/common/cylink/bn68000.c
new file mode 100644
index 0000000000..91bcd1d7af
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bn68000.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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/usr/src/lib/libresolv2/common/cylink/bn8086.c b/usr/src/lib/libresolv2/common/cylink/bn8086.c
new file mode 100644
index 0000000000..b50aab6ad6
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bn8086.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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/usr/src/lib/libresolv2/common/cylink/bninit16.c b/usr/src/lib/libresolv2/common/cylink/bninit16.c
new file mode 100644
index 0000000000..efe5bd3475
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bninit16.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "bn.h"
+#include "bn16.h"
+
+void
+bnInit(void)
+{
+ bnInit_16();
+}
diff --git a/usr/src/lib/libresolv2/common/cylink/bninit32.c b/usr/src/lib/libresolv2/common/cylink/bninit32.c
new file mode 100644
index 0000000000..1f90d66780
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bninit32.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "bn.h"
+#include "bn32.h"
+
+void
+bnInit(void)
+{
+ bnInit_32();
+}
diff --git a/usr/src/lib/libresolv2/common/cylink/bnsize00.h b/usr/src/lib/libresolv2/common/cylink/bnsize00.h
new file mode 100644
index 0000000000..d59f9f40ff
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bnsize00.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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/usr/src/lib/libresolv2/common/cylink/c_asm.h b/usr/src/lib/libresolv2/common/cylink/c_asm.h
new file mode 100644
index 0000000000..c22bc614fb
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/c_asm.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#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/usr/src/lib/libresolv2/common/cylink/cencrint.h b/usr/src/lib/libresolv2/common/cylink/cencrint.h
new file mode 100644
index 0000000000..16adb10348
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/cencrint.h
@@ -0,0 +1,262 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/****************************************************************************
+* INCLUDE FILES
+****************************************************************************/
+
+/* system files */
+#include <sys/types.h>
+#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/usr/src/lib/libresolv2/common/cylink/ctk_endian.h b/usr/src/lib/libresolv2/common/cylink/ctk_endian.h
new file mode 100644
index 0000000000..1e5a27682f
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/ctk_endian.h
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <arpa/nameser_compat.h>
+#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 <limits.h> */
+# 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/usr/src/lib/libresolv2/common/cylink/ctk_prime.c b/usr/src/lib/libresolv2/common/cylink/ctk_prime.c
new file mode 100644
index 0000000000..45b576eb3f
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/ctk_prime.c
@@ -0,0 +1,442 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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:
+*
+*
+****************************************************************************/
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/****************************************************************************
+* INCLUDE FILES
+****************************************************************************/
+
+#include "port_before.h"
+#include <sys/types.h>
+#include "cylink.h"
+#include "ctk_endian.h"
+
+/* system files */
+#ifdef VXD
+#include <vtoolsc.h>
+#else
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#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/usr/src/lib/libresolv2/common/cylink/cylink.h b/usr/src/lib/libresolv2/common/cylink/cylink.h
new file mode 100644
index 0000000000..1ebbfbbd92
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/cylink.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/param.h>
+#if (!defined(BSD)) || (BSD < 199306)
+# include <sys/bitypes.h>
+#else
+# include <sys/types.h>
+#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
+#define NULL (void *) 0
+#endif
+
+#endif /* CYLINK_H */
diff --git a/usr/src/lib/libresolv2/common/cylink/dss.c b/usr/src/lib/libresolv2/common/cylink/dss.c
new file mode 100644
index 0000000000..fe907a6f21
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/dss.c
@@ -0,0 +1,1209 @@
+/*
+ * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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:
+*
+*
+****************************************************************************/
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/****************************************************************************
+* INCLUDE FILES
+****************************************************************************/
+
+#include "port_before.h"
+#include <sys/types.h>
+#include "cylink.h"
+#include "ctk_endian.h"
+
+/* system files */
+#ifdef VXD
+#include <vtoolsc.h>
+#else
+#include <stdlib.h>
+#include <string.h>
+#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/usr/src/lib/libresolv2/common/cylink/dssnum.h b/usr/src/lib/libresolv2/common/cylink/dssnum.h
new file mode 100644
index 0000000000..f46f08fe61
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/dssnum.h
@@ -0,0 +1,731 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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/usr/src/lib/libresolv2/common/cylink/kludge.h b/usr/src/lib/libresolv2/common/cylink/kludge.h
new file mode 100644
index 0000000000..7c85615e89
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/kludge.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * 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 <assert.h> needs "stderr" defined, and "exit" declared... */
+#ifdef assert
+#if ASSERT_NEEDS_STDIO
+#include <stdio.h>
+#endif
+#if ASSERT_NEEDS_STDLIB
+#if !NO_STDLIB_H
+#include <stdlib.h>
+#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 <stdio.h> 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/usr/src/lib/libresolv2/common/cylink/lbn.h b/usr/src/lib/libresolv2/common/cylink/lbn.h
new file mode 100644
index 0000000000..c0385c60cc
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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 <limits.h>
+#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 <limits.h> 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 <limits.h> 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/usr/src/lib/libresolv2/common/cylink/lbn00.c b/usr/src/lib/libresolv2/common/cylink/lbn00.c
new file mode 100644
index 0000000000..f6686d7b00
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn00.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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/usr/src/lib/libresolv2/common/cylink/lbn16.c b/usr/src/lib/libresolv2/common/cylink/lbn16.c
new file mode 100644
index 0000000000..938651d1d4
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn16.c
@@ -0,0 +1,3651 @@
+/*
+ * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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 <assert.h>
+#else
+#define assert(x) (void)0
+#endif
+
+#if !NO_STRING_H
+#include <string.h> /* For memcpy */
+#elif HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#if NEED_MEMORY_H
+#include <memory.h>
+#endif
+
+#include "lbn.h"
+#include "lbn16.h"
+#include "lbnmem.h"
+#include "legal.h"
+
+#include "kludge.h"
+#include <port_after.h>
+
+#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. <Marvin mode on> Thrilling, isn't it? </Marvin>
+ * 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<<shift) | carry;
+ LITTLE(num++;)
+ carry = 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<<elen;
+ return 0;
+ }
+
+ /* Set bitpos to the most significant bit */
+ bitpos = (BNWORD16)1 << ((bits-1) & (16-1));
+
+ /* Now, count the bits in the modulus. */
+ bits = lbnBits_16(mod, mlen);
+ assert(bits > 1); /* a 1-bit modulus is just stupid... */
+
+ /*
+ * We start with 1<<e, where "e" is as many high bits of the
+ * exponent as we can manage without going over the modulus.
+ * This first loop finds "e".
+ */
+ e = 1;
+ while (elen) {
+ /* Consume the first bit */
+ bitpos >>= 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/usr/src/lib/libresolv2/common/cylink/lbn16.h b/usr/src/lib/libresolv2/common/cylink/lbn16.h
new file mode 100644
index 0000000000..52e156886e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn16.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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/usr/src/lib/libresolv2/common/cylink/lbn32.c b/usr/src/lib/libresolv2/common/cylink/lbn32.c
new file mode 100644
index 0000000000..4cdfabf48e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn32.c
@@ -0,0 +1,3650 @@
+/*
+ * Copyright (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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 <assert.h>
+#else
+#define assert(x) (void)0
+#endif
+
+#if !NO_STRING_H
+#include <string.h> /* For memcpy */
+#elif HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#if NEED_MEMORY_H
+#include <memory.h>
+#endif
+
+#include "lbn.h"
+#include "lbn32.h"
+#include "lbnmem.h"
+#include "legal.h"
+
+#include "kludge.h"
+#include <port_after.h>
+
+#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. <Marvin mode on> Thrilling, isn't it? </Marvin>
+ * 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<<shift) | carry;
+ LITTLE(num++;)
+ carry = 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<<elen;
+ return 0;
+ }
+
+ /* Set bitpos to the most significant bit */
+ bitpos = (BNWORD32)1 << ((bits-1) & (32-1));
+
+ /* Now, count the bits in the modulus. */
+ bits = lbnBits_32(mod, mlen);
+ assert(bits > 1); /* a 1-bit modulus is just stupid... */
+
+ /*
+ * We start with 1<<e, where "e" is as many high bits of the
+ * exponent as we can manage without going over the modulus.
+ * This first loop finds "e".
+ */
+ e = 1;
+ while (elen) {
+ /* Consume the first bit */
+ bitpos >>= 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/usr/src/lib/libresolv2/common/cylink/lbn32.h b/usr/src/lib/libresolv2/common/cylink/lbn32.h
new file mode 100644
index 0000000000..d0347390c2
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn32.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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/usr/src/lib/libresolv2/common/cylink/lbn68000.c b/usr/src/lib/libresolv2/common/cylink/lbn68000.c
new file mode 100644
index 0000000000..96404d674f
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn68000.c
@@ -0,0 +1,507 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.)
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <limits.h>
+
+#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/usr/src/lib/libresolv2/common/cylink/lbn68000.h b/usr/src/lib/libresolv2/common/cylink/lbn68000.h
new file mode 100644
index 0000000000..ebd667d177
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn68000.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.)
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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 <lbn68020.h>
diff --git a/usr/src/lib/libresolv2/common/cylink/lbn68020.c b/usr/src/lib/libresolv2/common/cylink/lbn68020.c
new file mode 100644
index 0000000000..f3562a3463
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn68020.c
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.)
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <limits.h>
+
+#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/usr/src/lib/libresolv2/common/cylink/lbn68020.h b/usr/src/lib/libresolv2/common/cylink/lbn68020.h
new file mode 100644
index 0000000000..4aff67f5ed
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn68020.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.)
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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/usr/src/lib/libresolv2/common/cylink/lbn80386.h b/usr/src/lib/libresolv2/common/cylink/lbn80386.h
new file mode 100644
index 0000000000..10e10e10a5
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn80386.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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/usr/src/lib/libresolv2/common/cylink/lbn8086.h b/usr/src/lib/libresolv2/common/cylink/lbn8086.h
new file mode 100644
index 0000000000..be9c2fab27
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn8086.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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/usr/src/lib/libresolv2/common/cylink/lbnmem.c b/usr/src/lib/libresolv2/common/cylink/lbnmem.c
new file mode 100644
index 0000000000..ebb44a2aae
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbnmem.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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 <stdlib.h> /* For malloc() & co. */
+#else
+void *malloc();
+void *realloc();
+void free();
+#endif
+
+#if !NO_STRING_H
+#include <string.h> /* For memset */
+#elif HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#if NEED_MEMORY_H
+#include <memory.h>
+#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/usr/src/lib/libresolv2/common/cylink/lbnmem.h b/usr/src/lib/libresolv2/common/cylink/lbnmem.h
new file mode 100644
index 0000000000..8a86eeaf0e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbnmem.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * 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/usr/src/lib/libresolv2/common/cylink/lbnppc.c b/usr/src/lib/libresolv2/common/cylink/lbnppc.c
new file mode 100644
index 0000000000..15eef0e28e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbnppc.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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/usr/src/lib/libresolv2/common/cylink/lbnppc.h b/usr/src/lib/libresolv2/common/cylink/lbnppc.h
new file mode 100644
index 0000000000..1d9d6e5418
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbnppc.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#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.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * 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/usr/src/lib/libresolv2/common/cylink/legal.c b/usr/src/lib/libresolv2/common/cylink/legal.c
new file mode 100644
index 0000000000..09447c8d3c
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/legal.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* Force inclusion of this... */
+#include "legal.h"
+volatile const char bnCopyright[] =
+ "bnlib 1.0.1 Copyright (c) 1995,1996 Colin Plumb.";
diff --git a/usr/src/lib/libresolv2/common/cylink/legal.h b/usr/src/lib/libresolv2/common/cylink/legal.h
new file mode 100644
index 0000000000..49c7c163bd
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/legal.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * 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/usr/src/lib/libresolv2/common/cylink/math.c b/usr/src/lib/libresolv2/common/cylink/math.c
new file mode 100644
index 0000000000..4c7b0e6a5e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/math.c
@@ -0,0 +1,1158 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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 )
+*
+****************************************************************************/
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/****************************************************************************
+* INCLUDE FILES
+****************************************************************************/
+/* bn files */
+#include "port_before.h"
+#include "bn.h"
+/* system files */
+#ifdef VXD
+#include <vtoolsc.h>
+#else
+#include <stdlib.h>
+#include <string.h>
+#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/usr/src/lib/libresolv2/common/cylink/ppcasm.h b/usr/src/lib/libresolv2/common/cylink/ppcasm.h
new file mode 100644
index 0000000000..23e1b28341
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/ppcasm.h
@@ -0,0 +1,582 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * 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/usr/src/lib/libresolv2/common/cylink/rand.c b/usr/src/lib/libresolv2/common/cylink/rand.c
new file mode 100644
index 0000000000..b2b6d6f85b
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/rand.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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)
+*
+****************************************************************************/
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/****************************************************************************
+* INCLUDE FILES
+****************************************************************************/
+
+#include "port_before.h"
+
+/* system files */
+#ifdef VXD
+#include <vtoolsc.h>
+#else
+#include <stdlib.h>
+#include <string.h>
+#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/usr/src/lib/libresolv2/common/cylink/sha.c b/usr/src/lib/libresolv2/common/cylink/sha.c
new file mode 100644
index 0000000000..bc67fcac79
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/sha.c
@@ -0,0 +1,706 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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
+*
+****************************************************************************/
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/****************************************************************************
+* INCLUDE FILES
+****************************************************************************/
+
+#include "port_before.h"
+#include <sys/types.h>
+
+/* system files */
+#ifdef VXD
+#include <vtoolsc.h>
+#else
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#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*/
+ /* on28 port: silence compiler warnings by changing 0x...L to 0x...U */
+ hash_context->state[0] = 0xEFCDAB89U;
+ hash_context->state[1] = 0x98BADCFEU;
+ hash_context->state[2] = 0x10325476U;
+ hash_context->state[3] = 0xC3D2E1F0U;
+ hash_context->state[4] = 0x67452301U;
+/*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/usr/src/lib/libresolv2/common/cylink/sha.h b/usr/src/lib/libresolv2/common/cylink/sha.h
new file mode 100644
index 0000000000..8442b3bfab
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/sha.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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*/
+
+/*
+ * Note: for on28 port, and to silence compiler warnings when the value is
+ * larger than or equal to 0x80000000, change constants to be U rather
+ * than L.
+ */
+
+/*SHS Constants */
+#define k1SHA 0x5a827999U
+#define k2SHA 0x6ed9eba1U
+#define k3SHA 0x8f1bbcdcU
+#define k4SHA 0xca62c1d6U
+
+/*SHS initial value */
+#define h0SHA 0x67452301U
+#define h1SHA 0xefcdab89U
+#define h2SHA 0x98badcfeU
+#define h3SHA 0x10325476U
+#define h4SHA 0xc3d2e1f0U
+
+/*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/usr/src/lib/libresolv2/common/cylink/sizetest.c b/usr/src/lib/libresolv2/common/cylink/sizetest.c
new file mode 100644
index 0000000000..6fc9a9ee89
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/sizetest.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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/usr/src/lib/libresolv2/common/cylink/swap.c b/usr/src/lib/libresolv2/common/cylink/swap.c
new file mode 100644
index 0000000000..6e4f33b967
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/swap.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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 )
+*
+****************************************************************************/
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/****************************************************************************
+* INCLUDE FILES
+****************************************************************************/
+/* system files */
+
+#include "port_before.h"
+#ifdef VXD
+#include <vtoolsc.h>
+#else
+#include <stdlib.h>
+#include <string.h>
+#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/usr/src/lib/libresolv2/common/cylink/toolkit.h b/usr/src/lib/libresolv2/common/cylink/toolkit.h
new file mode 100644
index 0000000000..b9ba25ad57
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/toolkit.h
@@ -0,0 +1,399 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/README.copyright b/usr/src/lib/libresolv2/common/dnssafe/README.copyright
new file mode 100644
index 0000000000..bfbd0a4d3b
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/README.copyright
@@ -0,0 +1,51 @@
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+[The copyright in this file amends the "RSA Data Security, Inc." copyrights
+in the source files in this directory, according to an email from David R.
+Conrad, executive director at ISC, on 02/07/2000.]
+
+
+
+ DNSSAFE LICENSE TERMS
+
+This BIND software includes the DNSsafe software from RSA Data
+Security, Inc., which is copyrighted software that can only be
+distributed under the terms of this license agreement.
+
+The DNSsafe software cannot be used or distributed separately from the
+BIND software. You only have the right to use it or distribute it as
+a bundled, integrated product.
+
+The DNSsafe software can ONLY be used to provide authentication for
+resource records in the Domain Name System, as specified in RFC 2065
+and successors. You cannot modify the BIND software to use the
+DNSsafe software for other purposes, or to make its cryptographic
+functions available to end-users for other uses.
+
+If you modify the DNSsafe software itself, you cannot modify its
+documented API, and you must grant RSA Data Security the right to use,
+modify, and distribute your modifications, including the right to use
+any patents or other intellectual property that your modifications
+depend upon.
+
+You must not remove, alter, or destroy any of RSA's copyright notices
+or license information. When distributing the software to the Federal
+Government, it must be licensed to them as "commercial computer
+software" protected under 48 CFR 12.212 of the FAR, or 48 CFR
+227.7202.1 of the DFARS.
+
+You must not violate United States export control laws by distributing
+the DNSsafe software or information about it, when such distribution
+is prohibited by law.
+
+THE DNSSAFE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY
+WHATSOEVER. RSA HAS NO OBLIGATION TO SUPPORT, CORRECT, UPDATE OR
+MAINTAIN THE RSA SOFTWARE. RSA DISCLAIMS ALL WARRANTIES, EXPRESS,
+IMPLIED OR STATUTORY, AS TO ANY MATTER WHATSOEVER, INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY RIGHTS.
+
+If you desire to use DNSsafe in ways that these terms do not permit,
+please contact RSA Data Security, Inc., 100 Marine Parkway, Redwood
+City, California 94065, USA, to discuss alternate licensing
+arrangements.
diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahcbcpad.c b/usr/src/lib/libresolv2/common/dnssafe/ahcbcpad.c
new file mode 100644
index 0000000000..bfdfd048aa
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahcbcpad.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahcbcpad.h b/usr/src/lib/libresolv2/common/dnssafe/ahcbcpad.h
new file mode 100644
index 0000000000..e72a5d770c
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahcbcpad.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahchdig.c b/usr/src/lib/libresolv2/common/dnssafe/ahchdig.c
new file mode 100644
index 0000000000..574bdb8154
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahchdig.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahchdig.h b/usr/src/lib/libresolv2/common/dnssafe/ahchdig.h
new file mode 100644
index 0000000000..a80c3d208e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahchdig.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahchencr.c b/usr/src/lib/libresolv2/common/dnssafe/ahchencr.c
new file mode 100644
index 0000000000..6d339824fc
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahchencr.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahchencr.h b/usr/src/lib/libresolv2/common/dnssafe/ahchencr.h
new file mode 100644
index 0000000000..82e1a59244
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahchencr.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahchgen.c b/usr/src/lib/libresolv2/common/dnssafe/ahchgen.c
new file mode 100644
index 0000000000..c0e94a7c15
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahchgen.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahchgen.h b/usr/src/lib/libresolv2/common/dnssafe/ahchgen.h
new file mode 100644
index 0000000000..ec38f97714
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahchgen.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahchrand.c b/usr/src/lib/libresolv2/common/dnssafe/ahchrand.c
new file mode 100644
index 0000000000..caecaf5dd2
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahchrand.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahchrand.h b/usr/src/lib/libresolv2/common/dnssafe/ahchrand.h
new file mode 100644
index 0000000000..349a97fe25
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahchrand.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahdigest.c b/usr/src/lib/libresolv2/common/dnssafe/ahdigest.c
new file mode 100644
index 0000000000..a0fa71355f
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahdigest.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahdigest.h b/usr/src/lib/libresolv2/common/dnssafe/ahdigest.h
new file mode 100644
index 0000000000..2abe53d76b
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahdigest.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahencryp.c b/usr/src/lib/libresolv2/common/dnssafe/ahencryp.c
new file mode 100644
index 0000000000..a8874dccd6
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahencryp.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahencryp.h b/usr/src/lib/libresolv2/common/dnssafe/ahencryp.h
new file mode 100644
index 0000000000..d57b7ca9b7
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahencryp.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahgen.c b/usr/src/lib/libresolv2/common/dnssafe/ahgen.c
new file mode 100644
index 0000000000..a65763429b
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahgen.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahgen.h b/usr/src/lib/libresolv2/common/dnssafe/ahgen.h
new file mode 100644
index 0000000000..afe0ef3bf9
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahgen.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahrandom.c b/usr/src/lib/libresolv2/common/dnssafe/ahrandom.c
new file mode 100644
index 0000000000..9a31e9b817
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahrandom.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahrandom.h b/usr/src/lib/libresolv2/common/dnssafe/ahrandom.h
new file mode 100644
index 0000000000..fd566879e6
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahrandom.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahrsaenc.c b/usr/src/lib/libresolv2/common/dnssafe/ahrsaenc.c
new file mode 100644
index 0000000000..3a8894d2d4
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahrsaenc.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahrsaenc.h b/usr/src/lib/libresolv2/common/dnssafe/ahrsaenc.h
new file mode 100644
index 0000000000..5fa5f9be08
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahrsaenc.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahrsaepr.c b/usr/src/lib/libresolv2/common/dnssafe/ahrsaepr.c
new file mode 100644
index 0000000000..e5d6dad1c6
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahrsaepr.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahrsaepr.h b/usr/src/lib/libresolv2/common/dnssafe/ahrsaepr.h
new file mode 100644
index 0000000000..9820017939
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahrsaepr.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahrsaepu.c b/usr/src/lib/libresolv2/common/dnssafe/ahrsaepu.c
new file mode 100644
index 0000000000..40a6c8db35
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahrsaepu.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ahrsaepu.h b/usr/src/lib/libresolv2/common/dnssafe/ahrsaepu.h
new file mode 100644
index 0000000000..5f13415fdf
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ahrsaepu.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/aichdig.c b/usr/src/lib/libresolv2/common/dnssafe/aichdig.c
new file mode 100644
index 0000000000..6aa7043b99
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/aichdig.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/aichdig.h b/usr/src/lib/libresolv2/common/dnssafe/aichdig.h
new file mode 100644
index 0000000000..a7366e40b5
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/aichdig.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/aichenc8.c b/usr/src/lib/libresolv2/common/dnssafe/aichenc8.c
new file mode 100644
index 0000000000..42f869d8ee
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/aichenc8.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/aichenc8.h b/usr/src/lib/libresolv2/common/dnssafe/aichenc8.h
new file mode 100644
index 0000000000..59c6bf44d2
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/aichenc8.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/aichencn.c b/usr/src/lib/libresolv2/common/dnssafe/aichencn.c
new file mode 100644
index 0000000000..0dc2fb6650
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/aichencn.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/aichencn.h b/usr/src/lib/libresolv2/common/dnssafe/aichencn.h
new file mode 100644
index 0000000000..99af4ff8c7
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/aichencn.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/aichencr.c b/usr/src/lib/libresolv2/common/dnssafe/aichencr.c
new file mode 100644
index 0000000000..4e50087014
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/aichencr.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/aichencr.h b/usr/src/lib/libresolv2/common/dnssafe/aichencr.h
new file mode 100644
index 0000000000..7d67ab0e31
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/aichencr.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/aichgen.c b/usr/src/lib/libresolv2/common/dnssafe/aichgen.c
new file mode 100644
index 0000000000..f23a715026
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/aichgen.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/aichgen.h b/usr/src/lib/libresolv2/common/dnssafe/aichgen.h
new file mode 100644
index 0000000000..0b5e7086fa
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/aichgen.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/aichrand.c b/usr/src/lib/libresolv2/common/dnssafe/aichrand.c
new file mode 100644
index 0000000000..9c3ea6d9fd
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/aichrand.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/aichrand.h b/usr/src/lib/libresolv2/common/dnssafe/aichrand.h
new file mode 100644
index 0000000000..f36d7bfe7c
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/aichrand.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/aimd5.c b/usr/src/lib/libresolv2/common/dnssafe/aimd5.c
new file mode 100644
index 0000000000..8ac7c4d3f7
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/aimd5.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/aimd5ran.c b/usr/src/lib/libresolv2/common/dnssafe/aimd5ran.c
new file mode 100644
index 0000000000..c4ee058b0f
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/aimd5ran.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ainfotyp.c b/usr/src/lib/libresolv2/common/dnssafe/ainfotyp.c
new file mode 100644
index 0000000000..2b4f21d67b
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ainfotyp.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ainfotyp.h b/usr/src/lib/libresolv2/common/dnssafe/ainfotyp.h
new file mode 100644
index 0000000000..5a6bc782f3
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ainfotyp.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ainull.c b/usr/src/lib/libresolv2/common/dnssafe/ainull.c
new file mode 100644
index 0000000000..2879369730
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ainull.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ainull.h b/usr/src/lib/libresolv2/common/dnssafe/ainull.h
new file mode 100644
index 0000000000..c15b892f29
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ainull.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/airsaepr.c b/usr/src/lib/libresolv2/common/dnssafe/airsaepr.c
new file mode 100644
index 0000000000..328366e90b
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/airsaepr.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/airsaepu.c b/usr/src/lib/libresolv2/common/dnssafe/airsaepu.c
new file mode 100644
index 0000000000..1271220f7c
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/airsaepu.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/airsakgn.c b/usr/src/lib/libresolv2/common/dnssafe/airsakgn.c
new file mode 100644
index 0000000000..dfe450fe37
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/airsakgn.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/airsaprv.c b/usr/src/lib/libresolv2/common/dnssafe/airsaprv.c
new file mode 100644
index 0000000000..4aaa53b37b
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/airsaprv.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/airsapub.c b/usr/src/lib/libresolv2/common/dnssafe/airsapub.c
new file mode 100644
index 0000000000..f0aef24046
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/airsapub.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/algae.h b/usr/src/lib/libresolv2/common/dnssafe/algae.h
new file mode 100644
index 0000000000..0f66f796f0
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/algae.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/algchoic.c b/usr/src/lib/libresolv2/common/dnssafe/algchoic.c
new file mode 100644
index 0000000000..b444c41be6
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/algchoic.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/algchoic.h b/usr/src/lib/libresolv2/common/dnssafe/algchoic.h
new file mode 100644
index 0000000000..699b5dbe7d
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/algchoic.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/algobj.c b/usr/src/lib/libresolv2/common/dnssafe/algobj.c
new file mode 100644
index 0000000000..6be38586f9
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/algobj.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/algobj.h b/usr/src/lib/libresolv2/common/dnssafe/algobj.h
new file mode 100644
index 0000000000..a101e8f719
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/algobj.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/amcrte.c b/usr/src/lib/libresolv2/common/dnssafe/amcrte.c
new file mode 100644
index 0000000000..beb2c4555b
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/amcrte.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/amdigest.h b/usr/src/lib/libresolv2/common/dnssafe/amdigest.h
new file mode 100644
index 0000000000..f58f2e1fcf
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/amdigest.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/amencdec.h b/usr/src/lib/libresolv2/common/dnssafe/amencdec.h
new file mode 100644
index 0000000000..0cacf5236c
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/amencdec.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/amgen.h b/usr/src/lib/libresolv2/common/dnssafe/amgen.h
new file mode 100644
index 0000000000..dfc56deba5
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/amgen.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ammd5.c b/usr/src/lib/libresolv2/common/dnssafe/ammd5.c
new file mode 100644
index 0000000000..26c7503952
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ammd5.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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 amMD5Query PROTO_LIST ((unsigned int *, POINTER));
+static int amMD5Init PROTO_LIST ((POINTER, POINTER, A_SURRENDER_CTX*));
+static int amMD5Update PROTO_LIST
+ ((POINTER, const unsigned char *, unsigned int, A_SURRENDER_CTX*));
+static int amMD5Final PROTO_LIST
+ ((POINTER, unsigned char *, unsigned int *, unsigned int, A_SURRENDER_CTX*));
+static int amMD5GetMaxOutputLen PROTO_LIST ((POINTER, unsigned int *));
+
+static A_DIGEST_ALGA A_MD5_DIGEST = {
+ amMD5Query, amMD5Init, amMD5Update, amMD5Final, amMD5GetMaxOutputLen
+};
+
+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 amMD5Query (contextLen, params)
+unsigned int *contextLen;
+POINTER params;
+{
+UNUSED_ARG (params)
+
+ *contextLen = sizeof (A_MD5_CTX);
+ return (0);
+}
+
+/* Returns 0.
+ */
+static int amMD5Init (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 amMD5Update (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 amMD5Final
+ (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 amMD5GetMaxOutputLen (context, outputLen)
+POINTER context;
+unsigned int *outputLen;
+{
+UNUSED_ARG (context)
+
+ *outputLen = A_MD5_DIGEST_LEN;
+ return(0);
+}
diff --git a/usr/src/lib/libresolv2/common/dnssafe/ammd5r.c b/usr/src/lib/libresolv2/common/dnssafe/ammd5r.c
new file mode 100644
index 0000000000..10ffb58635
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ammd5r.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/amrandom.h b/usr/src/lib/libresolv2/common/dnssafe/amrandom.h
new file mode 100644
index 0000000000..2576e389c8
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/amrandom.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/amrkg.c b/usr/src/lib/libresolv2/common/dnssafe/amrkg.c
new file mode 100644
index 0000000000..7fe6905899
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/amrkg.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/amrsae.c b/usr/src/lib/libresolv2/common/dnssafe/amrsae.c
new file mode 100644
index 0000000000..01a26bef47
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/amrsae.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/atypes.h b/usr/src/lib/libresolv2/common/dnssafe/atypes.h
new file mode 100644
index 0000000000..8fbfeb6b27
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/atypes.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/balg.c b/usr/src/lib/libresolv2/common/dnssafe/balg.c
new file mode 100644
index 0000000000..0105aa2873
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/balg.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/balg.h b/usr/src/lib/libresolv2/common/dnssafe/balg.h
new file mode 100644
index 0000000000..8c2e2cfe26
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/balg.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/balgmeth.h b/usr/src/lib/libresolv2/common/dnssafe/balgmeth.h
new file mode 100644
index 0000000000..98ea56077c
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/balgmeth.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bgclrbit.c b/usr/src/lib/libresolv2/common/dnssafe/bgclrbit.c
new file mode 100644
index 0000000000..717e985a7c
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bgclrbit.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bgmdmpyx.c b/usr/src/lib/libresolv2/common/dnssafe/bgmdmpyx.c
new file mode 100644
index 0000000000..8c0bc71172
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bgmdmpyx.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bgmdsqx.c b/usr/src/lib/libresolv2/common/dnssafe/bgmdsqx.c
new file mode 100644
index 0000000000..f976aa7bbd
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bgmdsqx.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bgmodexp.c b/usr/src/lib/libresolv2/common/dnssafe/bgmodexp.c
new file mode 100644
index 0000000000..9ae08ec962
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bgmodexp.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bgpegcd.c b/usr/src/lib/libresolv2/common/dnssafe/bgpegcd.c
new file mode 100644
index 0000000000..ade4d386b6
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bgpegcd.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/big2exp.c b/usr/src/lib/libresolv2/common/dnssafe/big2exp.c
new file mode 100644
index 0000000000..b0422779d6
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/big2exp.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigabs.c b/usr/src/lib/libresolv2/common/dnssafe/bigabs.c
new file mode 100644
index 0000000000..f6a105988d
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigabs.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigacc.c b/usr/src/lib/libresolv2/common/dnssafe/bigacc.c
new file mode 100644
index 0000000000..06d68ab680
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigacc.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigarith.c b/usr/src/lib/libresolv2/common/dnssafe/bigarith.c
new file mode 100644
index 0000000000..adc1b0b194
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigarith.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigcmp.c b/usr/src/lib/libresolv2/common/dnssafe/bigcmp.c
new file mode 100644
index 0000000000..f4df4281f8
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigcmp.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigconst.c b/usr/src/lib/libresolv2/common/dnssafe/bigconst.c
new file mode 100644
index 0000000000..e4754cb60d
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigconst.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/biginv.c b/usr/src/lib/libresolv2/common/dnssafe/biginv.c
new file mode 100644
index 0000000000..92fee05ebf
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/biginv.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/biglen.c b/usr/src/lib/libresolv2/common/dnssafe/biglen.c
new file mode 100644
index 0000000000..8f5ffb0a32
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/biglen.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigmath.h b/usr/src/lib/libresolv2/common/dnssafe/bigmath.h
new file mode 100644
index 0000000000..1675046bc7
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigmath.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigmaxes.h b/usr/src/lib/libresolv2/common/dnssafe/bigmaxes.h
new file mode 100644
index 0000000000..4f803e6025
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigmaxes.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigmodx.c b/usr/src/lib/libresolv2/common/dnssafe/bigmodx.c
new file mode 100644
index 0000000000..a58f6cdaab
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigmodx.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigmpy.c b/usr/src/lib/libresolv2/common/dnssafe/bigmpy.c
new file mode 100644
index 0000000000..7ef2d16a85
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigmpy.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigpdiv.c b/usr/src/lib/libresolv2/common/dnssafe/bigpdiv.c
new file mode 100644
index 0000000000..0609f469ef
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigpdiv.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigpmpy.c b/usr/src/lib/libresolv2/common/dnssafe/bigpmpy.c
new file mode 100644
index 0000000000..5baa3e5884
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigpmpy.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigpmpyh.c b/usr/src/lib/libresolv2/common/dnssafe/bigpmpyh.c
new file mode 100644
index 0000000000..6e94d3cf11
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigpmpyh.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigpmpyl.c b/usr/src/lib/libresolv2/common/dnssafe/bigpmpyl.c
new file mode 100644
index 0000000000..b6bd3d7617
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigpmpyl.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigpsq.c b/usr/src/lib/libresolv2/common/dnssafe/bigpsq.c
new file mode 100644
index 0000000000..ee058e2c82
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigpsq.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigqrx.c b/usr/src/lib/libresolv2/common/dnssafe/bigqrx.c
new file mode 100644
index 0000000000..7614783715
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigqrx.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigsmod.c b/usr/src/lib/libresolv2/common/dnssafe/bigsmod.c
new file mode 100644
index 0000000000..8e44e84773
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigsmod.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigtocan.c b/usr/src/lib/libresolv2/common/dnssafe/bigtocan.c
new file mode 100644
index 0000000000..c3722323ab
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigtocan.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigu.c b/usr/src/lib/libresolv2/common/dnssafe/bigu.c
new file mode 100644
index 0000000000..d5cc036706
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigu.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bigunexp.c b/usr/src/lib/libresolv2/common/dnssafe/bigunexp.c
new file mode 100644
index 0000000000..14b5302740
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bigunexp.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/binfocsh.c b/usr/src/lib/libresolv2/common/dnssafe/binfocsh.c
new file mode 100644
index 0000000000..ffc04dd2f2
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/binfocsh.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/binfocsh.h b/usr/src/lib/libresolv2/common/dnssafe/binfocsh.h
new file mode 100644
index 0000000000..8600e4bcb1
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/binfocsh.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bkey.c b/usr/src/lib/libresolv2/common/dnssafe/bkey.c
new file mode 100644
index 0000000000..be9b547452
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bkey.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bkey.h b/usr/src/lib/libresolv2/common/dnssafe/bkey.h
new file mode 100644
index 0000000000..0d9d761068
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bkey.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bmempool.c b/usr/src/lib/libresolv2/common/dnssafe/bmempool.c
new file mode 100644
index 0000000000..e5d9ae28e0
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bmempool.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bmempool.h b/usr/src/lib/libresolv2/common/dnssafe/bmempool.h
new file mode 100644
index 0000000000..923a5f6967
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bmempool.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/bsafe2.h b/usr/src/lib/libresolv2/common/dnssafe/bsafe2.h
new file mode 100644
index 0000000000..1bae822a8a
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/bsafe2.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/btypechk.h b/usr/src/lib/libresolv2/common/dnssafe/btypechk.h
new file mode 100644
index 0000000000..328e5008e1
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/btypechk.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/cantobig.c b/usr/src/lib/libresolv2/common/dnssafe/cantobig.c
new file mode 100644
index 0000000000..b41c3d758a
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/cantobig.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/crt2.c b/usr/src/lib/libresolv2/common/dnssafe/crt2.c
new file mode 100644
index 0000000000..0428183591
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/crt2.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/crt2.h b/usr/src/lib/libresolv2/common/dnssafe/crt2.h
new file mode 100644
index 0000000000..c26d7bdacb
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/crt2.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/digest.c b/usr/src/lib/libresolv2/common/dnssafe/digest.c
new file mode 100644
index 0000000000..4394f579ec
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/digest.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/digrand.c b/usr/src/lib/libresolv2/common/dnssafe/digrand.c
new file mode 100644
index 0000000000..62ba5ba337
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/digrand.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/digrand.h b/usr/src/lib/libresolv2/common/dnssafe/digrand.h
new file mode 100644
index 0000000000..f93ea1d63a
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/digrand.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/encrypt.c b/usr/src/lib/libresolv2/common/dnssafe/encrypt.c
new file mode 100644
index 0000000000..71e34ea714
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/encrypt.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/generate.c b/usr/src/lib/libresolv2/common/dnssafe/generate.c
new file mode 100644
index 0000000000..f892ad60e9
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/generate.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/global.h b/usr/src/lib/libresolv2/common/dnssafe/global.h
new file mode 100644
index 0000000000..811ba42cc4
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/global.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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 <sys/types.h>
+#include <sys/param.h>
+#if (!defined(BSD)) || (BSD < 199306)
+# include <sys/bitypes.h>
+#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/usr/src/lib/libresolv2/common/dnssafe/intbits.c b/usr/src/lib/libresolv2/common/dnssafe/intbits.c
new file mode 100644
index 0000000000..6a213d30ee
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/intbits.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/intitem.c b/usr/src/lib/libresolv2/common/dnssafe/intitem.c
new file mode 100644
index 0000000000..8c8d0ce4aa
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/intitem.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/intitem.h b/usr/src/lib/libresolv2/common/dnssafe/intitem.h
new file mode 100644
index 0000000000..6da83ce8e8
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/intitem.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/keyobj.c b/usr/src/lib/libresolv2/common/dnssafe/keyobj.c
new file mode 100644
index 0000000000..9ac577d6de
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/keyobj.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/keyobj.h b/usr/src/lib/libresolv2/common/dnssafe/keyobj.h
new file mode 100644
index 0000000000..41ad52e7eb
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/keyobj.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ki8byte.c b/usr/src/lib/libresolv2/common/dnssafe/ki8byte.c
new file mode 100644
index 0000000000..8e6a069cfc
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ki8byte.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/ki8byte.h b/usr/src/lib/libresolv2/common/dnssafe/ki8byte.h
new file mode 100644
index 0000000000..197d3dcbe3
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/ki8byte.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/kifulprv.c b/usr/src/lib/libresolv2/common/dnssafe/kifulprv.c
new file mode 100644
index 0000000000..050f115e4a
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/kifulprv.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/kifulprv.h b/usr/src/lib/libresolv2/common/dnssafe/kifulprv.h
new file mode 100644
index 0000000000..55cdd8c666
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/kifulprv.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/kiitem.c b/usr/src/lib/libresolv2/common/dnssafe/kiitem.c
new file mode 100644
index 0000000000..3aaa80f358
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/kiitem.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/kiitem.h b/usr/src/lib/libresolv2/common/dnssafe/kiitem.h
new file mode 100644
index 0000000000..ad0863722f
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/kiitem.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/kinfotyp.c b/usr/src/lib/libresolv2/common/dnssafe/kinfotyp.c
new file mode 100644
index 0000000000..fba31dc2ba
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/kinfotyp.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/kinfotyp.h b/usr/src/lib/libresolv2/common/dnssafe/kinfotyp.h
new file mode 100644
index 0000000000..8de4f5e883
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/kinfotyp.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/kipkcrpr.c b/usr/src/lib/libresolv2/common/dnssafe/kipkcrpr.c
new file mode 100644
index 0000000000..e0d3ff523e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/kipkcrpr.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/kipkcrpr.h b/usr/src/lib/libresolv2/common/dnssafe/kipkcrpr.h
new file mode 100644
index 0000000000..f61de3ce97
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/kipkcrpr.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/kirsacrt.c b/usr/src/lib/libresolv2/common/dnssafe/kirsacrt.c
new file mode 100644
index 0000000000..269724d7e8
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/kirsacrt.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/kirsapub.c b/usr/src/lib/libresolv2/common/dnssafe/kirsapub.c
new file mode 100644
index 0000000000..22baff948b
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/kirsapub.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/kirsapub.h b/usr/src/lib/libresolv2/common/dnssafe/kirsapub.h
new file mode 100644
index 0000000000..0e26eb3666
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/kirsapub.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/md5.h b/usr/src/lib/libresolv2/common/dnssafe/md5.h
new file mode 100644
index 0000000000..1a1c963a61
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/md5.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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
+
+#ifndef SUNW_LIBMD5
+
+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 *));
+
+#else
+
+#include <sys/md5.h>
+#define A_MD5_CTX MD5_CTX
+#define A_MD5Init(c) MD5Init((c))
+#define A_MD5Update(c, d, l) MD5Update((c), (d), (l))
+#define A_MD5Final(c, d) MD5Final((d), (c))
+
+#endif /* SUNW_LIBMD5 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/usr/src/lib/libresolv2/common/dnssafe/md5rand.c b/usr/src/lib/libresolv2/common/dnssafe/md5rand.c
new file mode 100644
index 0000000000..d8e910ec15
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/md5rand.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/md5rand.h b/usr/src/lib/libresolv2/common/dnssafe/md5rand.h
new file mode 100644
index 0000000000..a181e147d7
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/md5rand.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/prime.c b/usr/src/lib/libresolv2/common/dnssafe/prime.c
new file mode 100644
index 0000000000..a1819813f7
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/prime.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/prime.h b/usr/src/lib/libresolv2/common/dnssafe/prime.h
new file mode 100644
index 0000000000..4d94667a3e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/prime.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/random.c b/usr/src/lib/libresolv2/common/dnssafe/random.c
new file mode 100644
index 0000000000..8126b76926
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/random.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/rsa.c b/usr/src/lib/libresolv2/common/dnssafe/rsa.c
new file mode 100644
index 0000000000..5aeea63ccb
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/rsa.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/rsa.h b/usr/src/lib/libresolv2/common/dnssafe/rsa.h
new file mode 100644
index 0000000000..986af82afb
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/rsa.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/rsakeygn.c b/usr/src/lib/libresolv2/common/dnssafe/rsakeygn.c
new file mode 100644
index 0000000000..010c1e2414
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/rsakeygn.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/rsakeygn.h b/usr/src/lib/libresolv2/common/dnssafe/rsakeygn.h
new file mode 100644
index 0000000000..714bcea412
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/rsakeygn.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/seccbcd.c b/usr/src/lib/libresolv2/common/dnssafe/seccbcd.c
new file mode 100644
index 0000000000..b88d6f9438
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/seccbcd.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/seccbce.c b/usr/src/lib/libresolv2/common/dnssafe/seccbce.c
new file mode 100644
index 0000000000..e388bd9c4b
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/seccbce.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/secrcbc.h b/usr/src/lib/libresolv2/common/dnssafe/secrcbc.h
new file mode 100644
index 0000000000..3eab2d5fe6
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/secrcbc.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/surrendr.c b/usr/src/lib/libresolv2/common/dnssafe/surrendr.c
new file mode 100644
index 0000000000..d353ee8de6
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/surrendr.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dnssafe/surrendr.h b/usr/src/lib/libresolv2/common/dnssafe/surrendr.h
new file mode 100644
index 0000000000..4c18f1c543
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dnssafe/surrendr.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/common/dst/bsafe_link.c b/usr/src/lib/libresolv2/common/dst/bsafe_link.c
new file mode 100644
index 0000000000..8a9fbdf312
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dst/bsafe_link.c
@@ -0,0 +1,1128 @@
+/*
+ * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(BSAFE) || defined(DNSSAFE)
+static const char rcsid[] = "$Header: /proj/cvs/isc/bind8/src/lib/dst/bsafe_link.c,v 1.15 2001/09/25 04:50:28 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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include "dst_internal.h"
+
+# ifdef __STDC__
+# define PROTOTYPES 1
+# else
+# define PROTOTYPES 0
+# endif
+
+# ifdef BSAFE
+# include <aglobal.h>
+# include <bsafe.h>
+# else
+# include <global.h>
+# include <bsafe2.h>
+# include <bigmaxes.h>
+# endif
+
+#include "port_after.h"
+
+typedef struct bsafekey {
+ char *rk_signer;
+ B_KEY_OBJ rk_Private_Key;
+ B_KEY_OBJ rk_Public_Key;
+} RSA_Key;
+
+#ifndef MAX_RSA_MODULUS_BITS
+#define MAX_RSA_MODULUS_BITS 4096
+#define MAX_RSA_MODULUS_LEN (MAX_RSA_MODULUS_BITS/8)
+#define MAX_RSA_PRIME_LEN (MAX_RSA_MODULUS_LEN/2)
+#endif
+
+#define NULL_SURRENDER (A_SURRENDER_CTX *)NULL_PTR
+#define NULL_RANDOM (B_ALGORITHM_OBJ)NULL_PTR
+
+B_ALGORITHM_METHOD *CHOOSER[] =
+{
+ &AM_MD5,
+ &AM_MD5_RANDOM,
+ &AM_RSA_KEY_GEN,
+ &AM_RSA_ENCRYPT,
+ &AM_RSA_DECRYPT,
+ &AM_RSA_CRT_ENCRYPT,
+ &AM_RSA_CRT_DECRYPT,
+ (B_ALGORITHM_METHOD *) NULL_PTR
+};
+
+static u_char pkcs1[] =
+{
+ 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00,
+ 0x04, 0x10
+};
+
+static int dst_bsafe_md5digest(const int mode, B_ALGORITHM_OBJ *digest_obj,
+ const u_char *data, const int len,
+ u_char *digest, const int digest_len);
+
+static int dst_bsafe_key_size(RSA_Key *r_key);
+
+static int dst_bsafe_sign(const int mode, DST_KEY *dkey, void **context,
+ const u_char *data, const int len,
+ u_char *signature, const int sig_len);
+static int dst_bsafe_verify(const int mode, DST_KEY *dkey, void **context,
+ const u_char *data, const int len,
+ const u_char *signature, const int sig_len);
+static int dst_bsafe_to_dns_key(const DST_KEY *in_key, u_char *out_str,
+ const int out_len);
+static int dst_bsafe_from_dns_key(DST_KEY *s_key, const u_char *key,
+ const int len);
+static int dst_bsafe_key_to_file_format(const DST_KEY *key, char *buff,
+ const int buff_len);
+static int dst_bsafe_key_from_file_format(DST_KEY *d_key,
+ const char *buff,
+ const int buff_len);
+static int dst_bsafe_generate_keypair(DST_KEY *key, int exp);
+static int dst_bsafe_compare_keys(const DST_KEY *key1, const DST_KEY *key2);
+static void *dst_bsafe_free_key_structure(void *key);
+
+/*
+ * dst_bsafe_init() Function to answer set up function pointers for
+ * BSAFE/DNSSAFE related functions
+ */
+int
+dst_bsafe_init(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_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);
+ 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);
+
+ 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 (0);
+}
+
+
+/*
+ * 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;
+
+ B_GetKeyInfo((POINTER *) &pk_access, public, KI_RSAPublic);
+ 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/usr/src/lib/libresolv2/common/dst/cylink_link.c b/usr/src/lib/libresolv2/common/dst/cylink_link.c
new file mode 100644
index 0000000000..d7ee3a8af4
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dst/cylink_link.c
@@ -0,0 +1,677 @@
+/*
+ * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef CYLINK_DSS
+static const char rcsid[] = "$Header: /proj/cvs/isc/bind8/src/lib/dst/cylink_link.c,v 1.9 2001/05/29 05:48:05 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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+
+#include "dst_internal.h"
+#include <toolkit.h>
+
+#include "port_after.h"
+
+typedef struct cylinkkey {
+ char *dk_signer;
+ uchar *dk_p;
+ uchar *dk_q;
+ uchar *dk_g;
+ uchar *dk_x;
+ uchar *dk_y;
+ ushort dk_p_bytes;
+} DSA_Key;
+
+#define NULL_PRIV_KEY(k)(k == NULL || k->dk_p == NULL || k->dk_q == NULL || \
+ k->dk_g == NULL || k->dk_x == NULL)
+#define NULL_PUB_KEY(k)(k == NULL || k->dk_p == NULL || k->dk_q == NULL || \
+ k->dk_g == NULL || k->dk_y == NULL)
+
+static int dst_cylink_sign(const int mode, DST_KEY *dkey, void **context,
+ const u_char *data, const int len,
+ u_char *signature, const int sig_len);
+
+static int dst_cylink_verify(const int mode, DST_KEY *dkey, void **context,
+ const u_char *data, const int len,
+ const u_char *signature, const int sig_len);
+
+static int dst_cylink_to_dns_key(const DST_KEY *in_key, u_char *out_str,
+ const int out_len);
+static int dst_cylink_from_dns_key(DST_KEY *s_key, const u_char *key,
+ const int len);
+static int dst_cylink_key_to_file_format(const DST_KEY *key, char *buff,
+ const int buff_len);
+static int dst_cylink_key_from_file_format(DST_KEY *d_key,
+ const char *buff,
+ const int buff_len);
+static void *dst_cylink_free_key_structure(void *key);
+
+static int dst_cylink_generate_keypair(DST_KEY *key, int exp);
+static int dst_cylink_compare_keys(const DST_KEY *key1, const DST_KEY *key2);
+
+static void *memcpyend(void *dest, const void *src, size_t n, size_t size);
+
+/*
+ * dst_cylink_init() Function to answer set up function pointers for
+ * CYLINK related functions
+ */
+int
+dst_cylink_init()
+{
+ if (dst_t_func[KEY_DSA] != NULL)
+ return (1);
+ dst_t_func[KEY_DSA] = malloc(sizeof(struct dst_func));
+ if (dst_t_func[KEY_DSA] == NULL)
+ return (0);
+ memset(dst_t_func[KEY_DSA], 0, sizeof(struct dst_func));
+ dst_t_func[KEY_DSA]->sign = dst_cylink_sign;
+ dst_t_func[KEY_DSA]->verify = dst_cylink_verify;
+ dst_t_func[KEY_DSA]->compare = dst_cylink_compare_keys;
+ dst_t_func[KEY_DSA]->generate = dst_cylink_generate_keypair;
+ dst_t_func[KEY_DSA]->destroy = dst_cylink_free_key_structure;
+ dst_t_func[KEY_DSA]->from_dns_key = dst_cylink_from_dns_key;
+ dst_t_func[KEY_DSA]->to_dns_key = dst_cylink_to_dns_key;
+ dst_t_func[KEY_DSA]->from_file_fmt = dst_cylink_key_from_file_format;
+ dst_t_func[KEY_DSA]->to_file_fmt = dst_cylink_key_to_file_format;
+ SetDataOrder(1);
+ return (1);
+}
+
+/*
+ * dst_cylink_sign
+ * Call CYLINK signing functions to sign a block of data.
+ * There are three steps to signing, INIT (initialize structures),
+ * UPDATE (hash (more) data), FINAL (generate a signature). This
+ * routine performs one or more of these steps.
+ * Parameters
+ * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
+ * algobj structure holds context for a sign done in multiple calls.
+ * context the context to use for this computation
+ * data data to be signed.
+ * len length in bytes of data.
+ * priv_key key to use for signing.
+ * signature location to store signature.
+ * sig_len size in bytes of signature field.
+ * returns
+ * N Success on SIG_MODE_FINAL = returns signature length in bytes
+ * N is 41 for DNS
+ * 0 Success on SIG_MODE_INIT and UPDATE
+ * <0 Failure
+ */
+
+static int
+dst_cylink_sign(const int mode, DST_KEY *dkey, void **context,
+ const u_char *data, const int len,
+ u_char *signature, const int sig_len)
+{
+ int sign_len = 0;
+ int status;
+ SHA_context *ctx = NULL;
+
+ if (mode & SIG_MODE_INIT)
+ ctx = (SHA_context *) malloc(sizeof(SHA_context));
+ else if (context)
+ ctx = (SHA_context *) *context;
+ if (ctx == NULL)
+ return (-1);
+
+ if (mode & SIG_MODE_INIT)
+ SHAInit(ctx);
+
+ if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) {
+ status = SHAUpdate(ctx, 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_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];
+ int len, s_len = sizeof(s);
+ 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;
+
+ return (0);
+}
+
+
+/**************************************************************************
+ * 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, n;
+ DSA_Key *dsa;
+ u_char rand[SHA_LENGTH];
+
+ 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;
+ 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/usr/src/lib/libresolv2/common/dst/dst_api.c b/usr/src/lib/libresolv2/common/dst/dst_api.c
new file mode 100644
index 0000000000..f074b4a2a0
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dst/dst_api.c
@@ -0,0 +1,1100 @@
+#ifndef LINT
+static const char rcsid[] = "$Header: /proj/cvs/isc/bind8/src/lib/dst/dst_api.c,v 1.21 2002/06/28 06:58:19 marka Exp $";
+#endif
+
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
+ *
+ * Permission to use, copy modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
+ */
+/*
+ * This file contains the interface between the DST API and the crypto API.
+ * This is the only file that needs to be changed if the crypto system is
+ * changed. Exported functions are:
+ * void dst_init() Initialize the toolkit
+ * int dst_check_algorithm() Function to determines if alg is suppored.
+ * int dst_compare_keys() Function to compare two keys for equality.
+ * int dst_sign_data() Incremental signing routine.
+ * int dst_verify_data() Incremental verify routine.
+ * int dst_generate_key() Function to generate new KEY
+ * DST_KEY *dst_read_key() Function to retrieve private/public KEY.
+ * void dst_write_key() Function to write out a key.
+ * DST_KEY *dst_dnskey_to_key() Function to convert DNS KEY RR to a DST
+ * KEY structure.
+ * int dst_key_to_dnskey() Function to return a public key in DNS
+ * format binary
+ * DST_KEY *dst_buffer_to_key() Converst a data in buffer to KEY
+ * int *dst_key_to_buffer() Writes out DST_KEY key matterial in buffer
+ * void dst_free_key() Releases all memory referenced by key structure
+ */
+
+#include "port_before.h"
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <memory.h>
+#include <ctype.h>
+#include <time.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include "dst_internal.h"
+#include "port_after.h"
+
+/* static variables */
+static int done_init = 0;
+dst_func *dst_t_func[DST_MAX_ALGS];
+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:
+ * K<key->dk_name>+<key->dk_alg>+<key->dk_id>.<private key suffix>.
+ * If there is already a file with this name, an error is returned.
+ *
+ * Parameters
+ * key A DST managed key structure that contains
+ * all information needed about a key.
+ * Return
+ * >= 0 Correct behavior. Returns length of encoded key value
+ * written to disk.
+ * < 0 error.
+ */
+
+static int
+dst_s_write_private_key(const DST_KEY *key)
+{
+ u_char encoded_block[RAW_KEY_SIZE];
+ char file[PATH_MAX];
+ int len;
+ FILE *fp;
+
+ /* First encode the key into the portable key format */
+ if (key == NULL)
+ return (-1);
+ if (key->dk_KEY_struct == NULL)
+ return (0); /* null key has no private key */
+
+ if (key->dk_func == NULL || key->dk_func->to_file_fmt == NULL) {
+ EREPORT(("dst_write_private_key(): Unsupported operation %d\n",
+ key->dk_alg));
+ return (-5);
+ } else if ((len = key->dk_func->to_file_fmt(key, (char *)encoded_block,
+ sizeof(encoded_block))) <= 0) {
+ EREPORT(("dst_write_private_key(): Failed encoding private RSA bsafe key %d\n", len));
+ return (-8);
+ }
+ /* Now I can create the file I want to use */
+ dst_s_build_filename(file, key->dk_key_name, key->dk_id, key->dk_alg,
+ PRIVATE_KEY, PATH_MAX);
+
+ /* Do not overwrite an existing file */
+ if ((fp = dst_s_fopen(file, "w", 0600)) != NULL) {
+ int nn;
+ if ((nn = fwrite(encoded_block, 1, len, fp)) != len) {
+ EREPORT(("dst_write_private_key(): Write failure on %s %d != %d errno=%d\n",
+ file, len, nn, errno));
+ return (-5);
+ }
+ fclose(fp);
+ } else {
+ EREPORT(("dst_write_private_key(): Can not create file %s\n"
+ ,file));
+ return (-6);
+ }
+ memset(encoded_block, 0, len);
+ return (len);
+}
+
+/*
+*
+ * dst_read_public_key
+ * Read a public key from disk and store in a DST key structure.
+ * Parameters
+ * in_name K<in_name><in_id>.<public key suffix> is the
+ * filename of the key file to be read.
+ * Returns
+ * NULL If the key does not exist or no name is supplied.
+ * NON-NULL Initialized key structure if the key exists.
+ */
+
+static DST_KEY *
+dst_s_read_public_key(const char *in_name, const u_int16_t in_id, int in_alg)
+{
+ int flags, proto, alg, len, dlen;
+ int c;
+ char name[PATH_MAX], enckey[RAW_KEY_SIZE], *notspace;
+ u_char deckey[RAW_KEY_SIZE];
+ FILE *fp;
+
+ if (in_name == NULL) {
+ EREPORT(("dst_read_public_key(): No key name given\n"));
+ return (NULL);
+ }
+ if (dst_s_build_filename(name, in_name, in_id, in_alg, PUBLIC_KEY,
+ PATH_MAX) == -1) {
+ EREPORT(("dst_read_public_key(): Cannot make filename from %s, %d, and %s\n",
+ in_name, in_id, PUBLIC_KEY));
+ return (NULL);
+ }
+ /*
+ * Open the file and read it's formatted contents up to key
+ * File format:
+ * domain.name [ttl] [IN] KEY <flags> <protocol> <algorithm> <key>
+ * flags, proto, alg stored as decimal (or hex numbers FIXME).
+ * (FIXME: handle parentheses for line continuation.)
+ */
+ if ((fp = dst_s_fopen(name, "r", 0)) == NULL) {
+ EREPORT(("dst_read_public_key(): Public Key not found %s\n",
+ name));
+ return (NULL);
+ }
+ /* Skip domain name, which ends at first blank */
+ while ((c = getc(fp)) != EOF)
+ if (isspace(c))
+ break;
+ /* Skip blank to get to next field */
+ while ((c = getc(fp)) != EOF)
+ if (!isspace(c))
+ break;
+
+ /* Skip optional TTL -- if initial digit, skip whole word. */
+ if (isdigit(c)) {
+ while ((c = getc(fp)) != EOF)
+ if (isspace(c))
+ break;
+ while ((c = getc(fp)) != EOF)
+ if (!isspace(c))
+ break;
+ }
+ /* Skip optional "IN" */
+ if (c == 'I' || c == 'i') {
+ while ((c = getc(fp)) != EOF)
+ if (isspace(c))
+ break;
+ while ((c = getc(fp)) != EOF)
+ if (!isspace(c))
+ break;
+ }
+ /* Locate and skip "KEY" */
+ if (c != 'K' && c != 'k') {
+ EREPORT(("\"KEY\" doesn't appear in file: %s", name));
+ return NULL;
+ }
+ while ((c = getc(fp)) != EOF)
+ if (isspace(c))
+ break;
+ while ((c = getc(fp)) != EOF)
+ if (!isspace(c))
+ break;
+ ungetc(c, fp); /* return the charcter to the input field */
+ /* Handle hex!! FIXME. */
+
+ if (fscanf(fp, "%d %d %d", &flags, &proto, &alg) != 3) {
+ EREPORT(("dst_read_public_key(): Can not read flag/proto/alg field from %s\n"
+ ,name));
+ return (NULL);
+ }
+ /* read in the key string */
+ fgets(enckey, sizeof(enckey), fp);
+
+ /* If we aren't at end-of-file, something is wrong. */
+ while ((c = getc(fp)) != EOF)
+ if (!isspace(c))
+ break;
+ if (!feof(fp)) {
+ EREPORT(("Key too long in file: %s", name));
+ return NULL;
+ }
+ fclose(fp);
+
+ if ((len = strlen(enckey)) <= 0)
+ return (NULL);
+
+ /* discard \n */
+ enckey[--len] = '\0';
+
+ /* remove leading spaces */
+ for (notspace = (char *) enckey; isspace((*notspace)&0xff); 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;
+ int mode;
+
+ 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);
+ }
+ /* XXX in general this should be a check for symmetric keys */
+ mode = (key->dk_alg == KEY_HMAC_MD5) ? 0600 : 0644;
+ /* create public key file */
+ if ((fp = dst_s_fopen(filename, "w+", mode)) == 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_id = dst_s_dns_key_id(rdata, len);
+ 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;
+ int dnslen;
+ u_char dns[2048];
+
+ 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)
+ return 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));
+ }
+
+ dnslen = dst_key_to_dnskey(dkey, dns, sizeof(dns));
+ dkey->dk_id = dst_s_dns_key_id(dns, dnslen);
+ return (dkey);
+}
+
+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 ret, id;
+ char filename[PATH_MAX];
+ u_char in_buff[RAW_KEY_SIZE], *p;
+ FILE *fp;
+ int dnslen;
+ u_char dns[2048];
+
+ 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;
+
+ ret = pk_key->dk_func->from_file_fmt(pk_key, (char *)p, &in_buff[len] - p);
+ if (ret < 0)
+ goto fail;
+
+ dnslen = dst_key_to_dnskey(pk_key, dns, sizeof(dns));
+ id = dst_s_dns_key_id(dns, dnslen);
+
+ /* Make sure the actual key tag matches the input tag used in the filename
+ */
+ if (id != in_id) {
+ EREPORT(("dst_s_read_private_key_file(): actual tag of key read %d != input tag used to build filename %d.\n", id, in_id));
+ goto fail;
+ }
+ pk_key->dk_id = (u_int16_t) id;
+ pk_key->dk_alg = alg;
+ memset(in_buff, 0, cnt);
+ return (1);
+
+ fail:
+ memset(in_buff, 0, cnt);
+ return (0);
+}
+
+
+/*
+ * dst_generate_key
+ * Generate and store a public/private keypair.
+ * Keys will be stored in formatted files.
+ * Parameters
+ * name Name of the new key. Used to create key files
+ * K<name>+<alg>+<id>.public and K<name>+<alg>+<id>.private.
+ * bits Size of the new key in bits.
+ * exp What exponent to use:
+ * 0 use exponent 3
+ * non-zero use Fermant4
+ * flags The default value of the DNS Key flags.
+ * The DNS Key RR Flag field is defined in RFC 2065,
+ * section 3.3. The field has 16 bits.
+ * protocol
+ * Default value of the DNS Key protocol field.
+ * The DNS Key protocol field is defined in RFC 2065,
+ * section 3.4. The field has 8 bits.
+ * alg What algorithm to use. Currently defined:
+ * KEY_RSA 1
+ * KEY_DSA 3
+ * KEY_HMAC 157
+ * out_id The key tag is returned.
+ *
+ * Return
+ * NULL Failure
+ * non-NULL the generated key pair
+ * Caller frees the result, and its dk_name pointer.
+ */
+DST_KEY *
+dst_generate_key(const char *name, const int bits, const int exp,
+ const int flags, const int protocol, const int alg)
+{
+ DST_KEY *new_key = NULL;
+ int res;
+ int dnslen;
+ u_char dns[2048];
+
+ 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));
+ }
+
+ dnslen = dst_key_to_dnskey(new_key, dns, sizeof(dns));
+ if (dnslen != UNSUPPORTED_KEYALG)
+ new_key->dk_id = dst_s_dns_key_id(dns, dnslen);
+ else
+ new_key->dk_id = 0;
+
+ 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/usr/src/lib/libresolv2/common/dst/dst_internal.h b/usr/src/lib/libresolv2/common/dst/dst_internal.h
new file mode 100644
index 0000000000..05f2c48bbc
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dst/dst_internal.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef DST_INTERNAL_H
+#define DST_INTERNAL_H
+
+/*
+ * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
+ *
+ * Permission to use, copy modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
+ */
+#include <limits.h>
+#include <sys/param.h>
+#if (!defined(BSD)) || (BSD < 199306)
+# include <sys/bitypes.h>
+#else
+# include <sys/types.h>
+#endif
+
+#ifndef PATH_MAX
+# ifdef POSIX_PATH_MAX
+# define PATH_MAX POSIX_PATH_MAX
+# else
+# define PATH_MAX 255 /* this is the value of POSIX_PATH_MAX */
+# endif
+#endif
+
+typedef struct dst_key {
+ char *dk_key_name; /* name of the key */
+ int dk_key_size; /* this is the size of the key in bits */
+ int dk_proto; /* what protocols this key can be used for */
+ int dk_alg; /* algorithm number from key record */
+ u_int32_t dk_flags; /* and the flags of the public key */
+ u_int16_t dk_id; /* identifier of the key */
+ void *dk_KEY_struct; /* pointer to key in crypto pkg fmt */
+ struct dst_func *dk_func; /* point to cryptto pgk specific function table */
+} DST_KEY;
+#define HAS_DST_KEY
+
+#include <isc/dst.h>
+/*
+ * define what crypto systems are supported for RSA,
+ * BSAFE is prefered over RSAREF; only one can be set at any time
+ */
+#if defined(BSAFE) && defined(RSAREF)
+# error "Cannot have both BSAFE and RSAREF defined"
+#endif
+
+/* Declare dst_lib specific constants */
+#define KEY_FILE_FORMAT "1.2"
+
+/* suffixes for key file names */
+#define PRIVATE_KEY "private"
+#define PUBLIC_KEY "key"
+
+/* error handling */
+#ifdef REPORT_ERRORS
+#define EREPORT(str) printf str
+#else
+#define EREPORT(str) (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/usr/src/lib/libresolv2/common/dst/eay_dss_link.c b/usr/src/lib/libresolv2/common/dst/eay_dss_link.c
new file mode 100644
index 0000000000..5216010cd2
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dst/eay_dss_link.c
@@ -0,0 +1,637 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef EAY_DSS
+static const char rcsid[] = "$Header: /proj/cvs/isc/bind8/src/lib/dst/eay_dss_link.c,v 1.6 2001/05/29 05:48:09 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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+
+#include "dst_internal.h"
+
+#include "crypto.h"
+#include "bn.h"
+#include "dsa.h"
+#include "sha.h"
+
+#include "port_after.h"
+
+
+static int dst_eay_dss_sign(const int mode, DST_KEY *dkey, void **context,
+ const u_char *data, const int len,
+ u_char *signature, const int sig_len);
+
+static int dst_eay_dss_verify(const int mode, DST_KEY *dkey, void **context,
+ const u_char *data, const int len,
+ const u_char *signature, const int sig_len);
+
+static int dst_eay_dss_to_dns_key(const DST_KEY *in_key, u_char *out_str,
+ const int out_len);
+static int dst_eay_dss_from_dns_key(DST_KEY *s_key, const u_char *key,
+ const int len);
+static int dst_eay_dss_key_to_file_format(const DST_KEY *key, u_char *buff,
+ const int buff_len);
+static int dst_eay_dss_key_from_file_format(DST_KEY *d_key,
+ const u_char *buff,
+ const int buff_len);
+static void *dst_eay_dss_free_key_structure(void *key);
+
+static int dst_eay_dss_generate_keypair(DST_KEY *key, int exp);
+static int dst_eay_dss_compare_keys(const DST_KEY *key1, const DST_KEY *key2);
+
+/*
+ * dst_eay_dss_init() Function to answer set up function pointers for
+ * EAY DSS related functions
+ */
+int
+dst_eay_dss_init(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_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];
+ int len, s_len = sizeof(s);
+ 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);
+
+ return (0);
+}
+
+
+/**************************************************************************
+ * 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, n;
+ DSA *dsa;
+ u_char rand[SHA_DIGEST_LENGTH];
+
+ 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;
+ 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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+
+#include "dst_internal.h"
+#include "port_after.h"
+int
+dst_eay_dss_init(void)
+{
+ return (0);
+}
+#endif /* EAY_DSS */
diff --git a/usr/src/lib/libresolv2/common/dst/hmac_link.c b/usr/src/lib/libresolv2/common/dst/hmac_link.c
new file mode 100644
index 0000000000..77269667c2
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dst/hmac_link.c
@@ -0,0 +1,510 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef HMAC_MD5
+#ifndef LINT
+static const char rcsid[] = "$Header: /proj/cvs/isc/bind8/src/lib/dst/hmac_link.c,v 1.9 2001/05/29 05:48:10 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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include "dst_internal.h"
+#ifdef USE_MD5
+#ifndef SUNW_LIBMD5
+# include "md5.h"
+#else
+#include <sys/md5.h>
+#endif
+# 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
+#ifdef ORIGINAL_ISC_CODE
+dst_hmac_md5_init()
+#else
+dst_md5_hmac_init()
+#endif
+{
+ 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/usr/src/lib/libresolv2/common/dst/prandom.c b/usr/src/lib/libresolv2/common/dst/prandom.c
new file mode 100644
index 0000000000..0a4fd7d79e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dst/prandom.c
@@ -0,0 +1,860 @@
+#ifndef LINT
+static const char rcsid[] = "$Header: /proj/cvs/isc/bind8/src/lib/dst/prandom.c,v 1.12 2001/07/26 01:20:09 marka Exp $";
+#endif
+/*
+ * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * 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 <assert.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <dirent.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include "dst_internal.h"
+#include "prand_conf.h"
+
+#include "port_after.h"
+
+#ifndef DST_NUM_HASHES
+#define DST_NUM_HASHES 4
+#endif
+#ifndef DST_NUMBER_OF_COUNTERS
+#define DST_NUMBER_OF_COUNTERS 5 /* 32 * 5 == 160 == SHA(1) > MD5 */
+#endif
+
+/*
+ * the constant below is a prime number to make fixed data structues like
+ * stat and time wrap over blocks. This adds certain uncertanty to what is
+ * in each digested block.
+ * The prime number 2879 has the special property that when
+ * divided by 2,4 and 6 the result is also a prime numbers
+ */
+
+#ifndef DST_RANDOM_BLOCK_SIZE
+#define DST_RANDOM_BLOCK_SIZE 2879
+#endif
+
+/*
+ * This constant dictatates how many bits we shift to the right before using a
+ */
+#ifndef DST_SHIFT
+#define DST_SHIFT 9
+#endif
+
+/*
+ * An initalizer that is as bad as any other with half the bits set
+ */
+#ifndef DST_RANDOM_PATTERN
+#define DST_RANDOM_PATTERN 0x8765CA93
+#endif
+/*
+ * things must have changed in the last 3600 seconds to be used
+ */
+#define MAX_OLD 3600
+
+
+/*
+ * these two data structure are used to process input data into digests,
+ *
+ * The first structure is containts a pointer to a DST HMAC key
+ * the variables accompanying are used for
+ * step : select every step byte from input data for the hash
+ * block: number of data elements going into each hash
+ * digested: number of data elements digested so far
+ * curr: offset into the next input data for the first byte.
+ */
+typedef struct hash {
+ DST_KEY *key;
+ void *ctx;
+ int digested, block, step, curr;
+} prand_hash;
+
+/*
+ * This data structure controlls number of hashes and keeps track of
+ * overall progress in generating correct number of bytes of output.
+ * output : array to store the output data in
+ * needed : how many bytes of output are needed
+ * filled : number of bytes in output so far.
+ * bytes : total number of bytes processed by this structure
+ * file_digest : the HMAC key used to digest files.
+ */
+typedef struct work {
+ int needed, filled, bytes;
+ u_char *output;
+ prand_hash *hash[DST_NUM_HASHES];
+ DST_KEY *file_digest;
+} dst_work;
+
+
+/*
+ * forward function declarations
+ */
+static int get_dev_random(u_char *output, int size);
+static int do_time(dst_work *work);
+static int do_ls(dst_work *work);
+static int unix_cmd(dst_work *work);
+static int digest_file(dst_work *work);
+
+static void force_hash(dst_work *work, prand_hash *hash);
+static int do_hash(dst_work *work, prand_hash *hash, 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\n", i-1, work->filled));
+ 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\n", cmd_index, work->filled));
+ 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 f %6d\n",
+ ran_val, bytes, work->filled));
+/* pick a random number in the range of 0..7 based on that random number
+ * perform some operations that yield random data
+ */
+ start = work->filled;
+ n = (dst_s_quick_random(bytes) >> DST_SHIFT) & 0x07;
+ switch (n) {
+ case 0:
+ case 3:
+ if (sizeof(cmds) > 2 *sizeof(*cmds)) {
+ b = unix_cmd(work);
+ cmd += b;
+ }
+ break;
+
+ case 1:
+ case 7:
+ if (sizeof(dirs) > 2 *sizeof(*dirs)) {
+ b = do_ls(work);
+ dir += b;
+ }
+ break;
+
+ case 4:
+ case 5:
+ /* retry getting data from /dev/random */
+ b = get_dev_random(&work->output[work->filled],
+ work->needed - work->filled);
+ if (b > 0)
+ work->filled += b;
+ break;
+
+ case 6:
+ if (sizeof(files) > 2 * sizeof(*files)) {
+ b = digest_file(work);
+ dig += b;
+ }
+ break;
+
+ case 2:
+ default: /* to make sure we make some progress */
+ work->output[work->filled++] = 0xff &
+ dst_s_quick_random(bytes);
+ b = 1;
+ break;
+ }
+ if (b > 0)
+ bytes += b;
+ }
+ return (work->filled);
+}
+
+
+/*
+ * dst_s_random() This function will return the requested number of bytes
+ * of randomness to the caller it will use the best available sources of
+ * randomness.
+ * The current order is to use /dev/random, precalculated randomness, and
+ * finaly use some system calls and programs to generate semi random data that
+ * is then digested to generate randomness.
+ * This function is thread safe as each thread uses its own context, but
+ * concurrent treads will affect each other as they update shared state
+ * information.
+ * It is strongly recommended that this function be called requesting a size
+ * that is not a multiple of the output of the hash function used.
+ *
+ * If /dev/random is not available this function is not suitable to generate
+ * large ammounts of data, rather it is suitable to seed a pseudo-random
+ * generator
+ * Returns the number of bytes put in the output buffer
+ */
+int
+dst_s_random(u_char *output, int size)
+{
+ int n = 0, s, i;
+ static u_char old_unused[DST_HASH_SIZE * DST_NUM_HASHES];
+ static int unused = 0;
+
+ if (size <= 0 || output == NULL)
+ return (0);
+
+ if (size >= 2048)
+ return (-1);
+ /*
+ * Read from /dev/random
+ */
+ n = get_dev_random(output, size);
+ /*
+ * If old data is available and needed use it
+ */
+ if (n < size && unused > 0) {
+ int need = size - n;
+ if (unused <= need) {
+ memcpy(output, old_unused, unused);
+ n += unused;
+ unused = 0;
+ } else {
+ memcpy(output, old_unused, need);
+ n += need;
+ unused -= need;
+ memcpy(old_unused, &old_unused[need], unused);
+ }
+ }
+ /*
+ * If we need more use the simulated randomness here.
+ */
+ if (n < size) {
+ dst_work *my_work = (dst_work *) malloc(sizeof(dst_work));
+ if (my_work == NULL)
+ return (n);
+ my_work->needed = size - n;
+ my_work->filled = 0;
+ my_work->output = (u_char *) malloc(my_work->needed +
+ DST_HASH_SIZE *
+ DST_NUM_HASHES);
+ my_work->file_digest = NULL;
+ if (my_work->output == NULL)
+ return (n);
+ memset(my_work->output, 0x0, my_work->needed);
+/* allocate upto 4 different HMAC hash functions out of order */
+#if DST_NUM_HASHES >= 3
+ my_work->hash[2] = get_hmac_key(3, DST_RANDOM_BLOCK_SIZE / 2);
+#endif
+#if DST_NUM_HASHES >= 2
+ my_work->hash[1] = get_hmac_key(7, DST_RANDOM_BLOCK_SIZE / 6);
+#endif
+#if DST_NUM_HASHES >= 4
+ my_work->hash[3] = get_hmac_key(5, DST_RANDOM_BLOCK_SIZE / 4);
+#endif
+ my_work->hash[0] = get_hmac_key(1, DST_RANDOM_BLOCK_SIZE);
+ if (my_work->hash[0] == NULL) /* if failure bail out */
+ return (n);
+ s = own_random(my_work);
+/* if more generated than needed store it for future use */
+ if (s >= my_work->needed) {
+ EREPORT(("dst_s_random(): More than needed %d >= %d\n",
+ s, my_work->needed));
+ memcpy(&output[n], my_work->output, my_work->needed);
+ n += my_work->needed;
+ /* saving unused data for next time */
+ unused = s - my_work->needed;
+ memcpy(old_unused, &my_work->output[my_work->needed],
+ unused);
+ } else {
+ /* XXXX This should not happen */
+ EREPORT(("Not enough %d >= %d\n", s, my_work->needed));
+ memcpy(&output[n], my_work->output, s);
+ n += my_work->needed;
+ }
+
+/* delete the allocated work area */
+ for (i = 0; i < DST_NUM_HASHES; i++) {
+ dst_free_key(my_work->hash[i]->key);
+ SAFE_FREE(my_work->hash[i]);
+ }
+ SAFE_FREE(my_work->output);
+ SAFE_FREE(my_work);
+ }
+ return (n);
+}
+
+/*
+ * A random number generator that is fast and strong
+ * this random number generator is based on HASHing data,
+ * the input to the digest function is a collection of <NUMBER_OF_COUNTERS>
+ * counters that is incremented between digest operations
+ * each increment operation amortizes to 2 bits changed in that value
+ * for 5 counters thus the input will amortize to have 10 bits changed
+ * The counters are initaly set using the strong random function above
+ * the HMAC key is selected by the same methold as the HMAC keys for the
+ * strong random function.
+ * Each set of counters is used for 2^25 operations
+ *
+ * returns the number of bytes written to the output buffer
+ * or negative number in case of error
+ */
+int
+dst_s_semi_random(u_char *output, int size)
+{
+ static u_int32_t counter[DST_NUMBER_OF_COUNTERS];
+ static u_char semi_old[DST_HASH_SIZE];
+ static int semi_loc = 0, cnt = 0, hb_size = 0;
+ static DST_KEY *my_key = NULL;
+ prand_hash *hash;
+ int out = 0, i, n;
+
+ if (output == NULL || size <= 0)
+ return (-2);
+
+/* check if we need a new key */
+ if (my_key == NULL || cnt > (1 << 25)) { /* get HMAC KEY */
+ if (my_key)
+ my_key->dk_func->destroy(my_key);
+ if ((hash = get_hmac_key(1, DST_RANDOM_BLOCK_SIZE)) == NULL)
+ return (0);
+ my_key = hash->key;
+/* check if the key works stir the new key using some old random data */
+ hb_size = dst_sign_data(SIG_MODE_ALL, my_key, NULL,
+ (u_char *) counter, sizeof(counter),
+ semi_old, sizeof(semi_old));
+ if (hb_size <= 0) {
+ EREPORT(("dst_s_semi_random() Sign of alg %d failed %d\n",
+ my_key->dk_alg, hb_size));
+ return (-1);
+ }
+/* new set the counters to random values */
+ dst_s_random((u_char *) counter, sizeof(counter));
+ cnt = 0;
+ }
+/* if old data around use it first */
+ if (semi_loc < hb_size) {
+ if (size <= hb_size - semi_loc) { /* need less */
+ memcpy(output, &semi_old[semi_loc], size);
+ semi_loc += size;
+ return (size); /* DONE */
+ } else {
+ out = hb_size - semi_loc;
+ memcpy(output, &semi_old[semi_loc], out);
+ semi_loc += out;
+ }
+ }
+/* generate more randome stuff */
+ while (out < size) {
+ /*
+ * modify at least one bit by incrementing at least one counter
+ * based on the last bit of the last counter updated update
+ * the next one.
+ * minimaly this operation will modify at least 1 bit,
+ * amortized 2 bits
+ */
+ for (n = 0; n < DST_NUMBER_OF_COUNTERS; n++)
+ i = (int) counter[n]++;
+
+ i = dst_sign_data(SIG_MODE_ALL, my_key, NULL,
+ (u_char *) counter, hb_size,
+ semi_old, sizeof(semi_old));
+#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/usr/src/lib/libresolv2/common/dst/rsaref_link.c b/usr/src/lib/libresolv2/common/dst/rsaref_link.c
new file mode 100644
index 0000000000..b18d694825
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dst/rsaref_link.c
@@ -0,0 +1,768 @@
+/*
+ * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef RSAREF
+static const char rcsid[] = "$Header: /proj/cvs/isc/bind8/src/lib/dst/rsaref_link.c,v 1.10 2001/05/29 05:48:15 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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+
+#include "dst_internal.h"
+
+# ifdef __STDC__
+# define PROTOTYPES 1
+# else
+# define PROTOTYPES 0
+# endif
+
+# include <global.h>
+# include <rsaref.h>
+
+#include "port_after.h"
+
+
+typedef struct rsakey {
+ char *rk_signer;
+ R_RSA_PRIVATE_KEY *rk_Private_Key;
+ R_RSA_PUBLIC_KEY *rk_Public_Key;
+} RSA_Key;
+
+
+static int dst_rsaref_sign(const int mode, DST_KEY *key, void **context,
+ const u_char *data, const int len,
+ u_char *signature, const int sig_len);
+static int dst_rsaref_verify(const int mode, DST_KEY *key, void **context,
+ const u_char *data, const int len,
+ const u_char *signature, const int sig_len);
+
+static int dst_rsaref_to_dns_key(const DST_KEY *public, u_char *out_str,
+ const int out_len);
+static int dst_rsaref_from_dns_key(DST_KEY *s_key, const u_char *key,
+ const int len);
+
+static int dst_rsaref_key_to_file_format(const DST_KEY *dkey,
+ u_char *buff,
+ const int buff_len);
+static int dst_rsaref_key_from_file_format(DST_KEY *dkey,
+ const u_char *buff,
+ const int buff_len);
+
+static int dst_rsaref_compare_keys(const DST_KEY *rkey1,
+ const DST_KEY *rkey2);
+static void *dst_rsaref_free_key_structure(void *d_key);
+
+static int dst_rsaref_generate_keypair(DST_KEY *key, const int exp);
+
+static void dst_rsaref_init_random_struct(R_RANDOM_STRUCT * randomstruct);
+
+/*
+ * dst_rsaref_init() Function to answer set up function pointers for RSAREF
+ * related functions
+ */
+int
+dst_rsaref_init()
+{
+ if (dst_t_func[KEY_RSA] != NULL)
+ return (1);
+ dst_t_func[KEY_RSA] = malloc(sizeof(struct dst_func));
+ if (dst_t_func[KEY_RSA] == NULL)
+ return (0);
+ memset(dst_t_func[KEY_RSA], 0, sizeof(struct dst_func));
+ dst_t_func[KEY_RSA]->sign = dst_rsaref_sign;
+ dst_t_func[KEY_RSA]->verify = dst_rsaref_verify;
+ dst_t_func[KEY_RSA]->compare = dst_rsaref_compare_keys;
+ dst_t_func[KEY_RSA]->generate = dst_rsaref_generate_keypair;
+ dst_t_func[KEY_RSA]->destroy = dst_rsaref_free_key_structure;
+ dst_t_func[KEY_RSA]->to_dns_key = dst_rsaref_to_dns_key;
+ dst_t_func[KEY_RSA]->from_dns_key = dst_rsaref_from_dns_key;
+ dst_t_func[KEY_RSA]->to_file_fmt = dst_rsaref_key_to_file_format;
+ dst_t_func[KEY_RSA]->from_file_fmt = dst_rsaref_key_from_file_format;
+ return (1);
+}
+
+/*
+ * dst_rsa_sign
+ * Call RSAREF signing functions to sign a block of data.
+ * There are three steps to signing, INIT (initialize structures),
+ * UPDATE (hash (more) data), FINAL (generate a signature). This
+ * routine performs one or more of these steps.
+ * Parameters
+ * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
+ * key pointer to a RSA key structure that points to public key
+ * and context to use.
+ * data data to be signed.
+ * len length in bytes of data.
+ * signature location to store signature.
+ * sig_len size of the signature storage area
+ * returns
+ * N Success on SIG_MODE_FINAL = returns signature length in bytes
+ * 0 Success on SIG_MODE_INIT and UPDATE
+ * <0 Failure
+ */
+
+
+static int
+dst_rsaref_sign(const int mode, DST_KEY *dkey, void **context,
+ const u_char *data, const int len,
+ u_char *signature, const int sig_len)
+{
+ int sign_len = 0;
+ R_SIGNATURE_CTX *ctx = NULL;
+
+ if (mode & SIG_MODE_INIT)
+ ctx = malloc(sizeof(*ctx));
+ else if (context)
+ ctx = (R_SIGNATURE_CTX *) *context;
+ if (ctx == NULL)
+ return (-1);
+
+ if ((mode & SIG_MODE_INIT) && R_SignInit(ctx, DA_MD5))
+ return (SIGN_INIT_FAILURE);
+
+ /* equivalent of SIG_MODE_UPDATE */
+ if ((mode & SIG_MODE_UPDATE) && (data && len > 0) &&
+ R_SignUpdate(ctx, (u_char *) data, len))
+ return (SIGN_UPDATE_FAILURE);
+
+ if (mode & SIG_MODE_FINAL) {
+ RSA_Key *key = (RSA_Key *) dkey->dk_KEY_struct;
+ if (signature == NULL ||
+ sig_len < (int)(key->rk_Public_Key->bits + 7) / 8)
+ return (SIGN_FINAL_FAILURE);
+ if(key == NULL || key->rk_Private_Key == NULL)
+ return (-1);
+ if (R_SignFinal(ctx, signature, &sign_len,
+ key->rk_Private_Key))
+ return (SIGN_FINAL_FAILURE);
+ SAFE_FREE(ctx);
+ }
+ else {
+ if (context == NULL)
+ return (-1);
+ *context = (void *) ctx;
+ }
+ return (sign_len);
+}
+
+
+/*
+ * dst_rsaref_verify()
+ * Calls RSAREF verification routines. There are three steps to
+ * verification, INIT (initialize structures), UPDATE (hash (more) data),
+ * FINAL (generate a signature). This routine performs one or more of
+ * these steps.
+ * Parameters
+ * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
+ * key pointer to a RSA key structure that points to public key
+ * and context to use.
+ * data data signed.
+ * len length in bytes of data.
+ * signature signature.
+ * sig_len length in bytes of signature.
+ * returns
+ * 0 Success
+ * <0 Failure
+ */
+
+static int
+dst_rsaref_verify(const int mode, DST_KEY *dkey, void **context,
+ const u_char *data, const int len,
+ const u_char *signature, const int sig_len)
+{
+ R_SIGNATURE_CTX *ctx = NULL;
+
+ if (mode & SIG_MODE_INIT)
+ ctx = malloc(sizeof(*ctx));
+ else if (context)
+ ctx = (R_SIGNATURE_CTX *) *context;
+ if (ctx == NULL)
+ return (-1);
+
+ if ((mode & SIG_MODE_INIT) && R_VerifyInit(ctx, DA_MD5))
+ return (VERIFY_INIT_FAILURE);
+
+ if ((mode & SIG_MODE_UPDATE) && (data && len > 0) &&
+ R_VerifyUpdate(ctx, (u_char *) data, len))
+ return (VERIFY_UPDATE_FAILURE);
+
+ if ((mode & SIG_MODE_FINAL)) {
+ RSA_Key *key = (RSA_Key *) dkey->dk_KEY_struct;
+
+ if (key == NULL || key->rk_Public_Key == NULL)
+ return (-1);
+ if (signature == NULL || sig_len <= 0)
+ return (VERIFY_FINAL_FAILURE);
+ if (R_VerifyFinal(ctx, (u_char *) signature, sig_len,
+ key->rk_Public_Key))
+ return (VERIFY_FINAL_FAILURE);
+ }
+ else {
+ if (context == NULL)
+ return (-1);
+ *context = (void *) ctx;
+ }
+
+ return (0);
+}
+
+
+/*
+ * dst_rsaref_to_dns_key
+ * Converts key in RSAREF to DNS distribution format
+ * This function gets in a pointer to the public key and a work area
+ * to write the key into.
+ * Parameters
+ * public KEY structure
+ * out_str buffer to write encoded key into
+ * out_len size of out_str
+ * Return
+ * N >= 0 length of encoded key
+ * n < 0 error
+ */
+
+static int
+dst_rsaref_to_dns_key(const DST_KEY *in_key, u_char *out_str,
+ const int out_len)
+{
+ int n, loc;
+ R_RSA_PUBLIC_KEY *public;
+ u_char *op = (u_char *) out_str;
+
+ if (in_key == NULL || in_key->dk_KEY_struct == NULL ||
+ out_len <= 0 || out_str == NULL)
+ return (-1);
+ public = (R_RSA_PUBLIC_KEY *)
+ ((RSA_Key *) in_key->dk_KEY_struct)->rk_Public_Key;
+ if (public == NULL)
+ return (-1);
+
+ memset(op, 0, out_len);
+
+ /* find first non zero */
+ for (n = 0; public->exponent[n] == 0x0; n++) ;
+
+ n = (MAX_RSA_MODULUS_LEN - n); /* find lenght of exponent */
+ *op++ = (u_int8_t) n;
+
+ if (n > (out_len - (op-out_str)))
+ return (-1);
+ memcpy(op, &public->exponent[MAX_RSA_MODULUS_LEN - n], n);
+ op += n;
+ n++; /* include the lenght field in this count */
+
+ /* find first non zero */
+ for (loc = 0; public->modulus[loc] == 0x0; loc++) ;
+
+ /*copy exponent */
+ if ((MAX_RSA_MODULUS_LEN - loc) > (out_len - (op-out_str)))
+ return (-1);
+ memcpy(op, &public->modulus[loc], MAX_RSA_MODULUS_LEN - loc);
+ n += (MAX_RSA_MODULUS_LEN - loc);
+ return (n);
+}
+
+
+/*
+ * dst_rsaref_from_dns_key
+ * Converts from a DNS KEY RR format to an RSA KEY.
+ * Parameters
+ * len Length in bytes of DNS key
+ * key DNS key
+ * name Key name
+ * s_key DST structure that will point to the RSA key this routine
+ * will build.
+ * Return
+ * -1 The input key has fields that are larger than this package supports
+ * 0 The input key, s_key or name was null.
+ * 1 Success
+ */
+static int
+dst_rsaref_from_dns_key(DST_KEY *s_key, const u_char *key, const int len)
+{
+ int bytes;
+ u_char *key_ptr;
+ RSA_Key *r_key;
+
+ if (key == NULL || s_key == NULL || len < 0)
+ return (0);
+
+ if (s_key->dk_KEY_struct) { /* do not reuse */
+ dst_rsaref_free_key_structure(s_key->dk_KEY_struct);
+ s_key->dk_KEY_struct = NULL;
+ }
+ if (len == 0) /* null key no conversion needed */
+ return (1);
+
+ if ((r_key = (RSA_Key *) malloc(sizeof(RSA_Key))) == NULL) {
+ EREPORT(("dst_rsaref_from_dns_key(): Memory allocation error 1\n"));
+ return (0);
+ }
+ memset(r_key, 0, sizeof(RSA_Key));
+ s_key->dk_KEY_struct = (void *) r_key;
+ r_key->rk_signer = strdup(s_key->dk_key_name);
+ r_key->rk_Public_Key = (R_RSA_PUBLIC_KEY *)
+ malloc(sizeof(R_RSA_PUBLIC_KEY));
+ if (r_key->rk_Public_Key == NULL) {
+ EREPORT(("dst_rsaref_from_dns_key(): Memory allocation error 3\n"));
+ return (0);
+ }
+ memset(r_key->rk_Public_Key, 0, sizeof(R_RSA_PUBLIC_KEY));
+ key_ptr = (u_char *) key;
+ bytes = (int) *key_ptr++; /* length of exponent in bytes */
+ if (bytes == 0) { /* special case for long exponents */
+ bytes = (int) dst_s_get_int16(key_ptr);
+ key_ptr += sizeof(u_int16_t);
+ }
+ if (bytes > MAX_RSA_MODULUS_LEN) {
+ dst_rsaref_free_key_structure(r_key);
+ return (-1);
+ }
+ memcpy(&r_key->rk_Public_Key->exponent[MAX_RSA_MODULUS_LEN - bytes],
+ key_ptr, bytes);
+
+ key_ptr += bytes; /* beginning of modulus */
+ bytes = len - bytes - 1; /* length of modulus */
+ if (bytes > MAX_RSA_MODULUS_LEN) {
+ dst_rsaref_free_key_structure(r_key);
+ return (-1);
+ }
+ memcpy(&r_key->rk_Public_Key->modulus[MAX_RSA_MODULUS_LEN - bytes],
+ key_ptr, bytes);
+ r_key->rk_Public_Key->bits = bytes * 8;
+ s_key->dk_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;
+
+ return (0);
+}
+
+
+
+/*
+ * 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;
+
+ 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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+
+#include "dst_internal.h"
+#include "port_after.h"
+int /* rsaref is not available */
+dst_rsaref_init()
+{
+ return (0);
+}
+#endif /* RSAREF */
diff --git a/usr/src/lib/libresolv2/common/dst/support.c b/usr/src/lib/libresolv2/common/dst/support.c
new file mode 100644
index 0000000000..4b3438f604
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/dst/support.c
@@ -0,0 +1,465 @@
+static const char rcsid[] = "$Header: /proj/cvs/isc/bind8/src/lib/dst/support.c,v 1.11 2001/05/29 05:48:16 marka Exp $";
+
+/*
+ * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
+ *
+ * Permission to use, copy modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
+ */
+
+#include "port_before.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <memory.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include "dst_internal.h"
+
+#include "port_after.h"
+/*
+ * dst_s_conv_bignum_u8_to_b64
+ * This function converts binary data stored as a u_char[] to a
+ * base-64 string. Leading zeroes are discarded. If a header is
+ * supplied, it is prefixed to the input prior to encoding. The
+ * output is \n\0 terminated (the \0 is not included in output length).
+ * Parameters
+ * out_buf binary data to convert
+ * header character string to prefix to the output (label)
+ * bin_data binary data
+ * bin_len size of binary data
+ * Return
+ * -1 not enough space in output work area
+ * 0 no output
+ * >0 number of bytes written to output work area
+ */
+
+int
+dst_s_conv_bignum_u8_to_b64(char *out_buf, const int out_len,
+ const char *header, const u_char *bin_data,
+ const int bin_len)
+{
+ const u_char *bp = bin_data;
+ char *op = out_buf;
+ int lenh = 0, len64 = 0;
+ int local_in_len = bin_len;
+ int local_out_len = out_len;
+
+ if (bin_data == NULL || bin_len <= 0) /* no data no */
+ return (0);
+
+ if (out_buf == NULL || out_len <= 0) /* no output_work area */
+ return (-1);
+
+ /* suppress leading \0 */
+ for (; (*bp == 0x0) && (local_in_len > 0); local_in_len--)
+ bp++;
+
+ if (header) { /* add header to output string */
+ lenh = strlen(header);
+ if (lenh < out_len)
+ memcpy(op, header, lenh);
+ else
+ return (-1);
+ local_out_len -= lenh;
+ op += lenh;
+ }
+ len64 = b64_ntop(bp, local_in_len, op, local_out_len - 2);
+ if (len64 < 0)
+ return (-1);
+ op += len64++;
+ *(op++) = '\n'; /* put CR in the output */
+ *op = '\0'; /* make sure output is 0 terminated */
+ return (lenh + len64);
+}
+
+
+/*
+ * dst_s_verify_str()
+ * Validate that the input string(*str) is at the head of the input
+ * buffer(**buf). If so, move the buffer head pointer (*buf) to
+ * the first byte of data following the string(*str).
+ * Parameters
+ * buf Input buffer.
+ * str Input string.
+ * Return
+ * 0 *str is not the head of **buff
+ * 1 *str is the head of **buff, *buf is is advanced to
+ * the tail of **buf.
+ */
+
+int
+dst_s_verify_str(const char **buf, const char *str)
+{
+ int b, s;
+ if (*buf == NULL) /* error checks */
+ return (0);
+ if (str == NULL || *str == '\0')
+ return (1);
+
+ b = strlen(*buf); /* get length of strings */
+ s = strlen(str);
+ if (s > b || strncmp(*buf, str, s)) /* check if same */
+ return (0); /* not a match */
+ (*buf) += s; /* advance pointer */
+ return (1);
+}
+
+
+/*
+ * dst_s_conv_bignum_b64_to_u8
+ * Read a line of base-64 encoded string from the input buffer,
+ * convert it to binary, and store it in an output area. The
+ * input buffer is read until reaching a newline marker or the
+ * end of the buffer. The binary data is stored in the last X
+ * number of bytes of the output area where X is the size of the
+ * binary output. If the operation is successful, the input buffer
+ * pointer is advanced. This procedure does not do network to host
+ * byte order conversion.
+ * Parameters
+ * buf Pointer to encoded input string. Pointer is updated if
+ * function is successfull.
+ * loc Output area.
+ * loclen Size in bytes of output area.
+ * Return
+ * >0 Return = number of bytes of binary data stored in loc.
+ * 0 Failure.
+ */
+
+int
+dst_s_conv_bignum_b64_to_u8(const char **buf, u_char *loc, const int loclen)
+{
+ int blen;
+ char *bp;
+ u_char bstr[RAW_KEY_SIZE];
+
+ if (buf == NULL || *buf == NULL) { /* error checks */
+ EREPORT(("dst_s_conv_bignum_b64_to_u8: null input buffer.\n"));
+ return (0);
+ }
+ bp = strchr(*buf, '\n'); /* find length of input line */
+ if (bp != NULL)
+ *bp = (u_char) NULL;
+
+ blen = b64_pton(*buf, bstr, sizeof(bstr));
+ if (blen <= 0) {
+ EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is null.\n"));
+ return (0);
+ }
+ else if (loclen < blen) {
+ EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is longer than output buffer.\n"));
+ return (0);
+ }
+ if (bp)
+ *buf = bp; /* advancing buffer past \n */
+ memset(loc, 0, loclen - blen); /* clearing unused output area */
+ memcpy(loc + loclen - blen, bstr, blen); /* write last blen bytes */
+ return (blen);
+}
+
+
+/*
+ * dst_s_calculate_bits
+ * Given a binary number represented in a u_char[], determine
+ * the number of significant bits used.
+ * Parameters
+ * str An input character string containing a binary number.
+ * max_bits The maximum possible significant bits.
+ * Return
+ * N The number of significant bits in str.
+ */
+
+int
+dst_s_calculate_bits(const u_char *str, const int max_bits)
+{
+ const u_char *p = str;
+ u_char i, j = 0x80;
+ int bits;
+ for (bits = max_bits; *p == 0x00 && bits > 0; p++)
+ bits -= 8;
+ for (i = *p; (i & j) != j; j >>= 1)
+ bits--;
+ return (bits);
+}
+
+
+/*
+ * calculates a checksum used in dst for an 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 calculate DNSSEC footprint from KEY record
+ * rdata
+ * Input:
+ * dns_key_rdata: the raw data in wire format
+ * rdata_len: the size of the input data
+ * Output:
+ * the key footprint/id calculated from the key data
+ */
+u_int16_t
+dst_s_dns_key_id(const u_char *dns_key_rdata, const int rdata_len)
+{
+ if (!dns_key_rdata)
+ return 0;
+
+ /* 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 if (dns_key_rdata[3] == KEY_HMAC_MD5)
+ /* compatibility */
+ return 0;
+ else
+ /* compute a checksum on the key part of the key rr */
+ return dst_s_id_calc(dns_key_rdata, rdata_len);
+}
+
+/*
+ * dst_s_get_int16
+ * This routine extracts a 16 bit integer from a two byte character
+ * string. The character string is assumed to be in network byte
+ * order and may be unaligned. The number returned is in host order.
+ * Parameter
+ * buf A two byte character string.
+ * Return
+ * The converted integer value.
+ */
+
+u_int16_t
+dst_s_get_int16(const u_char *buf)
+{
+ register u_int16_t a = 0;
+ a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1]));
+ return (a);
+}
+
+
+/*
+ * dst_s_get_int32
+ * This routine extracts a 32 bit integer from a four byte character
+ * string. The character string is assumed to be in network byte
+ * order and may be unaligned. The number returned is in host order.
+ * Parameter
+ * buf A four byte character string.
+ * Return
+ * The converted integer value.
+ */
+
+u_int32_t
+dst_s_get_int32(const u_char *buf)
+{
+ register u_int32_t a = 0;
+ a = ((u_int32_t)(buf[0] << 24)) | ((u_int32_t)(buf[1] << 16)) |
+ ((u_int32_t)(buf[2] << 8)) | ((u_int32_t)(buf[3]));
+ return (a);
+}
+
+
+/*
+ * dst_s_put_int16
+ * Take a 16 bit integer and store the value in a two byte
+ * character string. The integer is assumed to be in network
+ * order and the string is returned in host order.
+ *
+ * Parameters
+ * buf Storage for a two byte character string.
+ * val 16 bit integer.
+ */
+
+void
+dst_s_put_int16(u_int8_t *buf, const u_int16_t val)
+{
+ buf[0] = (u_int8_t)(val >> 8);
+ buf[1] = (u_int8_t)(val);
+}
+
+
+/*
+ * dst_s_put_int32
+ * Take a 32 bit integer and store the value in a four byte
+ * character string. The integer is assumed to be in network
+ * order and the string is returned in host order.
+ *
+ * Parameters
+ * buf Storage for a four byte character string.
+ * val 32 bit integer.
+ */
+
+void
+dst_s_put_int32(u_int8_t *buf, const u_int32_t val)
+{
+ buf[0] = (u_int8_t)(val >> 24);
+ buf[1] = (u_int8_t)(val >> 16);
+ buf[2] = (u_int8_t)(val >> 8);
+ buf[3] = (u_int8_t)(val);
+}
+
+
+/*
+ * dst_s_filename_length
+ *
+ * This function returns the number of bytes needed to hold the
+ * filename for a key file. '/', '\' and ':' are not allowed.
+ * form: K<keyname>+<alg>+<id>.<suffix>
+ *
+ * Returns 0 if the filename would contain either '\', '/' or ':'
+ */
+size_t
+dst_s_filename_length(const char *name, const char *suffix)
+{
+ if (name == NULL)
+ return (0);
+ if (strrchr(name, '\\'))
+ return (0);
+ if (strrchr(name, '/'))
+ return (0);
+ if (strrchr(name, ':'))
+ return (0);
+ if (suffix == NULL)
+ return (0);
+ if (strrchr(suffix, '\\'))
+ return (0);
+ if (strrchr(suffix, '/'))
+ return (0);
+ if (strrchr(suffix, ':'))
+ return (0);
+ return (1 + strlen(name) + 6 + strlen(suffix));
+}
+
+
+/*
+ * dst_s_build_filename ()
+ * Builds a key filename from the key name, it's id, and a
+ * suffix. '\', '/' and ':' are not allowed. fA filename is of the
+ * form: K<keyname><id>.<suffix>
+ * form: K<keyname>+<alg>+<id>.<suffix>
+ *
+ * Returns -1 if the conversion fails:
+ * if the filename would be too long for space allotted
+ * if the filename would contain a '\', '/' or ':'
+ * Returns 0 on success
+ */
+
+int
+dst_s_build_filename(char *filename, const char *name, u_int16_t id,
+ int alg, const char *suffix, size_t filename_length)
+{
+ u_int32_t my_id;
+ if (filename == NULL)
+ return (-1);
+ memset(filename, 0, filename_length);
+ if (name == NULL)
+ return (-1);
+ if (suffix == NULL)
+ return (-1);
+ if (filename_length < 1 + strlen(name) + 4 + 6 + 1 + strlen(suffix))
+ return (-1);
+ my_id = id;
+ sprintf(filename, "K%s+%03d+%05d.%s", name, alg, my_id,
+ (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/usr/src/lib/libresolv2/common/inet/inet_addr.c b/usr/src/lib/libresolv2/common/inet/inet_addr.c
new file mode 100644
index 0000000000..06fe73bd4e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/inet/inet_addr.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+/*
+ * inet_aton() has been moved to usr/src/lib/libnsl/rpc/inet_ntoa.c
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
diff --git a/usr/src/lib/libresolv2/common/inet/inet_cidr_ntop.c b/usr/src/lib/libresolv2/common/inet/inet_cidr_ntop.c
new file mode 100644
index 0000000000..738d82d3dd
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/inet/inet_cidr_ntop.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_cidr_ntop.c,v 8.7 2001/09/28 05:19:36 marka Exp $";
+#endif
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static char * inet_cidr_ntop_ipv4 __P((const u_char *src, int bits,
+ char *dst, size_t size));
+static char * inet_cidr_ntop_ipv6 __P((const u_char *src, int bits,
+ char *dst, size_t size));
+
+/*
+ * char *
+ * inet_cidr_ntop(af, src, bits, dst, size)
+ * convert network address from network to presentation format.
+ * "src"'s size is determined from its "af".
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * 192.5.5.1/28 has a nonzero host part, which means it isn't a network
+ * as called for by inet_net_ntop() but it can be a host address with
+ * an included netmask.
+ * author:
+ * Paul Vixie (ISC), October 1998
+ */
+char *
+inet_cidr_ntop(int af, const void *src, int bits, char *dst, size_t size) {
+ switch (af) {
+ case AF_INET:
+ return (inet_cidr_ntop_ipv4(src, bits, dst, size));
+ case AF_INET6:
+ return (inet_cidr_ntop_ipv6(src, bits, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+}
+
+static int
+decoct(const u_char *src, int bytes, char *dst, size_t size) {
+ char *odst = dst;
+ char *t;
+ int b;
+
+ for (b = 1; b <= bytes; b++) {
+ if (size < sizeof "255.")
+ return (0);
+ t = dst;
+ dst += SPRINTF((dst, "%u", *src++));
+ if (b != bytes) {
+ *dst++ = '.';
+ *dst = '\0';
+ }
+ size -= (size_t)(dst - t);
+ }
+ return (dst - odst);
+}
+
+/*
+ * static char *
+ * inet_cidr_ntop_ipv4(src, bits, dst, size)
+ * convert IPv4 network address from network to presentation format.
+ * "src"'s size is determined from its "af".
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0b11110000 in its fourth octet.
+ * author:
+ * Paul Vixie (ISC), October 1998
+ */
+static char *
+inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size) {
+ char *odst = dst;
+ size_t len = 4;
+ size_t b;
+ size_t bytes;
+
+ if ((bits < -1) || (bits > 32)) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /* Find number of significant bytes in address. */
+ if (bits == -1)
+ len = 4;
+ else
+ for (len = 1, b = 1 ; b < 4; b++)
+ if (*(src + b))
+ len = b + 1;
+
+ /* Format whole octets plus nonzero trailing octets. */
+ bytes = (((bits <= 0) ? 1 : bits) + 7) / 8;
+ if (len > bytes)
+ bytes = len;
+ b = decoct(src, bytes, dst, size);
+ if (b == 0)
+ goto emsgsize;
+ dst += b;
+ size -= b;
+
+ if (bits != -1) {
+ /* Format CIDR /width. */
+ if (size < sizeof "/32")
+ goto emsgsize;
+ dst += SPRINTF((dst, "/%u", bits));
+ }
+
+ return (odst);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
+
+static char *
+inet_cidr_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) {
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"];
+ char *tp;
+ struct { int base, len; } best, cur;
+ u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
+ int i;
+
+ if ((bits < -1) || (bits > 128)) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /*
+ * Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, '\0', sizeof words);
+ for (i = 0; i < NS_IN6ADDRSZ; i++)
+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+ best.base = -1;
+ cur.base = -1;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ if (words[i] == 0) {
+ if (cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ } else {
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ }
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /*
+ * Format the result.
+ */
+ tp = tmp;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ /* Are we inside the best run of 0x00's? */
+ if (best.base != -1 && i >= best.base &&
+ i < (best.base + best.len)) {
+ if (i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if (i != 0)
+ *tp++ = ':';
+ /* Is this address an encapsulated IPv4? */
+ if (i == 6 && best.base == 0 && (best.len == 6 ||
+ (best.len == 7 && words[7] != 0x0001) ||
+ (best.len == 5 && words[5] == 0xffff))) {
+ int n;
+
+ if (src[15] || bits == -1 || bits > 120)
+ n = 4;
+ else if (src[14] || bits > 112)
+ n = 3;
+ else
+ n = 2;
+ n = decoct(src+12, n, tp, sizeof tmp - (tp - tmp));
+ if (n == 0) {
+ errno = EMSGSIZE;
+ return (NULL);
+ }
+ tp += strlen(tp);
+ break;
+ }
+ tp += SPRINTF((tp, "%x", words[i]));
+ }
+
+ /* Was it a trailing run of 0x00's? */
+ if (best.base != -1 && (best.base + best.len) ==
+ (NS_IN6ADDRSZ / NS_INT16SZ))
+ *tp++ = ':';
+ *tp = '\0';
+
+ if (bits != -1)
+ tp += SPRINTF((tp, "/%u", bits));
+
+ /*
+ * Check for overflow, copy, and we're done.
+ */
+ if ((size_t)(tp - tmp) > size) {
+ errno = EMSGSIZE;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
+}
diff --git a/usr/src/lib/libresolv2/common/inet/inet_cidr_pton.c b/usr/src/lib/libresolv2/common/inet/inet_cidr_pton.c
new file mode 100644
index 0000000000..26fe2e926a
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/inet/inet_cidr_pton.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_cidr_pton.c,v 8.7 2001/09/28 04:21:28 marka Exp $";
+#endif
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <isc/assertions.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static int inet_cidr_pton_ipv4 __P((const char *src, u_char *dst,
+ int *bits, int ipv6));
+static int inet_cidr_pton_ipv6 __P((const char *src, u_char *dst,
+ int *bits));
+
+static int getbits(const char *, int ipv6);
+
+/*
+ * int
+ * inet_cidr_pton(af, src, dst, *bits)
+ * convert network address from presentation to network format.
+ * accepts inet_pton()'s input for this "af" plus trailing "/CIDR".
+ * "dst" is assumed large enough for its "af". "bits" is set to the
+ * /CIDR prefix length, which can have defaults (like /32 for IPv4).
+ * return:
+ * -1 if an error occurred (inspect errno; ENOENT means bad format).
+ * 0 if successful conversion occurred.
+ * note:
+ * 192.5.5.1/28 has a nonzero host part, which means it isn't a network
+ * as called for by inet_net_pton() but it can be a host address with
+ * an included netmask.
+ * author:
+ * Paul Vixie (ISC), October 1998
+ */
+int
+inet_cidr_pton(int af, const char *src, void *dst, int *bits) {
+ switch (af) {
+ case AF_INET:
+ return (inet_cidr_pton_ipv4(src, dst, bits, 0));
+ case AF_INET6:
+ return (inet_cidr_pton_ipv6(src, dst, bits));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+}
+
+static const char digits[] = "0123456789";
+
+static int
+inet_cidr_pton_ipv4(const char *src, u_char *dst, int *pbits, int ipv6) {
+ const u_char *odst = dst;
+ int n, ch, tmp, bits;
+ size_t size = 4;
+
+ /* Get the mantissa. */
+ while (ch = *src++, (isascii(ch) && isdigit(ch))) {
+ tmp = 0;
+ do {
+ n = strchr(digits, ch) - digits;
+ INSIST(n >= 0 && n <= 9);
+ tmp *= 10;
+ tmp += n;
+ if (tmp > 255)
+ goto enoent;
+ } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
+ if (size-- == 0)
+ goto emsgsize;
+ *dst++ = (u_char) tmp;
+ if (ch == '\0' || ch == '/')
+ break;
+ if (ch != '.')
+ goto enoent;
+ }
+
+ /* Get the prefix length if any. */
+ bits = -1;
+ if (ch == '/' && dst > odst) {
+ bits = getbits(src, ipv6);
+ if (bits == -2)
+ goto enoent;
+ } else if (ch != '\0')
+ goto enoent;
+
+ /* Prefix length can default to /32 only if all four octets spec'd. */
+ if (bits == -1) {
+ if (dst - odst == 4)
+ bits = ipv6 ? 128 : 32;
+ else
+ goto enoent;
+ }
+
+ /* If nothing was written to the destination, we found no address. */
+ if (dst == odst)
+ goto enoent;
+
+ /* If prefix length overspecifies mantissa, life is bad. */
+ if (((bits - (ipv6 ? 96 : 0)) / 8) > (dst - odst))
+ goto enoent;
+
+ /* Extend address to four octets. */
+ while (size-- > 0)
+ *dst++ = 0;
+
+ *pbits = bits;
+ return (0);
+
+ enoent:
+ errno = ENOENT;
+ return (-1);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+static int
+inet_cidr_pton_ipv6(const char *src, u_char *dst, int *pbits) {
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ u_int val;
+ int bits;
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return (0);
+ curtok = src;
+ saw_xdigit = 0;
+ val = 0;
+ bits = -1;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (val > 0xffff)
+ return (0);
+ saw_xdigit = 1;
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!saw_xdigit) {
+ if (colonp)
+ return (0);
+ colonp = tp;
+ continue;
+ } else if (*src == '\0') {
+ return (0);
+ }
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ saw_xdigit = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ inet_cidr_pton_ipv4(curtok, tp, &bits, 1) == 0) {
+ tp += NS_INADDRSZ;
+ saw_xdigit = 0;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ if (ch == '/') {
+ bits = getbits(src, 1);
+ if (bits == -2)
+ goto enoent;
+ break;
+ }
+ goto enoent;
+ }
+ if (saw_xdigit) {
+ if (tp + NS_INT16SZ > endp)
+ goto emsgsize;
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ }
+ if (colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ if (tp == endp)
+ goto enoent;
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+
+ memcpy(dst, tmp, NS_IN6ADDRSZ);
+
+ *pbits = bits;
+ return (0);
+
+ enoent:
+ errno = ENOENT;
+ return (-1);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+int
+getbits(const char *src, int ipv6) {
+ int bits = 0;
+ char *cp, ch;
+
+ if (*src == '\0') /* syntax */
+ return (-2);
+ do {
+ ch = *src++;
+ cp = strchr(digits, ch);
+ if (cp == NULL) /* syntax */
+ return (-2);
+ bits *= 10;
+ bits += cp - digits;
+ if (bits == 0 && *src != '\0') /* no leading zeros */
+ return (-2);
+ if (bits > (ipv6 ? 128 : 32)) /* range error */
+ return (-2);
+ } while (*src != '\0');
+
+ return (bits);
+}
diff --git a/usr/src/lib/libresolv2/common/inet/inet_data.c b/usr/src/lib/libresolv2/common/inet/inet_data.c
new file mode 100644
index 0000000000..80a87e5660
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/inet/inet_data.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id: inet_data.c,v 1.2 2001/06/20 22:06:36 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "port_after.h"
+
+const struct in6_addr isc_in6addr_any = IN6ADDR_ANY_INIT;
+const struct in6_addr isc_in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
diff --git a/usr/src/lib/libresolv2/common/inet/inet_lnaof.c b/usr/src/lib/libresolv2/common/inet/inet_lnaof.c
new file mode 100644
index 0000000000..0212d18f51
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/inet/inet_lnaof.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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 <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "port_after.h"
+
+/*
+ * Return the local network address portion of an
+ * internet address; handles class a/b/c network
+ * number formats.
+ */
+#ifdef ORIGINAL_ISC_CODE
+u_long
+#else
+in_addr_t
+#endif
+inet_lnaof(in)
+ struct in_addr in;
+{
+#ifdef ORIGINAL_ISC_CODE
+ u_long i = ntohl(in.s_addr);
+#else
+ in_addr_t i = ntohl(in.s_addr);
+#endif
+
+ 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/usr/src/lib/libresolv2/common/inet/inet_makeaddr.c b/usr/src/lib/libresolv2/common/inet/inet_makeaddr.c
new file mode 100644
index 0000000000..59dc91d218
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/inet/inet_makeaddr.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1997-2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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 <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#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)
+#ifdef ORIGINAL_ISC_CODE
+ u_long net, host;
+#else
+ in_addr_t net, host;
+#endif
+{
+#ifdef ORIGINAL_ISC_CODE
+ u_long addr;
+#else
+ in_addr_t addr;
+ struct in_addr inaddr;
+#endif
+
+ 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;
+#ifdef ORIGINAL_ISC_CODE
+ addr = htonl(addr);
+ return (*(struct in_addr *)&addr);
+#else
+ inaddr.s_addr = htonl(addr);
+ return (inaddr);
+#endif
+}
diff --git a/usr/src/lib/libresolv2/common/inet/inet_net_ntop.c b/usr/src/lib/libresolv2/common/inet/inet_net_ntop.c
new file mode 100644
index 0000000000..0c77c1614a
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/inet/inet_net_ntop.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.8 2001/09/27 15:08:36 marka Exp $";
+#endif
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static char * inet_net_ntop_ipv4 __P((const u_char *src, int bits,
+ char *dst, size_t size));
+static char * inet_net_ntop_ipv6 __P((const u_char *src, int bits,
+ char *dst, size_t size));
+
+/*
+ * char *
+ * inet_net_ntop(af, src, bits, dst, size)
+ * convert network number from network to presentation format.
+ * generates CIDR style result always.
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * author:
+ * Paul Vixie (ISC), July 1996
+ */
+char *
+inet_net_ntop(af, src, bits, dst, size)
+ int af;
+ const void *src;
+ int bits;
+ char *dst;
+ size_t size;
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_net_ntop_ipv4(src, bits, dst, size));
+ case AF_INET6:
+ return (inet_net_ntop_ipv6(src, bits, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+}
+
+/*
+ * static char *
+ * inet_net_ntop_ipv4(src, bits, dst, size)
+ * convert IPv4 network number from network to presentation format.
+ * generates CIDR style result always.
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0b11110000 in its fourth octet.
+ * author:
+ * Paul Vixie (ISC), July 1996
+ */
+static char *
+inet_net_ntop_ipv4(src, bits, dst, size)
+ const u_char *src;
+ int bits;
+ char *dst;
+ size_t size;
+{
+ char *odst = dst;
+ char *t;
+ u_int m;
+ int b;
+
+ if (bits < 0 || bits > 32) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if (bits == 0) {
+ if (size < sizeof "0")
+ goto emsgsize;
+ *dst++ = '0';
+ size--;
+ *dst = '\0';
+ }
+
+ /* Format whole octets. */
+ for (b = bits / 8; b > 0; b--) {
+ if (size <= sizeof "255.")
+ goto emsgsize;
+ t = dst;
+ dst += SPRINTF((dst, "%u", *src++));
+ if (b > 1) {
+ *dst++ = '.';
+ *dst = '\0';
+ }
+ size -= (size_t)(dst - t);
+ }
+
+ /* Format partial octet. */
+ b = bits % 8;
+ if (b > 0) {
+ if (size <= sizeof ".255")
+ goto emsgsize;
+ t = dst;
+ if (dst != odst)
+ *dst++ = '.';
+ m = ((1 << b) - 1) << (8 - b);
+ dst += SPRINTF((dst, "%u", *src & m));
+ size -= (size_t)(dst - t);
+ }
+
+ /* Format CIDR /width. */
+ if (size <= sizeof "/32")
+ goto emsgsize;
+ dst += SPRINTF((dst, "/%u", bits));
+ return (odst);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
+
+/*
+ * static char *
+ * inet_net_ntop_ipv6(src, bits, fakebits, dst, size)
+ * convert IPv6 network number from network to presentation format.
+ * generates CIDR style result always. Picks the shortest representation
+ * unless the IP is really IPv4.
+ * always prints specified number of bits (bits).
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0b11110000 in its fourth octet.
+ * author:
+ * Vadim Kogan (UCB), June 2001
+ * Original version (IPv4) by Paul Vixie (ISC), July 1996
+ */
+
+static char *
+inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) {
+ u_int m;
+ int b;
+ int p;
+ int zero_s, zero_l, tmp_zero_s, tmp_zero_l;
+ int i;
+ int is_ipv4 = 0;
+ unsigned char inbuf[16];
+ char outbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
+ char *cp;
+ int words;
+ u_char *s;
+
+ if (bits < 0 || bits > 128) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ cp = outbuf;
+
+ if (bits == 0) {
+ *cp++ = ':';
+ *cp++ = ':';
+ *cp = '\0';
+ } else {
+ /* Copy src to private buffer. Zero host part. */
+ p = (bits + 7) / 8;
+ memcpy(inbuf, src, p);
+ memset(inbuf + p, 0, 16 - p);
+ b = bits % 8;
+ if (b != 0) {
+ m = ~0 << (8 - b);
+ inbuf[p-1] &= m;
+ }
+
+ s = inbuf;
+
+ /* how many words need to be displayed in output */
+ words = (bits + 15) / 16;
+ if (words == 1)
+ words = 2;
+
+ /* Find the longest substring of zero's */
+ zero_s = zero_l = tmp_zero_s = tmp_zero_l = 0;
+ for (i = 0; i < (words * 2); i += 2) {
+ if ((s[i] | s[i+1]) == 0) {
+ if (tmp_zero_l == 0)
+ tmp_zero_s = i / 2;
+ tmp_zero_l++;
+ } else {
+ if (tmp_zero_l && zero_l < tmp_zero_l) {
+ zero_s = tmp_zero_s;
+ zero_l = tmp_zero_l;
+ tmp_zero_l = 0;
+ }
+ }
+ }
+
+ if (tmp_zero_l && zero_l < tmp_zero_l) {
+ zero_s = tmp_zero_s;
+ zero_l = tmp_zero_l;
+ }
+
+ if (zero_l != words && zero_s == 0 && ((zero_l == 6) ||
+ ((zero_l == 5 && s[10] == 0xff && s[11] == 0xff) ||
+ ((zero_l == 7 && s[14] != 0 && s[15] != 1)))))
+ is_ipv4 = 1;
+
+ /* Format whole words. */
+ for (p = 0; p < words; p++) {
+ if (zero_l != 0 && p >= zero_s && p < zero_s + zero_l) {
+ /* Time to skip some zeros */
+ if (p == zero_s)
+ *cp++ = ':';
+ if (p == words - 1)
+ *cp++ = ':';
+ s++;
+ s++;
+ continue;
+ }
+
+ if (is_ipv4 && p > 5 ) {
+ *cp++ = (p == 6) ? ':' : '.';
+ cp += SPRINTF((cp, "%u", *s++));
+ /* we can potentially drop the last octet */
+ if (p != 7 || bits > 120) {
+ *cp++ = '.';
+ cp += SPRINTF((cp, "%u", *s++));
+ }
+ } else {
+ if (cp != outbuf)
+ *cp++ = ':';
+ cp += SPRINTF((cp, "%x", *s * 256 + s[1]));
+ s += 2;
+ }
+ }
+ }
+ /* Format CIDR /width. */
+ SPRINTF((cp, "/%u", bits));
+ if (strlen(outbuf) + 1 > size)
+ goto emsgsize;
+ strcpy(dst, outbuf);
+
+ return (dst);
+
+emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
diff --git a/usr/src/lib/libresolv2/common/inet/inet_net_pton.c b/usr/src/lib/libresolv2/common/inet/inet_net_pton.c
new file mode 100644
index 0000000000..18a89be9ae
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/inet/inet_net_pton.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_net_pton.c,v 1.13 2001/09/27 15:08:38 marka Exp $";
+#endif
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <isc/assertions.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/*
+ * static int
+ * inet_net_pton_ipv4(src, dst, size)
+ * convert IPv4 network number from presentation to network format.
+ * accepts hex octets, hex strings, decimal octets, and /CIDR.
+ * "size" is in bytes and describes "dst".
+ * return:
+ * number of bits, either imputed classfully or specified with /CIDR,
+ * or -1 if some failure occurred (check errno). ENOENT means it was
+ * not an IPv4 network specification.
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0b11110000 in its fourth octet.
+ * author:
+ * Paul Vixie (ISC), June 1996
+ */
+static int
+inet_net_pton_ipv4( const char *src, u_char *dst, size_t size) {
+ static const char xdigits[] = "0123456789abcdef";
+ static const char digits[] = "0123456789";
+ int n, ch, tmp = 0, dirty, bits;
+ const u_char *odst = dst;
+
+ ch = *src++;
+ if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
+ && isascii((unsigned char)(src[1]))
+ && isxdigit((unsigned char)(src[1]))) {
+ /* Hexadecimal: Eat nybble string. */
+ if (size <= 0)
+ goto emsgsize;
+ dirty = 0;
+ src++; /* skip x or X. */
+ while ((ch = *src++) != '\0' && isascii(ch) && isxdigit(ch)) {
+ if (isupper(ch))
+ ch = tolower(ch);
+ n = strchr(xdigits, ch) - xdigits;
+ INSIST(n >= 0 && n <= 15);
+ if (dirty == 0)
+ tmp = n;
+ else
+ tmp = (tmp << 4) | n;
+ if (++dirty == 2) {
+ if (size-- <= 0)
+ goto emsgsize;
+ *dst++ = (u_char) tmp;
+ dirty = 0;
+ }
+ }
+ if (dirty) { /* Odd trailing nybble? */
+ if (size-- <= 0)
+ goto emsgsize;
+ *dst++ = (u_char) (tmp << 4);
+ }
+ } else if (isascii(ch) && isdigit(ch)) {
+ /* Decimal: eat dotted digit string. */
+ for (;;) {
+ tmp = 0;
+ do {
+ n = strchr(digits, ch) - digits;
+ INSIST(n >= 0 && n <= 9);
+ tmp *= 10;
+ tmp += n;
+ if (tmp > 255)
+ goto enoent;
+ } while ((ch = *src++) != '\0' &&
+ isascii(ch) && isdigit(ch));
+ if (size-- <= 0)
+ goto emsgsize;
+ *dst++ = (u_char) tmp;
+ if (ch == '\0' || ch == '/')
+ break;
+ if (ch != '.')
+ goto enoent;
+ ch = *src++;
+ if (!isascii(ch) || !isdigit(ch))
+ goto enoent;
+ }
+ } else
+ goto enoent;
+
+ bits = -1;
+ if (ch == '/' && isascii((unsigned char)(src[0])) &&
+ isdigit((unsigned char)(src[0])) && dst > odst) {
+ /* CIDR width specifier. Nothing can follow it. */
+ ch = *src++; /* Skip over the /. */
+ bits = 0;
+ do {
+ n = strchr(digits, ch) - digits;
+ INSIST(n >= 0 && n <= 9);
+ bits *= 10;
+ bits += n;
+ } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
+ if (ch != '\0')
+ goto enoent;
+ if (bits > 32)
+ goto emsgsize;
+ }
+
+ /* Firey death and destruction unless we prefetched EOS. */
+ if (ch != '\0')
+ goto enoent;
+
+ /* If nothing was written to the destination, we found no address. */
+ if (dst == odst)
+ goto enoent;
+ /* If no CIDR spec was given, infer width from net class. */
+ if (bits == -1) {
+ if (*odst >= 240) /* Class E */
+ bits = 32;
+ else if (*odst >= 224) /* Class D */
+ bits = 4;
+ else if (*odst >= 192) /* Class C */
+ bits = 24;
+ else if (*odst >= 128) /* Class B */
+ bits = 16;
+ else /* Class A */
+ bits = 8;
+ /* If imputed mask is narrower than specified octets, widen. */
+ if (bits >= 8 && bits < ((dst - odst) * 8))
+ bits = (dst - odst) * 8;
+ }
+ /* Extend network to cover the actual mask. */
+ while (bits > ((dst - odst) * 8)) {
+ if (size-- <= 0)
+ goto emsgsize;
+ *dst++ = '\0';
+ }
+ return (bits);
+
+ enoent:
+ errno = ENOENT;
+ return (-1);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+static int
+getbits(const char *src, int *bitsp) {
+ static const char digits[] = "0123456789";
+ int n;
+ int val;
+ char ch;
+
+ val = 0;
+ n = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ pch = strchr(digits, ch);
+ if (pch != NULL) {
+ if (n++ != 0 && val == 0) /* no leading zeros */
+ return (0);
+ val *= 10;
+ val += (pch - digits);
+ if (val > 128) /* range */
+ return (0);
+ continue;
+ }
+ return (0);
+ }
+ if (n == 0)
+ return (0);
+ *bitsp = val;
+ return (1);
+}
+
+static int
+getv4(const char *src, u_char *dst, int *bitsp) {
+ static const char digits[] = "0123456789";
+ u_char *odst = dst;
+ int n;
+ u_int val;
+ char ch;
+
+ val = 0;
+ n = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ pch = strchr(digits, ch);
+ if (pch != NULL) {
+ if (n++ != 0 && val == 0) /* no leading zeros */
+ return (0);
+ val *= 10;
+ val += (pch - digits);
+ if (val > 255) /* range */
+ return (0);
+ continue;
+ }
+ if (ch == '.' || ch == '/') {
+ if (dst - odst > 3) /* too many octets? */
+ return (0);
+ *dst++ = val;
+ if (ch == '/')
+ return (getbits(src, bitsp));
+ val = 0;
+ n = 0;
+ continue;
+ }
+ return (0);
+ }
+ if (n == 0)
+ return (0);
+ if (dst - odst > 3) /* too many octets? */
+ return (0);
+ *dst++ = val;
+ return (1);
+}
+
+static int
+inet_net_pton_ipv6(const char *src, u_char *dst, size_t size) {
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ u_int val;
+ int digits;
+ int bits;
+ size_t bytes;
+ int words;
+ int ipv4;
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ goto enoent;
+ curtok = src;
+ saw_xdigit = 0;
+ val = 0;
+ digits = 0;
+ bits = -1;
+ ipv4 = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (++digits > 4)
+ goto enoent;
+ saw_xdigit = 1;
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!saw_xdigit) {
+ if (colonp)
+ goto enoent;
+ colonp = tp;
+ continue;
+ } else if (*src == '\0')
+ goto enoent;
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ saw_xdigit = 0;
+ digits = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ getv4(curtok, tp, &bits) > 0) {
+ tp += NS_INADDRSZ;
+ saw_xdigit = 0;
+ ipv4 = 1;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ if (ch == '/' && getbits(src, &bits) > 0)
+ break;
+ goto enoent;
+ }
+ if (saw_xdigit) {
+ if (tp + NS_INT16SZ > endp)
+ goto enoent;
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ }
+ if (bits == -1)
+ bits = 128;
+
+ words = (bits + 15) / 16;
+ if (words < 2)
+ words = 2;
+ if (ipv4)
+ words = 8;
+ endp = tmp + 2 * words;
+
+ if (colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ if (tp == endp)
+ goto enoent;
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ goto enoent;
+
+ bytes = (bits + 7) / 8;
+ if (bytes > size)
+ goto emsgsize;
+ memcpy(dst, tmp, bytes);
+ return (bits);
+
+ enoent:
+ errno = ENOENT;
+ return (-1);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+/*
+ * int
+ * inet_net_pton(af, src, dst, size)
+ * convert network number from presentation to network format.
+ * accepts hex octets, hex strings, decimal octets, and /CIDR.
+ * "size" is in bytes and describes "dst".
+ * return:
+ * number of bits, either imputed classfully or specified with /CIDR,
+ * or -1 if some failure occurred (check errno). ENOENT means it was
+ * not a valid network specification.
+ * author:
+ * Paul Vixie (ISC), June 1996
+ */
+int
+inet_net_pton(int af, const char *src, void *dst, size_t size) {
+ switch (af) {
+ case AF_INET:
+ return (inet_net_pton_ipv4(src, dst, size));
+ case AF_INET6:
+ return (inet_net_pton_ipv6(src, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+}
diff --git a/usr/src/lib/libresolv2/common/inet/inet_neta.c b/usr/src/lib/libresolv2/common/inet/inet_neta.c
new file mode 100644
index 0000000000..1a71b11906
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/inet/inet_neta.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_neta.c,v 1.6 1999/01/08 19:23:45 vixie Exp $";
+#endif
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "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/usr/src/lib/libresolv2/common/inet/inet_netof.c b/usr/src/lib/libresolv2/common/inet/inet_netof.c
new file mode 100644
index 0000000000..a5395af2d4
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/inet/inet_netof.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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 <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "port_after.h"
+
+/*
+ * Return the network number from an internet
+ * address; handles class a/b/c network #'s.
+ */
+#ifdef ORIGINAL_ISC_CODE
+u_long
+#else
+in_addr_t
+#endif
+inet_netof(in)
+ struct in_addr in;
+{
+#ifdef ORIGINAL_ISC_CODE
+ register u_long i = ntohl(in.s_addr);
+#else
+ register in_addr_t i = ntohl(in.s_addr);
+#endif
+
+ 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/usr/src/lib/libresolv2/common/inet/inet_network.c b/usr/src/lib/libresolv2/common/inet/inet_network.c
new file mode 100644
index 0000000000..e1f6f6d96a
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/inet/inet_network.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright 1997-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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 <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+
+#include "port_after.h"
+
+/*
+ * Internet network address interpretation routine.
+ * The library routines call this routine to interpret
+ * network numbers.
+ */
+#ifdef ORIGINAL_ISC_CODE
+u_long
+#else
+in_addr_t
+#endif
+inet_network(cp)
+ register const char *cp;
+{
+#ifdef ORIGINAL_ISC_CODE
+ register u_long val, base, n, i;
+#else
+ register in_addr_t val, base, n, i;
+#endif
+ register char c;
+#ifdef ORIGINAL_ISC_CODE
+ u_long parts[4], *pp = parts;
+#else
+ in_addr_t parts[4], *pp = parts;
+#endif
+ int digit;
+
+again:
+ val = 0; base = 10; digit = 0;
+ if (*cp == '0')
+ digit = 1, base = 8, cp++;
+ if (*cp == 'x' || *cp == 'X')
+ base = 16, cp++;
+ while ((c = *cp) != 0) {
+ if (isdigit((unsigned char)c)) {
+ if (base == 8 && (c == '8' || c == '9'))
+ return (INADDR_NONE);
+ val = (val * base) + (c - '0');
+ cp++;
+ digit = 1;
+ continue;
+ }
+ if (base == 16 && isxdigit((unsigned char)c)) {
+ val = (val << 4) +
+ (c + 10 - (islower((unsigned char)c) ? 'a' : 'A'));
+ cp++;
+ digit = 1;
+ continue;
+ }
+ break;
+ }
+ if (!digit)
+ return (INADDR_NONE);
+#ifdef ORIGINAL_ISC_CODE
+ if (*cp == '.') {
+ if (pp >= parts + 4 || val > 0xff)
+ return (INADDR_NONE);
+#else
+ if (pp >= parts + 4 || val > 0xff)
+ return (INADDR_NONE);
+ if (*cp == '.') {
+#endif
+ *pp++ = val, cp++;
+ goto again;
+ }
+ if (*cp && !isspace(*cp&0xff))
+ return (INADDR_NONE);
+ *pp++ = val;
+ n = pp - parts;
+ if (n > 4)
+ return (INADDR_NONE);
+ for (val = 0, i = 0; i < n; i++) {
+ val <<= 8;
+ val |= parts[i] & 0xff;
+ }
+ return (val);
+}
diff --git a/usr/src/lib/libresolv2/common/inet/inet_ntoa.c b/usr/src/lib/libresolv2/common/inet/inet_ntoa.c
new file mode 100644
index 0000000000..7c838ac458
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/inet/inet_ntoa.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)inet_ntoa.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: inet_ntoa.c,v 1.7 1999/05/14 18:16:55 vixie Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "port_after.h"
+
+/*
+ * Convert network-format internet address
+ * to base 256 d.d.d.d representation.
+ */
+#ifndef SUNW_LIBNSL /* We don't need this if linked with libnsl */
+/*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);
+}
+#endif /* SUNW_LIBNSL */
diff --git a/usr/src/lib/libresolv2/common/inet/inet_ntop.c b/usr/src/lib/libresolv2/common/inet/inet_ntop.c
new file mode 100644
index 0000000000..c13d5e3fc6
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/inet/inet_ntop.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_ntop.c,v 1.11 2001/09/27 15:12:57 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#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));
+
+#ifndef SUNW_LIBNSL /* We don't need this if linked with libnsl */
+
+/* char *
+ * inet_ntop(af, src, dst, size)
+ * convert a network format address to presentation format.
+ * return:
+ * pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ * Paul Vixie, 1996.
+ */
+const char *
+inet_ntop(af, src, dst, size)
+ int af;
+ const void *src;
+ char *dst;
+ size_t size;
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_ntop4(src, dst, size));
+ case AF_INET6:
+ return (inet_ntop6(src, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+ /* NOTREACHED */
+}
+
+/* const char *
+ * inet_ntop4(src, dst, size)
+ * format an IPv4 address
+ * return:
+ * `dst' (as a const)
+ * notes:
+ * (1) uses no statics
+ * (2) takes a u_char* not an in_addr as input
+ * author:
+ * Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop4(src, dst, size)
+ const u_char *src;
+ char *dst;
+ size_t size;
+{
+ static const char fmt[] = "%u.%u.%u.%u";
+ char tmp[sizeof "255.255.255.255"];
+
+ if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) >= size) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
+}
+
+/* const char *
+ * inet_ntop6(src, dst, size)
+ * convert IPv6 binary address into presentation (printable) format
+ * author:
+ * Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop6(src, dst, size)
+ const u_char *src;
+ char *dst;
+ size_t size;
+{
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
+ struct { int base, len; } best, cur;
+ u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
+ int i;
+
+ /*
+ * Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, '\0', sizeof words);
+ for (i = 0; i < NS_IN6ADDRSZ; i++)
+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+ best.base = -1;
+ cur.base = -1;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ if (words[i] == 0) {
+ if (cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ } else {
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ }
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /*
+ * Format the result.
+ */
+ tp = tmp;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ /* Are we inside the best run of 0x00's? */
+ if (best.base != -1 && i >= best.base &&
+ i < (best.base + best.len)) {
+ if (i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if (i != 0)
+ *tp++ = ':';
+ /* Is this address an encapsulated IPv4? */
+ if (i == 6 && best.base == 0 && (best.len == 6 ||
+ (best.len == 7 && words[7] != 0x0001) ||
+ (best.len == 5 && words[5] == 0xffff))) {
+ if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
+ return (NULL);
+ tp += strlen(tp);
+ break;
+ }
+ tp += SPRINTF((tp, "%x", words[i]));
+ }
+ /* Was it a trailing run of 0x00's? */
+ if (best.base != -1 && (best.base + best.len) ==
+ (NS_IN6ADDRSZ / NS_INT16SZ))
+ *tp++ = ':';
+ *tp++ = '\0';
+
+ /*
+ * Check for overflow, copy, and we're done.
+ */
+ if ((size_t)(tp - tmp) > size) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
+}
+#endif /* SUNW_LIBNSL */
diff --git a/usr/src/lib/libresolv2/common/inet/inet_pton.c b/usr/src/lib/libresolv2/common/inet/inet_pton.c
new file mode 100644
index 0000000000..465d1ded01
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/inet/inet_pton.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_pton.c,v 1.8 2001/07/16 03:22:24 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include "port_before.h"
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <string.h>
+#include <errno.h>
+#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));
+
+#ifndef SUNW_LIBNSL /* We don't need this if linked with libnsl */
+
+/* int
+ * inet_pton(af, src, dst)
+ * convert from presentation format (which usually means ASCII printable)
+ * to network format (which is usually some kind of binary format).
+ * return:
+ * 1 if the address was valid for the specified address family
+ * 0 if the address wasn't valid (`dst' is untouched in this case)
+ * -1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ * Paul Vixie, 1996.
+ */
+int
+inet_pton(af, src, dst)
+ int af;
+ const char *src;
+ void *dst;
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_pton4(src, dst));
+ case AF_INET6:
+ return (inet_pton6(src, dst));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+ /* NOTREACHED */
+}
+
+/* int
+ * inet_pton4(src, dst)
+ * like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ * 1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ * does not touch `dst' unless it's returning 1.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton4(src, dst)
+ const char *src;
+ u_char *dst;
+{
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ u_char tmp[NS_INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ *(tp = tmp) = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr(digits, ch)) != NULL) {
+ u_int new = *tp * 10 + (pch - digits);
+
+ if (saw_digit && *tp == 0)
+ return (0);
+ if (new > 255)
+ return (0);
+ *tp = new;
+ if (!saw_digit) {
+ if (++octets > 4)
+ return (0);
+ saw_digit = 1;
+ }
+ } else if (ch == '.' && saw_digit) {
+ if (octets == 4)
+ return (0);
+ *++tp = 0;
+ saw_digit = 0;
+ } else
+ return (0);
+ }
+ if (octets < 4)
+ return (0);
+ memcpy(dst, tmp, NS_INADDRSZ);
+ return (1);
+}
+
+/* int
+ * inet_pton6(src, dst)
+ * convert presentation level address to network order binary form.
+ * return:
+ * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ * (1) does not touch `dst' unless it's returning 1.
+ * (2) :: in a full address is silently ignored.
+ * credit:
+ * inspired by Mark Andrews.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton6(src, dst)
+ const char *src;
+ u_char *dst;
+{
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ u_int val;
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return (0);
+ curtok = src;
+ saw_xdigit = 0;
+ val = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (val > 0xffff)
+ return (0);
+ saw_xdigit = 1;
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!saw_xdigit) {
+ if (colonp)
+ return (0);
+ colonp = tp;
+ continue;
+ } else if (*src == '\0') {
+ return (0);
+ }
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ saw_xdigit = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ inet_pton4(curtok, tp) > 0) {
+ tp += NS_INADDRSZ;
+ saw_xdigit = 0;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ return (0);
+ }
+ if (saw_xdigit) {
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ }
+ if (colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ if (tp == endp)
+ return (0);
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ return (0);
+ memcpy(dst, tmp, NS_IN6ADDRSZ);
+ return (1);
+}
+#endif /* SUNW_LIBNSL */
diff --git a/usr/src/lib/libresolv2/common/inet/nsap_addr.c b/usr/src/lib/libresolv2/common/inet/nsap_addr.c
new file mode 100644
index 0000000000..cab8508187
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/inet/nsap_addr.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: nsap_addr.c,v 8.12 2001/05/28 07:37:46 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <resolv.h>
+
+#include "port_after.h"
+
+static char
+xtob(int c) {
+ return (c - (((c >= '0') && (c <= '9')) ? '0' : '7'));
+}
+
+u_int
+inet_nsap_addr(const char *ascii, u_char *binary, int maxlen) {
+ u_char c, nib;
+ u_int len = 0;
+
+ if (ascii[0] != '0' || (ascii[1] != 'x' && ascii[1] != 'X'))
+ return (0);
+ ascii += 2;
+
+ while ((c = *ascii++) != '\0' && len < (u_int)maxlen) {
+ if (c == '.' || c == '+' || c == '/')
+ continue;
+ if (!isascii(c))
+ return (0);
+ if (islower(c))
+ c = toupper(c);
+ if (isxdigit(c)) {
+ nib = xtob(c);
+ c = *ascii++;
+ if (c != '\0') {
+ c = toupper(c);
+ if (isxdigit(c)) {
+ *binary++ = (nib << 4) | xtob(c);
+ len++;
+ } else
+ return (0);
+ }
+ else
+ return (0);
+ }
+ else
+ return (0);
+ }
+ return (len);
+}
+
+char *
+inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii) {
+ int nib;
+ int i;
+#ifdef SUNW_MT_RESOLVER
+ char *tmpbuf = inet_nsap_ntoa_tmpbuf;
+#else
+ static char tmpbuf[2+255*3];
+#endif /* SUNW_MT_RESOLVER */
+ char *start;
+
+ if (ascii)
+ start = ascii;
+ else {
+ ascii = tmpbuf;
+ start = tmpbuf;
+ }
+
+ *ascii++ = '0';
+ *ascii++ = 'x';
+
+ if (binlen > 255)
+ binlen = 255;
+
+ for (i = 0; i < binlen; i++) {
+ nib = *binary >> 4;
+ *ascii++ = nib + (nib < 10 ? '0' : '7');
+ nib = *binary++ & 0x0f;
+ *ascii++ = nib + (nib < 10 ? '0' : '7');
+ if (((i % 2) == 0 && (i + 1) < binlen))
+ *ascii++ = '.';
+ }
+ *ascii = '\0';
+ return (start);
+}
diff --git a/usr/src/lib/libresolv2/common/irs/dns.c b/usr/src/lib/libresolv2/common/irs/dns.c
new file mode 100644
index 0000000000..30feb1b882
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/dns.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: dns.c,v 1.16 2001/05/29 05:48:26 marka Exp $";
+#endif
+
+/*
+ * dns.c --- this is the top-level accessor function for the dns
+ */
+
+#include "port_before.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <resolv.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#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/usr/src/lib/libresolv2/common/irs/dns_gr.c b/usr/src/lib/libresolv2/common/irs/dns_gr.c
new file mode 100644
index 0000000000..92da69b8c5
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/dns_gr.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: dns_gr.c,v 1.21 2002/07/08 06:26:09 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 <sys/param.h>
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <isc/memcluster.h>
+
+#include <irs.h>
+
+#include "port_after.h"
+
+#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 = 0;
+ 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/usr/src/lib/libresolv2/common/irs/dns_ho.c b/usr/src/lib/libresolv2/common/irs/dns_ho.c
new file mode 100644
index 0000000000..4d4b830dfe
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/dns_ho.c
@@ -0,0 +1,1163 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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.43 2003/05/27 23:36:52 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/* Imports. */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#include "irs_p.h"
+#include "dns_p.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) sprintf x
+#endif
+
+/* Definitions. */
+
+#define MAXALIASES 35
+#define MAXADDRS 35
+
+#define MAXPACKET (65535) /* Maximum TCP message size */
+
+#define BOUNDS_CHECK(ptr, count) \
+ if ((ptr) + (count) > eom) { \
+ had_error++; \
+ continue; \
+ } else (void)0
+
+typedef union {
+ HEADER hdr;
+ u_char buf[MAXPACKET];
+} querybuf;
+
+struct dns_res_target {
+ struct dns_res_target *next;
+ querybuf qbuf; /* query buffer */
+ u_char *answer; /* buffer to put answer */
+ int anslen; /* size of answer buffer */
+ int qclass, qtype; /* class and type of query */
+ int action; /* condition whether query is really issued */
+ char qname[MAXDNAME +1]; /* domain name */
+#if 0
+ int n; /* result length */
+#endif
+};
+enum {RESTGT_DOALWAYS, RESTGT_AFTERFAILURE, RESTGT_IGNORE};
+enum {RESQRY_SUCCESS, RESQRY_FAIL};
+
+struct pvt {
+ struct hostent host;
+ char * h_addr_ptrs[MAXADDRS + 1];
+ char * host_aliases[MAXALIASES];
+ char hostbuf[8*1024];
+ u_char host_addr[16]; /* IPv4 or IPv6 */
+ struct __res_state *res;
+ void (*free_res)(void *);
+};
+
+typedef union {
+ int32_t al;
+ char ac;
+} align;
+
+static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
+static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
+/* Note: the IPv6 loopback address is in the "tunnel" space */
+static const u_char v6local[] = { 0,0, 0,1 }; /* last 4 bytes of IPv6 addr */
+
+/* Forwards. */
+
+static void ho_close(struct irs_ho *this);
+static struct hostent * ho_byname(struct irs_ho *this, const char *name);
+static struct hostent * ho_byname2(struct irs_ho *this, const char *name,
+ int af);
+static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr,
+ int len, int af);
+static struct hostent * ho_next(struct irs_ho *this);
+static void ho_rewind(struct irs_ho *this);
+static void ho_minimize(struct irs_ho *this);
+static struct __res_state * ho_res_get(struct irs_ho *this);
+static void ho_res_set(struct irs_ho *this,
+ struct __res_state *res,
+ void (*free_res)(void *));
+static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name,
+ const struct addrinfo *pai);
+
+static void map_v4v6_hostent(struct hostent *hp, char **bp,
+ char *ep);
+static void addrsort(res_state, char **, int);
+static struct hostent * gethostans(struct irs_ho *this,
+ const u_char *ansbuf, int anslen,
+ const char *qname, int qtype,
+ int af, int size,
+ struct addrinfo **ret_aip,
+ const struct addrinfo *pai);
+static int add_hostent(struct pvt *pvt, char *bp, char **hap,
+ struct addrinfo *ai);
+static 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, *p;
+ int querystate = RESQRY_FAIL;
+
+ if (init(this) == -1)
+ return (NULL);
+
+ q = memget(sizeof(*q));
+ if (q == NULL) {
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
+ errno = ENOMEM;
+ goto cleanup;
+ }
+ memset(q, 0, sizeof(q));
+
+ 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 = T_AAAA;
+ q->answer = q->qbuf.buf;
+ q->anslen = sizeof(q->qbuf);
+ q->action = RESTGT_DOALWAYS;
+ break;
+ default:
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
+ errno = EAFNOSUPPORT;
+ hp = NULL;
+ goto cleanup;
+ }
+
+ /*
+ * if there aren't any dots, it could be a user-level alias.
+ * this is also done in res_nquery() since we are not the only
+ * function that looks up host names.
+ */
+ if (!strchr(name, '.') && (cp = res_hostalias(pvt->res, name,
+ tmp, sizeof tmp)))
+ name = cp;
+
+ for (p = q; p; p = p->next) {
+ switch(p->action) {
+ case RESTGT_DOALWAYS:
+ break;
+ case RESTGT_AFTERFAILURE:
+ if (querystate == RESQRY_SUCCESS)
+ continue;
+ break;
+ case RESTGT_IGNORE:
+ continue;
+ }
+
+ if ((n = res_nsearch(pvt->res, name, p->qclass, p->qtype,
+ p->answer, p->anslen)) < 0) {
+ querystate = RESQRY_FAIL;
+ continue;
+ }
+
+ memset(&ai, 0, sizeof(ai));
+ ai.ai_family = af;
+ if ((hp = gethostans(this, p->answer, n, name, p->qtype,
+ af, size, NULL,
+ (const struct addrinfo *)&ai)) != NULL)
+ goto cleanup; /* no more loop is necessary */
+
+ querystate = RESQRY_FAIL;
+ continue;
+ }
+
+ cleanup:
+ if (q != NULL)
+ memput(q, sizeof(*q));
+ return(hp);
+}
+
+static struct hostent *
+ho_byaddr(struct irs_ho *this, const void *addr, int len, int af)
+{
+ struct pvt *pvt = (struct pvt *)this->private;
+ const u_char *uaddr = addr;
+ char *qp;
+ struct hostent *hp = NULL;
+ struct addrinfo ai;
+ struct dns_res_target *q, *q2, *p;
+ int n, size, i;
+ int querystate = RESQRY_FAIL;
+
+ if (init(this) == -1)
+ return (NULL);
+
+ q = memget(sizeof(*q));
+ q2 = memget(sizeof(*q2));
+ if (q == NULL || q2 == NULL) {
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
+ errno = ENOMEM;
+ goto cleanup;
+ }
+ memset(q, 0, sizeof(q));
+ memset(q2, 0, sizeof(q2));
+
+ if (af == AF_INET6 && len == IN6ADDRSZ &&
+ (!memcmp(uaddr, mapped, sizeof mapped) ||
+ (!memcmp(uaddr, tunnelled, sizeof tunnelled) &&
+ memcmp(&uaddr[sizeof tunnelled], v6local, sizeof(v6local))))) {
+ /* Unmap. */
+ addr = (const char *)addr + sizeof mapped;
+ uaddr += sizeof mapped;
+ af = AF_INET;
+ len = INADDRSZ;
+ }
+ switch (af) {
+ case AF_INET:
+ size = INADDRSZ;
+ q->qclass = C_IN;
+ q->qtype = T_PTR;
+ q->answer = q->qbuf.buf;
+ q->anslen = sizeof(q->qbuf);
+ q->action = RESTGT_DOALWAYS;
+ break;
+ case AF_INET6:
+ size = IN6ADDRSZ;
+ q->qclass = C_IN;
+ q->qtype = T_PTR;
+ q->answer = q->qbuf.buf;
+ q->anslen = sizeof(q->qbuf);
+ q->next = q2;
+ q->action = RESTGT_DOALWAYS;
+ q2->qclass = C_IN;
+ q2->qtype = T_PTR;
+ q2->answer = q2->qbuf.buf;
+ q2->anslen = sizeof(q2->qbuf);
+ if ((pvt->res->options & RES_NO_NIBBLE2) != 0)
+ q2->action = RESTGT_IGNORE;
+ else
+ q2->action = RESTGT_AFTERFAILURE;
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
+ hp = NULL;
+ goto cleanup;
+ }
+ if (size > len) {
+ errno = EINVAL;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
+ hp = NULL;
+ goto cleanup;
+ }
+ switch (af) {
+ case AF_INET:
+ qp = q->qname;
+ (void) sprintf(qp, "%u.%u.%u.%u.in-addr.arpa",
+ (uaddr[3] & 0xff),
+ (uaddr[2] & 0xff),
+ (uaddr[1] & 0xff),
+ (uaddr[0] & 0xff));
+ break;
+ case AF_INET6:
+ if (q->action != RESTGT_IGNORE) {
+ qp = q->qname;
+ for (n = IN6ADDRSZ - 1; n >= 0; n--) {
+ i = SPRINTF((qp, "%x.%x.",
+ uaddr[n] & 0xf,
+ (uaddr[n] >> 4) & 0xf));
+ if (i < 0)
+ abort();
+ qp += i;
+ }
+#ifdef HAVE_STRLCAT
+ strlcat(q->qname, res_get_nibblesuffix(pvt->res),
+ sizeof(q->qname));
+#else
+ strcpy(qp, res_get_nibblesuffix(pvt->res));
+#endif
+ }
+ if (q2->action != RESTGT_IGNORE) {
+ qp = q2->qname;
+ for (n = IN6ADDRSZ - 1; n >= 0; n--) {
+ i = SPRINTF((qp, "%x.%x.",
+ uaddr[n] & 0xf,
+ (uaddr[n] >> 4) & 0xf));
+ if (i < 0)
+ abort();
+ qp += i;
+ }
+#ifdef HAVE_STRLCAT
+ strlcat(q->qname, res_get_nibblesuffix2(pvt->res),
+ sizeof(q->qname));
+#else
+ strcpy(qp, res_get_nibblesuffix2(pvt->res));
+#endif
+ }
+ break;
+ default:
+ abort();
+ }
+
+ for (p = q; p; p = p->next) {
+ switch(p->action) {
+ case RESTGT_DOALWAYS:
+ break;
+ case RESTGT_AFTERFAILURE:
+ if (querystate == RESQRY_SUCCESS)
+ continue;
+ break;
+ case RESTGT_IGNORE:
+ continue;
+ }
+
+ if ((n = res_nquery(pvt->res, p->qname, p->qclass, p->qtype,
+ p->answer, p->anslen)) < 0) {
+ querystate = RESQRY_FAIL;
+ continue;
+ }
+
+ memset(&ai, 0, sizeof(ai));
+ ai.ai_family = af;
+ hp = gethostans(this, p->answer, n, p->qname, T_PTR, af, size,
+ NULL, (const struct addrinfo *)&ai);
+ if (!hp) {
+ querystate = RESQRY_FAIL;
+ continue;
+ }
+
+ memcpy(pvt->host_addr, addr, len);
+ pvt->h_addr_ptrs[0] = (char *)pvt->host_addr;
+ pvt->h_addr_ptrs[1] = NULL;
+ if (af == AF_INET && (pvt->res->options & RES_USE_INET6)) {
+ map_v4v6_address((char*)pvt->host_addr,
+ (char*)pvt->host_addr);
+ pvt->host.h_addrtype = AF_INET6;
+ pvt->host.h_length = IN6ADDRSZ;
+ }
+
+ RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS);
+ goto cleanup; /* no more loop is necessary. */
+ }
+ hp = NULL; /* H_ERRNO was set by subroutines */
+
+ cleanup:
+ if (q != NULL)
+ memput(q, sizeof(*q));
+ if (q2 != NULL)
+ memput(q2, sizeof(*q2));
+ return(hp);
+}
+
+static struct hostent *
+ho_next(struct irs_ho *this) {
+
+ UNUSED(this);
+
+ return (NULL);
+}
+
+static void
+ho_rewind(struct irs_ho *this) {
+
+ UNUSED(this);
+
+ /* NOOP */
+}
+
+static void
+ho_minimize(struct irs_ho *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (pvt->res)
+ res_nclose(pvt->res);
+}
+
+static struct __res_state *
+ho_res_get(struct irs_ho *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (!pvt->res) {
+ struct __res_state *res;
+ res = (struct __res_state *)malloc(sizeof *res);
+ if (!res) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(res, 0, sizeof *res);
+ ho_res_set(this, res, free);
+ }
+
+ return (pvt->res);
+}
+
+/* XXX */
+extern struct addrinfo *addr2addrinfo __P((const struct addrinfo *,
+ const char *));
+
+static struct addrinfo *
+ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai)
+{
+ struct pvt *pvt = (struct pvt *)this->private;
+ int n;
+ char tmp[NS_MAXDNAME];
+ const char *cp;
+ struct dns_res_target *q, *q2, *p;
+ struct addrinfo sentinel, *cur;
+ int querystate = RESQRY_FAIL;
+
+ if (init(this) == -1)
+ return (NULL);
+
+ memset(&sentinel, 0, sizeof(sentinel));
+ cur = &sentinel;
+
+ q = memget(sizeof(*q));
+ q2 = memget(sizeof(*q2));
+ if (q == NULL || q2 == NULL) {
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
+ errno = ENOMEM;
+ goto cleanup;
+ }
+ memset(q, 0, sizeof(q2));
+ memset(q2, 0, sizeof(q2));
+
+ switch (pai->ai_family) {
+ case AF_UNSPEC:
+ /* prefer IPv6 */
+ q->qclass = C_IN;
+ q->qtype = T_AAAA;
+ q->answer = q->qbuf.buf;
+ q->anslen = sizeof(q->qbuf);
+ q->next = q2;
+ q->action = RESTGT_DOALWAYS;
+ q2->qclass = C_IN;
+ q2->qtype = T_A;
+ q2->answer = q2->qbuf.buf;
+ q2->anslen = sizeof(q2->qbuf);
+ q2->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 = T_AAAA;
+ q->answer = q->qbuf.buf;
+ q->anslen = sizeof(q->qbuf);
+ q->action = RESTGT_DOALWAYS;
+ break;
+ default:
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /* better error? */
+ goto cleanup;
+ }
+
+ /*
+ * if there aren't any dots, it could be a user-level alias.
+ * this is also done in res_nquery() since we are not the only
+ * function that looks up host names.
+ */
+ if (!strchr(name, '.') && (cp = res_hostalias(pvt->res, name,
+ tmp, sizeof tmp)))
+ name = cp;
+
+ for (p = q; p; p = p->next) {
+ struct addrinfo *ai;
+
+ switch(p->action) {
+ case RESTGT_DOALWAYS:
+ break;
+ case RESTGT_AFTERFAILURE:
+ if (querystate == RESQRY_SUCCESS)
+ continue;
+ break;
+ case RESTGT_IGNORE:
+ continue;
+ }
+
+ if ((n = res_nsearch(pvt->res, name, p->qclass, p->qtype,
+ p->answer, p->anslen)) < 0) {
+ querystate = RESQRY_FAIL;
+ continue;
+ }
+ (void)gethostans(this, p->answer, n, name, p->qtype,
+ pai->ai_family, /* XXX: meaningless */
+ 0, &ai, pai);
+ if (ai) {
+ querystate = RESQRY_SUCCESS;
+ cur->ai_next = ai;
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ }
+ else
+ querystate = RESQRY_FAIL;
+ }
+
+ cleanup:
+ if (q != NULL)
+ memput(q, sizeof(*q));
+ if (q2 != NULL)
+ memput(q2, sizeof(*q2));
+ return(sentinel.ai_next);
+}
+
+static void
+ho_res_set(struct irs_ho *this, struct __res_state *res,
+ void (*free_res)(void *)) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (pvt->res && pvt->free_res) {
+ res_nclose(pvt->res);
+ (*pvt->free_res)(pvt->res);
+ }
+
+ pvt->res = res;
+ pvt->free_res = free_res;
+}
+
+/* Private. */
+
+static struct hostent *
+gethostans(struct irs_ho *this,
+ const u_char *ansbuf, int anslen, const char *qname, int qtype,
+ int af, int size, /* meaningless for addrinfo cases */
+ struct addrinfo **ret_aip, const struct addrinfo *pai)
+{
+ struct pvt *pvt = (struct pvt *)this->private;
+ int type, class, ancount, qdcount, n, haveanswer, had_error;
+ int error = NETDB_SUCCESS, arcount;
+ int (*name_ok)(const char *);
+ const HEADER *hp;
+ const u_char *eom;
+ const u_char *eor;
+ const u_char *cp;
+ const char *tname;
+ const char *hname;
+ char *bp, *ep, **ap, **hap;
+ char tbuf[MAXDNAME+1];
+ struct addrinfo sentinel, *cur, ai;
+
+ 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 T_A:
+ case T_AAAA:
+ case T_ANY: /* use T_ANY only for T_A/T_AAAA lookup */
+ name_ok = res_hnok;
+ break;
+ case T_PTR:
+ name_ok = res_dnok;
+ break;
+ default:
+ abort();
+ }
+
+ pvt->host.h_addrtype = af;
+ pvt->host.h_length = size;
+ hname = pvt->host.h_name = NULL;
+
+ /*
+ * Find first satisfactory answer.
+ */
+ if (ansbuf + HFIXEDSZ > eom) {
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
+ return (NULL);
+ }
+ hp = (const HEADER *)ansbuf;
+ ancount = ntohs(hp->ancount);
+ qdcount = ntohs(hp->qdcount);
+ arcount = ntohs(hp->arcount);
+ bp = pvt->hostbuf;
+ ep = pvt->hostbuf + sizeof(pvt->hostbuf);
+ cp = ansbuf + HFIXEDSZ;
+ if (qdcount != 1) {
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
+ return (NULL);
+ }
+ n = dn_expand(ansbuf, eom, cp, bp, ep - bp);
+ if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) {
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
+ return (NULL);
+ }
+ cp += n + QFIXEDSZ;
+ if (cp > eom) {
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
+ return (NULL);
+ }
+ if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
+ /* res_nsend() has already verified that the query name is the
+ * same as the one we sent; this just gets the expanded name
+ * (i.e., with the succeeding search-domain tacked on).
+ */
+ n = strlen(bp) + 1; /* for the \0 */
+ if (n > MAXHOSTNAMELEN) {
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
+ return (NULL);
+ }
+ pvt->host.h_name = bp;
+ hname = bp;
+ bp += n;
+ /* The qname can be abbreviated, but hname is now absolute. */
+ qname = pvt->host.h_name;
+ }
+ ap = pvt->host_aliases;
+ *ap = NULL;
+ pvt->host.h_aliases = pvt->host_aliases;
+ hap = pvt->h_addr_ptrs;
+ *hap = NULL;
+ pvt->host.h_addr_list = pvt->h_addr_ptrs;
+ haveanswer = 0;
+ had_error = 0;
+ while (ancount-- > 0 && cp < eom && !had_error) {
+ n = dn_expand(ansbuf, eom, cp, bp, ep - bp);
+ if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) {
+ had_error++;
+ continue;
+ }
+ cp += n; /* name */
+ BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
+ type = ns_get16(cp);
+ cp += INT16SZ; /* type */
+ class = ns_get16(cp);
+ cp += INT16SZ + INT32SZ; /* class, TTL */
+ n = ns_get16(cp);
+ cp += INT16SZ; /* len */
+ BOUNDS_CHECK(cp, n);
+ if (class != C_IN) {
+ cp += n;
+ continue;
+ }
+ eor = cp + n;
+ if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
+ type == T_CNAME) {
+ if (haveanswer) {
+ int level = LOG_CRIT;
+#ifdef LOG_SECURITY
+ level |= LOG_SECURITY;
+#endif
+ syslog(level,
+ "gethostans: possible attempt to exploit buffer overflow while looking up %s",
+ *qname ? qname : ".");
+ }
+ n = dn_expand(ansbuf, eor, cp, tbuf, sizeof tbuf);
+ if (n < 0 || !maybe_ok(pvt->res, tbuf, name_ok)) {
+ had_error++;
+ continue;
+ }
+ cp += n;
+ /* Store alias. */
+ if (ap >= &pvt->host_aliases[MAXALIASES-1])
+ continue;
+ *ap++ = bp;
+ n = strlen(bp) + 1; /* for the \0 */
+ bp += n;
+ /* Get canonical name. */
+ n = strlen(tbuf) + 1; /* for the \0 */
+ if (n > (ep - bp) || n > MAXHOSTNAMELEN) {
+ had_error++;
+ continue;
+ }
+#ifdef HAVE_STRLCPY
+ strlcpy(bp, tbuf, ep - bp);
+#else
+ strcpy(bp, tbuf);
+#endif
+ pvt->host.h_name = bp;
+ hname = bp;
+ bp += n;
+ continue;
+ }
+ if (qtype == T_PTR && type == T_CNAME) {
+ n = dn_expand(ansbuf, eor, cp, tbuf, sizeof tbuf);
+ if (n < 0 || !maybe_dnok(pvt->res, tbuf)) {
+ had_error++;
+ continue;
+ }
+ cp += n;
+#ifdef RES_USE_DNAME
+ if ((pvt->res->options & RES_USE_DNAME) != 0)
+#endif
+ {
+ /*
+ * We may be able to check this regardless
+ * of the USE_DNAME bit, but we add the check
+ * for now since the DNAME support is
+ * experimental.
+ */
+ if (ns_samename(tname, bp) != 1)
+ continue;
+ }
+ /* Get canonical name. */
+ n = strlen(tbuf) + 1; /* for the \0 */
+ if (n > (ep - bp)) {
+ had_error++;
+ continue;
+ }
+#ifdef HAVE_STRLCPY
+ strlcpy(bp, tbuf, ep - bp);
+#else
+ strcpy(bp, tbuf);
+#endif
+ tname = bp;
+ bp += n;
+ continue;
+ }
+ if (qtype == T_ANY) {
+ if (!(type == T_A || type == T_AAAA)) {
+ cp += n;
+ continue;
+ }
+ } else if (type != qtype) {
+ cp += n;
+ continue;
+ }
+ switch (type) {
+ case T_PTR:
+ if (ret_aip != NULL) {
+ /* addrinfo never needs T_PTR */
+ cp += n;
+ continue;
+ }
+ if (ns_samename(tname, bp) != 1) {
+ cp += n;
+ continue;
+ }
+ n = dn_expand(ansbuf, eor, cp, bp, ep - bp);
+ if (n < 0 || !maybe_hnok(pvt->res, bp) ||
+ n >= MAXHOSTNAMELEN) {
+ had_error++;
+ break;
+ }
+ cp += n;
+ if (!haveanswer) {
+ pvt->host.h_name = bp;
+ hname = bp;
+ }
+ else if (ap < &pvt->host_aliases[MAXALIASES-1])
+ *ap++ = bp;
+ else
+ n = -1;
+ if (n != -1) {
+ n = strlen(bp) + 1; /* for the \0 */
+ bp += n;
+ }
+ break;
+ case T_A:
+ case T_AAAA:
+ if (ns_samename(hname, bp) != 1) {
+ cp += n;
+ continue;
+ }
+ if (type == T_A && n != INADDRSZ) {
+ cp += n;
+ continue;
+ }
+ if (type == T_AAAA && n != IN6ADDRSZ) {
+ cp += n;
+ continue;
+ }
+
+ /* make addrinfo. don't overwrite constant PAI */
+ ai = *pai;
+ ai.ai_family = (type == T_AAAA) ? AF_INET6 : AF_INET;
+ cur->ai_next = addr2addrinfo(
+ (const struct addrinfo *)&ai,
+ (const char *)cp);
+ if (cur->ai_next == NULL)
+ had_error++;
+
+ if (!haveanswer) {
+ int nn;
+
+ nn = strlen(bp) + 1; /* for the \0 */
+ if (nn >= MAXHOSTNAMELEN) {
+ cp += n;
+ had_error++;
+ continue;
+ }
+ pvt->host.h_name = bp;
+ hname = bp;
+ bp += nn;
+ }
+ /* Ensure alignment. */
+ bp = (char *)(((u_long)bp + (sizeof(align) - 1)) &
+ ~(sizeof(align) - 1));
+ /* Avoid overflows. */
+ if (bp + n >= &pvt->hostbuf[sizeof pvt->hostbuf]) {
+ had_error++;
+ continue;
+ }
+ if (ret_aip) { /* need addrinfo. keep it. */
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ } else if (cur->ai_next) { /* need hostent */
+ struct addrinfo *aip = cur->ai_next;
+
+ for (aip = cur->ai_next; aip;
+ aip = aip->ai_next) {
+ int m;
+
+ m = add_hostent(pvt, bp, hap, aip);
+ if (m < 0) {
+ had_error++;
+ break;
+ }
+ if (m == 0)
+ continue;
+ if (hap < &pvt->h_addr_ptrs[MAXADDRS-1])
+ hap++;
+ *hap = NULL;
+ bp += m;
+ }
+
+ freeaddrinfo(cur->ai_next);
+ cur->ai_next = NULL;
+ }
+ cp += n;
+ break;
+ default:
+ abort();
+ }
+ if (!had_error)
+ haveanswer++;
+ }
+ if (haveanswer) {
+ if (ret_aip == NULL) {
+ *ap = NULL;
+ *hap = NULL;
+
+ if (pvt->res->nsort && haveanswer > 1 && qtype == T_A)
+ addrsort(pvt->res, pvt->h_addr_ptrs,
+ haveanswer);
+ if (pvt->host.h_name == NULL) {
+ n = strlen(qname) + 1; /* for the \0 */
+ if (n > (ep - bp) || n >= MAXHOSTNAMELEN)
+ goto no_recovery;
+#ifdef HAVE_STRLCPY
+ strlcpy(bp, qname, ep - bp);
+#else
+ strcpy(bp, qname);
+#endif
+ pvt->host.h_name = bp;
+ bp += n;
+ }
+ if (pvt->res->options & RES_USE_INET6)
+ map_v4v6_hostent(&pvt->host, &bp, ep);
+ RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS);
+ return (&pvt->host);
+ } else {
+ if ((pai->ai_flags & AI_CANONNAME) != 0) {
+ if (pvt->host.h_name == NULL) {
+ sentinel.ai_next->ai_canonname =
+ strdup(qname);
+ }
+ else {
+ sentinel.ai_next->ai_canonname =
+ strdup(pvt->host.h_name);
+ }
+ }
+ *ret_aip = sentinel.ai_next;
+ return(NULL);
+ }
+ }
+ no_recovery:
+ if (sentinel.ai_next) {
+ /* this should be impossible, but check it for safety */
+ freeaddrinfo(sentinel.ai_next);
+ }
+ if (error == NETDB_SUCCESS)
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
+ else
+ RES_SET_H_ERRNO(pvt->res, error);
+ return(NULL);
+}
+
+static int
+add_hostent(struct pvt *pvt, char *bp, char **hap, struct addrinfo *ai)
+{
+ int addrlen;
+ char *addrp;
+ const char **tap;
+ char *obp = bp;
+
+ switch(ai->ai_addr->sa_family) {
+ case AF_INET6:
+ addrlen = IN6ADDRSZ;
+ addrp = (char *)&((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr;
+ break;
+ case AF_INET:
+ addrlen = INADDRSZ;
+ addrp = (char *)&((struct sockaddr_in *)ai->ai_addr)->sin_addr;
+ break;
+ default:
+ return(-1); /* abort? */
+ }
+
+ /* Ensure alignment. */
+ bp = (char *)(((u_long)bp + (sizeof(align) - 1)) &
+ ~(sizeof(align) - 1));
+ /* Avoid overflows. */
+ if (bp + addrlen >= &pvt->hostbuf[sizeof pvt->hostbuf])
+ return(-1);
+ if (hap >= &pvt->h_addr_ptrs[MAXADDRS-1])
+ return(0); /* fail, but not treat it as an error. */
+
+ /* Suppress duplicates. */
+ for (tap = (const char **)pvt->h_addr_ptrs;
+ *tap != NULL;
+ tap++)
+ if (memcmp(*tap, addrp, addrlen) == 0)
+ break;
+ if (*tap != NULL)
+ return (0);
+
+ memcpy(*hap = bp, addrp, addrlen);
+ return((bp + addrlen) - obp);
+}
+
+static void
+map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep) {
+ char **ap;
+
+ if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
+ return;
+ hp->h_addrtype = AF_INET6;
+ hp->h_length = IN6ADDRSZ;
+ for (ap = hp->h_addr_list; *ap; ap++) {
+ int i = (u_long)*bpp % sizeof(align);
+
+ if (i != 0)
+ i = sizeof(align) - i;
+
+ if ((ep - *bpp) < (i + IN6ADDRSZ)) {
+ /* Out of memory. Truncate address list here. */
+ *ap = NULL;
+ return;
+ }
+ *bpp += i;
+ map_v4v6_address(*ap, *bpp);
+ *ap = *bpp;
+ *bpp += IN6ADDRSZ;
+ }
+}
+
+static void
+addrsort(res_state statp, char **ap, int num) {
+ int i, j, needsort = 0, aval[MAXADDRS];
+ char **p;
+
+ p = ap;
+ for (i = 0; i < num; i++, p++) {
+ for (j = 0 ; (unsigned)j < statp->nsort; j++)
+ if (statp->sort_list[j].addr.s_addr ==
+ (((struct in_addr *)(*p))->s_addr &
+ statp->sort_list[j].mask))
+ break;
+ aval[i] = j;
+ if (needsort == 0 && i > 0 && j < aval[i-1])
+ needsort = i;
+ }
+ if (!needsort)
+ return;
+
+ while (needsort < num) {
+ for (j = needsort - 1; j >= 0; j--) {
+ if (aval[j] > aval[j+1]) {
+ char *hp;
+
+ i = aval[j];
+ aval[j] = aval[j+1];
+ aval[j+1] = i;
+
+ hp = ap[j];
+ ap[j] = ap[j+1];
+ ap[j+1] = hp;
+
+ } else
+ break;
+ }
+ needsort++;
+ }
+}
+
+static int
+init(struct irs_ho *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (!pvt->res && !ho_res_get(this))
+ return (-1);
+ if (((pvt->res->options & RES_INIT) == 0) &&
+ res_ninit(pvt->res) == -1)
+ return (-1);
+ return (0);
+}
diff --git a/usr/src/lib/libresolv2/common/irs/dns_nw.c b/usr/src/lib/libresolv2/common/irs/dns_nw.c
new file mode 100644
index 0000000000..bcae67480d
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/dns_nw.c
@@ -0,0 +1,601 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: dns_nw.c,v 1.25 2002/07/18 02:07:43 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/* Imports. */
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#include "irs_p.h"
+#include "dns_p.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) sprintf x
+#endif
+
+/* Definitions. */
+
+#define MAXALIASES 35
+
+#define MAXPACKET (64*1024)
+
+struct pvt {
+ struct nwent net;
+ char * ali[MAXALIASES];
+ char buf[BUFSIZ+1];
+ struct __res_state * res;
+ void (*free_res)(void *);
+};
+
+typedef union {
+ long al;
+ char ac;
+} align;
+
+enum by_what { by_addr, by_name };
+
+/* Forwards. */
+
+static void nw_close(struct irs_nw *);
+static struct nwent * nw_byname(struct irs_nw *, const char *, int);
+static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int);
+static struct nwent * nw_next(struct irs_nw *);
+static void nw_rewind(struct irs_nw *);
+static void nw_minimize(struct irs_nw *);
+static struct __res_state * nw_res_get(struct irs_nw *this);
+static void nw_res_set(struct irs_nw *this,
+ struct __res_state *res,
+ void (*free_res)(void *));
+
+static struct nwent * get1101byaddr(struct irs_nw *, u_char *, int);
+static struct nwent * get1101byname(struct irs_nw *, const char *);
+static struct nwent * get1101answer(struct irs_nw *,
+ u_char *ansbuf, int anslen,
+ enum by_what by_what,
+ int af, const char *name,
+ const u_char *addr, int addrlen);
+static struct nwent * get1101mask(struct irs_nw *this, struct nwent *);
+static int make1101inaddr(const u_char *, int, char *, int);
+static void normalize_name(char *name);
+static int init(struct irs_nw *this);
+
+/* Exports. */
+
+struct irs_nw *
+irs_dns_nw(struct irs_acc *this) {
+ struct irs_nw *nw;
+ struct pvt *pvt;
+
+ UNUSED(this);
+
+ if (!(pvt = memget(sizeof *pvt))) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pvt, 0, sizeof *pvt);
+ if (!(nw = memget(sizeof *nw))) {
+ memput(pvt, sizeof *pvt);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(nw, 0x5e, sizeof *nw);
+ nw->private = pvt;
+ nw->close = nw_close;
+ nw->byname = nw_byname;
+ nw->byaddr = nw_byaddr;
+ nw->next = nw_next;
+ nw->rewind = nw_rewind;
+ nw->minimize = nw_minimize;
+ nw->res_get = nw_res_get;
+ nw->res_set = nw_res_set;
+ return (nw);
+}
+
+/* Methods. */
+
+static void
+nw_close(struct irs_nw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ nw_minimize(this);
+
+ if (pvt->res && pvt->free_res)
+ (*pvt->free_res)(pvt->res);
+
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
+}
+
+static struct nwent *
+nw_byname(struct irs_nw *this, const char *name, int af) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (init(this) == -1)
+ return (NULL);
+
+ switch (af) {
+ case AF_INET:
+ return (get1101byname(this, name));
+ default:
+ (void)NULL;
+ }
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
+ errno = EAFNOSUPPORT;
+ return (NULL);
+}
+
+static struct nwent *
+nw_byaddr(struct irs_nw *this, void *net, int len, int af) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (init(this) == -1)
+ return (NULL);
+
+ switch (af) {
+ case AF_INET:
+ return (get1101byaddr(this, net, len));
+ default:
+ (void)NULL;
+ }
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
+ errno = EAFNOSUPPORT;
+ return (NULL);
+}
+
+static struct nwent *
+nw_next(struct irs_nw *this) {
+
+ UNUSED(this);
+
+ return (NULL);
+}
+
+static void
+nw_rewind(struct irs_nw *this) {
+ UNUSED(this);
+ /* NOOP */
+}
+
+static void
+nw_minimize(struct irs_nw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (pvt->res)
+ res_nclose(pvt->res);
+}
+
+static struct __res_state *
+nw_res_get(struct irs_nw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (!pvt->res) {
+ struct __res_state *res;
+ res = (struct __res_state *)malloc(sizeof *res);
+ if (!res) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(res, 0, sizeof *res);
+ nw_res_set(this, res, free);
+ }
+
+ return (pvt->res);
+}
+
+static void
+nw_res_set(struct irs_nw *this, struct __res_state *res,
+ void (*free_res)(void *)) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (pvt->res && pvt->free_res) {
+ res_nclose(pvt->res);
+ (*pvt->free_res)(pvt->res);
+ }
+
+ pvt->res = res;
+ pvt->free_res = free_res;
+}
+
+/* Private. */
+
+static struct nwent *
+get1101byname(struct irs_nw *this, const char *name) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ u_char *ansbuf;
+ int anslen;
+ struct nwent *result;
+
+ ansbuf = memget(MAXPACKET);
+ if (ansbuf == NULL) {
+ errno = ENOMEM;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
+ return (NULL);
+ }
+ anslen = res_nsearch(pvt->res, name, C_IN, T_PTR, ansbuf, MAXPACKET);
+ if (anslen < 0) {
+ memput(ansbuf, MAXPACKET);
+ return (NULL);
+ }
+ result = get1101mask(this, get1101answer(this, ansbuf, anslen, by_name,
+ AF_INET, name, NULL, 0));
+ memput(ansbuf, MAXPACKET);
+ return (result);
+}
+
+static struct nwent *
+get1101byaddr(struct irs_nw *this, u_char *net, int len) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ char qbuf[sizeof "255.255.255.255.in-addr.arpa"];
+ struct nwent *result;
+ u_char *ansbuf;
+ int anslen;
+
+ if (len < 1 || len > 32) {
+ errno = EINVAL;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
+ return (NULL);
+ }
+ if (make1101inaddr(net, len, qbuf, sizeof qbuf) < 0)
+ return (NULL);
+ ansbuf = memget(MAXPACKET);
+ if (ansbuf == NULL) {
+ errno = ENOMEM;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
+ return (NULL);
+ }
+ anslen = res_nquery(pvt->res, qbuf, C_IN, T_PTR, ansbuf, MAXPACKET);
+ if (anslen < 0) {
+ memput(ansbuf, MAXPACKET);
+ return (NULL);
+ }
+ result = get1101mask(this, get1101answer(this, ansbuf, anslen, by_addr,
+ AF_INET, NULL, net, len));
+ memput(ansbuf, MAXPACKET);
+ return (result);
+}
+
+static struct nwent *
+get1101answer(struct irs_nw *this,
+ u_char *ansbuf, int anslen, enum by_what by_what,
+ int af, const char *name, const u_char *addr, int addrlen)
+{
+ struct pvt *pvt = (struct pvt *)this->private;
+ int type, class, ancount, qdcount, haveanswer;
+ char *bp, *ep, **ap;
+ u_char *cp, *eom;
+ HEADER *hp;
+
+ /* Initialize, and parse header. */
+ eom = ansbuf + anslen;
+ if (ansbuf + HFIXEDSZ > eom) {
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
+ return (NULL);
+ }
+ hp = (HEADER *)ansbuf;
+ cp = ansbuf + HFIXEDSZ;
+ qdcount = ntohs(hp->qdcount);
+ while (qdcount-- > 0) {
+ int n = dn_skipname(cp, eom);
+ cp += n + QFIXEDSZ;
+ if (n < 0 || cp > eom) {
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
+ return (NULL);
+ }
+ }
+ ancount = ntohs(hp->ancount);
+ if (!ancount) {
+ if (hp->aa)
+ RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
+ else
+ RES_SET_H_ERRNO(pvt->res, TRY_AGAIN);
+ return (NULL);
+ }
+
+ /* Prepare a return structure. */
+ bp = pvt->buf;
+ ep = pvt->buf + sizeof (pvt->buf);
+ pvt->net.n_name = NULL;
+ pvt->net.n_aliases = pvt->ali;
+ pvt->net.n_addrtype = af;
+ pvt->net.n_addr = NULL;
+ pvt->net.n_length = addrlen;
+
+ /* Save input key if given. */
+ switch (by_what) {
+ case by_name:
+ if (name != NULL) {
+ int n = strlen(name) + 1;
+
+ if (n > (ep - bp)) {
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
+ return (NULL);
+ }
+#ifdef HAVE_STRLCPY
+ strlcpy(bp, name, ep - bp);
+ pvt->net.n_name = bp;
+#else
+ pvt->net.n_name = strcpy(bp, name);
+#endif
+ bp += n;
+ }
+ break;
+ case by_addr:
+ if (addr != NULL && addrlen != 0) {
+ int n = addrlen / 8 + ((addrlen % 8) != 0);
+
+ if (INADDRSZ > (ep - bp)) {
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
+ return (NULL);
+ }
+ memset(bp, 0, INADDRSZ);
+ memcpy(bp, addr, n);
+ pvt->net.n_addr = bp;
+ bp += INADDRSZ;
+ }
+ break;
+ default:
+ abort();
+ }
+
+ /* Parse the answer, collect aliases. */
+ ap = pvt->ali;
+ haveanswer = 0;
+ while (--ancount >= 0 && cp < eom) {
+ int n = dn_expand(ansbuf, eom, cp, bp, ep - bp);
+
+ cp += n; /* Owner */
+ if (n < 0 || !maybe_dnok(pvt->res, bp) ||
+ cp + 3 * INT16SZ + INT32SZ > eom) {
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
+ return (NULL);
+ }
+ GETSHORT(type, cp); /* Type */
+ GETSHORT(class, cp); /* Class */
+ cp += INT32SZ; /* TTL */
+ GETSHORT(n, cp); /* RDLENGTH */
+ if (class == C_IN && type == T_PTR) {
+ int nn;
+
+ nn = dn_expand(ansbuf, eom, cp, bp, ep - bp);
+ if (nn < 0 || !maybe_hnok(pvt->res, bp) || nn != n) {
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
+ return (NULL);
+ }
+ normalize_name(bp);
+ switch (by_what) {
+ case by_addr: {
+ if (pvt->net.n_name == NULL)
+ pvt->net.n_name = bp;
+ else if (ns_samename(pvt->net.n_name, bp) == 1)
+ break;
+ else
+ *ap++ = bp;
+ nn = strlen(bp) + 1;
+ bp += nn;
+ haveanswer++;
+ break;
+ }
+ case by_name: {
+ u_int b1, b2, b3, b4;
+
+ if (pvt->net.n_addr != NULL ||
+ sscanf(bp, "%u.%u.%u.%u.in-addr.arpa",
+ &b1, &b2, &b3, &b4) != 4)
+ break;
+ if ((ep - bp) < INADDRSZ) {
+ RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
+ return (NULL);
+ }
+ pvt->net.n_addr = bp;
+ *bp++ = b4;
+ *bp++ = b3;
+ *bp++ = b2;
+ *bp++ = b1;
+ pvt->net.n_length = INADDRSZ * 8;
+ haveanswer++;
+ }
+ }
+ }
+ cp += n; /* RDATA */
+ }
+ if (!haveanswer) {
+ RES_SET_H_ERRNO(pvt->res, TRY_AGAIN);
+ return (NULL);
+ }
+ *ap = NULL;
+
+ return (&pvt->net);
+}
+
+static struct nwent *
+get1101mask(struct irs_nw *this, struct nwent *nwent) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ char qbuf[sizeof "255.255.255.255.in-addr.arpa"], owner[MAXDNAME];
+ int anslen, type, class, ancount, qdcount;
+ u_char *ansbuf, *cp, *eom;
+ HEADER *hp;
+
+ if (!nwent)
+ return (NULL);
+ if (make1101inaddr(nwent->n_addr, nwent->n_length, qbuf, sizeof qbuf)
+ < 0) {
+ /* "First, do no harm." */
+ return (nwent);
+ }
+
+ ansbuf = memget(MAXPACKET);
+ if (ansbuf == NULL) {
+ errno = ENOMEM;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
+ return (NULL);
+ }
+ /* Query for the A RR that would hold this network's mask. */
+ anslen = res_nquery(pvt->res, qbuf, C_IN, T_A, ansbuf, MAXPACKET);
+ if (anslen < HFIXEDSZ) {
+ memput(ansbuf, MAXPACKET);
+ return (nwent);
+ }
+
+ /* Initialize, and parse header. */
+ hp = (HEADER *)ansbuf;
+ cp = ansbuf + HFIXEDSZ;
+ eom = ansbuf + anslen;
+ qdcount = ntohs(hp->qdcount);
+ while (qdcount-- > 0) {
+ int n = dn_skipname(cp, eom);
+ cp += n + QFIXEDSZ;
+ if (n < 0 || cp > eom) {
+ memput(ansbuf, MAXPACKET);
+ return (nwent);
+ }
+ }
+ ancount = ntohs(hp->ancount);
+
+ /* Parse the answer, collect aliases. */
+ while (--ancount >= 0 && cp < eom) {
+ int n = dn_expand(ansbuf, eom, cp, owner, sizeof owner);
+
+ if (n < 0 || !maybe_dnok(pvt->res, owner))
+ break;
+ cp += n; /* Owner */
+ if (cp + 3 * INT16SZ + INT32SZ > eom)
+ break;
+ GETSHORT(type, cp); /* Type */
+ GETSHORT(class, cp); /* Class */
+ cp += INT32SZ; /* TTL */
+ GETSHORT(n, cp); /* RDLENGTH */
+ if (cp + n > eom)
+ break;
+ if (n == INADDRSZ && class == C_IN && type == T_A &&
+ ns_samename(qbuf, owner) == 1) {
+ /* This A RR indicates the actual netmask. */
+ int nn, mm;
+
+ nwent->n_length = 0;
+ for (nn = 0; nn < INADDRSZ; nn++)
+ for (mm = 7; mm >= 0; mm--)
+ if (cp[nn] & (1 << mm))
+ nwent->n_length++;
+ else
+ break;
+ }
+ cp += n; /* RDATA */
+ }
+ memput(ansbuf, MAXPACKET);
+ return (nwent);
+}
+
+static int
+make1101inaddr(const u_char *net, int bits, char *name, int size) {
+ int n, m;
+ char *ep;
+
+ ep = name + size;
+
+ /* Zero fill any whole bytes left out of the prefix. */
+ for (n = (32 - bits) / 8; n > 0; n--) {
+ if (ep - name < (int)(sizeof "0."))
+ goto emsgsize;
+ m = SPRINTF((name, "0."));
+ name += m;
+ }
+
+ /* Format the partial byte, if any, within the prefix. */
+ if ((n = bits % 8) != 0) {
+ if (ep - name < (int)(sizeof "255."))
+ goto emsgsize;
+ m = SPRINTF((name, "%u.",
+ net[bits / 8] & ~((1 << (8 - n)) - 1)));
+ name += m;
+ }
+
+ /* Format the whole bytes within the prefix. */
+ for (n = bits / 8; n > 0; n--) {
+ if (ep - name < (int)(sizeof "255."))
+ goto emsgsize;
+ m = SPRINTF((name, "%u.", net[n - 1]));
+ name += m;
+ }
+
+ /* Add the static text. */
+ if (ep - name < (int)(sizeof "in-addr.arpa"))
+ goto emsgsize;
+ (void) SPRINTF((name, "in-addr.arpa"));
+ return (0);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+static void
+normalize_name(char *name) {
+ char *t;
+
+ /* Make lower case. */
+ for (t = name; *t; t++)
+ if (isascii((unsigned char)*t) && isupper((unsigned char)*t))
+ *t = tolower(*t);
+
+ /* Remove trailing dots. */
+ while (t > name && t[-1] == '.')
+ *--t = '\0';
+}
+
+static int
+init(struct irs_nw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (!pvt->res && !nw_res_get(this))
+ return (-1);
+ if (((pvt->res->options & RES_INIT) == 0) &&
+ res_ninit(pvt->res) == -1)
+ return (-1);
+ return (0);
+}
diff --git a/usr/src/lib/libresolv2/common/irs/dns_p.h b/usr/src/lib/libresolv2/common/irs/dns_p.h
new file mode 100644
index 0000000000..cc45a8e3fc
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/dns_p.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * $Id: dns_p.h,v 1.11 1999/06/03 20:50:36 vixie Exp $
+ */
+
+#ifndef _DNS_P_H_INCLUDED
+#define _DNS_P_H_INCLUDED
+
+#define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0 || \
+ (ok)(nm) != 0)
+#define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
+#define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)
+
+/*
+ * Object state.
+ */
+struct dns_p {
+ void *hes_ctx;
+ struct __res_state *res;
+ void (*free_res) __P((void *));
+};
+
+/*
+ * Methods.
+ */
+
+extern struct irs_gr * irs_dns_gr __P((struct irs_acc *));
+extern struct irs_pw * irs_dns_pw __P((struct irs_acc *));
+extern struct irs_sv * irs_dns_sv __P((struct irs_acc *));
+extern struct irs_pr * irs_dns_pr __P((struct irs_acc *));
+extern struct irs_ho * irs_dns_ho __P((struct irs_acc *));
+extern struct irs_nw * irs_dns_nw __P((struct irs_acc *));
+
+#endif /*_DNS_P_H_INCLUDED*/
diff --git a/usr/src/lib/libresolv2/common/irs/dns_pr.c b/usr/src/lib/libresolv2/common/irs/dns_pr.c
new file mode 100644
index 0000000000..10a574e0ea
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/dns_pr.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: dns_pr.c,v 1.15 2001/05/29 05:48:31 marka Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#include "irs_p.h"
+#include "hesiod.h"
+#include "dns_p.h"
+
+/* Types. */
+
+struct pvt {
+ struct dns_p * dns;
+ struct protoent proto;
+ char * prbuf;
+};
+
+/* Forward. */
+
+static void pr_close(struct irs_pr *);
+static struct protoent * pr_byname(struct irs_pr *, const char *);
+static struct protoent * pr_bynumber(struct irs_pr *, int);
+static struct protoent * pr_next(struct irs_pr *);
+static void pr_rewind(struct irs_pr *);
+static void pr_minimize(struct irs_pr *);
+static struct __res_state * pr_res_get(struct irs_pr *);
+static void pr_res_set(struct irs_pr *,
+ struct __res_state *,
+ void (*)(void *));
+
+static struct protoent * parse_hes_list(struct irs_pr *, char **);
+
+/* Public. */
+
+struct irs_pr *
+irs_dns_pr(struct irs_acc *this) {
+ struct dns_p *dns = (struct dns_p *)this->private;
+ struct pvt *pvt;
+ struct irs_pr *pr;
+
+ if (!dns->hes_ctx) {
+ errno = ENODEV;
+ return (NULL);
+ }
+ if (!(pvt = memget(sizeof *pvt))) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pvt, 0, sizeof *pvt);
+ if (!(pr = memget(sizeof *pr))) {
+ memput(pvt, sizeof *pvt);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pr, 0x5e, sizeof *pr);
+ pvt->dns = dns;
+ pr->private = pvt;
+ pr->byname = pr_byname;
+ pr->bynumber = pr_bynumber;
+ pr->next = pr_next;
+ pr->rewind = pr_rewind;
+ pr->close = pr_close;
+ pr->minimize = pr_minimize;
+ pr->res_get = pr_res_get;
+ pr->res_set = pr_res_set;
+ return (pr);
+}
+
+/* Methods. */
+
+static void
+pr_close(struct irs_pr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (pvt->proto.p_aliases)
+ free(pvt->proto.p_aliases);
+ if (pvt->prbuf)
+ free(pvt->prbuf);
+
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
+}
+
+static struct protoent *
+pr_byname(struct irs_pr *this, const char *name) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct dns_p *dns = pvt->dns;
+ struct protoent *proto;
+ char **hes_list;
+
+ if (!(hes_list = hesiod_resolve(dns->hes_ctx, name, "protocol")))
+ return (NULL);
+
+ proto = parse_hes_list(this, hes_list);
+ hesiod_free_list(dns->hes_ctx, hes_list);
+ return (proto);
+}
+
+static struct protoent *
+pr_bynumber(struct irs_pr *this, int num) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct dns_p *dns = pvt->dns;
+ struct protoent *proto;
+ char numstr[16];
+ char **hes_list;
+
+ sprintf(numstr, "%d", num);
+ if (!(hes_list = hesiod_resolve(dns->hes_ctx, numstr, "protonum")))
+ return (NULL);
+
+ proto = parse_hes_list(this, hes_list);
+ hesiod_free_list(dns->hes_ctx, hes_list);
+ return (proto);
+}
+
+static struct protoent *
+pr_next(struct irs_pr *this) {
+ UNUSED(this);
+ errno = ENODEV;
+ return (NULL);
+}
+
+static void
+pr_rewind(struct irs_pr *this) {
+ UNUSED(this);
+ /* NOOP */
+}
+
+static void
+pr_minimize(struct irs_pr *this) {
+ UNUSED(this);
+ /* NOOP */
+}
+
+static struct __res_state *
+pr_res_get(struct irs_pr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct dns_p *dns = pvt->dns;
+
+ return (__hesiod_res_get(dns->hes_ctx));
+}
+
+static void
+pr_res_set(struct irs_pr *this, struct __res_state * res,
+ void (*free_res)(void *)) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct dns_p *dns = pvt->dns;
+
+ __hesiod_res_set(dns->hes_ctx, res, free_res);
+}
+
+/* Private. */
+
+static struct protoent *
+parse_hes_list(struct irs_pr *this, char **hes_list) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ char *p, *cp, **cpp, **new;
+ int num = 0;
+ int max = 0;
+
+ for (cpp = hes_list; *cpp; cpp++) {
+ cp = *cpp;
+
+ /* Strip away comments, if any. */
+ if ((p = strchr(cp, '#')))
+ *p = 0;
+
+ /* Skip blank lines. */
+ p = cp;
+ while (*p && !isspace((unsigned char)*p))
+ p++;
+ if (!*p)
+ continue;
+
+ /* OK, we've got a live one. Let's parse it for real. */
+ if (pvt->prbuf)
+ free(pvt->prbuf);
+ pvt->prbuf = strdup(cp);
+
+ p = pvt->prbuf;
+ pvt->proto.p_name = p;
+ while (*p && !isspace((unsigned char)*p))
+ p++;
+ if (!*p)
+ continue;
+ *p++ = '\0';
+
+ pvt->proto.p_proto = atoi(p);
+ while (*p && !isspace((unsigned char)*p))
+ p++;
+ if (*p)
+ *p++ = '\0';
+
+ while (*p) {
+ if ((num + 1) >= max || !pvt->proto.p_aliases) {
+ max += 10;
+ new = realloc(pvt->proto.p_aliases,
+ max * sizeof(char *));
+ if (!new) {
+ errno = ENOMEM;
+ goto cleanup;
+ }
+ pvt->proto.p_aliases = new;
+ }
+ pvt->proto.p_aliases[num++] = p;
+ while (*p && !isspace((unsigned char)*p))
+ p++;
+ if (*p)
+ *p++ = '\0';
+ }
+ if (!pvt->proto.p_aliases)
+ pvt->proto.p_aliases = malloc(sizeof(char *));
+ if (!pvt->proto.p_aliases)
+ goto cleanup;
+ pvt->proto.p_aliases[num] = NULL;
+ return (&pvt->proto);
+ }
+
+ cleanup:
+ if (pvt->proto.p_aliases) {
+ free(pvt->proto.p_aliases);
+ pvt->proto.p_aliases = NULL;
+ }
+ if (pvt->prbuf) {
+ free(pvt->prbuf);
+ pvt->prbuf = NULL;
+ }
+ return (NULL);
+}
diff --git a/usr/src/lib/libresolv2/common/irs/dns_pw.c b/usr/src/lib/libresolv2/common/irs/dns_pw.c
new file mode 100644
index 0000000000..c40ef80e15
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/dns_pw.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: dns_pw.c,v 1.19 2001/05/29 05:48:32 marka Exp $";
+#endif
+
+#include "port_before.h"
+
+#ifndef WANT_IRS_PW
+static int __bind_irs_pw_unneeded;
+#else
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <isc/memcluster.h>
+
+#include <irs.h>
+
+#include "port_after.h"
+
+#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/usr/src/lib/libresolv2/common/irs/dns_sv.c b/usr/src/lib/libresolv2/common/irs/dns_sv.c
new file mode 100644
index 0000000000..6afeb5a56e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/dns_sv.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: dns_sv.c,v 1.20 2001/05/29 05:48:33 marka Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#include "irs_p.h"
+#include "hesiod.h"
+#include "dns_p.h"
+
+/* Definitions */
+
+struct pvt {
+ struct dns_p * dns;
+ struct servent serv;
+ char * svbuf;
+ struct __res_state * res;
+ void (*free_res)(void *);
+};
+
+/* Forward. */
+
+static void sv_close(struct irs_sv *);
+static struct servent * sv_byname(struct irs_sv *,
+ const char *, const char *);
+static struct servent * sv_byport(struct irs_sv *, int, const char *);
+static struct servent * sv_next(struct irs_sv *);
+static void sv_rewind(struct irs_sv *);
+static void sv_minimize(struct irs_sv *);
+#ifdef SV_RES_SETGET
+static struct __res_state * sv_res_get(struct irs_sv *);
+static void sv_res_set(struct irs_sv *,
+ struct __res_state *,
+ void (*)(void *));
+#endif
+
+static struct servent * parse_hes_list(struct irs_sv *,
+ char **, const char *);
+
+/* Public */
+
+struct irs_sv *
+irs_dns_sv(struct irs_acc *this) {
+ struct dns_p *dns = (struct dns_p *)this->private;
+ struct irs_sv *sv;
+ struct pvt *pvt;
+
+ if (!dns || !dns->hes_ctx) {
+ errno = ENODEV;
+ return (NULL);
+ }
+ if (!(pvt = memget(sizeof *pvt))) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pvt, 0, sizeof *pvt);
+ pvt->dns = dns;
+ if (!(sv = memget(sizeof *sv))) {
+ memput(pvt, sizeof *pvt);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(sv, 0x5e, sizeof *sv);
+ sv->private = pvt;
+ sv->byname = sv_byname;
+ sv->byport = sv_byport;
+ sv->next = sv_next;
+ sv->rewind = sv_rewind;
+ sv->close = sv_close;
+ sv->minimize = sv_minimize;
+#ifdef SV_RES_SETGET
+ sv->res_get = sv_res_get;
+ sv->res_set = sv_res_set;
+#else
+ sv->res_get = NULL; /* sv_res_get; */
+ sv->res_set = NULL; /* sv_res_set; */
+#endif
+ return (sv);
+}
+
+/* Methods */
+
+static void
+sv_close(struct irs_sv *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (pvt->serv.s_aliases)
+ free(pvt->serv.s_aliases);
+ if (pvt->svbuf)
+ free(pvt->svbuf);
+
+ if (pvt->res && pvt->free_res)
+ (*pvt->free_res)(pvt->res);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
+}
+
+static struct servent *
+sv_byname(struct irs_sv *this, const char *name, const char *proto) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct dns_p *dns = pvt->dns;
+ struct servent *s;
+ char **hes_list;
+
+ if (!(hes_list = hesiod_resolve(dns->hes_ctx, name, "service")))
+ return (NULL);
+
+ s = parse_hes_list(this, hes_list, proto);
+ hesiod_free_list(dns->hes_ctx, hes_list);
+ return (s);
+}
+
+static struct servent *
+sv_byport(struct irs_sv *this, int port, const char *proto) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct dns_p *dns = pvt->dns;
+ struct servent *s;
+ char portstr[16];
+ char **hes_list;
+
+ sprintf(portstr, "%d", ntohs(port));
+ if (!(hes_list = hesiod_resolve(dns->hes_ctx, portstr, "port")))
+ return (NULL);
+
+ s = parse_hes_list(this, hes_list, proto);
+ hesiod_free_list(dns->hes_ctx, hes_list);
+ return (s);
+}
+
+static struct servent *
+sv_next(struct irs_sv *this) {
+ UNUSED(this);
+ errno = ENODEV;
+ return (NULL);
+}
+
+static void
+sv_rewind(struct irs_sv *this) {
+ UNUSED(this);
+ /* NOOP */
+}
+
+/* Private */
+
+static struct servent *
+parse_hes_list(struct irs_sv *this, char **hes_list, const char *proto) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ char *p, *cp, **cpp, **new;
+ int proto_len;
+ int num = 0;
+ int max = 0;
+
+ for (cpp = hes_list; *cpp; cpp++) {
+ cp = *cpp;
+
+ /* Strip away comments, if any. */
+ if ((p = strchr(cp, '#')))
+ *p = 0;
+
+ /* Check to make sure the protocol matches. */
+ p = cp;
+ while (*p && !isspace((unsigned char)*p))
+ p++;
+ if (!*p)
+ continue;
+ if (proto) {
+ proto_len = strlen(proto);
+ if (strncasecmp(++p, proto, proto_len) != 0)
+ continue;
+ if (p[proto_len] && !isspace(p[proto_len]&0xff))
+ continue;
+ }
+ /* OK, we've got a live one. Let's parse it for real. */
+ if (pvt->svbuf)
+ free(pvt->svbuf);
+ pvt->svbuf = strdup(cp);
+
+ p = pvt->svbuf;
+ pvt->serv.s_name = p;
+ while (*p && !isspace(*p&0xff))
+ p++;
+ if (!*p)
+ continue;
+ *p++ = '\0';
+
+ pvt->serv.s_proto = p;
+ while (*p && !isspace(*p&0xff))
+ p++;
+ if (!*p)
+ continue;
+ *p++ = '\0';
+
+ pvt->serv.s_port = htons((u_short) atoi(p));
+ while (*p && !isspace(*p&0xff))
+ p++;
+ if (*p)
+ *p++ = '\0';
+
+ while (*p) {
+ if ((num + 1) >= max || !pvt->serv.s_aliases) {
+ max += 10;
+ new = realloc(pvt->serv.s_aliases,
+ max * sizeof(char *));
+ if (!new) {
+ errno = ENOMEM;
+ goto cleanup;
+ }
+ pvt->serv.s_aliases = new;
+ }
+ pvt->serv.s_aliases[num++] = p;
+ while (*p && !isspace(*p&0xff))
+ p++;
+ if (*p)
+ *p++ = '\0';
+ }
+ if (!pvt->serv.s_aliases)
+ pvt->serv.s_aliases = malloc(sizeof(char *));
+ if (!pvt->serv.s_aliases)
+ goto cleanup;
+ pvt->serv.s_aliases[num] = NULL;
+ return (&pvt->serv);
+ }
+
+ cleanup:
+ if (pvt->serv.s_aliases) {
+ free(pvt->serv.s_aliases);
+ pvt->serv.s_aliases = NULL;
+ }
+ if (pvt->svbuf) {
+ free(pvt->svbuf);
+ pvt->svbuf = NULL;
+ }
+ return (NULL);
+}
+
+static void
+sv_minimize(struct irs_sv *this) {
+ UNUSED(this);
+ /* NOOP */
+}
+
+#ifdef SV_RES_SETGET
+static struct __res_state *
+sv_res_get(struct irs_sv *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct dns_p *dns = pvt->dns;
+
+ return (__hesiod_res_get(dns->hes_ctx));
+}
+
+static void
+sv_res_set(struct irs_sv *this, struct __res_state * res,
+ void (*free_res)(void *)) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct dns_p *dns = pvt->dns;
+
+ __hesiod_res_set(dns->hes_ctx, res, free_res);
+}
+#endif
diff --git a/usr/src/lib/libresolv2/common/irs/gai_strerror.c b/usr/src/lib/libresolv2/common/irs/gai_strerror.c
new file mode 100644
index 0000000000..652d51debd
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/gai_strerror.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 2001 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <port_before.h>
+#include <netdb.h>
+#include <port_after.h>
+
+#ifdef DO_PTHREADS
+#include <pthread.h>
+#include <stdlib.h>
+#endif
+
+static const char *gai_errlist[] = {
+ "no error",
+ "address family not supported for name",/* EAI_ADDRFAMILY */
+ "temporary failure", /* EAI_AGAIN */
+ "invalid flags", /* EAI_BADFLAGS */
+ "permanent failure", /* EAI_FAIL */
+ "address family not supported", /* EAI_FAMILY */
+ "memory failure", /* EAI_MEMORY */
+ "no address", /* EAI_NODATA */
+ "unknown name or service", /* EAI_NONAME */
+ "service not supported for socktype", /* EAI_SERVICE */
+ "socktype not supported", /* EAI_SOCKTYPE */
+ "system failure", /* EAI_SYSTEM */
+ "bad hints", /* EAI_BADHINTS */
+ "bad protocol", /* EAI_PROTOCOL */
+
+ "unknown error" /* Must be last. */
+};
+
+static const int gai_nerr = (sizeof(gai_errlist)/sizeof(*gai_errlist));
+
+#define EAI_BUFSIZE 128
+
+const char *
+gai_strerror(int ecode) {
+#ifndef DO_PTHREADS
+ static char buf[EAI_BUFSIZE];
+#else /* DO_PTHREADS */
+ static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+ static pthread_key_t key;
+ static int once = 0;
+ char *buf;
+#endif
+
+ if (ecode >= 0 && ecode < (gai_nerr - 1))
+ return (gai_errlist[ecode]);
+
+#ifdef DO_PTHREADS
+ if (!once) {
+ pthread_mutex_lock(&lock);
+ if (!once++)
+ pthread_key_create(&key, free);
+ pthread_mutex_unlock(&lock);
+ }
+
+ buf = pthread_getspecific(key);
+ if (buf == NULL) {
+ buf = malloc(EAI_BUFSIZE);
+ if (buf == NULL)
+ return ("unknown error");
+ pthread_setspecific(key, buf);
+ }
+#endif
+ /*
+ * XXX This really should be snprintf(buf, EAI_BUFSIZE, ...).
+ * It is safe until message catalogs are used.
+ */
+ sprintf(buf, "%s: %d", gai_errlist[gai_nerr - 1], ecode);
+ return (buf);
+}
diff --git a/usr/src/lib/libresolv2/common/irs/gen.c b/usr/src/lib/libresolv2/common/irs/gen.c
new file mode 100644
index 0000000000..10acc388f1
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/gen.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: gen.c,v 1.26 2001/05/29 05:48:35 marka Exp $";
+#endif
+
+/*
+ * this is the top level dispatcher
+ *
+ * The dispatcher is implemented as an accessor class; it is an
+ * accessor class that calls other accessor classes, as controlled by a
+ * configuration file.
+ *
+ * A big difference between this accessor class and others is that the
+ * map class initializers are NULL, and the map classes are already
+ * filled in with method functions that will do the right thing.
+ */
+
+/* Imports */
+
+#include "port_before.h"
+
+#include <isc/assertions.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#include "irs_p.h"
+#include "gen_p.h"
+
+#ifdef SUNW_HOSTS_FALLBACK
+extern int __res_no_hosts_fallback(void);
+#endif /* SUNW_HOSTS_FALLBACK */
+
+/* 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, "");
+#ifdef SUNW_HOSTS_FALLBACK
+ if (__res_no_hosts_fallback())
+ add_rule(irs, irs_ho, irs_dns, "");
+ else {
+ add_rule(irs, irs_ho, irs_dns, "continue");
+ add_rule(irs, irs_ho, irs_lcl, "");
+ }
+#else /* SUNW_HOSTS_FALLBACK */
+ add_rule(irs, irs_ho, irs_dns, "continue");
+ add_rule(irs, irs_ho, irs_lcl, "");
+#endif /* SUNW_HOSTS_FALLBACK */
+ 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;
+
+#ifdef SUNW_HOSTS_FALLBACK
+ if (__res_no_hosts_fallback()) {
+ default_map_rules(irs);
+ return;
+ }
+#endif /* SUNW_HOSTS_FALLBACK */
+
+ if (conf_file == NULL)
+ conf_file = _PATH_IRS_CONF ;
+
+ /* A conf file of "" means compiled in defaults. Irpd wants this */
+ if (conf_file[0] == '\0' || (conf = fopen(conf_file, "r")) == NULL) {
+ default_map_rules(irs);
+ return;
+ }
+ (void) sprintf(pattern, "%%%ds %%%ds %%%ds\n",
+ sizeof mapname, sizeof accname, sizeof options);
+ while (fgets(line, sizeof line, conf)) {
+ enum irs_map_id map;
+ enum irs_acc_id acc;
+ char *tmp;
+ int n;
+
+ for (tmp = line;
+ isascii((unsigned char)*tmp) &&
+ isspace((unsigned char)*tmp);
+ tmp++)
+ (void)NULL;
+ if (*tmp == '#' || *tmp == '\n' || *tmp == '\0')
+ continue;
+ n = sscanf(tmp, pattern, mapname, accname, options);
+ if (n < 2)
+ continue;
+ if (n < 3)
+ options[0] = '\0';
+
+ n = find_name(mapname, map_names);
+ INSIST(n < irs_nmap);
+ if (n < 0)
+ continue;
+ map = (enum irs_map_id) n;
+
+ n = find_name(accname, acc_names);
+ INSIST(n < irs_nacc);
+ if (n < 0)
+ continue;
+ acc = (enum irs_acc_id) n;
+
+ add_rule(irs, map, acc, options);
+ }
+ fclose(conf);
+}
diff --git a/usr/src/lib/libresolv2/common/irs/gen_gr.c b/usr/src/lib/libresolv2/common/irs/gen_gr.c
new file mode 100644
index 0000000000..1caf7a22c5
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/gen_gr.c
@@ -0,0 +1,489 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: gen_gr.c,v 1.26 2002/07/18 02:07:44 marka Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#ifndef WANT_IRS_GR
+static int __bind_irs_gr_unneeded;
+#else
+
+#include <sys/types.h>
+
+#include <isc/assertions.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#include "irs_p.h"
+#include "gen_p.h"
+
+/* Definitions */
+
+struct pvt {
+ struct irs_rule * rules;
+ struct irs_rule * rule;
+ struct irs_gr * gr;
+ /*
+ * Need space to store the entries read from the group file.
+ * The members list also needs space per member, and the
+ * strings making up the user names must be allocated
+ * somewhere. Rather than doing lots of small allocations,
+ * we keep one buffer and resize it as needed.
+ */
+ struct group group;
+ size_t nmemb; /* Malloc'd max index of gr_mem[]. */
+ char * membuf;
+ size_t membufsize;
+ struct __res_state * res;
+ void (*free_res)(void *);
+};
+
+/* Forward */
+
+static void gr_close(struct irs_gr *);
+static struct group * gr_next(struct irs_gr *);
+static struct group * gr_byname(struct irs_gr *, const char *);
+static struct group * gr_bygid(struct irs_gr *, gid_t);
+static void gr_rewind(struct irs_gr *);
+static int gr_list(struct irs_gr *, const char *,
+ gid_t, gid_t *, int *);
+static void gr_minimize(struct irs_gr *);
+static struct __res_state * gr_res_get(struct irs_gr *);
+static void gr_res_set(struct irs_gr *,
+ struct __res_state *,
+ void (*)(void *));
+
+static void grmerge(struct irs_gr *gr, const struct group *src,
+ int preserve);
+
+static int countvec(char **vec);
+static int isnew(char **old, char *new);
+static int countnew(char **old, char **new);
+static size_t sizenew(char **old, char **new);
+static int newgid(int, gid_t *, gid_t);
+
+/* Public */
+
+struct irs_gr *
+irs_gen_gr(struct irs_acc *this) {
+ struct gen_p *accpvt = (struct gen_p *)this->private;
+ struct irs_gr *gr;
+ struct pvt *pvt;
+
+ if (!(gr = memget(sizeof *gr))) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(gr, 0x5e, sizeof *gr);
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(gr, sizeof *gr);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pvt, 0, sizeof *pvt);
+ pvt->rules = accpvt->map_rules[irs_gr];
+ pvt->rule = pvt->rules;
+ gr->private = pvt;
+ gr->close = gr_close;
+ gr->next = gr_next;
+ gr->byname = gr_byname;
+ gr->bygid = gr_bygid;
+ gr->rewind = gr_rewind;
+ gr->list = gr_list;
+ gr->minimize = gr_minimize;
+ gr->res_get = gr_res_get;
+ gr->res_set = gr_res_set;
+ return (gr);
+}
+
+/* Methods. */
+
+static void
+gr_close(struct irs_gr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
+}
+
+static struct group *
+gr_next(struct irs_gr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct group *rval;
+ struct irs_gr *gr;
+
+ while (pvt->rule) {
+ gr = pvt->rule->inst->gr;
+ rval = (*gr->next)(gr);
+ if (rval)
+ return (rval);
+ if (!(pvt->rule->flags & IRS_CONTINUE))
+ break;
+ pvt->rule = pvt->rule->next;
+ if (pvt->rule) {
+ gr = pvt->rule->inst->gr;
+ (*gr->rewind)(gr);
+ }
+ }
+ return (NULL);
+}
+
+static struct group *
+gr_byname(struct irs_gr *this, const char *name) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct irs_rule *rule;
+ struct group *tval;
+ struct irs_gr *gr;
+ int dirty;
+
+ dirty = 0;
+ for (rule = pvt->rules; rule; rule = rule->next) {
+ gr = rule->inst->gr;
+ tval = (*gr->byname)(gr, name);
+ if (tval) {
+ grmerge(this, tval, dirty++);
+ if (!(rule->flags & IRS_MERGE))
+ break;
+ } else {
+ if (!(rule->flags & IRS_CONTINUE))
+ break;
+ }
+ }
+ if (dirty)
+ return (&pvt->group);
+ return (NULL);
+}
+
+static struct group *
+gr_bygid(struct irs_gr *this, gid_t gid) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct irs_rule *rule;
+ struct group *tval;
+ struct irs_gr *gr;
+ int dirty;
+
+ dirty = 0;
+ for (rule = pvt->rules; rule; rule = rule->next) {
+ gr = rule->inst->gr;
+ tval = (*gr->bygid)(gr, gid);
+ if (tval) {
+ grmerge(this, tval, dirty++);
+ if (!(rule->flags & IRS_MERGE))
+ break;
+ } else {
+ if (!(rule->flags & IRS_CONTINUE))
+ break;
+ }
+ }
+ if (dirty)
+ return (&pvt->group);
+ return (NULL);
+}
+
+static void
+gr_rewind(struct irs_gr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct irs_gr *gr;
+
+ pvt->rule = pvt->rules;
+ if (pvt->rule) {
+ gr = pvt->rule->inst->gr;
+ (*gr->rewind)(gr);
+ }
+}
+
+static int
+gr_list(struct irs_gr *this, const char *name,
+ gid_t basegid, gid_t *groups, int *ngroups)
+{
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct irs_rule *rule;
+ struct irs_gr *gr;
+ int t_ngroups, maxgroups;
+ gid_t *t_groups;
+ int n, t, rval = 0;
+
+ maxgroups = *ngroups;
+ *ngroups = 0;
+ t_groups = (gid_t *)malloc(maxgroups * sizeof(gid_t));
+ if (!t_groups) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ for (rule = pvt->rules; rule; rule = rule->next) {
+ t_ngroups = maxgroups;
+ gr = rule->inst->gr;
+ t = (*gr->list)(gr, name, basegid, t_groups, &t_ngroups);
+ for (n = 0; n < t_ngroups; n++) {
+ if (newgid(*ngroups, groups, t_groups[n])) {
+ if (*ngroups == maxgroups) {
+ rval = -1;
+ goto done;
+ }
+ groups[(*ngroups)++] = t_groups[n];
+ }
+ }
+ if (t == 0) {
+ if (!(rule->flags & IRS_MERGE))
+ break;
+ } else {
+ if (!(rule->flags & IRS_CONTINUE))
+ break;
+ }
+ }
+ done:
+ free(t_groups);
+ return (rval);
+}
+
+static void
+gr_minimize(struct irs_gr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct irs_rule *rule;
+
+ for (rule = pvt->rules; rule != NULL; rule = rule->next) {
+ struct irs_gr *gr = rule->inst->gr;
+
+ (*gr->minimize)(gr);
+ }
+}
+
+static struct __res_state *
+gr_res_get(struct irs_gr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (!pvt->res) {
+ struct __res_state *res;
+ res = (struct __res_state *)malloc(sizeof *res);
+ if (!res) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(res, 0, sizeof *res);
+ gr_res_set(this, res, free);
+ }
+
+ return (pvt->res);
+}
+
+static void
+gr_res_set(struct irs_gr *this, struct __res_state *res,
+ void (*free_res)(void *)) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct irs_rule *rule;
+
+ if (pvt->res && pvt->free_res) {
+ res_nclose(pvt->res);
+ (*pvt->free_res)(pvt->res);
+ }
+
+ pvt->res = res;
+ pvt->free_res = free_res;
+
+ for (rule = pvt->rules; rule != NULL; rule = rule->next) {
+ struct irs_gr *gr = rule->inst->gr;
+
+ if (gr->res_set)
+ (*gr->res_set)(gr, pvt->res, NULL);
+ }
+}
+
+/* Private. */
+
+static void
+grmerge(struct irs_gr *this, const struct group *src, int preserve) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ char *cp, **m, **p, *oldmembuf, *ep;
+ int n, ndst, nnew;
+ size_t used;
+
+ if (!preserve) {
+ pvt->group.gr_gid = src->gr_gid;
+ if (pvt->nmemb < 1) {
+ m = malloc(sizeof *m);
+ if (!m) {
+ /* No harm done, no work done. */
+ return;
+ }
+ pvt->group.gr_mem = m;
+ pvt->nmemb = 1;
+ }
+ pvt->group.gr_mem[0] = NULL;
+ }
+ ndst = countvec(pvt->group.gr_mem);
+ nnew = countnew(pvt->group.gr_mem, src->gr_mem);
+
+ /*
+ * Make sure destination member array is large enough.
+ * p points to new portion.
+ */
+ n = ndst + nnew + 1;
+ if ((size_t)n > pvt->nmemb) {
+ m = realloc(pvt->group.gr_mem, n * sizeof *m);
+ if (!m) {
+ /* No harm done, no work done. */
+ return;
+ }
+ pvt->group.gr_mem = m;
+ pvt->nmemb = n;
+ }
+ p = pvt->group.gr_mem + ndst;
+
+ /*
+ * Enlarge destination membuf; cp points at new portion.
+ */
+ n = sizenew(pvt->group.gr_mem, src->gr_mem);
+ INSIST((nnew == 0) == (n == 0));
+ if (!preserve) {
+ n += strlen(src->gr_name) + 1;
+ n += strlen(src->gr_passwd) + 1;
+ }
+ if (n == 0) {
+ /* No work to do. */
+ return;
+ }
+ used = preserve ? pvt->membufsize : 0;
+ cp = malloc(used + n);
+ if (!cp) {
+ /* No harm done, no work done. */
+ return;
+ }
+ ep = cp + used + n;
+ if (used != 0)
+ memcpy(cp, pvt->membuf, used);
+ oldmembuf = pvt->membuf;
+ pvt->membuf = cp;
+ pvt->membufsize = used + n;
+ cp += used;
+
+ /*
+ * Adjust group.gr_mem.
+ */
+ if (pvt->membuf != oldmembuf)
+ for (m = pvt->group.gr_mem; *m; m++)
+ *m = pvt->membuf + (*m - oldmembuf);
+
+ /*
+ * Add new elements.
+ */
+ for (m = src->gr_mem; *m; m++)
+ if (isnew(pvt->group.gr_mem, *m)) {
+ *p++ = cp;
+ *p = NULL;
+#ifdef HAVE_STRLCPY
+ strlcpy(cp, *m, ep - cp);
+#else
+ strcpy(cp, *m);
+#endif
+ cp += strlen(cp) + 1;
+ }
+ if (preserve) {
+ pvt->group.gr_name = pvt->membuf +
+ (pvt->group.gr_name - oldmembuf);
+ pvt->group.gr_passwd = pvt->membuf +
+ (pvt->group.gr_passwd - oldmembuf);
+ } else {
+ pvt->group.gr_name = cp;
+#ifdef HAVE_STRLCPY
+ strlcpy(cp, src->gr_name, ep - cp);
+#else
+ strcpy(cp, src->gr_name);
+#endif
+ cp += strlen(src->gr_name) + 1;
+ pvt->group.gr_passwd = cp;
+#ifdef HAVE_STRLCPY
+ strlcpy(cp, src->gr_passwd, ep - cp);
+#else
+ strcpy(cp, src->gr_passwd);
+#endif
+ cp += strlen(src->gr_passwd) + 1;
+ }
+ if (oldmembuf != NULL)
+ free(oldmembuf);
+ INSIST(cp >= pvt->membuf && cp <= &pvt->membuf[pvt->membufsize]);
+}
+
+static int
+countvec(char **vec) {
+ int n = 0;
+
+ while (*vec++)
+ n++;
+ return (n);
+}
+
+static int
+isnew(char **old, char *new) {
+ for (; *old; old++)
+ if (strcmp(*old, new) == 0)
+ return (0);
+ return (1);
+}
+
+static int
+countnew(char **old, char **new) {
+ int n = 0;
+
+ for (; *new; new++)
+ n += isnew(old, *new);
+ return (n);
+}
+
+static size_t
+sizenew(char **old, char **new) {
+ size_t n = 0;
+
+ for (; *new; new++)
+ if (isnew(old, *new))
+ n += strlen(*new) + 1;
+ return (n);
+}
+
+static int
+newgid(int ngroups, gid_t *groups, gid_t group) {
+ ngroups--, groups++;
+ for (; ngroups-- > 0; groups++)
+ if (*groups == group)
+ return (0);
+ return (1);
+}
+
+#endif /* WANT_IRS_GR */
diff --git a/usr/src/lib/libresolv2/common/irs/gen_ho.c b/usr/src/lib/libresolv2/common/irs/gen_ho.c
new file mode 100644
index 0000000000..529738d8be
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/gen_ho.c
@@ -0,0 +1,398 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: gen_ho.c,v 1.16 2001/05/29 05:48:36 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/* Imports */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#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/usr/src/lib/libresolv2/common/irs/gen_ng.c b/usr/src/lib/libresolv2/common/irs/gen_ng.c
new file mode 100644
index 0000000000..c628193868
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/gen_ng.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: gen_ng.c,v 1.15 2001/05/29 05:48:38 marka Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#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/usr/src/lib/libresolv2/common/irs/gen_nw.c b/usr/src/lib/libresolv2/common/irs/gen_nw.c
new file mode 100644
index 0000000000..9fbb91a7bd
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/gen_nw.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: gen_nw.c,v 1.13 1999/10/13 16:39:29 vixie Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#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/usr/src/lib/libresolv2/common/irs/gen_p.h b/usr/src/lib/libresolv2/common/irs/gen_p.h
new file mode 100644
index 0000000000..f07d02b8fc
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/gen_p.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * $Id: gen_p.h,v 1.11 2001/05/29 05:48:39 marka Exp $
+ */
+
+/* Notes:
+ * We hope to create a complete set of thread-safe entry points someday,
+ * which will mean a set of getXbyY() functions that take as an argument
+ * a pointer to the map class, which will have a pointer to the private
+ * data, which will be used preferentially to the static variables that
+ * are necessary to support the "classic" interface. This "classic"
+ * interface will then be reimplemented as stubs on top of the thread
+ * safe modules, and will keep the map class pointers as their only
+ * static data. HOWEVER, we are not there yet. So while we will call
+ * the just-barely-converted map class methods with map class pointers,
+ * right now they probably all still use statics. We're not fooling
+ * anybody, and we're not trying to (yet).
+ */
+
+#ifndef _GEN_P_H_INCLUDED
+#define _GEN_P_H_INCLUDED
+
+/*
+ * These are the access methods.
+ */
+enum irs_acc_id {
+ irs_lcl, /* Local. */
+ irs_dns, /* DNS or Hesiod. */
+ irs_nis, /* Sun NIS ("YP"). */
+ irs_irp, /* IR protocol. */
+ irs_nacc
+};
+
+/*
+ * These are the map types.
+ */
+enum irs_map_id {
+ irs_gr, /* "group" */
+ irs_pw, /* "passwd" */
+ irs_sv, /* "services" */
+ irs_pr, /* "protocols" */
+ irs_ho, /* "hosts" */
+ irs_nw, /* "networks" */
+ irs_ng, /* "netgroup" */
+ irs_nmap
+};
+
+/*
+ * This is an accessor instance.
+ */
+struct irs_inst {
+ struct irs_acc *acc;
+ struct irs_gr * gr;
+ struct irs_pw * pw;
+ struct irs_sv * sv;
+ struct irs_pr * pr;
+ struct irs_ho * ho;
+ struct irs_nw * nw;
+ struct irs_ng * ng;
+};
+
+/*
+ * This is a search rule for some map type.
+ */
+struct irs_rule {
+ struct irs_rule * next;
+ struct irs_inst * inst;
+ int flags;
+};
+#define IRS_MERGE 0x0001 /* Don't stop if acc. has data? */
+#define IRS_CONTINUE 0x0002 /* Don't stop if acc. has no data? */
+
+/*
+ * This is the private data for a search access class.
+ */
+struct gen_p {
+ char * options;
+ struct irs_rule * map_rules[(int)irs_nmap];
+ struct irs_inst accessors[(int)irs_nacc];
+ struct __res_state * res;
+ void (*free_res) __P((void *));
+};
+
+/*
+ * Externs.
+ */
+
+extern struct irs_acc * irs_gen_acc __P((const char *, const char *conf_file));
+extern struct irs_gr * irs_gen_gr __P((struct irs_acc *));
+extern struct irs_pw * irs_gen_pw __P((struct irs_acc *));
+extern struct irs_sv * irs_gen_sv __P((struct irs_acc *));
+extern struct irs_pr * irs_gen_pr __P((struct irs_acc *));
+extern struct irs_ho * irs_gen_ho __P((struct irs_acc *));
+extern struct irs_nw * irs_gen_nw __P((struct irs_acc *));
+extern struct irs_ng * irs_gen_ng __P((struct irs_acc *));
+
+#endif /*_IRS_P_H_INCLUDED*/
diff --git a/usr/src/lib/libresolv2/common/irs/gen_pr.c b/usr/src/lib/libresolv2/common/irs/gen_pr.c
new file mode 100644
index 0000000000..eefffa75bf
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/gen_pr.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: gen_pr.c,v 1.12 1999/10/13 16:39:30 vixie Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#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/usr/src/lib/libresolv2/common/irs/gen_pw.c b/usr/src/lib/libresolv2/common/irs/gen_pw.c
new file mode 100644
index 0000000000..82d0452a12
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/gen_pw.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: gen_pw.c,v 1.14 1999/10/13 16:39:30 vixie Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#ifndef WANT_IRS_PW
+static int __bind_irs_pw_unneeded;
+#else
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <errno.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#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/usr/src/lib/libresolv2/common/irs/gen_sv.c b/usr/src/lib/libresolv2/common/irs/gen_sv.c
new file mode 100644
index 0000000000..db3c58b02b
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/gen_sv.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: gen_sv.c,v 1.12 1999/10/13 16:39:30 vixie Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#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/usr/src/lib/libresolv2/common/irs/getaddrinfo.c b/usr/src/lib/libresolv2/common/irs/getaddrinfo.c
new file mode 100644
index 0000000000..a84716a1ce
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/getaddrinfo.c
@@ -0,0 +1,1307 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* $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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <netdb.h>
+#include <resolv.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <stdarg.h>
+
+#include <irs.h>
+#include <isc/assertions.h>
+
+#include "port_after.h"
+
+#include "irs_data.h"
+
+#define SUCCESS 0
+#define ANY 0
+#define YES 1
+#define NO 0
+
+static const char in_addrany[] = { 0, 0, 0, 0 };
+static const char in6_addrany[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+static const char in_loopback[] = { 127, 0, 0, 1 };
+static const char in6_loopback[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+};
+
+static const struct afd {
+ int a_af;
+ int a_addrlen;
+ int a_socklen;
+ int a_off;
+ const char *a_addrany;
+ const char *a_loopback;
+ int a_scoped;
+} afdl [] = {
+ {PF_INET6, sizeof(struct in6_addr),
+ sizeof(struct sockaddr_in6),
+ offsetof(struct sockaddr_in6, sin6_addr),
+ in6_addrany, in6_loopback, 1},
+ {PF_INET, sizeof(struct in_addr),
+ sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr),
+ in_addrany, in_loopback, 0},
+ {0, 0, 0, 0, NULL, NULL, 0},
+};
+
+struct explore {
+ int e_af;
+ int e_socktype;
+ int e_protocol;
+ const char *e_protostr;
+ int e_wild;
+#define WILD_AF(ex) ((ex)->e_wild & 0x01)
+#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
+#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
+};
+
+static const struct explore explore[] = {
+#if 0
+ { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
+#endif
+ { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
+ { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+ { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
+ { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
+ { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+ { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
+ { -1, 0, 0, NULL, 0 },
+};
+
+#define PTON_MAX 16
+
+static int str_isnumber __P((const char *));
+static int explore_fqdn __P((const struct addrinfo *, const char *,
+ const char *, struct addrinfo **));
+static int explore_copy __P((const struct addrinfo *, const struct addrinfo *,
+ struct addrinfo **));
+static int explore_null __P((const struct addrinfo *,
+ const char *, struct addrinfo **));
+static int explore_numeric __P((const struct addrinfo *, const char *,
+ const char *, struct addrinfo **));
+static int explore_numeric_scope __P((const struct addrinfo *, const char *,
+ const char *, struct addrinfo **));
+static int get_canonname __P((const struct addrinfo *,
+ struct addrinfo *, const char *));
+static struct addrinfo *get_ai __P((const struct addrinfo *,
+ const struct afd *, const char *));
+static struct addrinfo *copy_ai __P((const struct addrinfo *));
+static int get_portmatch __P((const struct addrinfo *, const char *));
+static int get_port __P((const struct addrinfo *, const char *, int));
+static const struct afd *find_afd __P((int));
+static int addrconfig __P((int));
+static int ip6_str2scopeid __P((char *, struct sockaddr_in6 *,
+ u_int32_t *scopeidp));
+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)
+
+/*
+ * Our compiler does not like an unconditional branch out of a loop,
+ * especially one defined in a macro!
+ */
+#ifdef ORIGINAL_ISC_CODE
+#define ERR(err) \
+do { \
+ /* external reference: error, and label bad */ \
+ error = (err); \
+ goto bad; \
+ /*NOTREACHED*/ \
+} while (/*CONSTCOND*/0)
+#else
+#define ERR(err) \
+do { \
+ /* external reference: error */ \
+ error = (err); \
+ /*NOTREACHED*/ \
+} while (/*CONSTCOND*/0)
+#endif
+
+#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;
+ errno = 0;
+ (void)strtoul(p, &ep, 10);
+ if (errno == 0 && ep && *ep == '\0')
+ return YES;
+ else
+ return NO;
+}
+
+int
+getaddrinfo(hostname, servname, hints, res)
+ const char *hostname, *servname;
+ const struct addrinfo *hints;
+ struct addrinfo **res;
+{
+ struct addrinfo sentinel;
+ struct addrinfo *cur;
+ int error = 0;
+ struct addrinfo ai, ai0, *afai = NULL;
+ struct addrinfo *pai;
+ const struct explore *ex;
+
+ memset(&sentinel, 0, sizeof(sentinel));
+ cur = &sentinel;
+ pai = &ai;
+ pai->ai_flags = 0;
+ pai->ai_family = PF_UNSPEC;
+ pai->ai_socktype = ANY;
+ pai->ai_protocol = ANY;
+#ifndef ORIGINAL_ISC_CODE
+#ifdef __sparcv9
+ /*
+ * We need to clear _ai_pad to preserve binary
+ * compatibility with previously compiled 64-bit
+ * applications in a pre-SUSv3 environment by
+ * guaranteeing the upper 32-bits are empty.
+ */
+ pai->_ai_pad = 0;
+#endif /* __sparcv9 */
+#endif /* ORIGINAL_ISC_CODE */
+ 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 !defined(ORIGINAL_ISC_CODE)
+ goto bad;
+#endif
+ }
+/*
+ * The AI_ macros defined by ISC are different than those defined by Solaris.
+ * AI_MASK is defined by ISC to check the range of their flags and doesn't work
+ * with Solaris.
+ */
+#ifdef ORIGINAL_ISC_CODE
+ if (hints->ai_flags & ~AI_MASK) {
+ ERR(EAI_BADFLAGS);
+ }
+#endif
+ switch (hints->ai_family) {
+ case PF_UNSPEC:
+ case PF_INET:
+ case PF_INET6:
+ break;
+ default:
+ ERR(EAI_FAMILY);
+#if !defined(ORIGINAL_ISC_CODE)
+ goto bad;
+#endif
+ }
+ memcpy(pai, hints, sizeof(*pai));
+
+#ifndef ORIGINAL_ISC_CODE
+#ifdef __sparcv9
+ /*
+ * We need to clear _ai_pad to preserve binary
+ * compatibility. See prior comment.
+ */
+ pai->_ai_pad = 0;
+#endif /* __sparcv9 */
+#endif /* ORIGINAL_ISC_CODE */
+ /*
+ * 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);
+#if !defined(ORIGINAL_ISC_CODE)
+ goto bad;
+#endif
+ }
+ }
+ }
+ }
+
+ /*
+ * 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);
+#if !defined(ORIGINAL_ISC_CODE)
+ goto bad;
+#endif
+#else
+ pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED);
+ break;
+#endif
+ }
+
+ /*
+ * check for special cases. (1) numeric servname is disallowed if
+ * socktype/protocol are left unspecified. (2) servname is disallowed
+ * for raw and other inet{,6} sockets.
+ */
+ if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
+#ifdef PF_INET6
+ || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
+#endif
+ ) {
+ ai0 = *pai; /* backup *pai */
+
+ if (pai->ai_family == PF_UNSPEC) {
+#ifdef PF_INET6
+ pai->ai_family = PF_INET6;
+#else
+ pai->ai_family = PF_INET;
+#endif
+ }
+ error = get_portmatch(pai, servname);
+ if (error) {
+ ERR(error);
+#if !defined(ORIGINAL_ISC_CODE)
+ goto bad;
+#endif
+ }
+
+ *pai = ai0;
+ }
+
+ ai0 = *pai;
+
+ /* NULL hostname, or numeric hostname */
+ for (ex = explore; ex->e_af >= 0; ex++) {
+ *pai = ai0;
+
+ if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
+ continue;
+ if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
+ continue;
+ if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
+ continue;
+
+ if (pai->ai_family == PF_UNSPEC)
+ pai->ai_family = ex->e_af;
+ if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
+ pai->ai_socktype = ex->e_socktype;
+ if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
+ pai->ai_protocol = ex->e_protocol;
+
+ /*
+ * if the servname does not match socktype/protocol, ignore it.
+ */
+ if (get_portmatch(pai, servname) != 0)
+ continue;
+
+ if (hostname == NULL) {
+ /*
+ * filter out AFs that are not supported by the kernel
+ * XXX errno?
+ */
+ if (!addrconfig(pai->ai_family))
+ continue;
+ error = explore_null(pai, servname, &cur->ai_next);
+ } else
+ error = explore_numeric_scope(pai, hostname, servname,
+ &cur->ai_next);
+
+ if (error)
+ goto free;
+
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ }
+
+ /*
+ * XXX
+ * If numreic representation of AF1 can be interpreted as FQDN
+ * representation of AF2, we need to think again about the code below.
+ */
+ if (sentinel.ai_next)
+ goto good;
+
+ if (pai->ai_flags & AI_NUMERICHOST) {
+ ERR(EAI_NONAME);
+#if !defined(ORIGINAL_ISC_CODE)
+ goto bad;
+#endif
+ }
+ if (hostname == NULL) {
+ ERR(EAI_NONAME);
+#if !defined(ORIGINAL_ISC_CODE)
+ goto bad;
+#endif
+ }
+
+ /*
+ * hostname as alphabetical name.
+ * We'll make sure that
+ * - if returning addrinfo list is empty, return non-zero error
+ * value (already known one or EAI_NONAME).
+ * - otherwise,
+ * + if we haven't had any errors, return 0 (i.e. success).
+ * + if we've had an error, free the list and return the error.
+ * without any assumption on the behavior of explore_fqdn().
+ */
+
+ /* first, try to query DNS for all possible address families. */
+ *pai = ai0;
+ error = explore_fqdn(pai, hostname, servname, &afai);
+ if (error) {
+ if (afai != NULL)
+ freeaddrinfo(afai);
+ goto free;
+ }
+ if (afai == NULL) {
+ error = EAI_NONAME; /* we've had no errors. */
+ goto free;
+ }
+
+ /*
+ * we would like to prefer AF_INET6 than AF_INET, so we'll make an
+ * outer loop by AFs.
+ */
+ for (ex = explore; ex->e_af >= 0; ex++) {
+ *pai = ai0;
+
+ if (pai->ai_family == PF_UNSPEC)
+ pai->ai_family = ex->e_af;
+
+ if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
+ continue;
+ if (!MATCH(pai->ai_socktype, ex->e_socktype,
+ WILD_SOCKTYPE(ex))) {
+ continue;
+ }
+ if (!MATCH(pai->ai_protocol, ex->e_protocol,
+ WILD_PROTOCOL(ex))) {
+ continue;
+ }
+
+#ifdef AI_ADDRCONFIG
+ /*
+ * If AI_ADDRCONFIG is specified, check if we are
+ * expected to return the address family or not.
+ */
+ if ((pai->ai_flags & AI_ADDRCONFIG) != 0 &&
+ !addrconfig(pai->ai_family))
+ continue;
+#endif
+
+ if (pai->ai_family == PF_UNSPEC)
+ pai->ai_family = ex->e_af;
+ if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
+ pai->ai_socktype = ex->e_socktype;
+ if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
+ pai->ai_protocol = ex->e_protocol;
+
+ /*
+ * if the servname does not match socktype/protocol, ignore it.
+ */
+ if (get_portmatch(pai, servname) != 0)
+ continue;
+
+ if ((error = explore_copy(pai, afai, &cur->ai_next)) != 0) {
+ freeaddrinfo(afai);
+ goto free;
+ }
+
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ }
+
+ freeaddrinfo(afai); /* afai must not be NULL at this point. */
+
+ /* we must not have got any errors. */
+ if (error != 0) /* just for diagnosis */
+ abort();
+
+ if (sentinel.ai_next) {
+good:
+ *res = sentinel.ai_next;
+ return(SUCCESS);
+ } else {
+ /*
+ * All the process succeeded, but we've had an empty list.
+ * This can happen if the given hints do not match our
+ * candidates.
+ */
+ error = EAI_NONAME;
+ }
+
+free:
+bad:
+ if (sentinel.ai_next)
+ freeaddrinfo(sentinel.ai_next);
+ *res = NULL;
+ return(error);
+}
+
+/*
+ * FQDN hostname, DNS lookup
+ */
+static int
+explore_fqdn(pai, hostname, servname, res)
+ const struct addrinfo *pai;
+ const char *hostname;
+ const char *servname;
+ struct addrinfo **res;
+{
+ struct addrinfo *result;
+ struct addrinfo *cur;
+ struct net_data *net_data = init();
+ struct irs_ho *ho;
+ int error = 0;
+ char tmp[NS_MAXDNAME];
+ const char *cp;
+
+ INSIST(res != NULL && *res == NULL);
+
+ /*
+ * if the servname does not match socktype/protocol, ignore it.
+ */
+ if (get_portmatch(pai, servname) != 0)
+ return(0);
+
+ if (!net_data || !(ho = net_data->ho))
+ return(0);
+#if 0 /* XXX (notyet) */
+ if (net_data->ho_stayopen && net_data->ho_last &&
+ net_data->ho_last->h_addrtype == af) {
+ if (ns_samename(name, net_data->ho_last->h_name) == 1)
+ return (net_data->ho_last);
+ for (hap = net_data->ho_last->h_aliases; hap && *hap; hap++)
+ if (ns_samename(name, *hap) == 1)
+ return (net_data->ho_last);
+ }
+#endif
+ if (!strchr(hostname, '.') &&
+ (cp = res_hostalias(net_data->res, hostname,
+ tmp, sizeof(tmp))))
+ hostname = cp;
+ result = (*ho->addrinfo)(ho, hostname, pai);
+ if (!net_data->ho_stayopen) {
+ (*ho->minimize)(ho);
+ }
+ if (result == NULL) {
+ int e = h_errno;
+
+ switch(e) {
+ case NETDB_INTERNAL:
+ error = EAI_SYSTEM;
+ break;
+ case TRY_AGAIN:
+ error = EAI_AGAIN;
+ break;
+ case NO_RECOVERY:
+ error = EAI_FAIL;
+ break;
+ case HOST_NOT_FOUND:
+ case NO_DATA:
+ error = EAI_NONAME;
+ break;
+ default:
+ case NETDB_SUCCESS: /* should be impossible... */
+ error = EAI_NONAME;
+ break;
+ }
+ goto free;
+ }
+
+ for (cur = result; cur; cur = cur->ai_next) {
+ GET_PORT(cur, servname); /* XXX: redundant lookups... */
+ /* canonname should already be filled. */
+ }
+
+ *res = result;
+
+ return(0);
+
+free:
+ if (result)
+ freeaddrinfo(result);
+ return error;
+}
+
+static int
+explore_copy(pai, src0, res)
+ const struct addrinfo *pai; /* seed */
+ const struct addrinfo *src0; /* source */
+ struct addrinfo **res;
+{
+ int error;
+ struct addrinfo sentinel, *cur;
+ const struct addrinfo *src;
+
+ error = 0;
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+
+ for (src = src0; src != NULL; src = src->ai_next) {
+ if (src->ai_family != pai->ai_family)
+ continue;
+
+ cur->ai_next = copy_ai(src);
+ if (!cur->ai_next) {
+ error = EAI_MEMORY;
+ goto fail;
+ }
+
+ cur->ai_next->ai_socktype = pai->ai_socktype;
+ cur->ai_next->ai_protocol = pai->ai_protocol;
+ cur = cur->ai_next;
+ }
+
+ *res = sentinel.ai_next;
+ return 0;
+
+fail:
+ freeaddrinfo(sentinel.ai_next);
+ return error;
+}
+
+/*
+ * hostname == NULL.
+ * passive socket -> anyaddr (0.0.0.0 or ::)
+ * non-passive socket -> localhost (127.0.0.1 or ::1)
+ */
+static int
+explore_null(pai, servname, res)
+ const struct addrinfo *pai;
+ const char *servname;
+ struct addrinfo **res;
+{
+ const struct afd *afd;
+ struct addrinfo *cur;
+ struct addrinfo sentinel;
+ int error;
+
+ *res = NULL;
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+
+ afd = find_afd(pai->ai_family);
+ if (afd == NULL)
+ return 0;
+
+ if (pai->ai_flags & AI_PASSIVE) {
+ GET_AI(cur->ai_next, afd, afd->a_addrany);
+ /* xxx meaningless?
+ * GET_CANONNAME(cur->ai_next, "anyaddr");
+ */
+ GET_PORT(cur->ai_next, servname);
+ } else {
+ GET_AI(cur->ai_next, afd, afd->a_loopback);
+ /* xxx meaningless?
+ * GET_CANONNAME(cur->ai_next, "localhost");
+ */
+ GET_PORT(cur->ai_next, servname);
+ }
+ cur = cur->ai_next;
+
+ *res = sentinel.ai_next;
+ return 0;
+
+free:
+ if (sentinel.ai_next)
+ freeaddrinfo(sentinel.ai_next);
+ return error;
+}
+
+/*
+ * numeric hostname
+ */
+static int
+explore_numeric(pai, hostname, servname, res)
+ const struct addrinfo *pai;
+ const char *hostname;
+ const char *servname;
+ struct addrinfo **res;
+{
+ const struct afd *afd;
+ struct addrinfo *cur;
+ struct addrinfo sentinel;
+ int error;
+ char pton[PTON_MAX];
+
+ *res = NULL;
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+
+ afd = find_afd(pai->ai_family);
+ if (afd == NULL)
+ return 0;
+
+ switch (afd->a_af) {
+#if 0 /*X/Open spec*/
+ case AF_INET:
+ if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
+ if (pai->ai_family == afd->a_af ||
+ pai->ai_family == PF_UNSPEC /*?*/) {
+ GET_AI(cur->ai_next, afd, pton);
+ GET_PORT(cur->ai_next, servname);
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ } else
+ ERR(EAI_FAMILY); /*xxx*/
+ }
+ break;
+#endif
+ default:
+ if (inet_pton(afd->a_af, hostname, pton) == 1) {
+ if (pai->ai_family == afd->a_af ||
+ pai->ai_family == PF_UNSPEC /*?*/) {
+ GET_AI(cur->ai_next, afd, pton);
+ GET_PORT(cur->ai_next, servname);
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ } else {
+ ERR(EAI_FAMILY); /*xxx*/
+#if !defined(ORIGINAL_ISC_CODE)
+ goto bad;
+#endif
+ }
+ }
+ break;
+ }
+
+ *res = sentinel.ai_next;
+ return 0;
+
+free:
+bad:
+ if (sentinel.ai_next)
+ freeaddrinfo(sentinel.ai_next);
+ return error;
+}
+
+/*
+ * numeric hostname with scope
+ */
+static int
+explore_numeric_scope(pai, hostname, servname, res)
+ const struct addrinfo *pai;
+ const char *hostname;
+ const char *servname;
+ struct addrinfo **res;
+{
+#ifndef SCOPE_DELIMITER
+ return explore_numeric(pai, hostname, servname, res);
+#else
+ const struct afd *afd;
+ struct addrinfo *cur;
+ int error;
+ char *cp, *hostname2 = NULL, *scope, *addr;
+ struct sockaddr_in6 *sin6;
+
+ afd = find_afd(pai->ai_family);
+ if (afd == NULL)
+ return 0;
+
+ if (!afd->a_scoped)
+ return explore_numeric(pai, hostname, servname, res);
+
+ cp = strchr(hostname, SCOPE_DELIMITER);
+ if (cp == NULL)
+ return explore_numeric(pai, hostname, servname, res);
+
+ /*
+ * Handle special case of <scoped_address><delimiter><scope id>
+ */
+ hostname2 = strdup(hostname);
+ if (hostname2 == NULL)
+ return EAI_MEMORY;
+ /* terminate at the delimiter */
+ hostname2[cp - hostname] = '\0';
+ addr = hostname2;
+ scope = cp + 1;
+
+ error = explore_numeric(pai, addr, servname, res);
+ if (error == 0) {
+ u_int32_t scopeid = 0;
+
+ for (cur = *res; cur; cur = cur->ai_next) {
+ if (cur->ai_family != AF_INET6)
+ continue;
+ sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
+ if (!ip6_str2scopeid(scope, sin6, &scopeid)) {
+ free(hostname2);
+ return(EAI_NONAME); /* XXX: is return OK? */
+ }
+#ifdef HAVE_SIN6_SCOPE_ID
+ sin6->sin6_scope_id = scopeid;
+#endif
+ }
+ }
+
+ free(hostname2);
+
+ return error;
+#endif
+}
+
+static int
+get_canonname(pai, ai, str)
+ const struct addrinfo *pai;
+ struct addrinfo *ai;
+ const char *str;
+{
+ if ((pai->ai_flags & AI_CANONNAME) != 0) {
+ ai->ai_canonname = (char *)malloc(strlen(str) + 1);
+ if (ai->ai_canonname == NULL)
+ return EAI_MEMORY;
+ strcpy(ai->ai_canonname, str);
+ }
+ return 0;
+}
+
+static struct addrinfo *
+get_ai(pai, afd, addr)
+ const struct addrinfo *pai;
+ const struct afd *afd;
+ const char *addr;
+{
+ char *p;
+ struct addrinfo *ai;
+
+ ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
+ + (afd->a_socklen));
+ if (ai == NULL)
+ return NULL;
+
+ memcpy(ai, pai, sizeof(struct addrinfo));
+ ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
+ memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
+#ifdef HAVE_SA_LEN
+ ai->ai_addr->sa_len = afd->a_socklen;
+#endif
+ ai->ai_addrlen = afd->a_socklen;
+ ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
+ p = (char *)(void *)(ai->ai_addr);
+ memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
+ return ai;
+}
+
+/* XXX need to malloc() the same way we do from other functions! */
+static struct addrinfo *
+copy_ai(pai)
+ const struct addrinfo *pai;
+{
+ struct addrinfo *ai;
+ size_t l;
+
+ l = sizeof(*ai) + pai->ai_addrlen;
+ if ((ai = (struct addrinfo *)malloc(l)) == NULL)
+ return NULL;
+ memset(ai, 0, l);
+ memcpy(ai, pai, sizeof(*ai));
+ ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
+ memcpy(ai->ai_addr, pai->ai_addr, pai->ai_addrlen);
+
+ if (pai->ai_canonname) {
+ l = strlen(pai->ai_canonname) + 1;
+ if ((ai->ai_canonname = malloc(l)) == NULL) {
+ free(ai);
+ return NULL;
+ }
+#ifdef HAVE_STRLCPY
+ strlcpy(ai->ai_canonname, pai->ai_canonname, l);
+#else
+ strncpy(ai->ai_canonname, pai->ai_canonname, l);
+#endif
+ } else {
+ /* just to make sure */
+ ai->ai_canonname = NULL;
+ }
+
+ ai->ai_next = NULL;
+
+ return ai;
+}
+
+static int
+get_portmatch(const struct addrinfo *ai, const char *servname) {
+
+ /* get_port does not touch first argument. when matchonly == 1. */
+ /* LINTED const cast */
+ return get_port((const struct addrinfo *)ai, servname, 1);
+}
+
+static int
+get_port(const struct addrinfo *ai, const char *servname, int matchonly) {
+ const char *proto;
+ struct servent *sp;
+ int port;
+ int allownumeric;
+
+ if (servname == NULL)
+ return 0;
+ switch (ai->ai_family) {
+ case AF_INET:
+#ifdef AF_INET6
+ case AF_INET6:
+#endif
+ break;
+ default:
+ return 0;
+ }
+
+ switch (ai->ai_socktype) {
+ case SOCK_RAW:
+ return EAI_SERVICE;
+ case SOCK_DGRAM:
+ case SOCK_STREAM:
+ allownumeric = 1;
+ break;
+ case ANY:
+ switch (ai->ai_family) {
+ case AF_INET:
+#ifdef AF_INET6
+ case AF_INET6:
+#endif
+ allownumeric = 1;
+ break;
+ default:
+ allownumeric = 0;
+ break;
+ }
+ break;
+ default:
+ return EAI_SOCKTYPE;
+ }
+
+ if (str_isnumber(servname)) {
+ if (!allownumeric)
+ return EAI_SERVICE;
+ port = atoi(servname);
+ if (port < 0 || port > 65535)
+ return EAI_SERVICE;
+ port = htons(port);
+ } else {
+ switch (ai->ai_socktype) {
+ case SOCK_DGRAM:
+ proto = "udp";
+ break;
+ case SOCK_STREAM:
+ proto = "tcp";
+ break;
+ default:
+ proto = NULL;
+ break;
+ }
+
+ if ((sp = getservbyname(servname, proto)) == NULL)
+ return EAI_SERVICE;
+ port = sp->s_port;
+ }
+
+ if (!matchonly) {
+ switch (ai->ai_family) {
+ case AF_INET:
+ ((struct sockaddr_in *)(void *)
+ ai->ai_addr)->sin_port = port;
+ break;
+ case AF_INET6:
+ ((struct sockaddr_in6 *)(void *)
+ ai->ai_addr)->sin6_port = port;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static const struct afd *
+find_afd(af)
+ int af;
+{
+ const struct afd *afd;
+
+ if (af == PF_UNSPEC)
+ return NULL;
+ for (afd = afdl; afd->a_af; afd++) {
+ if (afd->a_af == af)
+ return afd;
+ }
+ return NULL;
+}
+
+/*
+ * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend
+ * will take care of it.
+ * the semantics of AI_ADDRCONFIG is not defined well. we are not sure
+ * if the code is right or not.
+ */
+static int
+addrconfig(af)
+ int af;
+{
+ int s;
+
+ /* XXX errno */
+ s = socket(af, SOCK_DGRAM, 0);
+ if (s < 0) {
+ if (errno != EMFILE)
+ return 0;
+ } else
+ close(s);
+ return 1;
+}
+
+/* convert a string to a scope identifier. XXX: IPv6 specific */
+static int
+ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6,
+ u_int32_t *scopeidp)
+{
+ u_int32_t scopeid;
+ u_long lscopeid;
+ struct in6_addr *a6 = &sin6->sin6_addr;
+ char *ep;
+
+ /* empty scopeid portion is invalid */
+ if (*scope == '\0')
+ return (0);
+
+#ifdef USE_IFNAMELINKID
+ if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
+ /*
+ * Using interface names as link indices can be allowed
+ * only when we can assume a one-to-one mappings between
+ * links and interfaces. See comments in getnameinfo.c.
+ */
+ scopeid = if_nametoindex(scope);
+ if (scopeid == 0)
+ goto trynumeric;
+ *scopeidp = scopeid;
+ return (1);
+ }
+#endif
+
+ /* still unclear about literal, allow numeric only - placeholder */
+ if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
+ goto trynumeric;
+ if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
+ goto trynumeric;
+ else
+ goto trynumeric; /* global */
+
+ /* try to convert to a numeric id as a last resort */
+trynumeric:
+ errno = 0;
+ lscopeid = strtoul(scope, &ep, 10);
+ scopeid = lscopeid & 0xffffffff;
+ if (errno == 0 && ep && *ep == '\0' && scopeid == lscopeid) {
+ *scopeidp = scopeid;
+ return (1);
+ } else
+ return (0);
+}
+
+struct addrinfo *
+hostent2addrinfo(hp, pai)
+ struct hostent *hp;
+ const struct addrinfo *pai;
+{
+ int i, af, error = 0;
+ char **aplist = NULL, *ap;
+ struct addrinfo sentinel, *cur;
+ const struct afd *afd;
+
+ af = hp->h_addrtype;
+ if (pai->ai_family != AF_UNSPEC && af != pai->ai_family)
+ return(NULL);
+
+ afd = find_afd(af);
+ if (afd == NULL)
+ return(NULL);
+
+ aplist = hp->h_addr_list;
+
+ memset(&sentinel, 0, sizeof(sentinel));
+ cur = &sentinel;
+
+ for (i = 0; (ap = aplist[i]) != NULL; i++) {
+#if 0 /* the trick seems too much */
+ af = hp->h_addr_list;
+ if (af == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
+ af = AF_INET;
+ ap = ap + sizeof(struct in6_addr)
+ - sizeof(struct in_addr);
+ }
+ afd = find_afd(af);
+ if (afd == NULL)
+ continue;
+#endif /* 0 */
+
+ GET_AI(cur->ai_next, afd, ap);
+
+ /* GET_PORT(cur->ai_next, servname); */
+ if ((pai->ai_flags & AI_CANONNAME) != 0) {
+ /*
+ * RFC2553 says that ai_canonname will be set only for
+ * the first element. we do it for all the elements,
+ * just for convenience.
+ */
+ GET_CANONNAME(cur->ai_next, hp->h_name);
+ }
+ while (cur && cur->ai_next) /* no need to loop, actually. */
+ cur = cur->ai_next;
+ continue;
+
+ free:
+ if (cur->ai_next)
+ freeaddrinfo(cur->ai_next);
+ cur->ai_next = NULL;
+ /* continue, without tht pointer CUR advanced. */
+ }
+
+ return(sentinel.ai_next);
+}
+
+struct addrinfo *
+addr2addrinfo(pai, cp)
+ const struct addrinfo *pai;
+ const char *cp;
+{
+ const struct afd *afd;
+
+ afd = find_afd(pai->ai_family);
+ if (afd == NULL)
+ return(NULL);
+
+ return(get_ai(pai, afd, cp));
+}
+
+static struct net_data *
+init()
+{
+ struct net_data *net_data;
+
+ if (!(net_data = net_data_init(NULL)))
+ goto error;
+ if (!net_data->ho) {
+ net_data->ho = (*net_data->irs->ho_map)(net_data->irs);
+ if (!net_data->ho || !net_data->res) {
+error:
+ errno = EIO;
+ if (net_data && net_data->res)
+ RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
+ return (NULL);
+ }
+
+ (*net_data->ho->res_set)(net_data->ho, net_data->res, NULL);
+ }
+
+ return (net_data);
+}
diff --git a/usr/src/lib/libresolv2/common/irs/getgrent.c b/usr/src/lib/libresolv2/common/irs/getgrent.c
new file mode 100644
index 0000000000..5ac15a1c87
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/getgrent.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: getgrent.c,v 1.20 2001/05/29 05:48:41 marka Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#if !defined(WANT_IRS_GR) || defined(__BIND_NOSTATIC)
+static int __bind_irs_gr_unneeded;
+#else
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <grp.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <irs.h>
+
+#include "port_after.h"
+
+#include "irs_data.h"
+
+/* Forward */
+
+static struct net_data *init(void);
+void endgrent(void);
+
+/* Public */
+
+struct group *
+getgrent() {
+ struct net_data *net_data = init();
+
+ return (getgrent_p(net_data));
+}
+
+struct group *
+getgrnam(const char *name) {
+ struct net_data *net_data = init();
+
+ return (getgrnam_p(name, net_data));
+}
+
+struct group *
+getgrgid(gid_t gid) {
+ struct net_data *net_data = init();
+
+ return (getgrgid_p(gid, net_data));
+}
+
+int
+setgroupent(int stayopen) {
+ struct net_data *net_data = init();
+
+ return (setgroupent_p(stayopen, net_data));
+}
+
+#ifdef SETGRENT_VOID
+void
+setgrent(void) {
+ struct net_data *net_data = init();
+
+ setgrent_p(net_data);
+}
+#else
+int
+setgrent(void) {
+ struct net_data *net_data = init();
+
+ return (setgrent_p(net_data));
+}
+#endif /* SETGRENT_VOID */
+
+void
+endgrent() {
+ struct net_data *net_data = init();
+
+ endgrent_p(net_data);
+}
+
+int
+getgrouplist(GETGROUPLIST_ARGS) {
+ struct net_data *net_data = init();
+
+ return (getgrouplist_p(name, basegid, groups, ngroups, net_data));
+}
+
+/* Shared private. */
+
+struct group *
+getgrent_p(struct net_data *net_data) {
+ struct irs_gr *gr;
+
+ if (!net_data || !(gr = net_data->gr))
+ return (NULL);
+ net_data->gr_last = (*gr->next)(gr);
+ return (net_data->gr_last);
+}
+
+struct group *
+getgrnam_p(const char *name, struct net_data *net_data) {
+ struct irs_gr *gr;
+
+ if (!net_data || !(gr = net_data->gr))
+ return (NULL);
+ if (net_data->gr_stayopen && net_data->gr_last &&
+ !strcmp(net_data->gr_last->gr_name, name))
+ return (net_data->gr_last);
+ net_data->gr_last = (*gr->byname)(gr, name);
+ if (!net_data->gr_stayopen)
+ endgrent();
+ return (net_data->gr_last);
+}
+
+struct group *
+getgrgid_p(gid_t gid, struct net_data *net_data) {
+ struct irs_gr *gr;
+
+ if (!net_data || !(gr = net_data->gr))
+ return (NULL);
+ if (net_data->gr_stayopen && net_data->gr_last &&
+ (gid_t)net_data->gr_last->gr_gid == gid)
+ return (net_data->gr_last);
+ net_data->gr_last = (*gr->bygid)(gr, gid);
+ if (!net_data->gr_stayopen)
+ endgrent();
+ return (net_data->gr_last);
+}
+
+int
+setgroupent_p(int stayopen, struct net_data *net_data) {
+ struct irs_gr *gr;
+
+ if (!net_data || !(gr = net_data->gr))
+ return (0);
+ (*gr->rewind)(gr);
+ net_data->gr_stayopen = (stayopen != 0);
+ if (stayopen == 0)
+ net_data_minimize(net_data);
+ return (1);
+}
+
+#ifdef SETGRENT_VOID
+void
+setgrent_p(struct net_data *net_data) {
+ (void)setgroupent_p(0, net_data);
+}
+#else
+int
+setgrent_p(struct net_data *net_data) {
+ return (setgroupent_p(0, net_data));
+}
+#endif /* SETGRENT_VOID */
+
+void
+endgrent_p(struct net_data *net_data) {
+ struct irs_gr *gr;
+
+ if ((net_data != NULL) && ((gr = net_data->gr) != NULL))
+ (*gr->minimize)(gr);
+}
+
+int
+getgrouplist_p(const char *name, gid_t basegid, gid_t *groups, int *ngroups,
+ struct net_data *net_data) {
+ struct irs_gr *gr;
+
+ if (!net_data || !(gr = net_data->gr)) {
+ *ngroups = 0;
+ return (-1);
+ }
+ return ((*gr->list)(gr, name, basegid, groups, ngroups));
+}
+
+/* Private */
+
+static struct net_data *
+init() {
+ struct net_data *net_data;
+
+ if (!(net_data = net_data_init(NULL)))
+ goto error;
+ if (!net_data->gr) {
+ net_data->gr = (*net_data->irs->gr_map)(net_data->irs);
+
+ if (!net_data->gr || !net_data->res) {
+ error:
+ errno = EIO;
+ return (NULL);
+ }
+ (*net_data->gr->res_set)(net_data->gr, net_data->res,
+ NULL);
+ }
+
+ return (net_data);
+}
+
+#endif /* WANT_IRS_GR */
diff --git a/usr/src/lib/libresolv2/common/irs/getgrent_r.c b/usr/src/lib/libresolv2/common/irs/getgrent_r.c
new file mode 100644
index 0000000000..01c0a936ed
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/getgrent_r.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] =
+ "$Id: getgrent_r.c,v 8.7 2001/11/01 08:02:08 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <port_before.h>
+#if !defined(_REENTRANT) || !defined(DO_PTHREADS) || !defined(WANT_IRS_PW)
+ static int getgrent_r_not_required = 0;
+#else
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#if (defined(POSIX_GETGRNAM_R) || defined(POSIX_GETGRGID_R)) && \
+ defined(_POSIX_PTHREAD_SEMANTICS)
+ /* turn off solaris remapping in <grp.h> */
+#define _UNIX95
+#undef _POSIX_PTHREAD_SEMANTICS
+#include <grp.h>
+#define _POSIX_PTHREAD_SEMANTICS 1
+#else
+#include <grp.h>
+#endif
+#include <sys/param.h>
+#include <port_after.h>
+
+#ifdef GROUP_R_RETURN
+
+static int
+copy_group(struct group *, struct group *, char *buf, int buflen);
+
+/* POSIX 1003.1c */
+#ifdef POSIX_GETGRNAM_R
+int
+__posix_getgrnam_r(const char *name, struct group *gptr,
+ char *buf, size_t buflen, struct group **result) {
+#else
+int
+getgrnam_r(const char *name, struct group *gptr,
+ char *buf, size_t buflen, struct group **result) {
+#endif
+ struct group *ge = getgrnam(name);
+ int res;
+
+ if (ge == NULL) {
+ *result = NULL;
+ return (0);
+ }
+
+ res = copy_group(ge, gptr, buf, buflen);
+ *result = res ? NULL : gptr;
+ return (res);
+}
+
+#ifdef POSIX_GETGRNAM_R
+struct group *
+getgrnam_r(const char *name, struct group *gptr,
+ char *buf, int buflen) {
+ struct group *ge = getgrnam(name);
+ int res;
+
+ if (ge == NULL)
+ return (NULL);
+ res = copy_group(ge, gptr, buf, buflen);
+ return (res ? NULL : gptr);
+}
+#endif /* POSIX_GETGRNAM_R */
+
+/* POSIX 1003.1c */
+#ifdef POSIX_GETGRGID_R
+int
+__posix_getgrgid_r(gid_t gid, struct group *gptr,
+ char *buf, size_t buflen, struct group **result) {
+#else /* POSIX_GETGRGID_R */
+int
+getgrgid_r(gid_t gid, struct group *gptr,
+ char *buf, size_t buflen, struct group **result) {
+#endif /* POSIX_GETGRGID_R */
+ struct group *ge = getgrgid(gid);
+ int res;
+
+ if (ge == NULL) {
+ *result = NULL;
+ return (0);
+ }
+
+ res = copy_group(ge, gptr, buf, buflen);
+ *result = res ? NULL : gptr;
+ return (res);
+}
+
+#ifdef POSIX_GETGRGID_R
+struct group *
+getgrgid_r(gid_t gid, struct group *gptr,
+ char *buf, int buflen) {
+ struct group *ge = getgrgid(gid);
+ int res;
+
+ if (ge == NULL)
+ return (NULL);
+
+ res = copy_group(ge, gptr, buf, buflen);
+ return (res ? NULL : gptr);
+}
+#endif
+
+/*
+ * These assume a single context is in operation per thread.
+ * If this is not the case we will need to call irs directly
+ * rather than through the base functions.
+ */
+
+GROUP_R_RETURN
+getgrent_r(struct group *gptr, GROUP_R_ARGS) {
+ struct group *ge = getgrent();
+ int res;
+
+ if (ge == NULL) {
+ return (GROUP_R_BAD);
+ }
+
+ res = copy_group(ge, gptr, buf, buflen);
+ return (res ? GROUP_R_BAD : GROUP_R_OK);
+}
+
+GROUP_R_SET_RETURN
+setgrent_r(GROUP_R_ENT_ARGS) {
+
+ setgrent();
+#ifdef GROUP_R_SET_RESULT
+ return (GROUP_R_SET_RESULT);
+#endif
+}
+
+GROUP_R_END_RETURN
+endgrent_r(GROUP_R_ENT_ARGS) {
+
+ endgrent();
+ GROUP_R_END_RESULT(GROUP_R_OK);
+}
+
+
+#if 0
+ /* XXX irs does not have a fgetgrent() */
+GROUP_R_RETURN
+fgetgrent_r(FILE *f, struct group *gptr, GROUP_R_ARGS) {
+ struct group *ge = fgetgrent(f);
+ int res;
+
+ if (ge == NULL)
+ return (GROUP_R_BAD);
+
+ res = copy_group(ge, gptr, buf, buflen);
+ return (res ? GROUP_R_BAD : GROUP_R_OK);
+}
+#endif
+
+/* Private */
+
+static int
+copy_group(struct group *ge, struct group *gptr, char *buf, int buflen) {
+ char *cp;
+ int i, n;
+ int numptr, len;
+
+ /* Find out the amount of space required to store the answer. */
+ numptr = 1; /* NULL ptr */
+ len = (char *)ALIGN(buf) - buf;
+ for (i = 0; ge->gr_mem[i]; i++, numptr++) {
+ len += strlen(ge->gr_mem[i]) + 1;
+ }
+ len += strlen(ge->gr_name) + 1;
+ len += strlen(ge->gr_passwd) + 1;
+ len += numptr * sizeof (char *);
+
+ if (len > buflen) {
+ errno = ERANGE;
+ return (ERANGE);
+ }
+
+ /* copy group id */
+ gptr->gr_gid = ge->gr_gid;
+
+ cp = (char *)ALIGN(buf) + numptr * sizeof (char *);
+
+ /* copy official name */
+ n = strlen(ge->gr_name) + 1;
+ strcpy(cp, ge->gr_name);
+ gptr->gr_name = cp;
+ cp += n;
+
+ /* copy member list */
+ gptr->gr_mem = (char **)ALIGN(buf);
+ for (i = 0; ge->gr_mem[i]; i++) {
+ n = strlen(ge->gr_mem[i]) + 1;
+ strcpy(cp, ge->gr_mem[i]);
+ gptr->gr_mem[i] = cp;
+ cp += n;
+ }
+ gptr->gr_mem[i] = NULL;
+
+ /* copy password */
+ n = strlen(ge->gr_passwd) + 1;
+ strcpy(cp, ge->gr_passwd);
+ gptr->gr_passwd = cp;
+ cp += n;
+
+ return (0);
+}
+#else /* GROUP_R_RETURN */
+ static int getgrent_r_unknown_system = 0;
+#endif /* GROUP_R_RETURN */
+#endif /* !def(_REENTRANT) || !def(DO_PTHREADS) || !def(WANT_IRS_PW) */
diff --git a/usr/src/lib/libresolv2/common/irs/gethostent.c b/usr/src/lib/libresolv2/common/irs/gethostent.c
new file mode 100644
index 0000000000..db88d06b20
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/gethostent.c
@@ -0,0 +1,1091 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: gethostent.c,v 1.34 2003/05/29 00:05:18 marka Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#if !defined(__BIND_NOSTATIC)
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <irs.h>
+#include <isc/memcluster.h>
+
+#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 *);
+
+#ifdef SUNW_OVERRIDE_RETRY
+extern int __res_retry(int);
+extern int __res_retry_reset(void);
+#endif /* SUNW_OVERRIDE_RETRY */
+
+/* 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 *
+#ifdef ORIGINAL_ISC_CODE
+gethostbyaddr(const char *addr, int len, int af) {
+#else
+gethostbyaddr(const void *addr, socklen_t len, int af) {
+#endif /* ORIGINAL_ISC_CODE */
+ 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));
+}
+
+#ifdef ORIGINAL_ISC_CODE
+void
+#else
+int
+#endif
+sethostent(int stayopen) {
+ struct net_data *net_data = init();
+ sethostent_p(stayopen, net_data);
+#ifdef ORIGINAL_ISC_CODE
+#else
+ return (0);
+#endif
+}
+
+
+#ifdef ORIGINAL_ISC_CODE
+void
+#else
+int
+#endif
+endhostent() {
+ struct net_data *net_data = init();
+ endhostent_p(net_data);
+#ifdef ORIGINAL_ISC_CODE
+#else
+ return (0);
+#endif
+}
+
+/* Shared private. */
+
+struct hostent *
+gethostbyname_p(const char *name, struct net_data *net_data) {
+ struct hostent *hp;
+
+ if (!net_data)
+#ifdef SUNW_SETHERRNO
+ {
+ /*
+ * Should set the context h_errno, but since net_data
+ * is NULL, we don't have a context.
+ */
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+#else
+ return (NULL);
+#endif /* SUNW_SETHERRNO */
+
+ 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))
+#ifdef SUNW_SETHERRNO
+ {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+#else
+ return (NULL);
+#endif /* SUNW_SETHERRNO */
+ 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);
+#ifdef SUNW_OVERRIDE_RETRY
+ net_data->res->retry = __res_retry(net_data->res->retry);
+#endif /* SUNW_OVERRIDE_RETRY */
+ net_data->ho_last = (*ho->byname2)(ho, name, af);
+#ifdef SUNW_OVERRIDE_RETRY
+ net_data->res->retry = __res_retry_reset();
+#endif /* SUNW_OVERRIDE_RETRY */
+ 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))
+#ifdef SUNW_SETHERRNO
+ {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+#else
+ return (NULL);
+#endif /* SUNW_SETHERRNO */
+ 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))
+#ifdef SUNW_SETHERRNO
+ {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+#else
+ return (NULL);
+#endif /* SUNW_SETHERRNO */
+ while ((hp = (*ho->next)(ho)) != NULL &&
+ hp->h_addrtype == AF_INET6 &&
+ (net_data->res->options & RES_USE_INET6) == 0)
+ continue;
+ net_data->ho_last = hp;
+ return (net_data->ho_last);
+}
+
+
+void
+sethostent_p(int stayopen, struct net_data *net_data) {
+ struct irs_ho *ho;
+
+ if (!net_data || !(ho = net_data->ho))
+ return;
+ freepvt(net_data);
+ (*ho->rewind)(ho);
+ net_data->ho_stayopen = (stayopen != 0);
+ if (stayopen == 0)
+ net_data_minimize(net_data);
+}
+
+void
+endhostent_p(struct net_data *net_data) {
+ struct irs_ho *ho;
+
+ if ((net_data != NULL) && ((ho = net_data->ho) != NULL))
+ (*ho->minimize)(ho);
+}
+
+#ifndef IN6_IS_ADDR_V4COMPAT
+static const unsigned char in6addr_compat[12] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+#define IN6_IS_ADDR_V4COMPAT(x) (!memcmp((x)->s6_addr, in6addr_compat, 12) && \
+ ((x)->s6_addr[12] != 0 || \
+ (x)->s6_addr[13] != 0 || \
+ (x)->s6_addr[14] != 0 || \
+ ((x)->s6_addr[15] != 0 && \
+ (x)->s6_addr[15] != 1)))
+#endif
+#ifndef IN6_IS_ADDR_V4MAPPED
+#define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12))
+#endif
+
+static const unsigned char in6addr_mapped[12] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
+
+static int scan_interfaces(int *, int *);
+static struct hostent *copyandmerge(struct hostent *, struct hostent *, int, int *);
+
+/*
+ * Public functions
+ */
+
+/*
+ * AI_V4MAPPED + AF_INET6
+ * If no IPv6 address then a query for IPv4 and map returned values.
+ *
+ * AI_ALL + AI_V4MAPPED + AF_INET6
+ * Return IPv6 and IPv4 mapped.
+ *
+ * AI_ADDRCONFIG
+ * Only return IPv6 / IPv4 address if there is an interface of that
+ * type active.
+ */
+
+struct hostent *
+getipnodebyname(const char *name, int af, int flags, int *error_num) {
+ int have_v4 = 1, have_v6 = 1;
+ struct in_addr in4;
+ struct in6_addr in6;
+ struct hostent he, *he1 = NULL, *he2 = NULL, *he3;
+ int v4 = 0, v6 = 0;
+ struct net_data *net_data = init();
+ u_long options;
+ int tmp_err;
+
+ if (net_data == NULL) {
+ *error_num = NO_RECOVERY;
+ return (NULL);
+ }
+
+ /* If we care about active interfaces then check. */
+ if ((flags & AI_ADDRCONFIG) != 0)
+ if (scan_interfaces(&have_v4, &have_v6) == -1) {
+ *error_num = NO_RECOVERY;
+ return (NULL);
+ }
+
+ /* Check for literal address. */
+ if ((v4 = inet_pton(AF_INET, name, &in4)) != 1)
+ v6 = inet_pton(AF_INET6, name, &in6);
+
+ /* Impossible combination? */
+
+ if ((af == AF_INET6 && (flags & AI_V4MAPPED) == 0 && v4 == 1) ||
+ (af == AF_INET && v6 == 1) ||
+ (have_v4 == 0 && v4 == 1) ||
+ (have_v6 == 0 && v6 == 1) ||
+ (have_v4 == 0 && af == AF_INET) ||
+ (have_v6 == 0 && af == AF_INET6)) {
+ *error_num = HOST_NOT_FOUND;
+ return (NULL);
+ }
+
+ /* Literal address? */
+ if (v4 == 1 || v6 == 1) {
+ char *addr_list[2];
+ char *aliases[1];
+
+ DE_CONST(name, he.h_name);
+ he.h_addr_list = addr_list;
+ he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6;
+ he.h_addr_list[1] = NULL;
+ he.h_aliases = aliases;
+ he.h_aliases[0] = NULL;
+ he.h_length = (v4 == 1) ? INADDRSZ : IN6ADDRSZ;
+ he.h_addrtype = (v4 == 1) ? AF_INET : AF_INET6;
+ return (copyandmerge(&he, NULL, af, error_num));
+ }
+
+ options = net_data->res->options;
+ net_data->res->options &= ~RES_USE_INET6;
+
+ tmp_err = NO_RECOVERY;
+ if (have_v6 && af == AF_INET6) {
+ he2 = gethostbyname2_p(name, AF_INET6, net_data);
+ if (he2 != NULL) {
+ he1 = copyandmerge(he2, NULL, af, error_num);
+ if (he1 == NULL)
+ return (NULL);
+ he2 = NULL;
+ } else {
+ tmp_err = net_data->res->res_h_errno;
+ }
+ }
+
+ if (have_v4 &&
+ ((af == AF_INET) ||
+ (af == AF_INET6 && (flags & AI_V4MAPPED) != 0 &&
+ (he1 == NULL || (flags & AI_ALL) != 0)))) {
+ he2 = gethostbyname2_p(name, AF_INET, net_data);
+ if (he1 == NULL && he2 == NULL) {
+ *error_num = net_data->res->res_h_errno;
+ return (NULL);
+ }
+ } else
+ *error_num = tmp_err;
+
+ net_data->res->options = options;
+
+ he3 = copyandmerge(he1, he2, af, error_num);
+
+ if (he1 != NULL)
+ freehostent(he1);
+ return (he3);
+}
+
+struct hostent *
+getipnodebyaddr(const void *src, size_t len, int af, int *error_num) {
+ struct hostent *he1, *he2;
+ struct net_data *net_data = init();
+
+ /* Sanity Checks. */
+ if (src == NULL) {
+ *error_num = NO_RECOVERY;
+ return (NULL);
+ }
+
+ switch (af) {
+ case AF_INET:
+ if (len != INADDRSZ) {
+ *error_num = NO_RECOVERY;
+ return (NULL);
+ }
+ break;
+ case AF_INET6:
+ if (len != IN6ADDRSZ) {
+ *error_num = NO_RECOVERY;
+ return (NULL);
+ }
+ break;
+ default:
+ *error_num = NO_RECOVERY;
+ return (NULL);
+ }
+
+ /*
+ * Lookup IPv4 and IPv4 mapped/compatible addresses
+ */
+ if ((af == AF_INET6 &&
+ IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)src)) ||
+ (af == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src)) ||
+ (af == AF_INET)) {
+ const char *cp = src;
+
+ if (af == AF_INET6)
+ cp += 12;
+ he1 = gethostbyaddr_p(cp, 4, AF_INET, net_data);
+ if (he1 == NULL) {
+ *error_num = net_data->res->res_h_errno;
+ return (NULL);
+ }
+ he2 = copyandmerge(he1, NULL, af, error_num);
+ if (he2 == NULL)
+ return (NULL);
+ /*
+ * Restore original address if mapped/compatible.
+ */
+ if (af == AF_INET6)
+ memcpy(he1->h_addr, src, len);
+ return (he2);
+ }
+
+ /*
+ * Lookup IPv6 address.
+ */
+ if (memcmp((const struct in6_addr *)src, &in6addr_any, 16) == 0) {
+ *error_num = HOST_NOT_FOUND;
+ return (NULL);
+ }
+
+ he1 = gethostbyaddr_p(src, 16, AF_INET6, net_data);
+ if (he1 == NULL) {
+ *error_num = net_data->res->res_h_errno;
+ return (NULL);
+ }
+ return (copyandmerge(he1, NULL, af, error_num));
+}
+
+void
+freehostent(struct hostent *he) {
+ char **cpp;
+ int names = 1;
+ int addresses = 1;
+
+ memput(he->h_name, strlen(he->h_name) + 1);
+
+ cpp = he->h_addr_list;
+ while (*cpp != NULL) {
+ memput(*cpp, (he->h_addrtype == AF_INET) ?
+ INADDRSZ : IN6ADDRSZ);
+ *cpp = NULL;
+ cpp++;
+ addresses++;
+ }
+
+ cpp = he->h_aliases;
+ while (*cpp != NULL) {
+ memput(*cpp, strlen(*cpp) + 1);
+ cpp++;
+ names++;
+ }
+
+ memput(he->h_aliases, sizeof(char *) * (names));
+ memput(he->h_addr_list, sizeof(char *) * (addresses));
+ memput(he, sizeof *he);
+}
+
+/*
+ * Private
+ */
+
+/*
+ * Scan the interface table and set have_v4 and have_v6 depending
+ * upon whether there are IPv4 and IPv6 interface addresses.
+ *
+ * Returns:
+ * 0 on success
+ * -1 on failure.
+ */
+
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
+ !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
+
+#define SETFAMILYFLAGS
+#define LIFCONF lifconf
+#define LIFREQ lifreq
+
+static void
+scan_interfaces6(int *have_v4, int *have_v6) {
+ struct LIFCONF lifc;
+ struct LIFREQ lifreq;
+ struct in_addr in4;
+ struct in6_addr in6;
+ char *buf = NULL, *cp, *cplim;
+ static unsigned int bufsiz = 4095;
+ int s, cpsize, n;
+
+ /* Get interface list from system. */
+ if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) == -1)
+ goto cleanup;
+
+ /*
+ * Grow buffer until large enough to contain all interface
+ * descriptions.
+ */
+ for (;;) {
+ buf = memget(bufsiz);
+ if (buf == NULL)
+ goto cleanup;
+#ifdef SETFAMILYFLAGS
+ lifc.lifc_family = AF_UNSPEC; /* request all families */
+ lifc.lifc_flags = 0;
+#endif
+ lifc.lifc_len = bufsiz;
+ lifc.lifc_buf = buf;
+ if ((n = ioctl(s, SIOCGLIFCONF, (char *)&lifc)) != -1) {
+ /*
+ * Some OS's just return what will fit rather
+ * than set EINVAL if the buffer is too small
+ * to fit all the interfaces in. If
+ * lifc.lifc_len is too near to the end of the
+ * buffer we will grow it just in case and
+ * retry.
+ */
+ if (lifc.lifc_len + 2 * sizeof(lifreq) < bufsiz)
+ break;
+ }
+ if ((n == -1) && errno != EINVAL)
+ goto cleanup;
+
+ if (bufsiz > 1000000)
+ goto cleanup;
+
+ 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;
+ cleanup:
+ if (buf != NULL)
+ memput(buf, bufsiz);
+ if (s != -1)
+ close(s);
+ /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
+ return;
+}
+#endif
+
+static int
+scan_interfaces(int *have_v4, int *have_v6) {
+ struct ifconf ifc;
+ union {
+ char _pad[256]; /* leave space for IPv6 addresses */
+ struct ifreq ifreq;
+ } u;
+ struct in_addr in4;
+ struct in6_addr in6;
+ char *buf = NULL, *cp, *cplim;
+ static unsigned int bufsiz = 4095;
+ int s, n;
+ size_t cpsize;
+
+ /* Set to zero. Used as loop terminators below. */
+ *have_v4 = *have_v6 = 0;
+
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
+ !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
+ /*
+ * Try to scan the interfaces using IPv6 ioctls().
+ */
+ scan_interfaces6(have_v4, have_v6);
+ if (*have_v4 != 0 && *have_v6 != 0)
+ return (0);
+#endif
+
+ /* Get interface list from system. */
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+ goto err_ret;
+
+ /*
+ * Grow buffer until large enough to contain all interface
+ * descriptions.
+ */
+ for (;;) {
+ buf = memget(bufsiz);
+ if (buf == NULL)
+ goto err_ret;
+ ifc.ifc_len = bufsiz;
+ ifc.ifc_buf = buf;
+#ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF
+ /*
+ * This is a fix for IRIX OS in which the call to ioctl with
+ * the flag SIOCGIFCONF may not return an entry for all the
+ * interfaces like most flavors of Unix.
+ */
+ if (emul_ioctl(&ifc) >= 0)
+ break;
+#else
+ if ((n = ioctl(s, SIOCGIFCONF, (char *)&ifc)) != -1) {
+ /*
+ * Some OS's just return what will fit rather
+ * than set EINVAL if the buffer is too small
+ * to fit all the interfaces in. If
+ * ifc.ifc_len is too near to the end of the
+ * buffer we will grow it just in case and
+ * retry.
+ */
+ if (ifc.ifc_len + 2 * sizeof(u.ifreq) < bufsiz)
+ break;
+ }
+#endif
+ if ((n == -1) && errno != EINVAL)
+ goto err_ret;
+
+ if (bufsiz > 1000000)
+ goto err_ret;
+
+ memput(buf, bufsiz);
+ bufsiz += 4096;
+ }
+
+ /* Parse system's interface list. */
+ cplim = buf + ifc.ifc_len; /* skip over if's with big ifr_addr's */
+ for (cp = buf;
+ (*have_v4 == 0 || *have_v6 == 0) && cp < cplim;
+ cp += cpsize) {
+ memcpy(&u.ifreq, cp, sizeof u.ifreq);
+#ifdef HAVE_SA_LEN
+#ifdef FIX_ZERO_SA_LEN
+ if (u.ifreq.ifr_addr.sa_len == 0)
+ u.ifreq.ifr_addr.sa_len = 16;
+#endif
+#ifdef HAVE_MINIMUM_IFREQ
+ cpsize = sizeof u.ifreq;
+ if (u.ifreq.ifr_addr.sa_len > sizeof (struct sockaddr))
+ cpsize += (int)u.ifreq.ifr_addr.sa_len -
+ (int)(sizeof (struct sockaddr));
+#else
+ cpsize = sizeof u.ifreq.ifr_name + u.ifreq.ifr_addr.sa_len;
+#endif /* HAVE_MINIMUM_IFREQ */
+ if (cpsize > sizeof u.ifreq && cpsize <= sizeof u)
+ memcpy(&u.ifreq, cp, cpsize);
+#elif defined SIOCGIFCONF_ADDR
+ cpsize = sizeof u.ifreq;
+#else
+ cpsize = sizeof u.ifreq.ifr_name;
+ /* XXX maybe this should be a hard error? */
+ if (ioctl(s, SIOCGIFADDR, (char *)&u.ifreq) < 0)
+ continue;
+#endif
+ switch (u.ifreq.ifr_addr.sa_family) {
+ case AF_INET:
+ if (*have_v4 == 0) {
+ memcpy(&in4,
+ &((struct sockaddr_in *)
+ &u.ifreq.ifr_addr)->sin_addr,
+ sizeof in4);
+ if (in4.s_addr == INADDR_ANY)
+ break;
+ n = ioctl(s, SIOCGIFFLAGS, (char *)&u.ifreq);
+ if (n < 0)
+ break;
+ if ((u.ifreq.ifr_flags & IFF_UP) == 0)
+ break;
+ *have_v4 = 1;
+ }
+ break;
+ case AF_INET6:
+ if (*have_v6 == 0) {
+ memcpy(&in6,
+ &((struct sockaddr_in6 *)
+ &u.ifreq.ifr_addr)->sin6_addr,
+ sizeof in6);
+ if (memcmp(&in6, &in6addr_any, sizeof in6) == 0)
+ break;
+ n = ioctl(s, SIOCGIFFLAGS, (char *)&u.ifreq);
+ if (n < 0)
+ break;
+ if ((u.ifreq.ifr_flags & IFF_UP) == 0)
+ break;
+ *have_v6 = 1;
+ }
+ break;
+ }
+ }
+ if (buf != NULL)
+ memput(buf, bufsiz);
+ close(s);
+ /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
+ return (0);
+ err_ret:
+ if (buf != NULL)
+ memput(buf, bufsiz);
+ if (s != -1)
+ close(s);
+ /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
+ return (-1);
+}
+
+static struct hostent *
+copyandmerge(struct hostent *he1, struct hostent *he2, int af, int *error_num) {
+ struct hostent *he = NULL;
+ int addresses = 1; /* NULL terminator */
+ int names = 1; /* NULL terminator */
+ int len = 0;
+ char **cpp, **npp;
+
+ /*
+ * Work out array sizes;
+ */
+ if (he1 != NULL) {
+ cpp = he1->h_addr_list;
+ while (*cpp != NULL) {
+ addresses++;
+ cpp++;
+ }
+ cpp = he1->h_aliases;
+ while (*cpp != NULL) {
+ names++;
+ cpp++;
+ }
+ }
+
+ if (he2 != NULL) {
+ cpp = he2->h_addr_list;
+ while (*cpp != NULL) {
+ addresses++;
+ cpp++;
+ }
+ if (he1 == NULL) {
+ cpp = he2->h_aliases;
+ while (*cpp != NULL) {
+ names++;
+ cpp++;
+ }
+ }
+ }
+
+ if (addresses == 1) {
+ *error_num = NO_ADDRESS;
+ return (NULL);
+ }
+
+ he = memget(sizeof *he);
+ if (he == NULL)
+ goto no_recovery;
+
+ he->h_addr_list = memget(sizeof(char *) * (addresses));
+ if (he->h_addr_list == NULL)
+ goto cleanup0;
+ memset(he->h_addr_list, 0, sizeof(char *) * (addresses));
+
+ /* copy addresses */
+ npp = he->h_addr_list;
+ if (he1 != NULL) {
+ cpp = he1->h_addr_list;
+ while (*cpp != NULL) {
+ *npp = memget((af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
+ if (*npp == NULL)
+ goto cleanup1;
+ /* convert to mapped if required */
+ if (af == AF_INET6 && he1->h_addrtype == AF_INET) {
+ memcpy(*npp, in6addr_mapped,
+ sizeof in6addr_mapped);
+ memcpy(*npp + sizeof in6addr_mapped, *cpp,
+ INADDRSZ);
+ } else {
+ memcpy(*npp, *cpp,
+ (af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
+ }
+ cpp++;
+ npp++;
+ }
+ }
+
+ if (he2 != NULL) {
+ cpp = he2->h_addr_list;
+ while (*cpp != NULL) {
+ *npp = memget((af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
+ if (*npp == NULL)
+ goto cleanup1;
+ /* convert to mapped if required */
+ if (af == AF_INET6 && he2->h_addrtype == AF_INET) {
+ memcpy(*npp, in6addr_mapped,
+ sizeof in6addr_mapped);
+ memcpy(*npp + sizeof in6addr_mapped, *cpp,
+ INADDRSZ);
+ } else {
+ memcpy(*npp, *cpp,
+ (af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
+ }
+ cpp++;
+ npp++;
+ }
+ }
+
+ he->h_aliases = memget(sizeof(char *) * (names));
+ if (he->h_aliases == NULL)
+ goto cleanup1;
+ memset(he->h_aliases, 0, sizeof(char *) * (names));
+
+ /* copy aliases */
+ npp = he->h_aliases;
+ cpp = (he1 != NULL) ? he1->h_aliases : he2->h_aliases;
+ while (*cpp != NULL) {
+ len = strlen (*cpp) + 1;
+ *npp = memget(len);
+ if (*npp == NULL)
+ goto cleanup2;
+ strcpy(*npp, *cpp);
+ npp++;
+ cpp++;
+ }
+
+ /* copy hostname */
+ he->h_name = memget(strlen((he1 != NULL) ?
+ he1->h_name : he2->h_name) + 1);
+ if (he->h_name == NULL)
+ goto cleanup2;
+ strcpy(he->h_name, (he1 != NULL) ? he1->h_name : he2->h_name);
+
+ /* set address type and length */
+ he->h_addrtype = af;
+ he->h_length = (af == AF_INET) ? INADDRSZ : IN6ADDRSZ;
+ return(he);
+
+ cleanup2:
+ cpp = he->h_aliases;
+ while (*cpp != NULL) {
+ memput(*cpp, strlen(*cpp) + 1);
+ cpp++;
+ }
+ memput(he->h_aliases, sizeof(char *) * (names));
+
+ cleanup1:
+ cpp = he->h_addr_list;
+ while (*cpp != NULL) {
+ memput(*cpp, (af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
+ *cpp = NULL;
+ cpp++;
+ }
+ memput(he->h_addr_list, sizeof(char *) * (addresses));
+
+ cleanup0:
+ memput(he, sizeof *he);
+
+ no_recovery:
+ *error_num = NO_RECOVERY;
+ return (NULL);
+}
+
+static struct net_data *
+init() {
+ struct net_data *net_data;
+
+ if (!(net_data = net_data_init(NULL)))
+ goto error;
+ if (!net_data->ho) {
+ net_data->ho = (*net_data->irs->ho_map)(net_data->irs);
+ if (!net_data->ho || !net_data->res) {
+ error:
+ errno = EIO;
+ if (net_data && net_data->res)
+ RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
+ return (NULL);
+ }
+
+ (*net_data->ho->res_set)(net_data->ho, net_data->res, NULL);
+ }
+
+ return (net_data);
+}
+
+static void
+freepvt(struct net_data *net_data) {
+ if (net_data->ho_data) {
+ free(net_data->ho_data);
+ net_data->ho_data = NULL;
+ }
+}
+
+static struct hostent *
+fakeaddr(const char *name, int af, struct net_data *net_data) {
+ struct pvt *pvt;
+
+ freepvt(net_data);
+ net_data->ho_data = malloc(sizeof (struct pvt));
+ if (!net_data->ho_data) {
+ errno = ENOMEM;
+ RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
+ return (NULL);
+ }
+ pvt = net_data->ho_data;
+#ifndef __bsdi__
+ /*
+ * Unlike its forebear(inet_aton), our friendly inet_pton() is strict
+ * in its interpretation of its input, and it will only return "1" if
+ * the input string is a formally valid(and thus unambiguous with
+ * respect to host names) internet address specification for this AF.
+ *
+ * This means "telnet 0xdeadbeef" and "telnet 127.1" are dead now.
+ */
+ if (inet_pton(af, name, pvt->addr) != 1) {
+#else
+ /* BSDI XXX
+ * We put this back to inet_aton -- we really want the old behavior
+ * Long live 127.1...
+ */
+ if ((af != AF_INET ||
+ inet_aton(name, (struct in_addr *)pvt->addr) != 1) &&
+ inet_pton(af, name, pvt->addr) != 1) {
+#endif
+ RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND);
+ return (NULL);
+ }
+ strncpy(pvt->name, name, NS_MAXDNAME);
+ pvt->name[NS_MAXDNAME] = '\0';
+ if (af == AF_INET && (net_data->res->options & RES_USE_INET6) != 0) {
+ map_v4v6_address(pvt->addr, pvt->addr);
+ af = AF_INET6;
+ }
+ pvt->host.h_addrtype = af;
+ switch(af) {
+ case AF_INET:
+ pvt->host.h_length = NS_INADDRSZ;
+ break;
+ case AF_INET6:
+ pvt->host.h_length = NS_IN6ADDRSZ;
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
+ return (NULL);
+ }
+ pvt->host.h_name = pvt->name;
+ pvt->host.h_aliases = pvt->aliases;
+ pvt->aliases[0] = NULL;
+ pvt->addrs[0] = (char *)pvt->addr;
+ pvt->addrs[1] = NULL;
+ pvt->host.h_addr_list = pvt->addrs;
+ RES_SET_H_ERRNO(net_data->res, NETDB_SUCCESS);
+ return (&pvt->host);
+}
+
+#ifdef grot /* for future use in gethostbyaddr(), for "SUNSECURITY" */
+ struct hostent *rhp;
+ char **haddr;
+ u_long old_options;
+ char hname2[MAXDNAME+1];
+
+ if (af == AF_INET) {
+ /*
+ * turn off search as the name should be absolute,
+ * 'localhost' should be matched by defnames
+ */
+ strncpy(hname2, hp->h_name, MAXDNAME);
+ hname2[MAXDNAME] = '\0';
+ old_options = net_data->res->options;
+ net_data->res->options &= ~RES_DNSRCH;
+ net_data->res->options |= RES_DEFNAMES;
+ if (!(rhp = gethostbyname(hname2))) {
+ net_data->res->options = old_options;
+ RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND);
+ return (NULL);
+ }
+ net_data->res->options = old_options;
+ for (haddr = rhp->h_addr_list; *haddr; haddr++)
+ if (!memcmp(*haddr, addr, INADDRSZ))
+ break;
+ if (!*haddr) {
+ RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND);
+ return (NULL);
+ }
+ }
+#endif /* grot */
+
+#endif /*__BIND_NOSTATIC*/
diff --git a/usr/src/lib/libresolv2/common/irs/gethostent_r.c b/usr/src/lib/libresolv2/common/irs/gethostent_r.c
new file mode 100644
index 0000000000..f6f77b7735
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/gethostent_r.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: gethostent_r.c,v 8.7 2001/11/01 08:02:09 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <port_before.h>
+#if !defined(_REENTRANT) || !defined(DO_PTHREADS)
+ static int gethostent_r_not_required = 0;
+#else
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/param.h>
+#include <port_after.h>
+
+#ifdef HOST_R_RETURN
+
+static HOST_R_RETURN
+copy_hostent(struct hostent *, struct hostent *, HOST_R_COPY_ARGS);
+
+HOST_R_RETURN
+gethostbyname_r(const char *name, struct hostent *hptr, HOST_R_ARGS) {
+ struct hostent *he = gethostbyname(name);
+#ifdef HOST_R_SETANSWER
+ int n = 0;
+#endif
+
+ HOST_R_ERRNO;
+
+#ifdef HOST_R_SETANSWER
+ if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) == 0)
+ *answerp = NULL;
+ else
+ *answerp = hptr;
+
+ return (n);
+#else
+ if (he == NULL)
+ return (HOST_R_BAD);
+
+ return (copy_hostent(he, hptr, HOST_R_COPY));
+#endif
+}
+
+HOST_R_RETURN
+gethostbyaddr_r(const char *addr, int len, int type,
+ struct hostent *hptr, HOST_R_ARGS) {
+ struct hostent *he = gethostbyaddr(addr, len, type);
+#ifdef HOST_R_SETANSWER
+ int n = 0;
+#endif
+
+ HOST_R_ERRNO;
+
+#ifdef HOST_R_SETANSWER
+ if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) == 0)
+ *answerp = NULL;
+ else
+ *answerp = hptr;
+
+ return (n);
+#else
+ if (he == NULL)
+ return (HOST_R_BAD);
+
+ return (copy_hostent(he, hptr, HOST_R_COPY));
+#endif
+}
+
+/*
+ * These assume a single context is in operation per thread.
+ * If this is not the case we will need to call irs directly
+ * rather than through the base functions.
+ */
+
+HOST_R_RETURN
+gethostent_r(struct hostent *hptr, HOST_R_ARGS) {
+ struct hostent *he = gethostent();
+#ifdef HOST_R_SETANSWER
+ int n = 0;
+#endif
+
+ HOST_R_ERRNO;
+
+#ifdef HOST_R_SETANSWER
+ if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) == 0)
+ *answerp = NULL;
+ else
+ *answerp = hptr;
+
+ return (n);
+#else
+ if (he == NULL)
+ return (HOST_R_BAD);
+
+ return (copy_hostent(he, hptr, HOST_R_COPY));
+#endif
+}
+
+HOST_R_SET_RETURN
+#ifdef HOST_R_ENT_ARGS
+sethostent_r(int stay_open, HOST_R_ENT_ARGS)
+#else
+sethostent_r(int stay_open)
+#endif
+{
+ sethostent(stay_open);
+#ifdef HOST_R_SET_RESULT
+ return (HOST_R_SET_RESULT);
+#endif
+}
+
+HOST_R_END_RETURN
+#ifdef HOST_R_ENT_ARGS
+endhostent_r(HOST_R_ENT_ARGS)
+#else
+endhostent_r(void)
+#endif
+{
+ endhostent();
+ HOST_R_END_RESULT(HOST_R_OK);
+}
+
+/* Private */
+
+#ifndef HOSTENT_DATA
+static HOST_R_RETURN
+copy_hostent(struct hostent *he, struct hostent *hptr, HOST_R_COPY_ARGS) {
+ char *cp;
+ char **ptr;
+ int i, n;
+ int nptr, len;
+
+ /* Find out the amount of space required to store the answer. */
+ nptr = 2; /* NULL ptrs */
+ len = (char *)ALIGN(buf) - buf;
+ for (i = 0; he->h_addr_list[i]; i++, nptr++) {
+ len += he->h_length;
+ }
+ for (i = 0; he->h_aliases[i]; i++, nptr++) {
+ len += strlen(he->h_aliases[i]) + 1;
+ }
+ len += strlen(he->h_name) + 1;
+ len += nptr * sizeof(char*);
+
+ if (len > buflen) {
+ errno = ERANGE;
+ return (HOST_R_BAD);
+ }
+
+ /* copy address size and type */
+ hptr->h_addrtype = he->h_addrtype;
+ n = hptr->h_length = he->h_length;
+
+ ptr = (char **)ALIGN(buf);
+ cp = (char *)ALIGN(buf) + nptr * sizeof(char *);
+
+ /* copy address list */
+ hptr->h_addr_list = ptr;
+ for (i = 0; he->h_addr_list[i]; i++ , ptr++) {
+ memcpy(cp, he->h_addr_list[i], n);
+ hptr->h_addr_list[i] = cp;
+ cp += n;
+ }
+ hptr->h_addr_list[i] = NULL;
+ ptr++;
+
+ /* copy official name */
+ n = strlen(he->h_name) + 1;
+ strcpy(cp, he->h_name);
+ hptr->h_name = cp;
+ cp += n;
+
+ /* copy aliases */
+ hptr->h_aliases = ptr;
+ for (i = 0 ; he->h_aliases[i]; i++) {
+ n = strlen(he->h_aliases[i]) + 1;
+ strcpy(cp, he->h_aliases[i]);
+ hptr->h_aliases[i] = cp;
+ cp += n;
+ }
+ hptr->h_aliases[i] = NULL;
+
+ return (HOST_R_OK);
+}
+#else /* !HOSTENT_DATA */
+static int
+copy_hostent(struct hostent *he, struct hostent *hptr, HOST_R_COPY_ARGS) {
+ char *cp, *eob;
+ int i, n;
+
+ /* copy address size and type */
+ hptr->h_addrtype = he->h_addrtype;
+ n = hptr->h_length = he->h_length;
+
+ /* copy up to first 35 addresses */
+ i = 0;
+ cp = hdptr->hostaddr;
+ eob = hdptr->hostaddr + sizeof(hdptr->hostaddr);
+ hptr->h_addr_list = hdptr->h_addr_ptrs;
+ while (he->h_addr_list[i] && i < (_MAXADDRS)) {
+ if (n < (eob - cp)) {
+ memcpy(cp, he->h_addr_list[i], n);
+ hptr->h_addr_list[i] = cp;
+ cp += n;
+ } else {
+ break;
+ }
+ i++;
+ }
+ hptr->h_addr_list[i] = NULL;
+
+ /* copy official name */
+ cp = hdptr->hostbuf;
+ eob = hdptr->hostbuf + sizeof(hdptr->hostbuf);
+ if ((n = strlen(he->h_name) + 1) < (eob - cp)) {
+ strcpy(cp, he->h_name);
+ hptr->h_name = cp;
+ cp += n;
+ } else {
+ return (-1);
+ }
+
+ /* copy aliases */
+ i = 0;
+ hptr->h_aliases = hdptr->host_aliases;
+ while (he->h_aliases[i] && i < (_MAXALIASES-1)) {
+ if ((n = strlen(he->h_aliases[i]) + 1) < (eob - cp)) {
+ strcpy(cp, he->h_aliases[i]);
+ hptr->h_aliases[i] = cp;
+ cp += n;
+ } else {
+ break;
+ }
+ i++;
+ }
+ hptr->h_aliases[i] = NULL;
+
+ return (HOST_R_OK);
+}
+#endif /* !HOSTENT_DATA */
+#else /* HOST_R_RETURN */
+ static int gethostent_r_unknown_system = 0;
+#endif /* HOST_R_RETURN */
+#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */
diff --git a/usr/src/lib/libresolv2/common/irs/getnameinfo.c b/usr/src/lib/libresolv2/common/irs/getnameinfo.c
new file mode 100644
index 0000000000..e645196a80
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/getnameinfo.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Issues to be discussed:
+ * - Thread safe-ness must be checked
+ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by WIDE Project and
+ * its contributors.
+ * 4. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <port_before.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+
+#include <netdb.h>
+#include <resolv.h>
+#include <string.h>
+#include <stddef.h>
+
+#include <port_after.h>
+
+/*
+ * Note that a_off will be dynamically adjusted so that to be consistent
+ * with the definition of sockaddr_in{,6}.
+ * The value presented below is just a guess.
+ */
+static struct afd {
+ int a_af;
+ int a_addrlen;
+ size_t a_socklen;
+ int a_off;
+} afdl [] = {
+ /* first entry is linked last... */
+ {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr)},
+ {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
+ offsetof(struct sockaddr_in6, sin6_addr)},
+ {0, 0, 0, 0},
+};
+
+struct sockinet {
+#ifdef HAVE_SA_LEN
+ u_char si_len;
+#endif
+ u_char si_family;
+ u_short si_port;
+};
+
+static int ip6_parsenumeric __P((const struct sockaddr *, const char *, char *,
+ size_t, int));
+#ifdef HAVE_SIN6_SCOPE_ID
+static int ip6_sa2str __P((const struct sockaddr_in6 *, char *, size_t, int));
+#endif
+
+int
+getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
+ const struct sockaddr *sa;
+#ifdef ORIGINAL_ISC_CODE
+ size_t salen;
+#else
+ socklen_t salen;
+#endif
+ char *host;
+#ifdef ORIGINAL_ISC_CODE
+ size_t hostlen;
+#else
+ socklen_t hostlen;
+#endif
+ char *serv;
+#ifdef ORIGINAL_ISC_CODE
+ size_t servlen;
+#else
+ socklen_t servlen;
+#endif
+ int flags;
+{
+ struct afd *afd;
+ struct servent *sp;
+ struct hostent *hp;
+ u_short port;
+#ifdef HAVE_SA_LEN
+ size_t len;
+#endif
+ int family, i;
+ const char *addr;
+ char *p;
+ char numserv[512];
+ char numaddr[512];
+ const struct sockaddr_in6 *sin6;
+
+ if (sa == NULL)
+ return EAI_FAIL;
+
+#ifdef HAVE_SA_LEN
+ len = sa->sa_len;
+ if (len != salen) return EAI_FAIL;
+#endif
+
+ family = sa->sa_family;
+ for (i = 0; afdl[i].a_af; i++)
+ if (afdl[i].a_af == family) {
+ afd = &afdl[i];
+ goto found;
+ }
+ return EAI_FAMILY;
+
+ found:
+ if (salen != afd->a_socklen) return EAI_FAIL;
+
+ port = ((const struct sockinet *)sa)->si_port; /* network byte order */
+ addr = (const char *)sa + afd->a_off;
+
+ if (serv == NULL || servlen == 0) {
+ /*
+ * rfc2553bis says that serv == NULL or servlen == 0 means that
+ * the caller does not want the result.
+ */
+ } else if (flags & NI_NUMERICSERV) {
+ sprintf(numserv, "%d", ntohs(port));
+ if (strlen(numserv) > servlen)
+ return EAI_MEMORY;
+ strcpy(serv, numserv);
+ } else {
+ sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
+ if (sp) {
+ if (strlen(sp->s_name) + 1 > servlen)
+ return EAI_MEMORY;
+ strcpy(serv, sp->s_name);
+ } else
+ return EAI_NONAME;
+ }
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ if (ntohl(*(const u_long *)addr) >> IN_CLASSA_NSHIFT == 0)
+ flags |= NI_NUMERICHOST;
+ break;
+ case AF_INET6:
+ sin6 = (const struct sockaddr_in6 *)sa;
+ switch (sin6->sin6_addr.s6_addr[0]) {
+ case 0x00:
+ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
+ ;
+ else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
+ ;
+ else
+ flags |= NI_NUMERICHOST;
+ break;
+ default:
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
+ flags |= NI_NUMERICHOST;
+ else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
+ flags |= NI_NUMERICHOST;
+ break;
+ }
+ break;
+ }
+ if (host == NULL || hostlen == 0) {
+ /*
+ * rfc2553bis says that host == NULL or hostlen == 0 means that
+ * the caller does not want the result.
+ */
+ } else if (flags & NI_NUMERICHOST) {
+ goto numeric;
+ } else {
+ hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
+
+ if (hp) {
+ if (flags & NI_NOFQDN) {
+ p = strchr(hp->h_name, '.');
+ if (p) *p = '\0';
+ }
+ if (strlen(hp->h_name) + 1 > hostlen)
+ return EAI_MEMORY;
+ strcpy(host, hp->h_name);
+ } else {
+ if (flags & NI_NAMEREQD)
+ return EAI_NONAME;
+ numeric:
+ switch(afd->a_af) {
+ case AF_INET6:
+ {
+ int error;
+
+ if ((error = ip6_parsenumeric(sa, addr, host,
+ hostlen,
+ flags)) != 0)
+ return(error);
+ break;
+ }
+
+ default:
+ if (inet_ntop(afd->a_af, addr, numaddr,
+ sizeof(numaddr)) == NULL)
+ return EAI_NONAME;
+ if (strlen(numaddr) + 1 > hostlen)
+ return EAI_MEMORY;
+ strcpy(host, numaddr);
+ }
+ }
+ }
+ return(0);
+}
+
+static int
+ip6_parsenumeric(const struct sockaddr *sa, const char *addr, char *host,
+ size_t hostlen, int flags)
+{
+ size_t numaddrlen;
+ char numaddr[512];
+
+#ifndef HAVE_SIN6_SCOPE_ID
+ UNUSED(sa);
+ UNUSED(flags);
+#endif
+
+ if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr))
+ == NULL)
+ return EAI_SYSTEM;
+
+ numaddrlen = strlen(numaddr);
+ if (numaddrlen + 1 > hostlen) /* don't forget terminator */
+ return EAI_MEMORY;
+ strcpy(host, numaddr);
+
+#ifdef HAVE_SIN6_SCOPE_ID
+ if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) {
+ char scopebuf[MAXHOSTNAMELEN]; /* XXX */
+ int scopelen;
+
+ /* ip6_sa2str never fails */
+ scopelen = ip6_sa2str((const struct sockaddr_in6 *)sa,
+ scopebuf, sizeof(scopebuf), flags);
+
+ if (scopelen + 1 + numaddrlen + 1 > hostlen)
+ return EAI_MEMORY;
+
+ /* construct <numeric-addr><delim><scopeid> */
+ memcpy(host + numaddrlen + 1, scopebuf,
+ scopelen);
+ host[numaddrlen] = SCOPE_DELIMITER;
+ host[numaddrlen + 1 + scopelen] = '\0';
+ }
+#endif
+
+ return 0;
+}
+
+#ifdef HAVE_SIN6_SCOPE_ID
+/* ARGSUSED */
+static int
+ip6_sa2str(const struct sockaddr_in6 *sa6, char *buf,
+ size_t bufsiz, int flags)
+{
+#ifdef USE_IFNAMELINKID
+ unsigned int ifindex = (unsigned int)sa6->sin6_scope_id;
+ const struct in6_addr *a6 = &sa6->sin6_addr;
+#endif
+ char tmp[64];
+
+#ifdef NI_NUMERICSCOPE
+ if (flags & NI_NUMERICSCOPE) {
+ sprintf(tmp, "%u", sa6->sin6_scope_id);
+ if (bufsiz != 0) {
+ strncpy(buf, tmp, bufsiz - 1);
+ buf[bufsiz - 1] = '\0';
+ }
+ return(strlen(tmp));
+ }
+#endif
+
+#ifdef USE_IFNAMELINKID
+ /*
+ * For a link-local address, convert the index to an interface
+ * name, assuming a one-to-one mapping between links and interfaces.
+ * Note, however, that this assumption is stronger than the
+ * specification of the scoped address architecture; the
+ * specficication says that more than one interfaces can belong to
+ * a single link.
+ */
+
+ /* if_indextoname() does not take buffer size. not a good api... */
+ if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) &&
+ bufsiz >= IF_NAMESIZE) {
+ char *p = if_indextoname(ifindex, buf);
+ if (p) {
+ return(strlen(p));
+ }
+ }
+#endif
+
+ /* last resort */
+ sprintf(tmp, "%u", sa6->sin6_scope_id);
+ if (bufsiz != 0) {
+ strncpy(buf, tmp, bufsiz - 1);
+ buf[bufsiz - 1] = '\0';
+ }
+ return(strlen(tmp));
+}
+#endif
diff --git a/usr/src/lib/libresolv2/common/irs/getnetent.c b/usr/src/lib/libresolv2/common/irs/getnetent.c
new file mode 100644
index 0000000000..8cf81d4699
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/getnetent.c
@@ -0,0 +1,370 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: getnetent.c,v 1.19 2001/05/29 05:48:47 marka Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#if !defined(__BIND_NOSTATIC)
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <irs.h>
+
+#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 *
+#ifdef ORIGINAL_ISC_CODE
+getnetbyaddr(unsigned long net, int type) {
+#else
+getnetbyaddr(in_addr_t net, int type) {
+#endif
+ struct net_data *net_data = init();
+
+ return (getnetbyaddr_p(net, type, net_data));
+}
+
+#ifdef ORIGINAL_ISC_CODE
+void
+#else
+int
+#endif
+setnetent(int stayopen) {
+ struct net_data *net_data = init();
+
+ setnetent_p(stayopen, net_data);
+#ifdef ORIGINAL_ISC_CODE
+#else
+ return (0);
+#endif
+}
+
+
+#ifdef ORIGINAL_ISC_CODE
+void
+#else
+int
+#endif
+endnetent() {
+ struct net_data *net_data = init();
+
+ endnetent_p(net_data);
+#ifdef ORIGINAL_ISC_CODE
+#else
+ return (0);
+#endif
+}
+
+/* Shared private. */
+
+struct netent *
+getnetent_p(struct net_data *net_data) {
+ struct irs_nw *nw;
+
+ if (!net_data || !(nw = net_data->nw))
+ return (NULL);
+ net_data->nww_last = (*nw->next)(nw);
+ net_data->nw_last = nw_to_net(net_data->nww_last, net_data);
+ return (net_data->nw_last);
+}
+
+struct netent *
+getnetbyname_p(const char *name, struct net_data *net_data) {
+ struct irs_nw *nw;
+ struct netent *np;
+ char **nap;
+
+ if (!net_data || !(nw = net_data->nw))
+ return (NULL);
+ if (net_data->nw_stayopen && net_data->nw_last) {
+ if (!strcmp(net_data->nw_last->n_name, name))
+ return (net_data->nw_last);
+ for (nap = net_data->nw_last->n_aliases; nap && *nap; nap++)
+ if (!strcmp(name, *nap))
+ return (net_data->nw_last);
+ }
+ if ((np = fakeaddr(name, AF_INET, net_data)) != NULL)
+ return (np);
+ net_data->nww_last = (*nw->byname)(nw, name, AF_INET);
+ net_data->nw_last = nw_to_net(net_data->nww_last, net_data);
+ if (!net_data->nw_stayopen)
+ endnetent();
+ return (net_data->nw_last);
+}
+
+struct netent *
+getnetbyaddr_p(unsigned long net, int type, struct net_data *net_data) {
+ struct irs_nw *nw;
+ u_char addr[4];
+ int bits;
+
+ if (!net_data || !(nw = net_data->nw))
+ return (NULL);
+ if (net_data->nw_stayopen && net_data->nw_last)
+ if (type == net_data->nw_last->n_addrtype &&
+ net == net_data->nw_last->n_net)
+ return (net_data->nw_last);
+
+ /* cannonize net(host order) */
+ if (net < 256) {
+ net <<= 24;
+ bits = 8;
+ } else if (net < 65536) {
+ net <<= 16;
+ bits = 16;
+ } else if (net < 16777216) {
+ net <<= 8;
+ bits = 24;
+ } else
+ bits = 32;
+
+ /* convert to net order */
+ addr[0] = (0xFF000000 & net) >> 24;
+ addr[1] = (0x00FF0000 & net) >> 16;
+ addr[2] = (0x0000FF00 & net) >> 8;
+ addr[3] = (0x000000FF & net);
+
+ /* reduce bits to as close to natural number as possible */
+ if ((bits == 32) && (addr[0] < 224) && (addr[3] == 0)) {
+ if ((addr[0] < 192) && (addr[2] == 0)) {
+ if ((addr[0] < 128) && (addr[1] == 0))
+ bits = 8;
+ else
+ bits = 16;
+ } else {
+ bits = 24;
+ }
+ }
+
+ net_data->nww_last = (*nw->byaddr)(nw, addr, bits, AF_INET);
+ net_data->nw_last = nw_to_net(net_data->nww_last, net_data);
+ if (!net_data->nw_stayopen)
+ endnetent();
+ return (net_data->nw_last);
+}
+
+
+
+
+void
+setnetent_p(int stayopen, struct net_data *net_data) {
+ struct irs_nw *nw;
+
+ if (!net_data || !(nw = net_data->nw))
+ return;
+ freepvt(net_data);
+ (*nw->rewind)(nw);
+ net_data->nw_stayopen = (stayopen != 0);
+ if (stayopen == 0)
+ net_data_minimize(net_data);
+}
+
+void
+endnetent_p(struct net_data *net_data) {
+ struct irs_nw *nw;
+
+ if ((net_data != NULL) && ((nw = net_data->nw) != NULL))
+ (*nw->minimize)(nw);
+}
+
+/* Private */
+
+static struct net_data *
+init() {
+ struct net_data *net_data;
+
+ if (!(net_data = net_data_init(NULL)))
+ goto error;
+ if (!net_data->nw) {
+ net_data->nw = (*net_data->irs->nw_map)(net_data->irs);
+
+ if (!net_data->nw || !net_data->res) {
+ error:
+ errno = EIO;
+ return (NULL);
+ }
+ (*net_data->nw->res_set)(net_data->nw, net_data->res, NULL);
+ }
+
+ return (net_data);
+}
+
+static void
+freepvt(struct net_data *net_data) {
+ if (net_data->nw_data) {
+ free(net_data->nw_data);
+ net_data->nw_data = NULL;
+ }
+}
+
+static struct netent *
+fakeaddr(const char *name, int af, struct net_data *net_data) {
+ struct pvt *pvt;
+ const char *cp;
+ u_long tmp;
+
+ if (af != AF_INET) {
+ /* XXX should support IPv6 some day */
+ errno = EAFNOSUPPORT;
+ RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
+ return (NULL);
+ }
+ if (!isascii((unsigned char)(name[0])) ||
+ !isdigit((unsigned char)(name[0])))
+ return (NULL);
+ for (cp = name; *cp; ++cp)
+ if (!isascii(*cp) || (!isdigit((unsigned char)*cp) && *cp != '.'))
+ return (NULL);
+ if (*--cp == '.')
+ return (NULL);
+
+ /* All-numeric, no dot at the end. */
+
+ tmp = inet_network(name);
+ if (tmp == INADDR_NONE) {
+ RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND);
+ return (NULL);
+ }
+
+ /* Valid network number specified.
+ * Fake up a netent as if we'd actually
+ * done a lookup.
+ */
+ freepvt(net_data);
+ net_data->nw_data = malloc(sizeof (struct pvt));
+ if (!net_data->nw_data) {
+ errno = ENOMEM;
+ RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
+ return (NULL);
+ }
+ pvt = net_data->nw_data;
+
+ strncpy(pvt->name, name, MAXDNAME);
+ pvt->name[MAXDNAME] = '\0';
+ pvt->netent.n_name = pvt->name;
+ pvt->netent.n_addrtype = AF_INET;
+ pvt->netent.n_aliases = pvt->aliases;
+ pvt->aliases[0] = NULL;
+ pvt->netent.n_net = tmp;
+
+ return (&pvt->netent);
+}
+
+static struct netent *
+nw_to_net(struct nwent *nwent, struct net_data *net_data) {
+ struct pvt *pvt;
+ u_long addr = 0;
+ int i;
+ int msbyte;
+
+ if (!nwent || nwent->n_addrtype != AF_INET)
+ return (NULL);
+ freepvt(net_data);
+ net_data->nw_data = malloc(sizeof (struct pvt));
+ if (!net_data->nw_data) {
+ errno = ENOMEM;
+ RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
+ return (NULL);
+ }
+ pvt = net_data->nw_data;
+ pvt->netent.n_name = nwent->n_name;
+ pvt->netent.n_aliases = nwent->n_aliases;
+ pvt->netent.n_addrtype = nwent->n_addrtype;
+
+/*
+ * What this code does: Converts net addresses from network to host form.
+ *
+ * msbyte: the index of the most significant byte in the n_addr array.
+ *
+ * Shift bytes in significant order into addr. When all signicant
+ * bytes are in, zero out bits in the LSB that are not part of the network.
+ */
+ msbyte = nwent->n_length / 8 +
+ ((nwent->n_length % 8) != 0 ? 1 : 0) - 1;
+ for (i = 0; i <= msbyte; i++)
+ addr = (addr << 8) | ((unsigned char *)nwent->n_addr)[i];
+ i = (32 - nwent->n_length) % 8;
+ if (i != 0)
+ addr &= ~((1 << (i + 1)) - 1);
+ pvt->netent.n_net = addr;
+ return (&pvt->netent);
+}
+
+#endif /*__BIND_NOSTATIC*/
diff --git a/usr/src/lib/libresolv2/common/irs/getnetent_r.c b/usr/src/lib/libresolv2/common/irs/getnetent_r.c
new file mode 100644
index 0000000000..1f8f9686c9
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/getnetent_r.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: getnetent_r.c,v 8.6 2001/11/01 08:02:11 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <port_before.h>
+#if !defined(_REENTRANT) || !defined(DO_PTHREADS)
+ static int getnetent_r_not_required = 0;
+#else
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/param.h>
+#include <port_after.h>
+
+#ifdef NET_R_RETURN
+
+static NET_R_RETURN
+copy_netent(struct netent *, struct netent *, NET_R_COPY_ARGS);
+
+NET_R_RETURN
+getnetbyname_r(const char *name, struct netent *nptr, NET_R_ARGS) {
+ struct netent *ne = getnetbyname(name);
+#ifdef NET_R_SETANSWER
+ int n = 0;
+
+ if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0)
+ *answerp = NULL;
+ else
+ *answerp = ne;
+ if (ne == NULL)
+ *h_errnop = h_errno;
+ return (n);
+#else
+ if (ne == NULL)
+ return (NET_R_BAD);
+
+ return (copy_netent(ne, nptr, NET_R_COPY));
+#endif
+}
+
+#ifndef GETNETBYADDR_ADDR_T
+#define GETNETBYADDR_ADDR_T long
+#endif
+NET_R_RETURN
+getnetbyaddr_r(GETNETBYADDR_ADDR_T addr, int type, struct netent *nptr, NET_R_ARGS) {
+ struct netent *ne = getnetbyaddr(addr, type);
+#ifdef NET_R_SETANSWER
+ int n = 0;
+
+ if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0)
+ *answerp = NULL;
+ else
+ *answerp = ne;
+ if (ne == NULL)
+ *h_errnop = h_errno;
+ return (n);
+#else
+
+ if (ne == NULL)
+ return (NET_R_BAD);
+
+ return (copy_netent(ne, nptr, NET_R_COPY));
+#endif
+}
+
+/*
+ * These assume a single context is in operation per thread.
+ * If this is not the case we will need to call irs directly
+ * rather than through the base functions.
+ */
+
+NET_R_RETURN
+getnetent_r(struct netent *nptr, NET_R_ARGS) {
+ struct netent *ne = getnetent();
+#ifdef NET_R_SETANSWER
+ int n = 0;
+
+ if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0)
+ *answerp = NULL;
+ else
+ *answerp = ne;
+ if (ne == NULL)
+ *h_errnop = h_errno;
+ return (n);
+#else
+
+ if (ne == NULL)
+ return (NET_R_BAD);
+
+ return (copy_netent(ne, nptr, NET_R_COPY));
+#endif
+}
+
+NET_R_SET_RETURN
+#ifdef NET_R_ENT_ARGS
+setnetent_r(int stay_open, NET_R_ENT_ARGS)
+#else
+setnetent_r(int stay_open)
+#endif
+{
+ setnetent(stay_open);
+#ifdef NET_R_SET_RESULT
+ return (NET_R_SET_RESULT);
+#endif
+}
+
+NET_R_END_RETURN
+#ifdef NET_R_ENT_ARGS
+endnetent_r(NET_R_ENT_ARGS)
+#else
+endnetent_r()
+#endif
+{
+ endnetent();
+ NET_R_END_RESULT(NET_R_OK);
+}
+
+/* Private */
+
+#ifndef NETENT_DATA
+static NET_R_RETURN
+copy_netent(struct netent *ne, struct netent *nptr, NET_R_COPY_ARGS) {
+ char *cp;
+ int i, n;
+ int numptr, len;
+
+ /* Find out the amount of space required to store the answer. */
+ numptr = 1; /* NULL ptr */
+ len = (char *)ALIGN(buf) - buf;
+ for (i = 0; ne->n_aliases[i]; i++, numptr++) {
+ len += strlen(ne->n_aliases[i]) + 1;
+ }
+ len += strlen(ne->n_name) + 1;
+ len += numptr * sizeof(char*);
+
+ if (len > (int)buflen) {
+ errno = ERANGE;
+ return (NET_R_BAD);
+ }
+
+ /* copy net value and type */
+ nptr->n_addrtype = ne->n_addrtype;
+ nptr->n_net = ne->n_net;
+
+ cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
+
+ /* copy official name */
+ n = strlen(ne->n_name) + 1;
+ strcpy(cp, ne->n_name);
+ nptr->n_name = cp;
+ cp += n;
+
+ /* copy aliases */
+ nptr->n_aliases = (char **)ALIGN(buf);
+ for (i = 0 ; ne->n_aliases[i]; i++) {
+ n = strlen(ne->n_aliases[i]) + 1;
+ strcpy(cp, ne->n_aliases[i]);
+ nptr->n_aliases[i] = cp;
+ cp += n;
+ }
+ nptr->n_aliases[i] = NULL;
+
+ return (NET_R_OK);
+}
+#else /* !NETENT_DATA */
+static int
+copy_netent(struct netent *ne, struct netent *nptr, NET_R_COPY_ARGS) {
+ char *cp, *eob;
+ int i, n;
+
+ /* copy net value and type */
+ nptr->n_addrtype = ne->n_addrtype;
+ nptr->n_net = ne->n_net;
+
+ /* copy official name */
+ cp = ndptr->line;
+ eob = ndptr->line + sizeof(ndptr->line);
+ if ((n = strlen(ne->n_name) + 1) < (eob - cp)) {
+ strcpy(cp, ne->n_name);
+ nptr->n_name = cp;
+ cp += n;
+ } else {
+ return (-1);
+ }
+
+ /* copy aliases */
+ i = 0;
+ nptr->n_aliases = ndptr->net_aliases;
+ while (ne->n_aliases[i] && i < (_MAXALIASES-1)) {
+ if ((n = strlen(ne->n_aliases[i]) + 1) < (eob - cp)) {
+ strcpy(cp, ne->n_aliases[i]);
+ nptr->n_aliases[i] = cp;
+ cp += n;
+ } else {
+ break;
+ }
+ i++;
+ }
+ nptr->n_aliases[i] = NULL;
+
+ return (NET_R_OK);
+}
+#endif /* !NETENT_DATA */
+#else /* NET_R_RETURN */
+ static int getnetent_r_unknown_system = 0;
+#endif /* NET_R_RETURN */
+#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */
diff --git a/usr/src/lib/libresolv2/common/irs/getnetgrent.c b/usr/src/lib/libresolv2/common/irs/getnetgrent.c
new file mode 100644
index 0000000000..69e322d647
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/getnetgrent.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: getnetgrent.c,v 1.17 2003/04/29 05:51:14 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/* Imports */
+
+#include "port_before.h"
+
+#if !defined(__BIND_NOSTATIC)
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <stdio.h>
+
+#include <irs.h>
+
+#include "port_after.h"
+
+#include "irs_data.h"
+
+/* Forward */
+
+static struct net_data *init(void);
+
+
+/* Public */
+
+#ifndef SETNETGRENT_ARGS
+#define SETNETGRENT_ARGS const char *netgroup
+#endif
+
+#ifdef ORIGINAL_ISC_CODE
+void
+#else
+int
+#endif
+setnetgrent(SETNETGRENT_ARGS) {
+ struct net_data *net_data = init();
+
+ setnetgrent_p(netgroup, net_data);
+#ifdef ORIGINAL_ISC_CODE
+#else
+ return (0);
+#endif
+}
+
+#ifdef ORIGINAL_ISC_CODE
+void
+#else
+int
+#endif
+endnetgrent(void) {
+ struct net_data *net_data = init();
+
+ endnetgrent_p(net_data);
+#ifdef ORIGINAL_ISC_CODE
+#else
+ return (0);
+#endif
+}
+
+#ifndef INNETGR_ARGS
+#define INNETGR_ARGS const char *netgroup, const char *host, \
+ const char *user, const char *domain
+#endif
+int
+innetgr(INNETGR_ARGS) {
+ struct net_data *net_data = init();
+
+ return (innetgr_p(netgroup, host, user, domain, net_data));
+}
+
+#ifdef ORIGINAL_ISC_CODE
+int
+getnetgrent(const char **host, const char **user, const char **domain) {
+ struct net_data *net_data = init();
+ const char *ch, *cu, *cd;
+ int ret;
+
+ ret = getnetgrent_p(&ch, &cu, &cd, net_data);
+ if (ret != 1)
+ return (ret);
+
+ DE_CONST(ch, *host);
+ DE_CONST(cu, *user);
+ DE_CONST(cd, *domain);
+ return (ret);
+}
+#else
+int
+getnetgrent(char **host, char **user, char **domain) {
+ struct net_data *net_data = init();
+
+ return (getnetgrent_p((const char **)host, (const char **)user,
+ (const char **)domain, net_data));
+
+}
+#endif /* ORIGINAL_ISC_CODE */
+
+/* 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/usr/src/lib/libresolv2/common/irs/getnetgrent_r.c b/usr/src/lib/libresolv2/common/irs/getnetgrent_r.c
new file mode 100644
index 0000000000..a53ebd2cee
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/getnetgrent_r.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: getnetgrent_r.c,v 8.7 2003/04/29 05:51:14 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <port_before.h>
+#if !defined(_REENTRANT) || !defined(DO_PTHREADS)
+ static int getnetgrent_r_not_required = 0;
+#else
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <netgroup.h>
+#include <stdlib.h>
+#include <port_after.h>
+
+#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) {
+ char *ng, *ho, *us, *dom;
+
+ DE_CONST(netgroup, ng);
+ DE_CONST(host, ho);
+ DE_CONST(user, us);
+ DE_CONST(domain, dom);
+
+ return (innetgr(ng, ho, us, dom));
+}
+
+/*
+ * These assume a single context is in operation per thread.
+ * If this is not the case we will need to call irs directly
+ * rather than through the base functions.
+ */
+
+NGR_R_RETURN
+getnetgrent_r(char **machinep, char **userp, char **domainp, NGR_R_ARGS) {
+ char *mp, *up, *dp;
+ int res = getnetgrent(&mp, &up, &dp);
+
+ if (res != 1)
+ return (res);
+
+ return (copy_protoent(machinep, userp, domainp,
+ mp, up, dp, NGR_R_COPY));
+}
+
+NGR_R_SET_RETURN
+#ifdef NGR_R_ENT_ARGS
+setnetgrent_r(const char *netgroup, NGR_R_ENT_ARGS)
+#else
+setnetgrent_r(const char *netgroup)
+#endif
+{
+ setnetgrent(netgroup);
+#ifdef NGR_R_PRIVATE
+ *buf = NULL;
+#endif
+#ifdef NGR_R_SET_RESULT
+ return (NGR_R_SET_RESULT);
+#endif
+}
+
+NGR_R_END_RETURN
+#ifdef NGR_R_ENT_ARGS
+endnetgrent_r(NGR_R_ENT_ARGS)
+#else
+endnetgrent_r(void)
+#endif
+{
+ endnetgrent();
+#ifdef NGR_R_PRIVATE
+ if (*buf != NULL)
+ free(*buf);
+ *buf = NULL;
+#endif
+ NGR_R_END_RESULT(NGR_R_OK);
+}
+
+/* Private */
+
+static int
+copy_protoent(char **machinep, char **userp, char **domainp,
+ const char *mp, const char *up, const char *dp,
+ NGR_R_COPY_ARGS) {
+ char *cp;
+ int n;
+ int len;
+
+ /* Find out the amount of space required to store the answer. */
+ len = 0;
+ if (mp != NULL) len += strlen(mp) + 1;
+ if (up != NULL) len += strlen(up) + 1;
+ if (dp != NULL) len += strlen(dp) + 1;
+
+#ifdef NGR_R_PRIVATE
+ free(*buf);
+ *buf = malloc(len);
+ if (*buf == NULL)
+ return(NGR_R_BAD);
+ cp = *buf;
+#else
+ if (len > (int)buflen) {
+ errno = ERANGE;
+ return (NGR_R_BAD);
+ }
+ cp = buf;
+#endif
+
+
+ if (mp != NULL) {
+ n = strlen(mp) + 1;
+ strcpy(cp, mp);
+ *machinep = cp;
+ cp += n;
+ } else
+ *machinep = NULL;
+
+ if (up != NULL) {
+ n = strlen(up) + 1;
+ strcpy(cp, up);
+ *userp = cp;
+ cp += n;
+ } else
+ *userp = NULL;
+
+ if (dp != NULL) {
+ n = strlen(dp) + 1;
+ strcpy(cp, dp);
+ *domainp = cp;
+ cp += n;
+ } else
+ *domainp = NULL;
+
+ return (NGR_R_OK);
+}
+#else /* NGR_R_RETURN */
+ static int getnetgrent_r_unknown_system = 0;
+#endif /* NGR_R_RETURN */
+#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */
diff --git a/usr/src/lib/libresolv2/common/irs/getprotoent.c b/usr/src/lib/libresolv2/common/irs/getprotoent.c
new file mode 100644
index 0000000000..9a2b7332e3
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/getprotoent.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: getprotoent.c,v 1.16 2001/11/01 07:34:33 marka Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#if !defined(__BIND_NOSTATIC)
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <irs.h>
+
+#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));
+}
+
+#ifdef ORIGINAL_ISC_CODE
+void
+#else
+int
+#endif
+setprotoent(int stayopen) {
+ struct net_data *net_data = init();
+
+ setprotoent_p(stayopen, net_data);
+#ifdef ORIGINAL_ISC_CODE
+#else
+ return (0);
+#endif
+}
+
+#ifdef ORIGINAL_ISC_CODE
+void
+#else
+int
+#endif
+endprotoent() {
+ struct net_data *net_data = init();
+
+ endprotoent_p(net_data);
+#ifdef ORIGINAL_ISC_CODE
+#else
+ return (0);
+#endif
+}
+
+/* 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/usr/src/lib/libresolv2/common/irs/getprotoent_r.c b/usr/src/lib/libresolv2/common/irs/getprotoent_r.c
new file mode 100644
index 0000000000..c8f540d5c1
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/getprotoent_r.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: getprotoent_r.c,v 8.6 2001/11/01 08:02:14 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <port_before.h>
+#if !defined(_REENTRANT) || !defined(DO_PTHREADS)
+ static int getprotoent_r_not_required = 0;
+#else
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <port_after.h>
+
+#ifdef PROTO_R_RETURN
+
+static PROTO_R_RETURN
+copy_protoent(struct protoent *, struct protoent *, PROTO_R_COPY_ARGS);
+
+PROTO_R_RETURN
+getprotobyname_r(const char *name, struct protoent *pptr, PROTO_R_ARGS) {
+ struct protoent *pe = getprotobyname(name);
+#ifdef PROTO_R_SETANSWER
+ int n = 0;
+
+ if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0)
+ *answerp = NULL;
+ else
+ *answerp = pptr;
+
+ return (n);
+#else
+ if (pe == NULL)
+ return (PROTO_R_BAD);
+
+ return (copy_protoent(pe, pptr, PROTO_R_COPY));
+#endif
+}
+
+PROTO_R_RETURN
+getprotobynumber_r(int proto, struct protoent *pptr, PROTO_R_ARGS) {
+ struct protoent *pe = getprotobynumber(proto);
+#ifdef PROTO_R_SETANSWER
+ int n = 0;
+
+ if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0)
+ *answerp = NULL;
+ else
+ *answerp = pptr;
+
+ return (n);
+#else
+ if (pe == NULL)
+ return (PROTO_R_BAD);
+
+ return (copy_protoent(pe, pptr, PROTO_R_COPY));
+#endif
+}
+
+/*
+ * These assume a single context is in operation per thread.
+ * If this is not the case we will need to call irs directly
+ * rather than through the base functions.
+ */
+
+PROTO_R_RETURN
+getprotoent_r(struct protoent *pptr, PROTO_R_ARGS) {
+ struct protoent *pe = getprotoent();
+#ifdef PROTO_R_SETANSWER
+ int n = 0;
+
+ if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0)
+ *answerp = NULL;
+ else
+ *answerp = pptr;
+
+ return (n);
+#else
+ if (pe == NULL)
+ return (PROTO_R_BAD);
+
+ return (copy_protoent(pe, pptr, PROTO_R_COPY));
+#endif
+}
+
+PROTO_R_SET_RETURN
+#ifdef PROTO_R_ENT_ARGS
+setprotoent_r(int stay_open, PROTO_R_ENT_ARGS)
+#else
+setprotoent_r(int stay_open)
+#endif
+{
+ setprotoent(stay_open);
+#ifdef PROTO_R_SET_RESULT
+ return (PROTO_R_SET_RESULT);
+#endif
+}
+
+PROTO_R_END_RETURN
+#ifdef PROTO_R_ENT_ARGS
+endprotoent_r(PROTO_R_ENT_ARGS)
+#else
+endprotoent_r()
+#endif
+{
+ endprotoent();
+ PROTO_R_END_RESULT(PROTO_R_OK);
+}
+
+/* Private */
+
+#ifndef PROTOENT_DATA
+static PROTO_R_RETURN
+copy_protoent(struct protoent *pe, struct protoent *pptr, PROTO_R_COPY_ARGS) {
+ char *cp;
+ int i, n;
+ int numptr, len;
+
+ /* Find out the amount of space required to store the answer. */
+ numptr = 1; /* NULL ptr */
+ len = (char *)ALIGN(buf) - buf;
+ for (i = 0; pe->p_aliases[i]; i++, numptr++) {
+ len += strlen(pe->p_aliases[i]) + 1;
+ }
+ len += strlen(pe->p_name) + 1;
+ len += numptr * sizeof(char*);
+
+ if (len > (int)buflen) {
+ errno = ERANGE;
+ return (PROTO_R_BAD);
+ }
+
+ /* copy protocol value*/
+ pptr->p_proto = pe->p_proto;
+
+ cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
+
+ /* copy official name */
+ n = strlen(pe->p_name) + 1;
+ strcpy(cp, pe->p_name);
+ pptr->p_name = cp;
+ cp += n;
+
+ /* copy aliases */
+ pptr->p_aliases = (char **)ALIGN(buf);
+ for (i = 0 ; pe->p_aliases[i]; i++) {
+ n = strlen(pe->p_aliases[i]) + 1;
+ strcpy(cp, pe->p_aliases[i]);
+ pptr->p_aliases[i] = cp;
+ cp += n;
+ }
+ pptr->p_aliases[i] = NULL;
+
+ return (PROTO_R_OK);
+}
+#else /* !PROTOENT_DATA */
+static int
+copy_protoent(struct protoent *pe, struct protoent *pptr, PROTO_R_COPY_ARGS) {
+ char *cp, *eob;
+ int i, n;
+
+ /* copy protocol value */
+ pptr->p_proto = pe->p_proto;
+
+ /* copy official name */
+ cp = pdptr->line;
+ eob = pdptr->line + sizeof(pdptr->line);
+ if ((n = strlen(pe->p_name) + 1) < (eob - cp)) {
+ strcpy(cp, pe->p_name);
+ pptr->p_name = cp;
+ cp += n;
+ } else {
+ return (-1);
+ }
+
+ /* copy aliases */
+ i = 0;
+ pptr->p_aliases = pdptr->proto_aliases;
+ while (pe->p_aliases[i] && i < (_MAXALIASES-1)) {
+ if ((n = strlen(pe->p_aliases[i]) + 1) < (eob - cp)) {
+ strcpy(cp, pe->p_aliases[i]);
+ pptr->p_aliases[i] = cp;
+ cp += n;
+ } else {
+ break;
+ }
+ i++;
+ }
+ pptr->p_aliases[i] = NULL;
+
+ return (PROTO_R_OK);
+}
+#endif /* PROTOENT_DATA */
+#else /* PROTO_R_RETURN */
+ static int getprotoent_r_unknown_system = 0;
+#endif /* PROTO_R_RETURN */
+#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */
diff --git a/usr/src/lib/libresolv2/common/irs/getpwent.c b/usr/src/lib/libresolv2/common/irs/getpwent.c
new file mode 100644
index 0000000000..8b4667c716
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/getpwent.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 1997-2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: getpwent.c,v 1.21 2000/02/21 21:40:56 vixie Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#if !defined(WANT_IRS_PW) || defined(__BIND_NOSTATIC)
+static int __bind_irs_pw_unneeded;
+#else
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <pwd.h>
+#include <resolv.h>
+#include <stdio.h>
+
+#include <irs.h>
+
+#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/usr/src/lib/libresolv2/common/irs/getpwent_r.c b/usr/src/lib/libresolv2/common/irs/getpwent_r.c
new file mode 100644
index 0000000000..4e3b8a2578
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/getpwent_r.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] =
+ "$Id: getpwent_r.c,v 8.6 2001/11/01 08:02:15 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <port_before.h>
+#if !defined(_REENTRANT) || !defined(DO_PTHREADS) || !defined(WANT_IRS_PW)
+ static int getpwent_r_not_required = 0;
+#else
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#if (defined(POSIX_GETPWNAM_R) || defined(POSIX_GETPWUID_R))
+#if defined(_POSIX_PTHREAD_SEMANTICS)
+ /* turn off solaris remapping in <grp.h> */
+#undef _POSIX_PTHREAD_SEMANTICS
+#include <pwd.h>
+#define _POSIX_PTHREAD_SEMANTICS 1
+#else
+#define _UNIX95 1
+#include <pwd.h>
+#endif
+#else
+#include <pwd.h>
+#endif
+#include <port_after.h>
+
+#ifdef PASS_R_RETURN
+
+static int
+copy_passwd(struct passwd *, struct passwd *, char *buf, int buflen);
+
+/* POSIX 1003.1c */
+#ifdef POSIX_GETPWNAM_R
+int
+__posix_getpwnam_r(const char *login, struct passwd *pwptr,
+ char *buf, size_t buflen, struct passwd **result) {
+#else
+int
+getpwnam_r(const char *login, struct passwd *pwptr,
+ char *buf, size_t buflen, struct passwd **result) {
+#endif
+ struct passwd *pw = getpwnam(login);
+ int res;
+
+ if (pw == NULL) {
+ *result = NULL;
+ return (0);
+ }
+
+ res = copy_passwd(pw, pwptr, buf, buflen);
+ *result = res ? NULL : pwptr;
+ return (res);
+}
+
+#ifdef POSIX_GETPWNAM_R
+struct passwd *
+getpwnam_r(const char *login, struct passwd *pwptr, char *buf, int buflen) {
+ struct passwd *pw = getpwnam(login);
+ int res;
+
+ if (pw == NULL)
+ return (NULL);
+
+ res = copy_passwd(pw, pwptr, buf, buflen);
+ return (res ? NULL : pwptr);
+}
+#endif
+
+/* POSIX 1003.1c */
+#ifdef POSIX_GETPWUID_R
+int
+__posix_getpwuid_r(uid_t uid, struct passwd *pwptr,
+ char *buf, size_t buflen, struct passwd **result) {
+#else
+int
+getpwuid_r(uid_t uid, struct passwd *pwptr,
+ char *buf, size_t buflen, struct passwd **result) {
+#endif
+ struct passwd *pw = getpwuid(uid);
+ int res;
+
+ if (pw == NULL) {
+ *result = NULL;
+ return (0);
+ }
+
+ res = copy_passwd(pw, pwptr, buf, buflen);
+ *result = res ? NULL : pwptr;
+ return (res);
+}
+
+#ifdef POSIX_GETPWUID_R
+struct passwd *
+getpwuid_r(uid_t uid, struct passwd *pwptr, char *buf, int buflen) {
+ struct passwd *pw = getpwuid(uid);
+ int res;
+
+ if (pw == NULL)
+ return (NULL);
+
+ res = copy_passwd(pw, pwptr, buf, buflen);
+ return (res ? NULL : pwptr);
+}
+#endif
+
+/*
+ * These assume a single context is in operation per thread.
+ * If this is not the case we will need to call irs directly
+ * rather than through the base functions.
+ */
+
+PASS_R_RETURN
+getpwent_r(struct passwd *pwptr, PASS_R_ARGS) {
+ struct passwd *pw = getpwent();
+ int res;
+
+ if (pw == NULL)
+ return (PASS_R_BAD);
+
+ res = copy_passwd(pw, pwptr, buf, buflen);
+ return (res ? PASS_R_BAD : PASS_R_OK);
+}
+
+PASS_R_SET_RETURN
+#ifdef PASS_R_ENT_ARGS
+setpassent_r(int stayopen, PASS_R_ENT_ARGS)
+#else
+setpassent_r(int stayopen)
+#endif
+{
+
+ setpassent(stayopen);
+#ifdef PASS_R_SET_RESULT
+ return (PASS_R_SET_RESULT);
+#endif
+}
+
+PASS_R_SET_RETURN
+#ifdef PASS_R_ENT_ARGS
+setpwent_r(PASS_R_ENT_ARGS)
+#else
+setpwent_r(void)
+#endif
+{
+
+ setpwent();
+#ifdef PASS_R_SET_RESULT
+ return (PASS_R_SET_RESULT);
+#endif
+}
+
+PASS_R_END_RETURN
+#ifdef PASS_R_ENT_ARGS
+endpwent_r(PASS_R_ENT_ARGS)
+#else
+endpwent_r(void)
+#endif
+{
+
+ endpwent();
+ PASS_R_END_RESULT(PASS_R_OK);
+}
+
+
+#ifdef HAS_FGETPWENT
+PASS_R_RETURN
+fgetpwent_r(FILE *f, struct passwd *pwptr, PASS_R_COPY_ARGS) {
+ struct passwd *pw = fgetpwent(f);
+ int res;
+
+ if (pw == NULL)
+ return (PASS_R_BAD);
+
+ res = copy_passwd(pw, pwptr, PASS_R_COPY);
+ return (res ? PASS_R_BAD : PASS_R_OK);
+}
+#endif
+
+/* Private */
+
+static int
+copy_passwd(struct passwd *pw, struct passwd *pwptr, char *buf, int buflen) {
+ char *cp;
+ int n;
+ int len;
+
+ /* Find out the amount of space required to store the answer. */
+ len = strlen(pw->pw_name) + 1;
+ len += strlen(pw->pw_passwd) + 1;
+#ifdef HAVE_PW_CLASS
+ len += strlen(pw->pw_class) + 1;
+#endif
+ len += strlen(pw->pw_gecos) + 1;
+ len += strlen(pw->pw_dir) + 1;
+ len += strlen(pw->pw_shell) + 1;
+
+ if (len > buflen) {
+ errno = ERANGE;
+ return (ERANGE);
+ }
+
+ /* copy fixed atomic values */
+ pwptr->pw_uid = pw->pw_uid;
+ pwptr->pw_gid = pw->pw_gid;
+#ifdef HAVE_PW_CHANGE
+ pwptr->pw_change = pw->pw_change;
+#endif
+#ifdef HAVE_PW_EXPIRE
+ pwptr->pw_expire = pw->pw_expire;
+#endif
+
+ cp = buf;
+
+ /* copy official name */
+ n = strlen(pw->pw_name) + 1;
+ strcpy(cp, pw->pw_name);
+ pwptr->pw_name = cp;
+ cp += n;
+
+ /* copy password */
+ n = strlen(pw->pw_passwd) + 1;
+ strcpy(cp, pw->pw_passwd);
+ pwptr->pw_passwd = cp;
+ cp += n;
+
+#ifdef HAVE_PW_CLASS
+ /* copy class */
+ n = strlen(pw->pw_class) + 1;
+ strcpy(cp, pw->pw_class);
+ pwptr->pw_class = cp;
+ cp += n;
+#endif
+
+ /* copy gecos */
+ n = strlen(pw->pw_gecos) + 1;
+ strcpy(cp, pw->pw_gecos);
+ pwptr->pw_gecos = cp;
+ cp += n;
+
+ /* copy directory */
+ n = strlen(pw->pw_dir) + 1;
+ strcpy(cp, pw->pw_dir);
+ pwptr->pw_dir = cp;
+ cp += n;
+
+ /* copy login shell */
+ n = strlen(pw->pw_shell) + 1;
+ strcpy(cp, pw->pw_shell);
+ pwptr->pw_shell = cp;
+ cp += n;
+
+ return (0);
+}
+#else /* PASS_R_RETURN */
+ static int getpwent_r_unknown_system = 0;
+#endif /* PASS_R_RETURN */
+#endif /* !def(_REENTRANT) || !def(DO_PTHREADS) || !def(WANT_IRS_PW) */
diff --git a/usr/src/lib/libresolv2/common/irs/getservent.c b/usr/src/lib/libresolv2/common/irs/getservent.c
new file mode 100644
index 0000000000..395aa2aba6
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/getservent.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: getservent.c,v 1.17 2001/11/01 07:33:16 marka Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#if !defined(__BIND_NOSTATIC)
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <irs.h>
+
+#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));
+}
+
+#ifdef ORIGINAL_ISC_CODE
+void
+#else
+int
+#endif
+setservent(int stayopen) {
+ struct net_data *net_data = init();
+
+ setservent_p(stayopen, net_data);
+#ifdef ORIGINAL_ISC_CODE
+#else
+ return (0);
+#endif
+}
+
+#ifdef ORIGINAL_ISC_CODE
+void
+#else
+int
+#endif
+endservent() {
+ struct net_data *net_data = init();
+
+ endservent_p(net_data);
+#ifdef ORIGINAL_ISC_CODE
+#else
+ return (0);
+#endif
+}
+
+/* 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/usr/src/lib/libresolv2/common/irs/getservent_r.c b/usr/src/lib/libresolv2/common/irs/getservent_r.c
new file mode 100644
index 0000000000..8548a85bba
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/getservent_r.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: getservent_r.c,v 8.5 2001/11/01 08:02:16 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <port_before.h>
+#if !defined(_REENTRANT) || !defined(DO_PTHREADS)
+ static int getservent_r_not_required = 0;
+#else
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/param.h>
+#include <port_after.h>
+
+#ifdef SERV_R_RETURN
+
+static SERV_R_RETURN
+copy_servent(struct servent *, struct servent *, SERV_R_COPY_ARGS);
+
+SERV_R_RETURN
+getservbyname_r(const char *name, const char *proto,
+ struct servent *sptr, SERV_R_ARGS) {
+ struct servent *se = getservbyname(name, proto);
+#ifdef SERV_R_SETANSWER
+ int n = 0;
+
+ if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0)
+ *answerp = NULL;
+ else
+ *answerp = sptr;
+
+ return (n);
+#else
+ if (se == NULL)
+ return (SERV_R_BAD);
+
+ return (copy_servent(se, sptr, SERV_R_COPY));
+#endif
+}
+
+SERV_R_RETURN
+getservbyport_r(int port, const char *proto,
+ struct servent *sptr, SERV_R_ARGS) {
+ struct servent *se = getservbyport(port, proto);
+#ifdef SERV_R_SETANSWER
+ int n = 0;
+
+ if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0)
+ *answerp = NULL;
+ else
+ *answerp = sptr;
+
+ return (n);
+#else
+ if (se == NULL)
+ return (SERV_R_BAD);
+
+ return (copy_servent(se, sptr, SERV_R_COPY));
+#endif
+}
+
+/*
+ * These assume a single context is in operation per thread.
+ * If this is not the case we will need to call irs directly
+ * rather than through the base functions.
+ */
+
+SERV_R_RETURN
+getservent_r(struct servent *sptr, SERV_R_ARGS) {
+ struct servent *se = getservent();
+#ifdef SERV_R_SETANSWER
+ int n = 0;
+
+ if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0)
+ *answerp = NULL;
+ else
+ *answerp = sptr;
+
+ return (n);
+#else
+ if (se == NULL)
+ return (SERV_R_BAD);
+
+ return (copy_servent(se, sptr, SERV_R_COPY));
+#endif
+}
+
+SERV_R_SET_RETURN
+#ifdef SERV_R_ENT_ARGS
+setservent_r(int stay_open, SERV_R_ENT_ARGS)
+#else
+setservent_r(int stay_open)
+#endif
+{
+
+ setservent(stay_open);
+#ifdef SERV_R_SET_RESULT
+ return (SERV_R_SET_RESULT);
+#endif
+}
+
+SERV_R_END_RETURN
+#ifdef SERV_R_ENT_ARGS
+endservent_r(SERV_R_ENT_ARGS)
+#else
+endservent_r()
+#endif
+{
+
+ endservent();
+ SERV_R_END_RESULT(SERV_R_OK);
+}
+
+/* Private */
+
+#ifndef SERVENT_DATA
+static SERV_R_RETURN
+copy_servent(struct servent *se, struct servent *sptr, SERV_R_COPY_ARGS) {
+ char *cp;
+ int i, n;
+ int numptr, len;
+
+ /* Find out the amount of space required to store the answer. */
+ numptr = 1; /* NULL ptr */
+ len = (char *)ALIGN(buf) - buf;
+ for (i = 0; se->s_aliases[i]; i++, numptr++) {
+ len += strlen(se->s_aliases[i]) + 1;
+ }
+ len += strlen(se->s_name) + 1;
+ len += strlen(se->s_proto) + 1;
+ len += numptr * sizeof(char*);
+
+ if (len > (int)buflen) {
+ errno = ERANGE;
+ return (SERV_R_BAD);
+ }
+
+ /* copy port value */
+ sptr->s_port = se->s_port;
+
+ cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
+
+ /* copy official name */
+ n = strlen(se->s_name) + 1;
+ strcpy(cp, se->s_name);
+ sptr->s_name = cp;
+ cp += n;
+
+ /* copy aliases */
+ sptr->s_aliases = (char **)ALIGN(buf);
+ for (i = 0 ; se->s_aliases[i]; i++) {
+ n = strlen(se->s_aliases[i]) + 1;
+ strcpy(cp, se->s_aliases[i]);
+ sptr->s_aliases[i] = cp;
+ cp += n;
+ }
+ sptr->s_aliases[i] = NULL;
+
+ /* copy proto */
+ n = strlen(se->s_proto) + 1;
+ strcpy(cp, se->s_proto);
+ sptr->s_proto = cp;
+ cp += n;
+
+ return (SERV_R_OK);
+}
+#else /* !SERVENT_DATA */
+static int
+copy_servent(struct servent *se, struct servent *sptr, SERV_R_COPY_ARGS) {
+ char *cp, *eob;
+ int i, n;
+
+ /* copy port value */
+ sptr->s_port = se->s_port;
+
+ /* copy official name */
+ cp = ndptr->line;
+ eob = ndptr->line + sizeof(ndptr->line);
+ if ((n = strlen(se->s_name) + 1) < (eob - cp)) {
+ strcpy(cp, se->s_name);
+ sptr->s_name = cp;
+ cp += n;
+ } else {
+ return (-1);
+ }
+
+ /* copy aliases */
+ i = 0;
+ sptr->s_aliases = ndptr->serv_aliases;
+ while (se->s_aliases[i] && i < (_MAXALIASES-1)) {
+ if ((n = strlen(se->s_aliases[i]) + 1) < (eob - cp)) {
+ strcpy(cp, se->s_aliases[i]);
+ sptr->s_aliases[i] = cp;
+ cp += n;
+ } else {
+ break;
+ }
+ i++;
+ }
+ sptr->s_aliases[i] = NULL;
+
+ /* copy proto */
+ if ((n = strlen(se->s_proto) + 1) < (eob - cp)) {
+ strcpy(cp, se->s_proto);
+ sptr->s_proto = cp;
+ cp += n;
+ } else {
+ return (-1);
+ }
+
+ return (SERV_R_OK);
+}
+#endif /* !SERVENT_DATA */
+#else /*SERV_R_RETURN */
+ static int getservent_r_unknown_system = 0;
+#endif /*SERV_R_RETURN */
+#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */
diff --git a/usr/src/lib/libresolv2/common/irs/hesiod.c b/usr/src/lib/libresolv2/common/irs/hesiod.c
new file mode 100644
index 0000000000..74c76bb879
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/hesiod.c
@@ -0,0 +1,535 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: hesiod.c,v 1.23 2002/07/18 02:07:45 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>.
+ */
+
+/*
+ * 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 <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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);
+ }
+
+#ifdef ORIGINAL_ISC_CODE
+ ctx->LHS = NULL;
+ ctx->RHS = NULL;
+ ctx->res = NULL;
+#else
+ memset(ctx, 0, sizeof (*ctx));
+#endif /* ORIGINAL_ISC_CODE */
+
+ 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;
+ }
+#ifdef HAVE_STRLCPY
+ strlcpy(ctx->LHS, DEF_LHS, strlen(DEF_LHS) + 1);
+ strlcpy(ctx->RHS, DEF_RHS, strlen(DEF_RHS) + 1);
+#else
+ strcpy(ctx->LHS, DEF_LHS);
+ strcpy(ctx->RHS, DEF_RHS);
+#endif
+#else
+ goto cleanup;
+#endif
+ }
+ /*
+ * The default RHS can be overridden by an environment
+ * variable.
+ */
+ if ((cp = getenv("HES_DOMAIN")) != NULL) {
+ size_t RHSlen = strlen(cp) + 2;
+ if (ctx->RHS)
+ free(ctx->RHS);
+ ctx->RHS = malloc(RHSlen);
+ if (!ctx->RHS) {
+ errno = ENOMEM;
+ goto cleanup;
+ }
+ if (cp[0] == '.') {
+#ifdef HAVE_STRLCPY
+ strlcpy(ctx->RHS, cp, RHSlen);
+#else
+ strcpy(ctx->RHS, cp);
+#endif
+ } else {
+#ifdef HAVE_STRLCPY
+ strlcpy(ctx->RHS, ".", RHSlen);
+#else
+ strcpy(ctx->RHS, ".");
+#endif
+#ifdef HAVE_STRLCAT
+ strlcat(ctx->RHS, cp, RHSlen);
+#else
+ strcat(ctx->RHS, cp);
+#endif
+ }
+ }
+
+ /*
+ * 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/usr/src/lib/libresolv2/common/irs/hesiod_p.h b/usr/src/lib/libresolv2/common/irs/hesiod_p.h
new file mode 100644
index 0000000000..7a9b68bc35
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/hesiod_p.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>.
+ */
+
+/*
+ * $Id: hesiod_p.h,v 1.9 1999/01/08 19:24:39 vixie Exp $
+ */
+
+/*
+ * hesiod_p.h -- private definitions for the hesiod library
+ */
+
+#ifndef _HESIOD_P_H_INCLUDED
+#define _HESIOD_P_H_INCLUDED
+
+#define DEF_RHS ".Athena.MIT.EDU" /* Defaults if HESIOD_CONF */
+#define DEF_LHS ".ns" /* file is not */
+ /* present. */
+struct hesiod_p {
+ char * LHS; /* normally ".ns" */
+ char * RHS; /* AKA the default hesiod domain */
+ struct __res_state * res; /* resolver context */
+ void (*free_res)(void *);
+ void (*res_set)(struct hesiod_p *, struct __res_state *,
+ void (*)(void *));
+ struct __res_state * (*res_get)(struct hesiod_p *);
+};
+
+#define MAX_HESRESP 1024
+
+#endif /*_HESIOD_P_H_INCLUDED*/
diff --git a/usr/src/lib/libresolv2/common/irs/irp.c b/usr/src/lib/libresolv2/common/irs/irp.c
new file mode 100644
index 0000000000..ceb17b735c
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/irp.c
@@ -0,0 +1,599 @@
+/*
+ * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: irp.c,v 8.8 2001/09/25 04:50:29 marka Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#include <syslog.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#include <isc/memcluster.h>
+
+#include <irs.h>
+#include <irp.h>
+
+#include "irs_p.h"
+#include "irp_p.h"
+
+#include "port_after.h"
+
+/* Forward. */
+
+static void irp_close(struct irs_acc *);
+
+#define LINEINCR 128
+
+#if !defined(SUN_LEN)
+#define SUN_LEN(su) \
+ (sizeof (*(su)) - sizeof ((su)->sun_path) + strlen((su)->sun_path))
+#endif
+
+
+/* Public */
+
+
+/* send errors to syslog if true. */
+int irp_log_errors = 1;
+
+/*
+ * This module handles the irp module connection to irpd.
+ *
+ * The client expects a synchronous interface to functions like
+ * getpwnam(3), so we can't use the ctl_* i/o library on this end of
+ * the wire (it's used in the server).
+ */
+
+/*
+ * irs_acc *irs_irp_acc(const char *options);
+ *
+ * Initialize the irp module.
+ */
+struct irs_acc *
+irs_irp_acc(const char *options) {
+ struct irs_acc *acc;
+ struct irp_p *irp;
+
+ UNUSED(options);
+
+ if (!(acc = memget(sizeof *acc))) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(acc, 0x5e, sizeof *acc);
+ if (!(irp = memget(sizeof *irp))) {
+ errno = ENOMEM;
+ free(acc);
+ return (NULL);
+ }
+ irp->inlast = 0;
+ irp->incurr = 0;
+ irp->fdCxn = -1;
+ acc->private = irp;
+
+#ifdef WANT_IRS_GR
+ acc->gr_map = irs_irp_gr;
+#else
+ acc->gr_map = NULL;
+#endif
+#ifdef WANT_IRS_PW
+ acc->pw_map = irs_irp_pw;
+#else
+ acc->pw_map = NULL;
+#endif
+ acc->sv_map = irs_irp_sv;
+ acc->pr_map = irs_irp_pr;
+ acc->ho_map = irs_irp_ho;
+ acc->nw_map = irs_irp_nw;
+ acc->ng_map = irs_irp_ng;
+ acc->close = irp_close;
+ return (acc);
+}
+
+
+int
+irs_irp_connection_setup(struct irp_p *cxndata, int *warned) {
+ if (irs_irp_is_connected(cxndata)) {
+ return (0);
+ } else if (irs_irp_connect(cxndata) != 0) {
+ if (warned != NULL && !*warned) {
+ syslog(LOG_ERR, "irpd connection failed: %m\n");
+ (*warned)++;
+ }
+
+ return (-1);
+ }
+
+ return (0);
+}
+
+
+/*
+ * int irs_irp_connect(void);
+ *
+ * Sets up the connection to the remote irpd server.
+ *
+ * Returns:
+ *
+ * 0 on success, -1 on failure.
+ *
+ */
+int
+irs_irp_connect(struct irp_p *pvt) {
+ int flags;
+ struct sockaddr *addr;
+ struct sockaddr_in iaddr;
+#ifndef NO_SOCKADDR_UN
+ struct sockaddr_un uaddr;
+#endif
+ long ipaddr;
+ const char *irphost;
+ int code;
+ char text[256];
+ int socklen = 0;
+
+ if (pvt->fdCxn != -1) {
+ perror("fd != 1");
+ return (-1);
+ }
+
+#ifndef NO_SOCKADDR_UN
+ memset(&uaddr, 0, sizeof uaddr);
+#endif
+ memset(&iaddr, 0, sizeof iaddr);
+
+ irphost = getenv(IRPD_HOST_ENV);
+ if (irphost == NULL) {
+ irphost = "127.0.0.1";
+ }
+
+#ifndef NO_SOCKADDR_UN
+ if (irphost[0] == '/') {
+ addr = (struct sockaddr *)&uaddr;
+ strncpy(uaddr.sun_path, irphost, sizeof uaddr.sun_path);
+ uaddr.sun_family = AF_UNIX;
+ socklen = SUN_LEN(&uaddr);
+#ifdef HAVE_SA_LEN
+ uaddr.sun_len = socklen;
+#endif
+ } else
+#endif
+ {
+ if (inet_pton(AF_INET, irphost, &ipaddr) != 1) {
+ errno = EADDRNOTAVAIL;
+ perror("inet_pton");
+ return (-1);
+ }
+
+ addr = (struct sockaddr *)&iaddr;
+ socklen = sizeof iaddr;
+#ifdef HAVE_SA_LEN
+ iaddr.sin_len = socklen;
+#endif
+ iaddr.sin_family = AF_INET;
+ iaddr.sin_port = htons(IRPD_PORT);
+ iaddr.sin_addr.s_addr = ipaddr;
+ }
+
+
+ pvt->fdCxn = socket(addr->sa_family, SOCK_STREAM, PF_UNSPEC);
+ if (pvt->fdCxn < 0) {
+ perror("socket");
+ return (-1);
+ }
+
+ if (connect(pvt->fdCxn, addr, socklen) != 0) {
+ perror("connect");
+ return (-1);
+ }
+
+ flags = fcntl(pvt->fdCxn, F_GETFL, 0);
+ if (flags < 0) {
+ close(pvt->fdCxn);
+ perror("close");
+ return (-1);
+ }
+
+#if 0
+ flags |= O_NONBLOCK;
+ if (fcntl(pvt->fdCxn, F_SETFL, flags) < 0) {
+ close(pvt->fdCxn);
+ perror("fcntl");
+ return (-1);
+ }
+#endif
+
+ code = irs_irp_read_response(pvt, text, sizeof text);
+ if (code != IRPD_WELCOME_CODE) {
+ if (irp_log_errors) {
+ syslog(LOG_WARNING, "Connection failed: %s", text);
+ }
+ irs_irp_disconnect(pvt);
+ return (-1);
+ }
+
+ return (0);
+}
+
+
+
+/*
+ * int irs_irp_is_connected(struct irp_p *pvt);
+ *
+ * Returns:
+ *
+ * Non-zero if streams are setup to remote.
+ *
+ */
+
+int
+irs_irp_is_connected(struct irp_p *pvt) {
+ return (pvt->fdCxn >= 0);
+}
+
+
+
+/*
+ * void
+ * irs_irp_disconnect(struct irp_p *pvt);
+ *
+ * Closes streams to remote.
+ */
+
+void
+irs_irp_disconnect(struct irp_p *pvt) {
+ if (pvt->fdCxn != -1) {
+ close(pvt->fdCxn);
+ pvt->fdCxn = -1;
+ }
+}
+
+
+
+int
+irs_irp_read_line(struct irp_p *pvt, char *buffer, int len) {
+ char *realstart = &pvt->inbuffer[0];
+ char *p, *start, *end;
+ int spare;
+ int i;
+ int buffpos = 0;
+ int left = len - 1;
+
+ while (left > 0) {
+ start = p = &pvt->inbuffer[pvt->incurr];
+ end = &pvt->inbuffer[pvt->inlast];
+
+ while (p != end && *p != '\n')
+ p++;
+
+ if (p == end) {
+ /* Found no newline so shift data down if necessary
+ * and append new data to buffer
+ */
+ if (start > realstart) {
+ memmove(realstart, start, end - start);
+ pvt->inlast = end - start;
+ start = realstart;
+ pvt->incurr = 0;
+ end = &pvt->inbuffer[pvt->inlast];
+ }
+
+ spare = sizeof (pvt->inbuffer) - pvt->inlast;
+
+ p = end;
+ i = read(pvt->fdCxn, end, spare);
+ if (i < 0) {
+ close(pvt->fdCxn);
+ pvt->fdCxn = -1;
+ return (buffpos > 0 ? buffpos : -1);
+ } else if (i == 0) {
+ return (buffpos);
+ }
+
+ end += i;
+ pvt->inlast += i;
+
+ while (p != end && *p != '\n')
+ p++;
+ }
+
+ if (p == end) {
+ /* full buffer and still no newline */
+ i = sizeof pvt->inbuffer;
+ } else {
+ /* include newline */
+ i = p - start + 1;
+ }
+
+ if (i > left)
+ i = left;
+ memcpy(buffer + buffpos, start, i);
+ pvt->incurr += i;
+ buffpos += i;
+ buffer[buffpos] = '\0';
+
+ if (p != end) {
+ left = 0;
+ } else {
+ left -= i;
+ }
+ }
+
+#if 0
+ fprintf(stderr, "read line: %s\n", buffer);
+#endif
+ return (buffpos);
+}
+
+
+
+
+
+/*
+ * int irp_read_response(struct irp_p *pvt);
+ *
+ * Returns:
+ *
+ * The number found at the beginning of the line read from
+ * FP. 0 on failure(0 is not a legal response code). The
+ * rest of the line is discarded.
+ *
+ */
+
+int
+irs_irp_read_response(struct irp_p *pvt, char *text, size_t textlen) {
+ char line[1024];
+ int code;
+ char *p;
+
+ if (irs_irp_read_line(pvt, line, sizeof line) <= 0) {
+ return (0);
+ }
+
+ p = strchr(line, '\n');
+ if (p == NULL) {
+ return (0);
+ }
+
+ if (sscanf(line, "%d", &code) != 1) {
+ code = 0;
+ } else if (text != NULL && textlen > 0) {
+ p = line;
+ while (isspace((unsigned char)*p)) p++;
+ while (isdigit((unsigned char)*p)) p++;
+ while (isspace((unsigned char)*p)) p++;
+ strncpy(text, p, textlen - 1);
+ p[textlen - 1] = '\0';
+ }
+
+ return (code);
+}
+
+
+
+/*
+ * char *irp_read_body(struct irp_p *pvt, size_t *size);
+ *
+ * Read in the body of a response. Terminated by a line with
+ * just a dot on it. Lines should be terminated with a CR-LF
+ * sequence, but we're nt piccky if the CR is missing.
+ * No leading dot escaping is done as the protcol doesn't
+ * use leading dots anywhere.
+ *
+ * Returns:
+ *
+ * Pointer to null-terminated buffer allocated by memget.
+ * *SIZE is set to the length of the buffer.
+ *
+ */
+
+char *
+irs_irp_read_body(struct irp_p *pvt, size_t *size) {
+ char line[1024];
+ u_int linelen;
+ size_t len = LINEINCR;
+ char *buffer = memget(len);
+ int idx = 0;
+
+ for (;;) {
+ if (irs_irp_read_line(pvt, line, sizeof line) <= 0 ||
+ strchr(line, '\n') == NULL)
+ goto death;
+
+ linelen = strlen(line);
+
+ if (line[linelen - 1] != '\n')
+ goto death;
+
+ /* We're not strict about missing \r. Should we be?? */
+ if (linelen > 2 && line[linelen - 2] == '\r') {
+ line[linelen - 2] = '\n';
+ line[linelen - 1] = '\0';
+ linelen--;
+ }
+
+ if (linelen == 2 && line[0] == '.') {
+ *size = len;
+ buffer[idx] = '\0';
+
+ return (buffer);
+ }
+
+ if (linelen > (len - (idx + 1))) {
+ char *p = memget(len + LINEINCR);
+
+ if (p == NULL)
+ goto death;
+ memcpy(p, buffer, len);
+ memput(buffer, len);
+ buffer = p;
+ len += LINEINCR;
+ }
+
+ memcpy(buffer + idx, line, linelen);
+ idx += linelen;
+ }
+ death:
+ memput(buffer, len);
+ return (NULL);
+}
+
+
+/*
+ * int irs_irp_get_full_response(struct irp_p *pvt, int *code,
+ * char **body, size_t *bodylen);
+ *
+ * Gets the response to a command. If the response indicates
+ * there's a body to follow(code % 10 == 1), then the
+ * body buffer is allcoated with memget and stored in
+ * *BODY. The length of the allocated body buffer is stored
+ * in *BODY. The caller must give the body buffer back to
+ * memput when done. The results code is stored in *CODE.
+ *
+ * Returns:
+ *
+ * 0 if a result was read. -1 on some sort of failure.
+ *
+ */
+
+int
+irs_irp_get_full_response(struct irp_p *pvt, int *code, char *text,
+ size_t textlen, char **body, size_t *bodylen) {
+ int result = irs_irp_read_response(pvt, text, textlen);
+
+ *body = NULL;
+
+ if (result == 0) {
+ return (-1);
+ }
+
+ *code = result;
+
+ /* Code that matches 2xx is a good result code.
+ * Code that matches xx1 means there's a response body coming.
+ */
+ if ((result / 100) == 2 && (result % 10) == 1) {
+ *body = irs_irp_read_body(pvt, bodylen);
+ if (*body == NULL) {
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+
+
+/*
+ * int irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...);
+ *
+ * Sends command to remote connected via the PVT
+ * struture. FMT and args after it are fprintf-like
+ * arguments for formatting.
+ *
+ * Returns:
+ *
+ * 0 on success, -1 on failure.
+ */
+
+int
+irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...) {
+ va_list ap;
+ char buffer[1024];
+ int pos = 0;
+ int i, todo;
+
+
+ if (pvt->fdCxn < 0) {
+ return (-1);
+ }
+
+ va_start(ap, fmt);
+ todo = vsprintf(buffer, fmt, ap);
+ va_end(ap);
+ if (todo > (int)sizeof(buffer) - 3) {
+ syslog(LOG_CRIT, "memory overrun in irs_irp_send_command()");
+ exit(1);
+ }
+ strcat(buffer, "\r\n");
+ todo = strlen(buffer);
+
+ while (todo > 0) {
+ i = write(pvt->fdCxn, buffer + pos, todo);
+#if 0
+ /* XXX brister */
+ fprintf(stderr, "Wrote: \"");
+ fwrite(buffer + pos, sizeof (char), todo, stderr);
+ fprintf(stderr, "\"\n");
+#endif
+ if (i < 0) {
+ close(pvt->fdCxn);
+ pvt->fdCxn = -1;
+ return (-1);
+ }
+ todo -= i;
+ }
+
+ return (0);
+}
+
+
+/* Methods */
+
+
+
+/*
+ * void irp_close(struct irs_acc *this)
+ *
+ */
+
+static void
+irp_close(struct irs_acc *this) {
+ struct irp_p *irp = (struct irp_p *)this->private;
+
+ if (irp != NULL) {
+ irs_irp_disconnect(irp);
+ memput(irp, sizeof *irp);
+ }
+
+ memput(this, sizeof *this);
+}
+
+
+
diff --git a/usr/src/lib/libresolv2/common/irs/irp_gr.c b/usr/src/lib/libresolv2/common/irs/irp_gr.c
new file mode 100644
index 0000000000..e77468af7e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/irp_gr.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: irp_gr.c,v 8.3 2001/05/29 05:48:57 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/* extern */
+
+#include "port_before.h"
+
+#ifndef WANT_IRS_PW
+static int __bind_irs_gr_unneeded;
+#else
+
+#include <syslog.h>
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <syslog.h>
+
+#include <irs.h>
+#include <irp.h>
+#include <isc/memcluster.h>
+#include <isc/irpmarshall.h>
+
+#include "irs_p.h"
+#include "lcl_p.h"
+#include "irp_p.h"
+
+#include "port_after.h"
+
+
+/* Types. */
+
+/*
+ * Module for the getnetgrent(3) family to use when connected to a
+ * remote irp daemon.
+ *
+ * See irpd.c for justification of caching done here.
+ *
+ */
+
+struct pvt {
+ struct irp_p *girpdata; /* global IRP data */
+ int warned;
+ struct group group;
+};
+
+/* Forward. */
+
+static void gr_close(struct irs_gr *);
+static struct group * gr_next(struct irs_gr *);
+static struct group * gr_byname(struct irs_gr *, const char *);
+static struct group * gr_bygid(struct irs_gr *, gid_t);
+static void gr_rewind(struct irs_gr *);
+static void gr_minimize(struct irs_gr *);
+
+/* Private */
+static void free_group(struct group *gr);
+
+
+/* Public. */
+
+
+
+
+
+/*
+ * struct irs_gr * irs_irp_gr(struct irs_acc *this)
+ *
+ * Notes:
+ *
+ * Initialize the group sub-module.
+ *
+ * Notes:
+ *
+ * Module data.
+ *
+ */
+
+struct irs_gr *
+irs_irp_gr(struct irs_acc *this) {
+ struct irs_gr *gr;
+ struct pvt *pvt;
+
+ if (!(gr = memget(sizeof *gr))) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(gr, 0x0, sizeof *gr);
+
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(gr, sizeof *gr);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pvt, 0x0, sizeof *pvt);
+ pvt->girpdata = this->private;
+
+ gr->private = pvt;
+ gr->close = gr_close;
+ gr->next = gr_next;
+ gr->byname = gr_byname;
+ gr->bygid = gr_bygid;
+ gr->rewind = gr_rewind;
+ gr->list = make_group_list;
+ gr->minimize = gr_minimize;
+ return (gr);
+}
+
+/* Methods. */
+
+
+
+/*
+ * void gr_close(struct irs_gr *this)
+ *
+ * Notes:
+ *
+ * Close the sub-module.
+ *
+ */
+
+static void
+gr_close(struct irs_gr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ gr_minimize(this);
+
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
+}
+
+
+
+
+/*
+ * struct group * gr_next(struct irs_gr *this)
+ *
+ * Notes:
+ *
+ * Gets the next group out of the cached data and returns it.
+ *
+ */
+
+static struct group *
+gr_next(struct irs_gr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct group *gr = &pvt->group;
+ char *body;
+ size_t bodylen;
+ int code;
+ char text[256];
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_send_command(pvt->girpdata, "getgrent") != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_get_full_response(pvt->girpdata, &code,
+ text, sizeof text,
+ &body, &bodylen) != 0) {
+ if (irp_log_errors) {
+ syslog(LOG_WARNING, "getgrent failed: %s", text);
+ }
+ return (NULL);
+ }
+
+ if (code == IRPD_GETGROUP_OK) {
+ free_group(gr);
+ if (irp_unmarshall_gr(gr, body) != 0) {
+ gr = NULL;
+ }
+ } else {
+ gr = NULL;
+ }
+
+ if (body != NULL) {
+ memput(body, bodylen);
+ }
+
+ return (gr);
+}
+
+
+
+
+
+/*
+ * struct group * gr_byname(struct irs_gr *this, const char *name)
+ *
+ * Notes:
+ *
+ * Gets a group by name from irpd and returns it.
+ *
+ */
+
+static struct group *
+gr_byname(struct irs_gr *this, const char *name) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct group *gr = &pvt->group;
+ char *body;
+ size_t bodylen;
+ int code;
+ char text[256];
+
+
+ if (gr->gr_name != NULL && strcmp(name, gr->gr_name) == 0) {
+ return (gr);
+ }
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_send_command(pvt->girpdata, "getgrnam %s", name) != 0)
+ return (NULL);
+
+ if (irs_irp_get_full_response(pvt->girpdata, &code,
+ text, sizeof text,
+ &body, &bodylen) != 0) {
+ return (NULL);
+ }
+
+ if (code == IRPD_GETGROUP_OK) {
+ free_group(gr);
+ if (irp_unmarshall_gr(gr, body) != 0) {
+ gr = NULL;
+ }
+ } else {
+ gr = NULL;
+ }
+
+ if (body != NULL) {
+ memput(body, bodylen);
+ }
+
+ return (gr);
+}
+
+
+
+
+
+/*
+ * struct group * gr_bygid(struct irs_gr *this, gid_t gid)
+ *
+ * Notes:
+ *
+ * Gets a group by gid from irpd and returns it.
+ *
+ */
+
+static struct group *
+gr_bygid(struct irs_gr *this, gid_t gid) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct group *gr = &pvt->group;
+ char *body;
+ size_t bodylen;
+ int code;
+ char text[256];
+
+ if (gr->gr_name != NULL && (gid_t)gr->gr_gid == gid) {
+ return (gr);
+ }
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_send_command(pvt->girpdata, "getgrgid %d", gid) != 0)
+ return (NULL);
+
+ if (irs_irp_get_full_response(pvt->girpdata, &code,
+ text, sizeof text,
+ &body, &bodylen) != 0) {
+ return (NULL);
+ }
+
+ if (code == IRPD_GETGROUP_OK) {
+ free_group(gr);
+ if (irp_unmarshall_gr(gr, body) != 0) {
+ gr = NULL;
+ }
+ } else {
+ gr = NULL;
+ }
+
+ if (body != NULL) {
+ memput(body, bodylen);
+ }
+
+ return (gr);
+}
+
+
+
+
+/*
+ * void gr_rewind(struct irs_gr *this)
+ *
+ */
+
+static void
+gr_rewind(struct irs_gr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ char text[256];
+ int code;
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return;
+ }
+
+ if (irs_irp_send_command(pvt->girpdata, "setgrent") != 0) {
+ return;
+ }
+
+ code = irs_irp_read_response(pvt->girpdata, text, sizeof text);
+ if (code != IRPD_GETGROUP_SETOK) {
+ if (irp_log_errors) {
+ syslog(LOG_WARNING, "setgrent failed: %s", text);
+ }
+ }
+
+ return;
+}
+
+
+
+
+/*
+ * void gr_minimize(struct irs_gr *this)
+ *
+ * Notes:
+ *
+ * Frees up cached data and disconnects(if necessary) from the remote.
+ *
+ */
+
+static void
+gr_minimize(struct irs_gr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ free_group(&pvt->group);
+ irs_irp_disconnect(pvt->girpdata);
+}
+
+/* Private. */
+
+
+
+/*
+ * static void free_group(struct group *gr);
+ *
+ * Deallocate all the memory irp_unmarshall_gr allocated.
+ *
+ */
+
+static void
+free_group(struct group *gr) {
+ char **p;
+
+ if (gr == NULL)
+ return;
+
+ if (gr->gr_name != NULL)
+ free(gr->gr_name);
+
+ if (gr->gr_passwd != NULL)
+ free(gr->gr_passwd);
+
+ for (p = gr->gr_mem ; p != NULL && *p != NULL ; p++)
+ free(*p);
+
+ if (gr->gr_mem)
+ free(gr->gr_mem);
+
+ if (p != NULL)
+ free(p);
+}
+
+
+#endif /* WANT_IRS_GR */
diff --git a/usr/src/lib/libresolv2/common/irs/irp_ho.c b/usr/src/lib/libresolv2/common/irs/irp_ho.c
new file mode 100644
index 0000000000..12a03edd1b
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/irp_ho.c
@@ -0,0 +1,436 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: irp_ho.c,v 8.3 2001/05/29 05:48:59 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/* Imports. */
+
+#include "port_before.h"
+
+#include <syslog.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
+#include <irs.h>
+#include <irp.h>
+#include <isc/irpmarshall.h>
+#include <isc/memcluster.h>
+
+#include "irs_p.h"
+#include "dns_p.h"
+#include "irp_p.h"
+
+#include "port_after.h"
+
+/* Definitions. */
+
+#define MAXALIASES 35
+#define MAXADDRS 35
+#define Max(a,b) ((a) > (b) ? (a) : (b))
+
+
+struct pvt {
+ struct irp_p *girpdata;
+ int warned;
+ struct hostent host;
+};
+
+/* Forward. */
+
+static void ho_close(struct irs_ho *this);
+static struct hostent * ho_byname(struct irs_ho *this, const char *name);
+static struct hostent * ho_byname2(struct irs_ho *this, const char *name,
+ int af);
+static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr,
+ int len, int af);
+static struct hostent * ho_next(struct irs_ho *this);
+static void ho_rewind(struct irs_ho *this);
+static void ho_minimize(struct irs_ho *this);
+
+static void free_host(struct hostent *ho);
+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/usr/src/lib/libresolv2/common/irs/irp_ng.c b/usr/src/lib/libresolv2/common/irs/irp_ng.c
new file mode 100644
index 0000000000..d585e636a0
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/irp_ng.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: irp_ng.c,v 8.3 2001/05/29 05:49:00 marka Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <syslog.h>
+
+#include <irs.h>
+#include <irp.h>
+#include <isc/memcluster.h>
+#include <isc/irpmarshall.h>
+
+#include "irs_p.h"
+#include "irp_p.h"
+
+#include "port_after.h"
+
+/* Definitions */
+
+struct pvt {
+ struct irp_p *girpdata;
+ int warned;
+};
+
+
+/* Forward */
+
+static void ng_rewind(struct irs_ng *, const char*);
+static void ng_close(struct irs_ng *);
+static int ng_next(struct irs_ng *, 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/usr/src/lib/libresolv2/common/irs/irp_nw.c b/usr/src/lib/libresolv2/common/irs/irp_nw.c
new file mode 100644
index 0000000000..7c18f4cbac
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/irp_nw.c
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: irp_nw.c,v 8.1 1999/01/18 07:46:54 vixie Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#if 0
+
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#include <syslog.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
+#include <irs.h>
+#include <irp.h>
+#include <isc/irpmarshall.h>
+
+#include <isc/memcluster.h>
+#include <isc/misc.h>
+
+#include "irs_p.h"
+#include "lcl_p.h"
+#include "irp_p.h"
+
+#include "port_after.h"
+
+#define MAXALIASES 35
+#define MAXADDRSIZE 4
+
+struct pvt {
+ struct irp_p *girpdata;
+ int warned;
+ struct nwent net;
+};
+
+/* Forward */
+
+static void nw_close(struct irs_nw *);
+static struct nwent * nw_byname(struct irs_nw *, const char *, int);
+static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int);
+static struct nwent * nw_next(struct irs_nw *);
+static void nw_rewind(struct irs_nw *);
+static void nw_minimize(struct irs_nw *);
+
+static void free_nw(struct nwent *nw);
+
+
+/* Public */
+
+
+
+/*
+ * struct irs_nw * irs_irp_nw(struct irs_acc *this)
+ *
+ */
+
+struct irs_nw *
+irs_irp_nw(struct irs_acc *this) {
+ struct irs_nw *nw;
+ struct pvt *pvt;
+
+ if (!(pvt = memget(sizeof *pvt))) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pvt, 0, sizeof *pvt);
+
+ if (!(nw = memget(sizeof *nw))) {
+ memput(pvt, sizeof *pvt);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(nw, 0x0, sizeof *nw);
+ pvt->girpdata = this->private;
+
+ nw->private = pvt;
+ nw->close = nw_close;
+ nw->byname = nw_byname;
+ nw->byaddr = nw_byaddr;
+ nw->next = nw_next;
+ nw->rewind = nw_rewind;
+ nw->minimize = nw_minimize;
+ return (nw);
+}
+
+/* Methods */
+
+
+
+/*
+ * void nw_close(struct irs_nw *this)
+ *
+ */
+
+static void
+nw_close(struct irs_nw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ nw_minimize(this);
+
+ free_nw(&pvt->net);
+
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
+}
+
+
+
+
+/*
+ * struct nwent * nw_byaddr(struct irs_nw *this, void *net,
+ * int length, int type)
+ *
+ */
+
+static struct nwent *
+nw_byaddr(struct irs_nw *this, void *net, int length, int type) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct nwent *nw = &pvt->net;
+ char *body = NULL;
+ size_t bodylen;
+ int code;
+ char paddr[24]; /* bigenough for ip4 w/ cidr spec. */
+ char text[256];
+
+ if (inet_net_ntop(type, net, length, paddr, sizeof paddr) == NULL) {
+ return (NULL);
+ }
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_send_command(pvt->girpdata, "getnetbyaddr %s %s",
+ paddr, ADDR_T_STR(type)) != 0)
+ return (NULL);
+
+ if (irs_irp_get_full_response(pvt->girpdata, &code,
+ text, sizeof text,
+ &body, &bodylen) != 0) {
+ return (NULL);
+ }
+
+ if (code == IRPD_GETNET_OK) {
+ free_nw(nw);
+ if (irp_unmarshall_nw(nw, body) != 0) {
+ nw = NULL;
+ }
+ } else {
+ nw = NULL;
+ }
+
+ if (body != NULL) {
+ memput(body, bodylen);
+ }
+
+ return (nw);
+}
+
+
+
+
+/*
+ * struct nwent * nw_byname(struct irs_nw *this, const char *name, int type)
+ *
+ */
+
+static struct nwent *
+nw_byname(struct irs_nw *this, const char *name, int type) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct nwent *nw = &pvt->net;
+ char *body = NULL;
+ size_t bodylen;
+ int code;
+ char text[256];
+
+ if (nw->n_name != NULL &&
+ strcmp(name, nw->n_name) == 0 &&
+ nw->n_addrtype == type) {
+ return (nw);
+ }
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_send_command(pvt->girpdata, "getnetbyname %s", name) != 0)
+ return (NULL);
+
+ if (irs_irp_get_full_response(pvt->girpdata, &code,
+ text, sizeof text,
+ &body, &bodylen) != 0) {
+ return (NULL);
+ }
+
+ if (code == IRPD_GETNET_OK) {
+ free_nw(nw);
+ if (irp_unmarshall_nw(nw, body) != 0) {
+ nw = NULL;
+ }
+ } else {
+ nw = NULL;
+ }
+
+ if (body != NULL) {
+ memput(body, bodylen);
+ }
+
+ return (nw);
+}
+
+
+
+
+/*
+ * void nw_rewind(struct irs_nw *this)
+ *
+ */
+
+static void
+nw_rewind(struct irs_nw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ char text[256];
+ int code;
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return;
+ }
+
+ if (irs_irp_send_command(pvt->girpdata, "setnetent") != 0) {
+ return;
+ }
+
+ code = irs_irp_read_response(pvt->girpdata, text, sizeof text);
+ if (code != IRPD_GETNET_SETOK) {
+ if (irp_log_errors) {
+ syslog(LOG_WARNING, "setnetent failed: %s", text);
+ }
+ }
+
+ return;
+}
+
+
+
+
+
+
+/*
+ * struct nwent * nw_next(struct irs_nw *this)
+ *
+ * Notes:
+ *
+ * Prepares the cache if necessary and returns the first, or
+ * next item from it.
+ */
+
+static struct nwent *
+nw_next(struct irs_nw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct nwent *nw = &pvt->net;
+ char *body;
+ size_t bodylen;
+ int code;
+ char text[256];
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_send_command(pvt->girpdata, "getnetent") != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_get_full_response(pvt->girpdata, &code,
+ text, sizeof text,
+ &body, &bodylen) != 0) {
+ return (NULL);
+ }
+
+ if (code == IRPD_GETNET_OK) {
+ free_nw(nw);
+ if (irp_unmarshall_nw(nw, body) != 0) {
+ nw = NULL;
+ }
+ } else {
+ nw = NULL;
+ }
+
+ return (nw);
+}
+
+
+
+
+
+
+/*
+ * void nw_minimize(struct irs_nw *this)
+ *
+ */
+
+static void
+nw_minimize(struct irs_nw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ irs_irp_disconnect(pvt->girpdata);
+}
+
+
+
+
+/* private. */
+
+
+
+/*
+ * static void free_passwd(struct passwd *pw);
+ *
+ * deallocate all the memory irp_unmarshall_pw allocated.
+ *
+ */
+
+static void
+free_nw(struct nwent *nw) {
+ char **p;
+
+ if (nw == NULL)
+ return;
+
+ if (nw->n_name != NULL)
+ free(nw->n_name);
+
+ if (nw->n_aliases != NULL) {
+ for (p = nw->n_aliases ; *p != NULL ; p++) {
+ free(*p);
+ }
+ free(nw->n_aliases);
+ }
+
+ if (nw->n_addr != NULL)
+ free(nw->n_addr);
+}
diff --git a/usr/src/lib/libresolv2/common/irs/irp_p.h b/usr/src/lib/libresolv2/common/irs/irp_p.h
new file mode 100644
index 0000000000..0527d85d8e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/irp_p.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * $Id: irp_p.h,v 8.3 2003/04/29 01:26:06 marka Exp $
+ */
+
+#ifndef _IRP_P_H_INCLUDED
+#define _IRP_P_H_INCLUDED
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+
+struct irp_p {
+ char inbuffer[1024];
+ int inlast; /* index of one past the last char in buffer */
+ int incurr; /* index of the next char to be read from buffer */
+
+ int fdCxn;
+};
+
+/*
+ * Externs.
+ */
+
+extern struct irs_acc * irs_irp_acc __P((const char *));
+extern struct irs_gr * irs_irp_gr __P((struct irs_acc *));
+extern struct irs_pw * irs_irp_pw __P((struct irs_acc *));
+extern struct irs_sv * irs_irp_sv __P((struct irs_acc *));
+extern struct irs_pr * irs_irp_pr __P((struct irs_acc *));
+extern struct irs_ho * irs_irp_ho __P((struct irs_acc *));
+extern struct irs_nw * irs_irp_nw __P((struct irs_acc *));
+extern struct irs_ng * irs_irp_ng __P((struct irs_acc *));
+
+int irs_irp_connect(struct irp_p *pvt);
+int irs_irp_is_connected(struct irp_p *pvt);
+void irs_irp_disconnect(struct irp_p *pvt);
+int irs_irp_read_response(struct irp_p *pvt, char *text, size_t textlen);
+char *irs_irp_read_body(struct irp_p *pvt, size_t *size);
+int irs_irp_get_full_response(struct irp_p *pvt, int *code,
+ char *text, size_t textlen,
+ char **body, size_t *bodylen);
+
+extern int irp_log_errors;
+
+#endif
diff --git a/usr/src/lib/libresolv2/common/irs/irp_pr.c b/usr/src/lib/libresolv2/common/irs/irp_pr.c
new file mode 100644
index 0000000000..e72f6c2fe4
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/irp_pr.c
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: irp_pr.c,v 8.1 1999/01/18 07:46:54 vixie Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/* extern */
+
+#include "port_before.h"
+
+#include <syslog.h>
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <syslog.h>
+
+#include <irs.h>
+#include <irp.h>
+#include <isc/memcluster.h>
+#include <isc/irpmarshall.h>
+
+#include "irs_p.h"
+#include "lcl_p.h"
+#include "irp_p.h"
+
+#include "port_after.h"
+
+
+#define MAXALIASES 35
+
+/* Types */
+
+struct pvt {
+ struct irp_p *girpdata;
+ int warned;
+ struct protoent proto;
+};
+
+/* Forward */
+
+static void pr_close(struct irs_pr *);
+static struct protoent * pr_next(struct irs_pr *);
+static struct protoent * pr_byname(struct irs_pr *, const char *);
+static struct protoent * pr_bynumber(struct irs_pr *, int);
+static void pr_rewind(struct irs_pr *);
+static void pr_minimize(struct irs_pr *);
+
+static void free_proto(struct protoent *pr);
+
+/* Public */
+
+
+
+/*
+ * struct irs_pr * irs_irp_pr(struct irs_acc *this)
+ *
+ */
+
+struct irs_pr *
+irs_irp_pr(struct irs_acc *this) {
+ struct irs_pr *pr;
+ struct pvt *pvt;
+
+ if (!(pr = memget(sizeof *pr))) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pr, 0x0, sizeof *pr);
+
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(pr, sizeof *pr);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pvt, 0, sizeof *pvt);
+ pvt->girpdata = this->private;
+
+ pr->private = pvt;
+ pr->close = pr_close;
+ pr->byname = pr_byname;
+ pr->bynumber = pr_bynumber;
+ pr->next = pr_next;
+ pr->rewind = pr_rewind;
+ pr->minimize = pr_minimize;
+ return (pr);
+}
+
+/* Methods */
+
+
+
+/*
+ * void pr_close(struct irs_pr *this)
+ *
+ */
+
+static void
+pr_close(struct irs_pr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ pr_minimize(this);
+
+ free_proto(&pvt->proto);
+
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
+}
+
+
+
+/*
+ * struct protoent * pr_byname(struct irs_pr *this, const char *name)
+ *
+ */
+
+static struct protoent *
+pr_byname(struct irs_pr *this, const char *name) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct protoent *pr = &pvt->proto;
+ char *body = NULL;
+ size_t bodylen;
+ int code;
+ int i;
+ char text[256];
+
+ if (pr->p_name != NULL && strcmp(name, pr->p_name) == 0) {
+ return (pr);
+ }
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return (NULL);
+ }
+
+ i = irs_irp_send_command(pvt->girpdata, "getprotobyname %s", name);
+ if (i != 0)
+ return (NULL);
+
+ if (irs_irp_get_full_response(pvt->girpdata, &code,
+ text, sizeof text,
+ &body, &bodylen) != 0) {
+ return (NULL);
+ }
+
+ if (code == IRPD_GETPROTO_OK) {
+ free_proto(pr);
+ if (irp_unmarshall_pr(pr, body) != 0) {
+ pr = NULL;
+ }
+ } else {
+ pr = NULL;
+ }
+
+ if (body != NULL) {
+ memput(body, bodylen);
+ }
+
+ return (pr);
+}
+
+
+
+/*
+ * struct protoent * pr_bynumber(struct irs_pr *this, int proto)
+ *
+ */
+
+static struct protoent *
+pr_bynumber(struct irs_pr *this, int proto) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct protoent *pr = &pvt->proto;
+ char *body = NULL;
+ size_t bodylen;
+ int code;
+ int i;
+ char text[256];
+
+ if (pr->p_name != NULL && proto == pr->p_proto) {
+ return (pr);
+ }
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return (NULL);
+ }
+
+ i = irs_irp_send_command(pvt->girpdata, "getprotobynumber %d", proto);
+ if (i != 0)
+ return (NULL);
+
+ if (irs_irp_get_full_response(pvt->girpdata, &code,
+ text, sizeof text,
+ &body, &bodylen) != 0) {
+ return (NULL);
+ }
+
+ if (code == IRPD_GETPROTO_OK) {
+ free_proto(pr);
+ if (irp_unmarshall_pr(pr, body) != 0) {
+ pr = NULL;
+ }
+ } else {
+ pr = NULL;
+ }
+
+ if (body != NULL) {
+ memput(body, bodylen);
+ }
+
+ return (pr);
+}
+
+
+
+
+/*
+ * void pr_rewind(struct irs_pr *this)
+ *
+ */
+
+static void
+pr_rewind(struct irs_pr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ char text[256];
+ int code;
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return;
+ }
+
+ if (irs_irp_send_command(pvt->girpdata, "setprotoent") != 0) {
+ return;
+ }
+
+ code = irs_irp_read_response(pvt->girpdata, text, sizeof text);
+ if (code != IRPD_GETPROTO_SETOK) {
+ if (irp_log_errors) {
+ syslog(LOG_WARNING, "setprotoent failed: %s", text);
+ }
+ }
+
+ return;
+}
+
+
+
+
+/*
+ * struct protoent * pr_next(struct irs_pr *this)
+ *
+ * Notes:
+ *
+ * Prepares the cache if necessary and returns the next item in it.
+ *
+ */
+
+static struct protoent *
+pr_next(struct irs_pr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct protoent *pr = &pvt->proto;
+ char *body;
+ size_t bodylen;
+ int code;
+ char text[256];
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_send_command(pvt->girpdata, "getprotoent") != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_get_full_response(pvt->girpdata, &code,
+ text, sizeof text,
+ &body, &bodylen) != 0) {
+ return (NULL);
+ }
+
+ if (code == IRPD_GETPROTO_OK) {
+ free_proto(pr);
+ if (irp_unmarshall_pr(pr, body) != 0) {
+ pr = NULL;
+ }
+ } else {
+ pr = NULL;
+ }
+
+ if (body != NULL) {
+ memput(body, bodylen);
+ }
+
+ return (pr);
+}
+
+
+
+
+/*
+ * void pr_minimize(struct irs_pr *this)
+ *
+ */
+
+static void
+pr_minimize(struct irs_pr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ irs_irp_disconnect(pvt->girpdata);
+}
+
+
+
+
+
+
+/*
+ * static void free_proto(struct protoent *pw);
+ *
+ * Deallocate all the memory irp_unmarshall_pr allocated.
+ *
+ */
+
+static void
+free_proto(struct protoent *pr) {
+ char **p;
+
+ if (pr == NULL)
+ return;
+
+ if (pr->p_name != NULL)
+ free(pr->p_name);
+
+ for (p = pr->p_aliases ; p != NULL && *p != NULL ; p++)
+ free(*p);
+}
diff --git a/usr/src/lib/libresolv2/common/irs/irp_pw.c b/usr/src/lib/libresolv2/common/irs/irp_pw.c
new file mode 100644
index 0000000000..aa6fcbcbce
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/irp_pw.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: irp_pw.c,v 8.2 2001/11/01 07:29:26 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/* Extern */
+
+#include "port_before.h"
+
+#ifndef WANT_IRS_PW
+static int __bind_irs_pw_unneeded;
+#else
+
+#include <syslog.h>
+#include <sys/param.h>
+
+#include <db.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <utmp.h>
+#include <unistd.h>
+
+#include <irs.h>
+#include <irp.h>
+#include <isc/memcluster.h>
+#include <isc/irpmarshall.h>
+
+#include "port_after.h"
+
+#include "irs_p.h"
+#include "irp_p.h"
+
+
+/* Types */
+
+struct pvt {
+ struct irp_p *girpdata; /* global IRP data */
+ int warned;
+ struct passwd passwd; /* password structure */
+};
+
+/* Forward */
+
+static void pw_close(struct irs_pw *);
+static struct passwd * pw_next(struct irs_pw *);
+static struct passwd * pw_byname(struct irs_pw *, const char *);
+static struct passwd * pw_byuid(struct irs_pw *, uid_t);
+static void pw_rewind(struct irs_pw *);
+static void pw_minimize(struct irs_pw *);
+
+static void free_passwd(struct passwd *pw);
+
+/* Public */
+struct irs_pw *
+irs_irp_pw(struct irs_acc *this) {
+ struct irs_pw *pw;
+ struct pvt *pvt;
+
+ if (!(pw = memget(sizeof *pw))) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pw, 0, sizeof *pw);
+
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(pw, sizeof *pw);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pvt, 0, sizeof *pvt);
+ pvt->girpdata = this->private;
+
+ pw->private = pvt;
+ pw->close = pw_close;
+ pw->next = pw_next;
+ pw->byname = pw_byname;
+ pw->byuid = pw_byuid;
+ pw->rewind = pw_rewind;
+ pw->minimize = pw_minimize;
+
+ return (pw);
+}
+
+/* Methods */
+
+
+
+/*
+ * void pw_close(struct irs_pw *this)
+ *
+ */
+
+static void
+pw_close(struct irs_pw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ pw_minimize(this);
+
+ free_passwd(&pvt->passwd);
+
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
+}
+
+
+
+
+/*
+ * struct passwd * pw_next(struct irs_pw *this)
+ *
+ */
+
+static struct passwd *
+pw_next(struct irs_pw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct passwd *pw = &pvt->passwd;
+ char *body;
+ size_t bodylen;
+ int code;
+ char text[256];
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_send_command(pvt->girpdata, "getpwent") != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_get_full_response(pvt->girpdata, &code,
+ text, sizeof text,
+ &body, &bodylen) != 0) {
+ return (NULL);
+ }
+
+ if (code == IRPD_GETUSER_OK) {
+ free_passwd(pw);
+ if (irp_unmarshall_pw(pw, body) != 0) {
+ pw = NULL;
+ }
+ } else {
+ pw = NULL;
+ }
+
+ if (body != NULL) {
+ memput(body, bodylen);
+ }
+
+ return (pw);
+}
+
+
+
+
+/*
+ * struct passwd * pw_byname(struct irs_pw *this, const char *name)
+ *
+ */
+
+static struct passwd *
+pw_byname(struct irs_pw *this, const char *name) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct passwd *pw = &pvt->passwd;
+ char *body = NULL;
+ char text[256];
+ size_t bodylen;
+ int code;
+
+ if (pw->pw_name != NULL && strcmp(name, pw->pw_name) == 0) {
+ return (pw);
+ }
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_send_command(pvt->girpdata, "getpwnam %s", name) != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_get_full_response(pvt->girpdata, &code,
+ text, sizeof text,
+ &body, &bodylen) != 0) {
+ return (NULL);
+ }
+
+ if (code == IRPD_GETUSER_OK) {
+ free_passwd(pw);
+ if (irp_unmarshall_pw(pw, body) != 0) {
+ pw = NULL;
+ }
+ } else {
+ pw = NULL;
+ }
+
+ if (body != NULL) {
+ memput(body, bodylen);
+ }
+
+ return (pw);
+}
+
+
+
+
+/*
+ * struct passwd * pw_byuid(struct irs_pw *this, uid_t uid)
+ *
+ */
+
+static struct passwd *
+pw_byuid(struct irs_pw *this, uid_t uid) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ char *body;
+ char text[256];
+ size_t bodylen;
+ int code;
+ struct passwd *pw = &pvt->passwd;
+
+ if (pw->pw_name != NULL && pw->pw_uid == uid) {
+ return (pw);
+ }
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_send_command(pvt->girpdata, "getpwuid %d", uid) != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_get_full_response(pvt->girpdata, &code,
+ text, sizeof text,
+ &body, &bodylen) != 0) {
+ return (NULL);
+ }
+
+ if (code == IRPD_GETUSER_OK) {
+ free_passwd(pw);
+ if (irp_unmarshall_pw(pw, body) != 0) {
+ pw = NULL;
+ }
+ } else {
+ pw = NULL;
+ }
+
+ if (body != NULL) {
+ memput(body, bodylen);
+ }
+
+ return (pw);
+}
+
+
+
+
+/*
+ * void pw_rewind(struct irs_pw *this)
+ *
+ */
+
+static void
+pw_rewind(struct irs_pw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ char text[256];
+ int code;
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return;
+ }
+
+ if (irs_irp_send_command(pvt->girpdata, "setpwent") != 0) {
+ return;
+ }
+
+ code = irs_irp_read_response(pvt->girpdata, text, sizeof text);
+ if (code != IRPD_GETUSER_SETOK) {
+ if (irp_log_errors) {
+ syslog(LOG_WARNING, "setpwent failed: %s", text);
+ }
+ }
+
+ return;
+}
+
+
+/*
+ * void pw_minimize(struct irs_pw *this)
+ *
+ */
+
+static void
+pw_minimize(struct irs_pw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ irs_irp_disconnect(pvt->girpdata);
+}
+
+
+/* Private. */
+
+
+
+/*
+ * static void free_passwd(struct passwd *pw);
+ *
+ * Deallocate all the memory irp_unmarshall_pw allocated.
+ *
+ */
+
+static void
+free_passwd(struct passwd *pw) {
+ if (pw == NULL)
+ return;
+
+ if (pw->pw_name != NULL)
+ free(pw->pw_name);
+
+ if (pw->pw_passwd != NULL)
+ free(pw->pw_passwd);
+
+#ifdef HAVE_PW_CLASS
+ if (pw->pw_class != NULL)
+ free(pw->pw_class);
+#endif
+
+ if (pw->pw_gecos != NULL)
+ free(pw->pw_gecos);
+
+ if (pw->pw_dir != NULL)
+ free(pw->pw_dir);
+
+ if (pw->pw_shell != NULL)
+ free(pw->pw_shell);
+}
+
+#endif /* WANT_IRS_PW */
diff --git a/usr/src/lib/libresolv2/common/irs/irp_sv.c b/usr/src/lib/libresolv2/common/irs/irp_sv.c
new file mode 100644
index 0000000000..144ae5a7fc
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/irp_sv.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: irp_sv.c,v 8.1 1999/01/18 07:46:54 vixie Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/* extern */
+
+#include "port_before.h"
+
+#include <syslog.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#ifdef IRS_LCL_SV_DB
+#include <db.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslog.h>
+
+#include <irs.h>
+#include <irp.h>
+#include <isc/irpmarshall.h>
+#include <isc/memcluster.h>
+
+#include "irs_p.h"
+#include "lcl_p.h"
+#include "irp_p.h"
+
+#include "port_after.h"
+
+/* Types */
+
+struct pvt {
+ struct irp_p *girpdata;
+ int warned;
+ struct servent service;
+};
+
+/* Forward */
+
+static void sv_close(struct irs_sv*);
+static struct servent * sv_next(struct irs_sv *);
+static struct servent * sv_byname(struct irs_sv *, const char *,
+ const char *);
+static struct servent * sv_byport(struct irs_sv *, int, const char *);
+static void sv_rewind(struct irs_sv *);
+static void sv_minimize(struct irs_sv *);
+
+static void free_service(struct servent *sv);
+
+
+
+/* Public */
+
+
+
+/*
+ * struct irs_sv * irs_irp_sv(struct irs_acc *this)
+ *
+ */
+
+struct irs_sv *
+irs_irp_sv(struct irs_acc *this) {
+ struct irs_sv *sv;
+ struct pvt *pvt;
+
+ if ((sv = memget(sizeof *sv)) == NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(sv, 0x0, sizeof *sv);
+
+ if ((pvt = memget(sizeof *pvt)) == NULL) {
+ memput(sv, sizeof *sv);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pvt, 0, sizeof *pvt);
+ pvt->girpdata = this->private;
+
+ sv->private = pvt;
+ sv->close = sv_close;
+ sv->next = sv_next;
+ sv->byname = sv_byname;
+ sv->byport = sv_byport;
+ sv->rewind = sv_rewind;
+ sv->minimize = sv_minimize;
+
+ return (sv);
+}
+
+/* Methods */
+
+
+
+/*
+ * void sv_close(struct irs_sv *this)
+ *
+ */
+
+static void
+sv_close(struct irs_sv *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ sv_minimize(this);
+
+ free_service(&pvt->service);
+
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
+}
+
+
+
+
+/*
+ * struct servent * sv_next(struct irs_sv *this)
+ *
+ * Notes:
+ *
+ * Fills the cache if necessary and returns the next item from it.
+ *
+ */
+
+static struct servent *
+sv_next(struct irs_sv *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct servent *sv = &pvt->service;
+ char *body;
+ size_t bodylen;
+ int code;
+ char text[256];
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_send_command(pvt->girpdata, "getservent") != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_get_full_response(pvt->girpdata, &code,
+ text, sizeof text,
+ &body, &bodylen) != 0) {
+ return (NULL);
+ }
+
+ if (code == IRPD_GETSERVICE_OK) {
+ free_service(sv);
+ if (irp_unmarshall_sv(sv, body) != 0) {
+ sv = NULL;
+ }
+ } else {
+ sv = NULL;
+ }
+
+ if (body != NULL) {
+ memput(body, bodylen);
+ }
+
+ return (sv);
+}
+
+
+
+
+/*
+ * struct servent * sv_byname(struct irs_sv *this, const char *name,
+ * const char *proto)
+ *
+ */
+
+static struct servent *
+sv_byname(struct irs_sv *this, const char *name, const char *proto) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct servent *sv = &pvt->service;
+ char *body;
+ char text[256];
+ size_t bodylen;
+ int code;
+
+ if (sv->s_name != NULL &&
+ strcmp(name, sv->s_name) == 0 &&
+ strcasecmp(proto, sv->s_proto) == 0) {
+ return (sv);
+ }
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_send_command(pvt->girpdata, "getservbyname %s %s",
+ name, proto) != 0)
+ return (NULL);
+
+ if (irs_irp_get_full_response(pvt->girpdata, &code,
+ text, sizeof text,
+ &body, &bodylen) != 0) {
+ return (NULL);
+ }
+
+ if (code == IRPD_GETSERVICE_OK) {
+ free_service(sv);
+ if (irp_unmarshall_sv(sv, body) != 0) {
+ sv = NULL;
+ }
+ } else {
+ sv = NULL;
+ }
+
+ if (body != NULL) {
+ memput(body, bodylen);
+ }
+
+ return (sv);
+}
+
+
+
+
+/*
+ * struct servent * sv_byport(struct irs_sv *this, int port,
+ * const char *proto)
+ *
+ */
+
+static struct servent *
+sv_byport(struct irs_sv *this, int port, const char *proto) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct servent *sv = &pvt->service;
+ char *body;
+ size_t bodylen;
+ char text[256];
+ int code;
+
+ if (sv->s_name != NULL &&
+ port == sv->s_port &&
+ strcasecmp(proto, sv->s_proto) == 0) {
+ return (sv);
+ }
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_send_command(pvt->girpdata, "getservbyport %d %s",
+ ntohs((short)port), proto) != 0) {
+ return (NULL);
+ }
+
+ if (irs_irp_get_full_response(pvt->girpdata, &code,
+ text, sizeof text,
+ &body, &bodylen) != 0) {
+ return (NULL);
+ }
+
+ if (code == IRPD_GETSERVICE_OK) {
+ free_service(sv);
+ if (irp_unmarshall_sv(sv, body) != 0) {
+ sv = NULL;
+ }
+ } else {
+ sv = NULL;
+ }
+
+ if (body != NULL) {
+ memput(body, bodylen);
+ }
+
+ return (sv);
+}
+
+
+
+
+
+/*
+ * void sv_rewind(struct irs_sv *this)
+ *
+ */
+
+static void
+sv_rewind(struct irs_sv *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ char text[256];
+ int code;
+
+ if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
+ return;
+ }
+
+ if (irs_irp_send_command(pvt->girpdata, "setservent") != 0) {
+ return;
+ }
+
+ code = irs_irp_read_response(pvt->girpdata, text, sizeof text);
+ if (code != IRPD_GETSERVICE_SETOK) {
+ if (irp_log_errors) {
+ syslog(LOG_WARNING, "setservent failed: %s", text);
+ }
+ }
+
+ return;
+}
+
+
+
+
+
+/*
+ * void sv_minimize(struct irs_sv *this)
+ *
+ */
+
+static void
+sv_minimize(struct irs_sv *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ irs_irp_disconnect(pvt->girpdata);
+}
+
+
+
+
+
+
+static void
+free_service(struct servent *sv) {
+ char **p;
+
+ if (sv == NULL) {
+ return;
+ }
+
+ if (sv->s_name != NULL) {
+ free(sv->s_name);
+ }
+
+ for (p = sv->s_aliases ; p != NULL && *p != NULL ; p++) {
+ free(*p);
+ }
+
+ if (sv->s_proto != NULL) {
+ free(sv->s_proto);
+ }
+}
+
+
diff --git a/usr/src/lib/libresolv2/common/irs/irpmarshall.c b/usr/src/lib/libresolv2/common/irs/irpmarshall.c
new file mode 100644
index 0000000000..dfeb984262
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/irpmarshall.c
@@ -0,0 +1,2351 @@
+/*
+ * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: irpmarshall.c,v 8.7 2001/05/29 05:49:01 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#if 0
+
+Check values are in approrpriate endian order.
+
+Double check memory allocations on unmarhsalling
+
+#endif
+
+
+/* Extern */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <utmp.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <irs.h>
+#include <isc/memcluster.h>
+#include <isc/irpmarshall.h>
+
+#include "port_after.h"
+
+
+#ifndef HAVE_STRNDUP
+static char *strndup(const char *str, size_t len);
+#endif
+
+static char **splitarray(const char *buffer, const char *buffend, char delim);
+static int joinarray(char * const * argv, char *buffer, char delim);
+static char *getfield(char **res, size_t reslen, char **buffer, char delim);
+static size_t joinlength(char * const *argv);
+static void free_array(char **argv, size_t entries);
+
+#define ADDR_T_STR(x) (x == AF_INET ? "AF_INET" :\
+ (x == AF_INET6 ? "AF_INET6" : "UNKNOWN"))
+
+#define MAXPADDRSIZE (sizeof "255.255.255.255" + 1)
+
+static char COMMA = ',';
+
+static const char *COMMASTR = ",";
+static const char *COLONSTR = ":";
+
+
+
+/* See big comment at bottom of irpmarshall.h for description. */
+
+
+#ifdef WANT_IRS_PW
+/* +++++++++++++++++++++++++ struct passwd +++++++++++++++++++++++++ */
+
+
+/*
+ * int irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len)
+ *
+ * notes:
+ *
+ * See above
+ *
+ * return:
+ *
+ * 0 on sucess, -1 on failure.
+ *
+ */
+
+int
+irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len) {
+ size_t need = 1 ; /* for null byte */
+ char pwUid[24];
+ char pwGid[24];
+ char pwChange[24];
+ char pwExpire[24];
+ const char *pwClass;
+ const char *fieldsep = COLONSTR;
+
+ if (pw == NULL || len == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ sprintf(pwUid, "%ld", (long)pw->pw_uid);
+ sprintf(pwGid, "%ld", (long)pw->pw_gid);
+
+#ifdef HAVE_PW_CHANGE
+ sprintf(pwChange, "%ld", (long)pw->pw_change);
+#else
+ pwChange[0] = '0';
+ pwChange[1] = '\0';
+#endif
+
+#ifdef HAVE_PW_EXPIRE
+ sprintf(pwExpire, "%ld", (long)pw->pw_expire);
+#else
+ pwExpire[0] = '0';
+ pwExpire[1] = '\0';
+#endif
+
+#ifdef HAVE_PW_CLASS
+ pwClass = pw->pw_class;
+#else
+ pwClass = "";
+#endif
+
+ need += strlen(pw->pw_name) + 1; /* one for fieldsep */
+ need += strlen(pw->pw_passwd) + 1;
+ need += strlen(pwUid) + 1;
+ need += strlen(pwGid) + 1;
+ need += strlen(pwClass) + 1;
+ need += strlen(pwChange) + 1;
+ need += strlen(pwExpire) + 1;
+ need += strlen(pw->pw_gecos) + 1;
+ need += strlen(pw->pw_dir) + 1;
+ need += strlen(pw->pw_shell) + 1;
+
+ if (buffer == NULL) {
+ *len = need;
+ return (0);
+ }
+
+ if (*buffer != NULL && need > *len) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (*buffer == NULL) {
+ need += 2; /* for CRLF */
+ *buffer = memget(need);
+ if (*buffer == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ *len = need;
+ }
+
+ strcpy(*buffer, pw->pw_name); strcat(*buffer, fieldsep);
+ strcat(*buffer, pw->pw_passwd); strcat(*buffer, fieldsep);
+ strcat(*buffer, pwUid); strcat(*buffer, fieldsep);
+ strcat(*buffer, pwGid); strcat(*buffer, fieldsep);
+ strcat(*buffer, pwClass); strcat(*buffer, fieldsep);
+ strcat(*buffer, pwChange); strcat(*buffer, fieldsep);
+ strcat(*buffer, pwExpire); strcat(*buffer, fieldsep);
+ strcat(*buffer, pw->pw_gecos); strcat(*buffer, fieldsep);
+ strcat(*buffer, pw->pw_dir); strcat(*buffer, fieldsep);
+ strcat(*buffer, pw->pw_shell); strcat(*buffer, fieldsep);
+
+ return (0);
+}
+
+
+
+
+
+/*
+ * int irp_unmarshall_pw(struct passwd *pw, char *buffer)
+ *
+ * notes:
+ *
+ * see above
+ *
+ * return:
+ *
+ * 0 on success, -1 on failure
+ *
+ */
+
+int
+irp_unmarshall_pw(struct passwd *pw, char *buffer) {
+ char *name, *pass, *class, *gecos, *dir, *shell;
+ uid_t pwuid;
+ gid_t pwgid;
+ time_t pwchange;
+ time_t pwexpire;
+ char *p;
+ long t;
+ char tmpbuf[24];
+ char *tb = &tmpbuf[0];
+ char fieldsep = ':';
+ int myerrno = EINVAL;
+
+ name = pass = class = gecos = dir = shell = NULL;
+ p = buffer;
+
+ /* pw_name field */
+ name = NULL;
+ if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) {
+ goto error;
+ }
+
+ /* pw_passwd field */
+ pass = NULL;
+ if (getfield(&pass, 0, &p, fieldsep) == NULL) { /* field can be empty */
+ goto error;
+ }
+
+
+ /* pw_uid field */
+ tb = tmpbuf;
+ if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
+ strlen(tb) == 0) {
+ goto error;
+ }
+ t = strtol(tmpbuf, &tb, 10);
+ if (*tb) {
+ goto error; /* junk in value */
+ }
+ pwuid = (uid_t)t;
+ if ((long) pwuid != t) { /* value must have been too big. */
+ goto error;
+ }
+
+
+
+ /* pw_gid field */
+ tb = tmpbuf;
+ if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
+ strlen(tb) == 0) {
+ goto error;
+ }
+ t = strtol(tmpbuf, &tb, 10);
+ if (*tb) {
+ goto error; /* junk in value */
+ }
+ pwgid = (gid_t)t;
+ if ((long)pwgid != t) { /* value must have been too big. */
+ goto error;
+ }
+
+
+
+ /* pw_class field */
+ class = NULL;
+ if (getfield(&class, 0, &p, fieldsep) == NULL) {
+ goto error;
+ }
+
+
+
+ /* pw_change field */
+ tb = tmpbuf;
+ if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
+ strlen(tb) == 0) {
+ goto error;
+ }
+ t = strtol(tmpbuf, &tb, 10);
+ if (*tb) {
+ goto error; /* junk in value */
+ }
+ pwchange = (time_t)t;
+ if ((long)pwchange != t) { /* value must have been too big. */
+ goto error;
+ }
+
+
+
+ /* pw_expire field */
+ tb = tmpbuf;
+ if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
+ strlen(tb) == 0) {
+ goto error;
+ }
+ t = strtol(tmpbuf, &tb, 10);
+ if (*tb) {
+ goto error; /* junk in value */
+ }
+ pwexpire = (time_t)t;
+ if ((long) pwexpire != t) { /* value must have been too big. */
+ goto error;
+ }
+
+
+
+ /* pw_gecos field */
+ gecos = NULL;
+ if (getfield(&gecos, 0, &p, fieldsep) == NULL) {
+ goto error;
+ }
+
+
+
+ /* pw_dir field */
+ dir = NULL;
+ if (getfield(&dir, 0, &p, fieldsep) == NULL) {
+ goto error;
+ }
+
+
+
+ /* pw_shell field */
+ shell = NULL;
+ if (getfield(&shell, 0, &p, fieldsep) == NULL) {
+ goto error;
+ }
+
+
+
+ pw->pw_name = name;
+ pw->pw_passwd = pass;
+ pw->pw_uid = pwuid;
+ pw->pw_gid = pwgid;
+ pw->pw_gecos = gecos;
+ pw->pw_dir = dir;
+ pw->pw_shell = shell;
+
+#ifdef HAVE_PW_CHANGE
+ pw->pw_change = pwchange;
+#endif
+#ifdef HAVE_PW_CLASS
+ pw->pw_class = class;
+#endif
+#ifdef HAVE_PW_EXPIRE
+ pw->pw_expire = pwexpire;
+#endif
+
+ return (0);
+
+ error:
+ errno = myerrno;
+
+ if (name != NULL) free(name);
+ if (pass != NULL) free(pass);
+ if (gecos != NULL) free(gecos);
+ if (dir != NULL) free(dir);
+ if (shell != NULL) free(shell);
+
+ return (-1);
+}
+
+/* ------------------------- struct passwd ------------------------- */
+#endif /* WANT_IRS_PW */
+
+
+
+/* +++++++++++++++++++++++++ struct group +++++++++++++++++++++++++ */
+
+
+
+/*
+ * int irp_marshall_gr(const struct group *gr, char **buffer, size_t *len)
+ *
+ * notes:
+ *
+ * see above.
+ *
+ * return:
+ *
+ * 0 on success, -1 on failure
+ */
+
+int
+irp_marshall_gr(const struct group *gr, char **buffer, size_t *len) {
+ size_t need = 1; /* for null byte */
+ char grGid[24];
+ const char *fieldsep = COLONSTR;
+
+ if (gr == NULL || len == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ sprintf(grGid, "%ld", (long)gr->gr_gid);
+
+ need += strlen(gr->gr_name) + 1;
+#ifndef MISSING_GR_PASSWD
+ need += strlen(gr->gr_passwd) + 1;
+#else
+ need++;
+#endif
+ need += strlen(grGid) + 1;
+ need += joinlength(gr->gr_mem) + 1;
+
+ if (buffer == NULL) {
+ *len = need;
+ return (0);
+ }
+
+ if (*buffer != NULL && need > *len) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (*buffer == NULL) {
+ need += 2; /* for CRLF */
+ *buffer = memget(need);
+ if (*buffer == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ *len = need;
+ }
+
+ strcpy(*buffer, gr->gr_name); strcat(*buffer, fieldsep);
+#ifndef MISSING_GR_PASSWD
+ strcat(*buffer, gr->gr_passwd);
+#endif
+ strcat(*buffer, fieldsep);
+ strcat(*buffer, grGid); strcat(*buffer, fieldsep);
+ joinarray(gr->gr_mem, *buffer, COMMA) ; strcat(*buffer, fieldsep);
+
+ return (0);
+}
+
+
+
+
+/*
+ * int irp_unmarshall_gr(struct group *gr, char *buffer)
+ *
+ * notes:
+ *
+ * see above
+ *
+ * return:
+ *
+ * 0 on success and -1 on failure.
+ *
+ */
+
+int
+irp_unmarshall_gr(struct group *gr, char *buffer) {
+ char *p, *q;
+ gid_t grgid;
+ long t;
+ char *name = NULL;
+ char *pass = NULL;
+ char **members = NULL;
+ char tmpbuf[24];
+ char *tb;
+ char fieldsep = ':';
+ int myerrno = EINVAL;
+
+ if (gr == NULL || buffer == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ p = buffer;
+
+ /* gr_name field */
+ name = NULL;
+ if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) {
+ goto error;
+ }
+
+
+ /* gr_passwd field */
+ pass = NULL;
+ if (getfield(&pass, 0, &p, fieldsep) == NULL) {
+ goto error;
+ }
+
+
+ /* gr_gid field */
+ tb = tmpbuf;
+ if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
+ strlen(tb) == 0) {
+ goto error;
+ }
+ t = strtol(tmpbuf, &tb, 10);
+ if (*tb) {
+ goto error; /* junk in value */
+ }
+ grgid = (gid_t)t;
+ if ((long) grgid != t) { /* value must have been too big. */
+ goto error;
+ }
+
+
+ /* gr_mem field. Member names are separated by commas */
+ q = strchr(p, fieldsep);
+ if (q == NULL) {
+ goto error;
+ }
+ members = splitarray(p, q, COMMA);
+ if (members == NULL) {
+ myerrno = errno;
+ goto error;
+ }
+ p = q + 1;
+
+
+ gr->gr_name = name;
+#ifndef MISSING_GR_PASSWD
+ gr->gr_passwd = pass;
+#endif
+ gr->gr_gid = grgid;
+ gr->gr_mem = members;
+
+ return (0);
+
+ error:
+ errno = myerrno;
+
+ if (name != NULL) free(name);
+ if (pass != NULL) free(pass);
+
+ return (-1);
+}
+
+
+/* ------------------------- struct group ------------------------- */
+
+
+
+
+/* +++++++++++++++++++++++++ struct servent +++++++++++++++++++++++++ */
+
+
+
+/*
+ * int irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len)
+ *
+ * notes:
+ *
+ * see above
+ *
+ * return:
+ *
+ * 0 on success, -1 on failure.
+ *
+ */
+
+int
+irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len) {
+ size_t need = 1; /* for null byte */
+ char svPort[24];
+ const char *fieldsep = COLONSTR;
+ short realport;
+
+ if (sv == NULL || len == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /* the int s_port field is actually a short in network order. We
+ want host order to make the marshalled data look correct */
+ realport = ntohs((short)sv->s_port);
+ sprintf(svPort, "%d", realport);
+
+ need += strlen(sv->s_name) + 1;
+ need += joinlength(sv->s_aliases) + 1;
+ need += strlen(svPort) + 1;
+ need += strlen(sv->s_proto) + 1;
+
+ if (buffer == NULL) {
+ *len = need;
+ return (0);
+ }
+
+ if (*buffer != NULL && need > *len) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (*buffer == NULL) {
+ need += 2; /* for CRLF */
+ *buffer = memget(need);
+ if (*buffer == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ *len = need;
+ }
+
+ strcpy(*buffer, sv->s_name); strcat(*buffer, fieldsep);
+ joinarray(sv->s_aliases, *buffer, COMMA); strcat(*buffer, fieldsep);
+ strcat(*buffer, svPort); strcat(*buffer, fieldsep);
+ strcat(*buffer, sv->s_proto); strcat(*buffer, fieldsep);
+
+ return (0);
+}
+
+
+
+
+
+/*
+ * int irp_unmarshall_sv(struct servent *sv, char *buffer)
+ *
+ * notes:
+ *
+ * see above
+ *
+ * return:
+ *
+ * 0 on success, -1 on failure.
+ *
+ */
+
+int
+irp_unmarshall_sv(struct servent *sv, char *buffer) {
+ char *p, *q;
+ short svport;
+ long t;
+ char *name = NULL;
+ char *proto = NULL;
+ char **aliases = NULL;
+ char tmpbuf[24];
+ char *tb;
+ char fieldsep = ':';
+ int myerrno = EINVAL;
+
+ if (sv == NULL || buffer == NULL)
+ return (-1);
+
+ p = buffer;
+
+
+ /* s_name field */
+ name = NULL;
+ if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) {
+ goto error;
+ }
+
+
+ /* s_aliases field */
+ q = strchr(p, fieldsep);
+ if (q == NULL) {
+ goto error;
+ }
+ aliases = splitarray(p, q, COMMA);
+ if (aliases == NULL) {
+ myerrno = errno;
+ goto error;
+ }
+ p = q + 1;
+
+
+ /* s_port field */
+ tb = tmpbuf;
+ if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
+ strlen(tb) == 0) {
+ goto error;
+ }
+ t = strtol(tmpbuf, &tb, 10);
+ if (*tb) {
+ goto error; /* junk in value */
+ }
+ svport = (short)t;
+ if ((long) svport != t) { /* value must have been too big. */
+ goto error;
+ }
+ svport = htons(svport);
+
+ /* s_proto field */
+ proto = NULL;
+ if (getfield(&proto, 0, &p, fieldsep) == NULL) {
+ goto error;
+ }
+
+ sv->s_name = name;
+ sv->s_aliases = aliases;
+ sv->s_port = svport;
+ sv->s_proto = proto;
+
+ return (0);
+
+ error:
+ errno = myerrno;
+
+ if (name != NULL) free(name);
+ if (proto != NULL) free(proto);
+ free_array(aliases, 0);
+
+ return (-1);
+}
+
+
+/* ------------------------- struct servent ------------------------- */
+
+/* +++++++++++++++++++++++++ struct protoent +++++++++++++++++++++++++ */
+
+
+
+/*
+ * int irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len)
+ *
+ * notes:
+ *
+ * see above
+ *
+ * return:
+ *
+ * 0 on success and -1 on failure.
+ *
+ */
+
+int
+irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len) {
+ size_t need = 1; /* for null byte */
+ char prProto[24];
+ const char *fieldsep = COLONSTR;
+
+ if (pr == NULL || len == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ sprintf(prProto, "%d", (int)pr->p_proto);
+
+ need += strlen(pr->p_name) + 1;
+ need += joinlength(pr->p_aliases) + 1;
+ need += strlen(prProto) + 1;
+
+ if (buffer == NULL) {
+ *len = need;
+ return (0);
+ }
+
+ if (*buffer != NULL && need > *len) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (*buffer == NULL) {
+ need += 2; /* for CRLF */
+ *buffer = memget(need);
+ if (*buffer == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ *len = need;
+ }
+
+ strcpy(*buffer, pr->p_name); strcat(*buffer, fieldsep);
+ joinarray(pr->p_aliases, *buffer, COMMA); strcat(*buffer, fieldsep);
+ strcat(*buffer, prProto); strcat(*buffer, fieldsep);
+
+ return (0);
+
+}
+
+
+
+/*
+ * int irp_unmarshall_pr(struct protoent *pr, char *buffer)
+ *
+ * notes:
+ *
+ * See above
+ *
+ * return:
+ *
+ * 0 on success, -1 on failure
+ *
+ */
+
+int irp_unmarshall_pr(struct protoent *pr, char *buffer) {
+ char *p, *q;
+ int prproto;
+ long t;
+ char *name = NULL;
+ char **aliases = NULL;
+ char tmpbuf[24];
+ char *tb;
+ char fieldsep = ':';
+ int myerrno = EINVAL;
+
+ if (pr == NULL || buffer == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ p = buffer;
+
+ /* p_name field */
+ name = NULL;
+ if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) {
+ goto error;
+ }
+
+
+ /* p_aliases field */
+ q = strchr(p, fieldsep);
+ if (q == NULL) {
+ goto error;
+ }
+ aliases = splitarray(p, q, COMMA);
+ if (aliases == NULL) {
+ myerrno = errno;
+ goto error;
+ }
+ p = q + 1;
+
+
+ /* p_proto field */
+ tb = tmpbuf;
+ if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
+ strlen(tb) == 0) {
+ goto error;
+ }
+ t = strtol(tmpbuf, &tb, 10);
+ if (*tb) {
+ goto error; /* junk in value */
+ }
+ prproto = (int)t;
+ if ((long) prproto != t) { /* value must have been too big. */
+ goto error;
+ }
+
+ pr->p_name = name;
+ pr->p_aliases = aliases;
+ pr->p_proto = prproto;
+
+ return (0);
+
+ error:
+ errno = myerrno;
+
+ if (name != NULL) free(name);
+ free_array(aliases, 0);
+
+ return (-1);
+}
+
+/* ------------------------- struct protoent ------------------------- */
+
+
+
+/* +++++++++++++++++++++++++ struct hostent +++++++++++++++++++++++++ */
+
+
+/*
+ * int irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len)
+ *
+ * notes:
+ *
+ * see above.
+ *
+ * return:
+ *
+ * 0 on success, -1 on failure.
+ *
+ */
+
+int
+irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len) {
+ size_t need = 1; /* for null byte */
+ char hoaddrtype[24];
+ char holength[24];
+ char **av;
+ char *p;
+ int addrlen;
+ int malloced = 0;
+ size_t remlen;
+ const char *fieldsep = "@";
+
+ if (ho == NULL || len == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ switch(ho->h_addrtype) {
+ case AF_INET:
+ strcpy(hoaddrtype, "AF_INET");
+ break;
+
+ case AF_INET6:
+ strcpy(hoaddrtype, "AF_INET6");
+ break;
+
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+
+ sprintf(holength, "%d", ho->h_length);
+
+ need += strlen(ho->h_name) + 1;
+ need += joinlength(ho->h_aliases) + 1;
+ need += strlen(hoaddrtype) + 1;
+ need += strlen(holength) + 1;
+
+ /* we determine an upper bound on the string length needed, not an
+ exact length. */
+ addrlen = (ho->h_addrtype == AF_INET ? 16 : 46) ; /* XX other AF's?? */
+ for (av = ho->h_addr_list; av != NULL && *av != NULL ; av++)
+ need += addrlen;
+
+ if (buffer == NULL) {
+ *len = need;
+ return (0);
+ }
+
+ if (*buffer != NULL && need > *len) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (*buffer == NULL) {
+ need += 2; /* for CRLF */
+ *buffer = memget(need);
+ if (*buffer == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ *len = need;
+ malloced = 1;
+ }
+
+ strcpy(*buffer, ho->h_name); strcat(*buffer, fieldsep);
+ joinarray(ho->h_aliases, *buffer, COMMA); strcat(*buffer, fieldsep);
+ strcat(*buffer, hoaddrtype); strcat(*buffer, fieldsep);
+ strcat(*buffer, holength); strcat(*buffer, fieldsep);
+
+ p = *buffer + strlen(*buffer);
+ remlen = need - strlen(*buffer);
+ for (av = ho->h_addr_list ; av != NULL && *av != NULL ; av++) {
+ if (inet_ntop(ho->h_addrtype, *av, p, remlen) == NULL) {
+ goto error;
+ }
+ if (*(av + 1) != NULL)
+ strcat(p, COMMASTR);
+ remlen -= strlen(p);
+ p += strlen(p);
+ }
+ strcat(*buffer, fieldsep);
+
+ return (0);
+
+ error:
+ if (malloced) {
+ memput(*buffer, need);
+ }
+
+ return (-1);
+}
+
+
+
+/*
+ * int irp_unmarshall_ho(struct hostent *ho, char *buffer)
+ *
+ * notes:
+ *
+ * See above.
+ *
+ * return:
+ *
+ * 0 on success, -1 on failure.
+ *
+ */
+
+int
+irp_unmarshall_ho(struct hostent *ho, char *buffer) {
+ char *p, *q, *r;
+ int hoaddrtype;
+ int holength;
+ long t;
+ char *name = NULL;
+ char **aliases = NULL;
+ char **hohaddrlist = NULL;
+ size_t hoaddrsize;
+ char tmpbuf[24];
+ char *tb;
+ char **alist;
+ int addrcount;
+ char fieldsep = '@';
+ int myerrno = EINVAL;
+
+ if (ho == NULL || buffer == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ p = buffer;
+
+ /* h_name field */
+ name = NULL;
+ if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) {
+ goto error;
+ }
+
+
+ /* h_aliases field */
+ q = strchr(p, fieldsep);
+ if (q == NULL) {
+ goto error;
+ }
+ aliases = splitarray(p, q, COMMA);
+ if (aliases == NULL) {
+ myerrno = errno;
+ goto error;
+ }
+ p = q + 1;
+
+
+ /* h_addrtype field */
+ tb = tmpbuf;
+ if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
+ strlen(tb) == 0) {
+ goto error;
+ }
+ if (strcmp(tmpbuf, "AF_INET") == 0)
+ hoaddrtype = AF_INET;
+ else if (strcmp(tmpbuf, "AF_INET6") == 0)
+ hoaddrtype = AF_INET6;
+ else
+ goto error;
+
+
+ /* h_length field */
+ tb = tmpbuf;
+ if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
+ strlen(tb) == 0) {
+ goto error;
+ }
+ t = strtol(tmpbuf, &tb, 10);
+ if (*tb) {
+ goto error; /* junk in value */
+ }
+ holength = (int)t;
+ if ((long) holength != t) { /* value must have been too big. */
+ goto error;
+ }
+
+
+ /* h_addr_list field */
+ q = strchr(p, fieldsep);
+ if (q == NULL)
+ goto error;
+
+ /* count how many addresss are in there */
+ if (q > p + 1) {
+ for (addrcount = 1, r = p ; r != q ; r++) {
+ if (*r == COMMA)
+ addrcount++;
+ }
+ } else {
+ addrcount = 0;
+ }
+
+ hoaddrsize = (addrcount + 1) * sizeof (char *);
+ hohaddrlist = malloc(hoaddrsize);
+ if (hohaddrlist == NULL) {
+ myerrno = ENOMEM;
+ goto error;
+ }
+
+ memset(hohaddrlist, 0x0, hoaddrsize);
+
+ alist = hohaddrlist;
+ for (t = 0, r = p ; r != q ; p = r + 1, t++) {
+ char saved;
+ while (r != q && *r != COMMA) r++;
+ saved = *r;
+ *r = 0x0;
+
+ alist[t] = malloc(hoaddrtype == AF_INET ? 4 : 16);
+ if (alist[t] == NULL) {
+ myerrno = ENOMEM;
+ goto error;
+ }
+
+ if (inet_pton(hoaddrtype, p, alist[t]) == -1)
+ goto error;
+ *r = saved;
+ }
+ alist[t] = NULL;
+
+ ho->h_name = name;
+ ho->h_aliases = aliases;
+ ho->h_addrtype = hoaddrtype;
+ ho->h_length = holength;
+ ho->h_addr_list = hohaddrlist;
+
+ return (0);
+
+ error:
+ errno = myerrno;
+
+ if (name != NULL) free(name);
+ free_array(aliases, 0);
+
+ return (-1);
+}
+
+/* ------------------------- struct hostent------------------------- */
+
+
+
+/* +++++++++++++++++++++++++ struct netgrp +++++++++++++++++++++++++ */
+
+
+/*
+ * int irp_marshall_ng(const char *host, const char *user,
+ * const char *domain, char *buffer, size_t *len)
+ *
+ * notes:
+ *
+ * See note for irp_marshall_ng_start
+ *
+ * return:
+ *
+ * 0 on success, 0 on failure.
+ *
+ */
+
+int
+irp_marshall_ng(const char *host, const char *user, const char *domain,
+ char **buffer, size_t *len) {
+ size_t need = 1; /* for nul byte */
+ const char *fieldsep = ",";
+
+ if (len == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ need += 4; /* two parens and two commas */
+ need += (host == NULL ? 0 : strlen(host));
+ need += (user == NULL ? 0 : strlen(user));
+ need += (domain == NULL ? 0 : strlen(domain));
+
+ if (buffer == NULL) {
+ *len = need;
+ return (0);
+ } else if (*buffer != NULL && need > *len) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (*buffer == NULL) {
+ need += 2; /* for CRLF */
+ *buffer = memget(need);
+ if (*buffer == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ *len = need;
+ }
+
+ (*buffer)[0] = '(';
+ (*buffer)[1] = '\0';
+
+ if (host != NULL)
+ strcat(*buffer, host);
+ strcat(*buffer, fieldsep);
+
+ if (user != NULL)
+ strcat(*buffer, user);
+ strcat(*buffer, fieldsep);
+
+ if (domain != NULL)
+ strcat(*buffer, domain);
+ strcat(*buffer, ")");
+
+ return (0);
+}
+
+
+
+/* ---------- */
+
+
+/*
+ * int irp_unmarshall_ng(const char **host, const char **user,
+ * const char **domain, char *buffer)
+ *
+ * notes:
+ *
+ * Unpacks the BUFFER into 3 character arrays it allocates and assigns
+ * to *HOST, *USER and *DOMAIN. If any field of the value is empty,
+ * then the corresponding paramater value will be set to NULL.
+ *
+ * return:
+ *
+ * 0 on success and -1 on failure.
+ */
+
+int
+irp_unmarshall_ng(const char **hostp, const char **userp, const char **domainp,
+ char *buffer)
+{
+ char *p, *q;
+ char fieldsep = ',';
+ int myerrno = EINVAL;
+ char *host, *user, *domain;
+
+ if (userp == NULL || hostp == NULL ||
+ domainp == NULL || buffer == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ host = user = domain = NULL;
+
+ p = buffer;
+ while (isspace((unsigned char)*p)) {
+ p++;
+ }
+ if (*p != '(') {
+ goto error;
+ }
+
+ q = p + 1;
+ while (*q && *q != fieldsep)
+ q++;
+ if (!*q) {
+ goto error;
+ } else if (q > p + 1) {
+ host = strndup(p, q - p);
+ }
+
+ p = q + 1;
+ if (!*p) {
+ goto error;
+ } else if (*p != fieldsep) {
+ q = p + 1;
+ while (*q && *q != fieldsep)
+ q++;
+ if (!*q) {
+ goto error;
+ }
+ user = strndup(p, q - p);
+ } else {
+ p++;
+ }
+
+ if (!*p) {
+ goto error;
+ } else if (*p != ')') {
+ q = p + 1;
+ while (*q && *q != ')')
+ q++;
+ if (!*q) {
+ goto error;
+ }
+ domain = strndup(p, q - p);
+ }
+ *hostp = host;
+ *userp = user;
+ *domainp = domain;
+
+ return (0);
+
+ error:
+ errno = myerrno;
+
+ if (host != NULL) free(host);
+ if (user != NULL) free(user);
+ if (domain != NULL) free(domain);
+
+ return (-1);
+}
+
+/* ------------------------- struct netgrp ------------------------- */
+
+
+
+
+/* +++++++++++++++++++++++++ struct nwent +++++++++++++++++++++++++ */
+
+
+/*
+ * int irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len)
+ *
+ * notes:
+ *
+ * See at top.
+ *
+ * return:
+ *
+ * 0 on success and -1 on failure.
+ *
+ */
+
+int
+irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len) {
+ size_t need = 1; /* for null byte */
+ char nAddrType[24];
+ char nNet[MAXPADDRSIZE];
+ const char *fieldsep = COLONSTR;
+
+ if (ne == NULL || len == NULL) {
+ return (-1);
+ }
+
+ strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype));
+
+ if (inet_net_ntop(ne->n_addrtype, ne->n_addr, ne->n_length,
+ nNet, sizeof nNet) == NULL) {
+ return (-1);
+ }
+
+
+ need += strlen(ne->n_name) + 1;
+ need += joinlength(ne->n_aliases) + 1;
+ need += strlen(nAddrType) + 1;
+ need += strlen(nNet) + 1;
+
+ if (buffer == NULL) {
+ *len = need;
+ return (0);
+ }
+
+ if (*buffer != NULL && need > *len) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (*buffer == NULL) {
+ need += 2; /* for CRLF */
+ *buffer = memget(need);
+ if (*buffer == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ *len = need;
+ }
+
+ strcpy(*buffer, ne->n_name); strcat(*buffer, fieldsep);
+ joinarray(ne->n_aliases, *buffer, COMMA) ; strcat(*buffer, fieldsep);
+ strcat(*buffer, nAddrType); strcat(*buffer, fieldsep);
+ strcat(*buffer, nNet); strcat(*buffer, fieldsep);
+
+ return (0);
+}
+
+
+
+/*
+ * int irp_unmarshall_nw(struct nwent *ne, char *buffer)
+ *
+ * notes:
+ *
+ * See note up top.
+ *
+ * return:
+ *
+ * 0 on success and -1 on failure.
+ *
+ */
+
+int
+irp_unmarshall_nw(struct nwent *ne, char *buffer) {
+ char *p, *q;
+ int naddrtype;
+ long nnet;
+ int bits;
+ char *name = NULL;
+ char **aliases = NULL;
+ char tmpbuf[24];
+ char *tb;
+ char fieldsep = ':';
+ int myerrno = EINVAL;
+
+ if (ne == NULL || buffer == NULL) {
+ goto error;
+ }
+
+ p = buffer;
+
+ /* n_name field */
+ name = NULL;
+ if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) {
+ goto error;
+ }
+
+
+ /* n_aliases field. Aliases are separated by commas */
+ q = strchr(p, fieldsep);
+ if (q == NULL) {
+ goto error;
+ }
+ aliases = splitarray(p, q, COMMA);
+ if (aliases == NULL) {
+ myerrno = errno;
+ goto error;
+ }
+ p = q + 1;
+
+
+ /* h_addrtype field */
+ tb = tmpbuf;
+ if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
+ strlen(tb) == 0) {
+ goto error;
+ }
+ if (strcmp(tmpbuf, "AF_INET") == 0)
+ naddrtype = AF_INET;
+ else if (strcmp(tmpbuf, "AF_INET6") == 0)
+ naddrtype = AF_INET6;
+ else
+ goto error;
+
+
+ /* n_net field */
+ tb = tmpbuf;
+ if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
+ strlen(tb) == 0) {
+ goto error;
+ }
+ nnet = 0;
+ bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet);
+ if (bits < 0) {
+ goto error;
+ }
+
+ /* nnet = ntohl(nnet); */ /* keep in network order for nwent */
+
+ ne->n_name = name;
+ ne->n_aliases = aliases;
+ ne->n_addrtype = naddrtype;
+ ne->n_length = bits;
+ ne->n_addr = malloc(sizeof nnet);
+ if (ne->n_addr == NULL) {
+ goto error;
+ }
+
+ memcpy(ne->n_addr, &nnet, sizeof nnet);
+
+ return (0);
+
+ error:
+ errno = myerrno;
+
+ if (name != NULL) free(name);
+ free_array(aliases, 0);
+
+ return (-1);
+}
+
+
+/* ------------------------- struct nwent ------------------------- */
+
+
+/* +++++++++++++++++++++++++ struct netent +++++++++++++++++++++++++ */
+
+
+/*
+ * int irp_marshall_ne(struct netent *ne, char **buffer, size_t *len)
+ *
+ * notes:
+ *
+ * See at top.
+ *
+ * return:
+ *
+ * 0 on success and -1 on failure.
+ *
+ */
+
+int
+irp_marshall_ne(struct netent *ne, char **buffer, size_t *len) {
+ size_t need = 1; /* for null byte */
+ char nAddrType[24];
+ char nNet[MAXPADDRSIZE];
+ const char *fieldsep = COLONSTR;
+ long nval;
+
+ if (ne == NULL || len == NULL) {
+ return (-1);
+ }
+
+ strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype));
+
+ nval = htonl(ne->n_net);
+ if (inet_ntop(ne->n_addrtype, &nval, nNet, sizeof nNet) == NULL) {
+ return (-1);
+ }
+
+ need += strlen(ne->n_name) + 1;
+ need += joinlength(ne->n_aliases) + 1;
+ need += strlen(nAddrType) + 1;
+ need += strlen(nNet) + 1;
+
+ if (buffer == NULL) {
+ *len = need;
+ return (0);
+ }
+
+ if (*buffer != NULL && need > *len) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (*buffer == NULL) {
+ need += 2; /* for CRLF */
+ *buffer = memget(need);
+ if (*buffer == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ *len = need;
+ }
+
+ strcpy(*buffer, ne->n_name); strcat(*buffer, fieldsep);
+ joinarray(ne->n_aliases, *buffer, COMMA) ; strcat(*buffer, fieldsep);
+ strcat(*buffer, nAddrType); strcat(*buffer, fieldsep);
+ strcat(*buffer, nNet); strcat(*buffer, fieldsep);
+
+ return (0);
+}
+
+
+
+/*
+ * int irp_unmarshall_ne(struct netent *ne, char *buffer)
+ *
+ * notes:
+ *
+ * See note up top.
+ *
+ * return:
+ *
+ * 0 on success and -1 on failure.
+ *
+ */
+
+int
+irp_unmarshall_ne(struct netent *ne, char *buffer) {
+ char *p, *q;
+ int naddrtype;
+ long nnet;
+ int bits;
+ char *name = NULL;
+ char **aliases = NULL;
+ char tmpbuf[24];
+ char *tb;
+ char fieldsep = ':';
+ int myerrno = EINVAL;
+
+ if (ne == NULL || buffer == NULL) {
+ goto error;
+ }
+
+ p = buffer;
+
+ /* n_name field */
+ name = NULL;
+ if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) {
+ goto error;
+ }
+
+
+ /* n_aliases field. Aliases are separated by commas */
+ q = strchr(p, fieldsep);
+ if (q == NULL) {
+ goto error;
+ }
+ aliases = splitarray(p, q, COMMA);
+ if (aliases == NULL) {
+ myerrno = errno;
+ goto error;
+ }
+ p = q + 1;
+
+
+ /* h_addrtype field */
+ tb = tmpbuf;
+ if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
+ strlen(tb) == 0) {
+ goto error;
+ }
+ if (strcmp(tmpbuf, "AF_INET") == 0)
+ naddrtype = AF_INET;
+ else if (strcmp(tmpbuf, "AF_INET6") == 0)
+ naddrtype = AF_INET6;
+ else
+ goto error;
+
+
+ /* n_net field */
+ tb = tmpbuf;
+ if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
+ strlen(tb) == 0) {
+ goto error;
+ }
+ bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet);
+ if (bits < 0) {
+ goto error;
+ }
+ nnet = ntohl(nnet);
+
+ ne->n_name = name;
+ ne->n_aliases = aliases;
+ ne->n_addrtype = naddrtype;
+ ne->n_net = nnet;
+
+ return (0);
+
+ error:
+ errno = myerrno;
+
+ if (name != NULL) free(name);
+ free_array(aliases, 0);
+
+ return (-1);
+}
+
+
+/* ------------------------- struct netent ------------------------- */
+
+
+/* =========================================================================== */
+
+
+/*
+ * static char ** splitarray(const char *buffer, const char *buffend, char delim)
+ *
+ * notes:
+ *
+ * Split a delim separated astring. Not allowed
+ * to have two delims next to each other. BUFFER points to begining of
+ * string, BUFFEND points to one past the end of the string
+ * (i.e. points at where the null byte would be if null
+ * terminated).
+ *
+ * return:
+ *
+ * Returns a malloced array of pointers, each pointer pointing to a
+ * malloced string. If BUFEER is an empty string, then return values is
+ * array of 1 pointer that is NULL. Returns NULL on failure.
+ *
+ */
+
+static char **
+splitarray(const char *buffer, const char *buffend, char delim) {
+ const char *p, *q;
+ int count = 0;
+ char **arr = NULL;
+ char **aptr;
+
+ if (buffend < buffer)
+ return (NULL);
+ else if (buffend > buffer && *buffer == delim)
+ return (NULL);
+ else if (buffend > buffer && *(buffend - 1) == delim)
+ return (NULL);
+
+ /* count the number of field and make sure none are empty */
+ if (buffend > buffer + 1) {
+ for (count = 1, q = buffer ; q != buffend ; q++) {
+ if (*q == delim) {
+ if (q > buffer && (*(q - 1) == delim)) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ count++;
+ }
+ }
+ }
+
+ if (count > 0) {
+ count++ ; /* for NULL at end */
+ aptr = arr = malloc(count * sizeof (char *));
+ if (aptr == NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+
+ memset(arr, 0x0, count * sizeof (char *));
+ for (p = buffer ; p < buffend ; p++) {
+ for (q = p ; *q != delim && q != buffend ; q++)
+ /* nothing */;
+ *aptr = strndup(p, q - p);
+
+ p = q;
+ aptr++;
+ }
+ *aptr = NULL;
+ } else {
+ arr = malloc(sizeof (char *));
+ if (arr == NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+
+ *arr = NULL;
+ }
+
+ return (arr);
+}
+
+
+
+
+/*
+ * static size_t joinlength(char * const *argv)
+ *
+ * return:
+ *
+ * the number of bytes in all the arrays pointed at
+ * by argv, including their null bytes(which will usually be turned
+ * into commas).
+ *
+ *
+ */
+
+static size_t
+joinlength(char * const *argv) {
+ int len = 0;
+
+ while (argv && *argv) {
+ len += (strlen(*argv) + 1);
+ argv++;
+ }
+
+ return (len);
+}
+
+
+
+/*
+ * int joinarray(char * const *argv, char *buffer, char delim)
+ *
+ * notes:
+ *
+ * Copy all the ARGV strings into the end of BUFFER
+ * separating them with DELIM. BUFFER is assumed to have
+ * enough space to hold everything and to be already null-terminated.
+ *
+ * return:
+ *
+ * 0 unless argv or buffer is NULL.
+ *
+ *
+ */
+
+static int
+joinarray(char * const *argv, char *buffer, char delim) {
+ char * const *p;
+ char sep[2];
+
+ if (argv == NULL || buffer == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ sep[0] = delim;
+ sep[1] = 0x0;
+
+ for (p = argv ; *p != NULL ; p++) {
+ strcat(buffer, *p);
+ if (*(p + 1) != NULL) {
+ strcat(buffer, sep);
+ }
+ }
+
+ return (0);
+}
+
+
+/*
+ * static char * getfield(char **res, size_t reslen, char **ptr, char delim)
+ *
+ * notes:
+ *
+ * Stores in *RES, which is a buffer of length RESLEN, a
+ * copy of the bytes from *PTR up to and including the first
+ * instance of DELIM. If *RES is NULL, then it will be
+ * assigned a malloced buffer to hold the copy. *PTR is
+ * modified to point at the found delimiter.
+ *
+ * return:
+ *
+ * If there was no delimiter, then NULL is returned,
+ * otherewise *RES is returned.
+ *
+ */
+
+static char *
+getfield(char **res, size_t reslen, char **ptr, char delim) {
+ char *q;
+
+ if (res == NULL || ptr == NULL || *ptr == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ q = strchr(*ptr, delim);
+
+ if (q == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ } else {
+ if (*res == NULL) {
+ *res = strndup(*ptr, q - *ptr);
+ } else {
+ if ((size_t)(q - *ptr + 1) > reslen) { /* to big for res */
+ errno = EINVAL;
+ return (NULL);
+ } else {
+ strncpy(*res, *ptr, q - *ptr);
+ (*res)[q - *ptr] = 0x0;
+ }
+ }
+ *ptr = q + 1;
+ }
+
+ return (*res);
+}
+
+
+
+
+
+
+/*
+ * static char * strndup(const char *str, size_t len)
+ *
+ * notes:
+ *
+ * like strdup, except do len bytes instead of the whole string. Always
+ * null-terminates.
+ *
+ * return:
+ *
+ * The newly malloced string.
+ *
+ */
+
+static char *
+strndup(const char *str, size_t len) {
+ char *p = malloc(len + 1);
+
+ if (p == NULL)
+ return (NULL);
+ strncpy(p, str, len);
+ p[len] = 0x0;
+ return (p);
+}
+
+
+#if WANT_MAIN
+
+/*
+ * static int strcmp_nws(const char *a, const char *b)
+ *
+ * notes:
+ *
+ * do a strcmp, except uneven lengths of whitespace compare the same
+ *
+ * return:
+ *
+ */
+
+static int
+strcmp_nws(const char *a, const char *b) {
+ while (*a && *b) {
+ if (isspace(*a) && isspace(*b)) {
+ do {
+ a++;
+ } while (isspace(*a));
+ do {
+ b++;
+ } while (isspace(*b));
+ }
+ if (*a < *b)
+ return (-1);
+ else if (*a > *b)
+ return (1);
+
+ a++;
+ b++;;
+ }
+
+ if (*a == *b)
+ return (0);
+ else if (*a > *b)
+ return (1);
+ else
+ return (-1);
+}
+
+#endif
+
+
+
+
+
+/*
+ * static void free_array(char **argv, size_t entries)
+ *
+ * notes:
+ *
+ * Free argv and each of the pointers inside it. The end of
+ * the array is when a NULL pointer is found inside. If
+ * entries is > 0, then NULL pointers inside the array do
+ * not indicate the end of the array.
+ *
+ */
+
+static void
+free_array(char **argv, size_t entries) {
+ char **p = argv;
+ int useEntries = (entries > 0);
+
+ if (argv == NULL)
+ return;
+
+ while ((useEntries && entries > 0) || *p) {
+ if (*p)
+ free(*p);
+ p++;
+ if (useEntries)
+ entries--;
+ }
+ free(argv);
+}
+
+
+
+
+
+/* ************************************************** */
+
+#if WANT_MAIN
+
+/* takes an option to indicate what sort of marshalling(read the code) and
+ an argument. If the argument looks like a marshalled buffer(has a ':'
+ embedded) then it's unmarshalled and the remarshalled and the new string
+ is compared to the old one.
+*/
+
+int
+main(int argc, char **argv) {
+ char buffer[1024];
+ char *b = &buffer[0];
+ size_t len = sizeof buffer;
+ char option;
+
+ if (argc < 2 || argv[1][0] != '-')
+ exit(1);
+
+ option = argv[1][1];
+ argv++;
+ argc--;
+
+
+#if 0
+ {
+ char buff[10];
+ char *p = argv[1], *q = &buff[0];
+
+ while (getfield(&q, sizeof buff, &p, ':') != NULL) {
+ printf("field: \"%s\"\n", q);
+ p++;
+ }
+ printf("p is now \"%s\"\n", p);
+ }
+#endif
+
+#if 0
+ {
+ char **x = splitarray(argv[1], argv[1] + strlen(argv[1]),
+ argv[2][0]);
+ char **p;
+
+ if (x == NULL)
+ printf("split failed\n");
+
+ for (p = x ; p != NULL && *p != NULL ; p++) {
+ printf("\"%s\"\n", *p);
+ }
+ }
+#endif
+
+#if 1
+ switch(option) {
+ case 'n': {
+ struct nwent ne;
+ int i;
+
+ if (strchr(argv[1], ':') != NULL) {
+ if (irp_unmarshall_nw(&ne, argv[1]) != 0) {
+ printf("Unmarhsalling failed\n");
+ exit(1);
+ }
+
+ printf("Name: \"%s\"\n", ne.n_name);
+ printf("Aliases:");
+ for (i = 0 ; ne.n_aliases[i] != NULL ; i++)
+ printf("\n\t\"%s\"", ne.n_aliases[i]);
+ printf("\nAddrtype: %s\n", ADDR_T_STR(ne.n_addrtype));
+ inet_net_ntop(ne.n_addrtype, ne.n_addr, ne.n_length,
+ buffer, sizeof buffer);
+ printf("Net: \"%s\"\n", buffer);
+ *((long*)ne.n_addr) = htonl(*((long*)ne.n_addr));
+ inet_net_ntop(ne.n_addrtype, ne.n_addr, ne.n_length,
+ buffer, sizeof buffer);
+ printf("Corrected Net: \"%s\"\n", buffer);
+ } else {
+ struct netent *np1 = getnetbyname(argv[1]);
+ ne.n_name = np1->n_name;
+ ne.n_aliases = np1->n_aliases;
+ ne.n_addrtype = np1->n_addrtype;
+ ne.n_addr = &np1->n_net;
+ ne.n_length = (IN_CLASSA(np1->n_net) ?
+ 8 :
+ (IN_CLASSB(np1->n_net) ?
+ 16 :
+ (IN_CLASSC(np1->n_net) ?
+ 24 : -1)));
+ np1->n_net = htonl(np1->n_net);
+ if (irp_marshall_nw(&ne, &b, &len) != 0) {
+ printf("Marshalling failed\n");
+ }
+ printf("%s\n", b);
+ }
+ break;
+ }
+
+
+ case 'r': {
+ char **hosts, **users, **domains;
+ size_t entries;
+ int i;
+ char *buff;
+ size_t size;
+ char *ngname;
+
+ if (strchr(argv[1], '(') != NULL) {
+ if (irp_unmarshall_ng(&ngname, &entries,
+ &hosts, &users, &domains,
+ argv[1]) != 0) {
+ printf("unmarshall failed\n");
+ exit(1);
+ }
+
+#define STRVAL(x) (x == NULL ? "*" : x)
+
+ printf("%s {\n", ngname);
+ for (i = 0 ; i < entries ; i++)
+ printf("\t\"%s\" : \"%s\" : \"%s\"\n",
+ STRVAL(hosts[i]),
+ STRVAL(users[i]),
+ STRVAL(domains[i]));
+ printf("}\n\n\n");
+
+
+ irp_marshall_ng_start(ngname, NULL, &size);
+ for (i = 0 ; i < entries ; i++)
+ irp_marshall_ng_next(hosts[i], users[i],
+ domains[i], NULL, &size);
+ irp_marshall_ng_end(NULL, &size);
+
+ buff = malloc(size);
+
+ irp_marshall_ng_start(ngname, buff, &size);
+ for (i = 0 ; i < entries ; i++) {
+ if (irp_marshall_ng_next(hosts[i], users[i],
+ domains[i], buff,
+ &size) != 0)
+ printf("next marshalling failed.\n");
+ }
+ irp_marshall_ng_end(buff, &size);
+
+ if (strcmp_nws(argv[1], buff) != 0) {
+ printf("compare failed:\n\t%s\n\t%s\n",
+ buffer, argv[1]);
+ } else {
+ printf("compare ok\n");
+ }
+ } else {
+ char *h, *u, *d, *buff;
+ size_t size;
+
+ /* run through two times. First to figure out how
+ much of a buffer we need. Second to do the
+ actual marshalling */
+
+ setnetgrent(argv[1]);
+ irp_marshall_ng_start(argv[1], NULL, &size);
+ while (getnetgrent(&h, &u, &d) == 1)
+ irp_marshall_ng_next(h, u, d, NULL, &size);
+ irp_marshall_ng_end(NULL, &size);
+ endnetgrent(argv[1]);
+
+ buff = malloc(size);
+
+ setnetgrent(argv[1]);
+ if (irp_marshall_ng_start(argv[1], buff, &size) != 0)
+ printf("Marshalling start failed\n");
+
+ while (getnetgrent(&h, &u, &d) == 1) {
+ if (irp_marshall_ng_next(h, u, d, buff, &size)
+ != 0) {
+ printf("Marshalling failed\n");
+ }
+ }
+
+ irp_marshall_ng_end(buff, &size);
+ endnetgrent();
+
+ printf("success: %s\n", buff);
+ }
+ break;
+ }
+
+
+
+ case 'h': {
+ struct hostent he, *hp;
+ int i;
+
+
+ if (strchr(argv[1], '@') != NULL) {
+ if (irp_unmarshall_ho(&he, argv[1]) != 0) {
+ printf("unmarshall failed\n");
+ exit(1);
+ }
+
+ printf("Host: \"%s\"\nAliases:", he.h_name);
+ for (i = 0 ; he.h_aliases[i] != NULL ; i++)
+ printf("\n\t\t\"%s\"", he.h_aliases[i]);
+ printf("\nAddr Type: \"%s\"\n",
+ ADDR_T_STR(he.h_addrtype));
+ printf("Length: %d\nAddresses:", he.h_length);
+ for (i = 0 ; he.h_addr_list[i] != 0 ; i++) {
+ inet_ntop(he.h_addrtype, he.h_addr_list[i],
+ buffer, sizeof buffer);
+ printf("\n\t\"%s\"\n", buffer);
+ }
+ printf("\n\n");
+
+ irp_marshall_ho(&he, &b, &len);
+ if (strcmp(argv[1], buffer) != 0) {
+ printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
+ buffer, argv[1]);
+ } else {
+ printf("compare ok\n");
+ }
+ } else {
+ if ((hp = gethostbyname(argv[1])) == NULL) {
+ perror("gethostbyname");
+ printf("\"%s\"\n", argv[1]);
+ exit(1);
+ }
+
+ if (irp_marshall_ho(hp, &b, &len) != 0) {
+ printf("irp_marshall_ho failed\n");
+ exit(1);
+ }
+
+ printf("success: \"%s\"\n", buffer);
+ }
+ break;
+ }
+
+
+ case 's': {
+ struct servent *sv;
+ struct servent sv1;
+
+ if (strchr(argv[1], ':') != NULL) {
+ sv = &sv1;
+ memset(sv, 0xef, sizeof (struct servent));
+ if (irp_unmarshall_sv(sv, argv[1]) != 0) {
+ printf("unmarshall failed\n");
+
+ }
+
+ irp_marshall_sv(sv, &b, &len);
+ if (strcmp(argv[1], buffer) != 0) {
+ printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
+ buffer, argv[1]);
+ } else {
+ printf("compare ok\n");
+ }
+ } else {
+ if ((sv = getservbyname(argv[1], argv[2])) == NULL) {
+ perror("getservent");
+ exit(1);
+ }
+
+ if (irp_marshall_sv(sv, &b, &len) != 0) {
+ printf("irp_marshall_sv failed\n");
+ exit(1);
+ }
+
+ printf("success: \"%s\"\n", buffer);
+ }
+ break;
+ }
+
+ case 'g': {
+ struct group *gr;
+ struct group gr1;
+
+ if (strchr(argv[1], ':') != NULL) {
+ gr = &gr1;
+ memset(gr, 0xef, sizeof (struct group));
+ if (irp_unmarshall_gr(gr, argv[1]) != 0) {
+ printf("unmarshall failed\n");
+
+ }
+
+ irp_marshall_gr(gr, &b, &len);
+ if (strcmp(argv[1], buffer) != 0) {
+ printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
+ buffer, argv[1]);
+ } else {
+ printf("compare ok\n");
+ }
+ } else {
+ if ((gr = getgrnam(argv[1])) == NULL) {
+ perror("getgrnam");
+ exit(1);
+ }
+
+ if (irp_marshall_gr(gr, &b, &len) != 0) {
+ printf("irp_marshall_gr failed\n");
+ exit(1);
+ }
+
+ printf("success: \"%s\"\n", buffer);
+ }
+ break;
+ }
+
+
+ case 'p': {
+ struct passwd *pw;
+ struct passwd pw1;
+
+ if (strchr(argv[1], ':') != NULL) {
+ pw = &pw1;
+ memset(pw, 0xef, sizeof (*pw));
+ if (irp_unmarshall_pw(pw, argv[1]) != 0) {
+ printf("unmarshall failed\n");
+ exit(1);
+ }
+
+ printf("User: \"%s\"\nPasswd: \"%s\"\nUid: %ld\nGid: %ld\n",
+ pw->pw_name, pw->pw_passwd, (long)pw->pw_uid,
+ (long)pw->pw_gid);
+ printf("Class: \"%s\"\nChange: %ld\nGecos: \"%s\"\n",
+ pw->pw_class, (long)pw->pw_change, pw->pw_gecos);
+ printf("Shell: \"%s\"\nDirectory: \"%s\"\n",
+ pw->pw_shell, pw->pw_dir);
+
+ pw = getpwnam(pw->pw_name);
+ irp_marshall_pw(pw, &b, &len);
+ if (strcmp(argv[1], buffer) != 0) {
+ printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
+ buffer, argv[1]);
+ } else {
+ printf("compare ok\n");
+ }
+ } else {
+ if ((pw = getpwnam(argv[1])) == NULL) {
+ perror("getpwnam");
+ exit(1);
+ }
+
+ if (irp_marshall_pw(pw, &b, &len) != 0) {
+ printf("irp_marshall_pw failed\n");
+ exit(1);
+ }
+
+ printf("success: \"%s\"\n", buffer);
+ }
+ break;
+ }
+
+ default:
+ printf("Wrong option: %c\n", option);
+ break;
+ }
+
+#endif
+
+ return (0);
+}
+
+#endif
diff --git a/usr/src/lib/libresolv2/common/irs/irs_data.c b/usr/src/lib/libresolv2/common/irs/irs_data.c
new file mode 100644
index 0000000000..14d965bf0c
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/irs_data.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: irs_data.c,v 1.22 2003/06/20 07:09:33 marka Exp $";
+#endif
+
+#include "port_before.h"
+
+#ifndef __BIND_NOSTATIC
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+#include <isc/memcluster.h>
+#include <stdlib.h>
+
+#ifdef DO_PTHREADS
+#include <pthread.h>
+#endif
+
+#include <irs.h>
+
+#include "port_after.h"
+
+#include "irs_data.h"
+#undef _res
+#undef h_errno
+
+extern struct __res_state _res;
+extern int h_errno;
+
+#ifdef DO_PTHREADS
+static pthread_key_t key;
+static int once = 0;
+#else
+static struct net_data *net_data;
+#endif
+
+void
+irs_destroy(void) {
+#ifndef DO_PTHREADS
+ if (net_data != NULL)
+ net_data_destroy(net_data);
+ net_data = NULL;
+#endif
+}
+
+void
+net_data_destroy(void *p) {
+ struct net_data *net_data = p;
+
+ res_ndestroy(net_data->res);
+ if (net_data->gr != NULL) {
+ (*net_data->gr->close)(net_data->gr);
+ net_data->gr = NULL;
+ }
+ if (net_data->pw != NULL) {
+ (*net_data->pw->close)(net_data->pw);
+ net_data->pw = NULL;
+ }
+ if (net_data->sv != NULL) {
+ (*net_data->sv->close)(net_data->sv);
+ net_data->sv = NULL;
+ }
+ if (net_data->pr != NULL) {
+ (*net_data->pr->close)(net_data->pr);
+ net_data->pr = NULL;
+ }
+ if (net_data->ho != NULL) {
+ (*net_data->ho->close)(net_data->ho);
+ net_data->ho = NULL;
+ }
+ if (net_data->nw != NULL) {
+ (*net_data->nw->close)(net_data->nw);
+ net_data->nw = NULL;
+ }
+ if (net_data->ng != NULL) {
+ (*net_data->ng->close)(net_data->ng);
+ net_data->ng = NULL;
+ }
+ if (net_data->ho_data != NULL) {
+ free(net_data->ho_data);
+ net_data->ho_data = NULL;
+ }
+ if (net_data->nw_data != NULL) {
+ free(net_data->nw_data);
+ net_data->nw_data = 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) {
+ memput(net_data, sizeof (struct net_data));
+ 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) {
+ (*net_data->irs->close)(net_data->irs);
+ memput(net_data, sizeof (struct net_data));
+ return (NULL);
+ }
+
+ if ((net_data->res->options & RES_INIT) == 0 &&
+ res_ninit(net_data->res) == -1) {
+ (*net_data->irs->close)(net_data->irs);
+ memput(net_data, sizeof (struct net_data));
+ return (NULL);
+ }
+
+ return (net_data);
+}
+
+
+
+void
+net_data_minimize(struct net_data *net_data) {
+ res_nclose(net_data->res);
+}
+
+#ifdef _REENTRANT
+struct __res_state *
+__res_state(void) {
+ /* NULL param here means use the default config file. */
+ struct net_data *net_data = net_data_init(NULL);
+ if (net_data && net_data->res)
+ return (net_data->res);
+
+ return (&_res);
+}
+#endif
+
+int *
+__h_errno(void) {
+ /* NULL param here means use the default config file. */
+ struct net_data *net_data = net_data_init(NULL);
+ if (net_data && net_data->res)
+ return (&net_data->res->res_h_errno);
+ return (&h_errno);
+}
+
+void
+__h_errno_set(struct __res_state *res, int err) {
+
+ h_errno = res->res_h_errno = err;
+}
+
+#endif /*__BIND_NOSTATIC*/
diff --git a/usr/src/lib/libresolv2/common/irs/irs_data.h b/usr/src/lib/libresolv2/common/irs/irs_data.h
new file mode 100644
index 0000000000..4c5fdf3c64
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/irs_data.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * $Id: irs_data.h,v 1.12 1999/01/18 07:46:55 vixie Exp $
+ */
+
+#ifndef __BIND_NOSTATIC
+
+#ifndef _IRS_DATA_H
+#define _IRS_DATA_H
+
+#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 /* _IR_DATA_H */
+
+#endif /*__BIND_NOSTATIC*/
diff --git a/usr/src/lib/libresolv2/common/irs/irs_p.h b/usr/src/lib/libresolv2/common/irs/irs_p.h
new file mode 100644
index 0000000000..64043b90aa
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/irs_p.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * $Id: irs_p.h,v 1.8 1999/01/08 19:24:42 vixie Exp $
+ */
+
+#ifndef _IRS_P_H_INCLUDED
+#define _IRS_P_H_INCLUDED
+
+#include <stdio.h>
+
+#include "pathnames.h"
+
+#define IRS_SV_MAXALIASES 35
+
+struct lcl_sv {
+ FILE * fp;
+ char line[BUFSIZ+1];
+ struct servent serv;
+ char * serv_aliases[IRS_SV_MAXALIASES];
+};
+
+#define irs_nul_ng __irs_nul_ng
+#define map_v4v6_address __map_v4v6_address
+#define make_group_list __make_group_list
+#define irs_lclsv_fnxt __irs_lclsv_fnxt
+
+extern void map_v4v6_address(const char *src, char *dst);
+extern int make_group_list(struct irs_gr *, const char *,
+ gid_t, gid_t *, int *);
+extern struct irs_ng * irs_nul_ng(struct irs_acc *);
+extern struct servent * irs_lclsv_fnxt(struct lcl_sv *);
+
+#endif
diff --git a/usr/src/lib/libresolv2/common/irs/lcl.c b/usr/src/lib/libresolv2/common/irs/lcl.c
new file mode 100644
index 0000000000..3d86033209
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/lcl.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: lcl.c,v 1.17 2001/05/29 05:49:02 marka Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <isc/memcluster.h>
+
+#include <irs.h>
+
+#include "port_after.h"
+
+#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/usr/src/lib/libresolv2/common/irs/lcl_gr.c b/usr/src/lib/libresolv2/common/irs/lcl_gr.c
new file mode 100644
index 0000000000..0a655f0d8f
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/lcl_gr.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: lcl_gr.c,v 1.26 2001/05/29 05:49:03 marka Exp $";
+/* from getgrent.c 8.2 (Berkeley) 3/21/94"; */
+/* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */
+#endif /* LIBC_SCCS and not lint */
+
+/* extern */
+
+#include "port_before.h"
+
+#ifndef WANT_IRS_PW
+static int __bind_irs_gr_unneeded;
+#else
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <irs.h>
+#include <isc/memcluster.h>
+
+#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/usr/src/lib/libresolv2/common/irs/lcl_ho.c b/usr/src/lib/libresolv2/common/irs/lcl_ho.c
new file mode 100644
index 0000000000..cebf63ef08
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/lcl_ho.c
@@ -0,0 +1,629 @@
+/*
+ * Copyright 1997-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* from gethostnamadr.c 8.1 (Berkeley) 6/4/93 */
+/* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: lcl_ho.c,v 1.26 2001/05/29 05:49:04 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/* Imports. */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <irs.h>
+#include <isc/memcluster.h>
+
+#include "port_after.h"
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+#include "../../../libnsl/include/nsl_stdio_prv.h"
+#endif
+
+#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 {
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+ __NSL_FILE * fp;
+#else
+ FILE * fp;
+#endif
+ 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)
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+ (void) __nsl_fclose(pvt->fp);
+#else
+ (void) fclose(pvt->fp);
+#endif
+ 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:
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+ if (!(p = __nsl_fgets(bufp + offset, bufsiz - offset, pvt->fp))) {
+#else
+ if (!(p = fgets(bufp + offset, bufsiz - offset, pvt->fp))) {
+#endif
+ RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
+ if (dbuf)
+ free(dbuf);
+ return (NULL);
+ }
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+ if (!strchr(p, '\n') && !__nsl_feof(pvt->fp)) {
+#else
+ if (!strchr(p, '\n') && !feof(pvt->fp)) {
+#endif
+#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 */
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+ while ((c = __nsl_getc(pvt->fp)) != EOF)
+#else
+ while ((c = getc(pvt->fp)) != EOF)
+#endif
+ if (c == '\n')
+ break;
+ if (c != EOF)
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+ __nsl_ungetc(c, pvt->fp);
+#else
+ ungetc(c, pvt->fp);
+#endif
+ }
+ 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;
+
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+ if (pvt->fp) {
+ if (__nsl_fseek(pvt->fp, 0L, SEEK_SET) == 0)
+ return;
+ (void)__nsl_fclose(pvt->fp);
+ }
+ if (!(pvt->fp = __nsl_fopen(_PATH_HOSTS, "r")))
+ return;
+ if (fcntl(__nsl_fileno(pvt->fp), F_SETFD, 1) < 0) {
+ (void)__nsl_fclose(pvt->fp);
+ pvt->fp = NULL;
+ }
+#else
+ 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;
+ }
+#endif
+
+}
+
+static void
+ho_minimize(struct irs_ho *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (pvt->fp != NULL) {
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+ (void)__nsl_fclose(pvt->fp);
+#else
+ (void)fclose(pvt->fp);
+#endif
+ 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/usr/src/lib/libresolv2/common/irs/lcl_ng.c b/usr/src/lib/libresolv2/common/irs/lcl_ng.c
new file mode 100644
index 0000000000..05adcdf9f9
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/lcl_ng.c
@@ -0,0 +1,451 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: lcl_ng.c,v 1.17 2001/05/29 05:49:05 marka Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <irs.h>
+#include <isc/memcluster.h>
+
+#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/usr/src/lib/libresolv2/common/irs/lcl_nw.c b/usr/src/lib/libresolv2/common/irs/lcl_nw.c
new file mode 100644
index 0000000000..38a7d584a3
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/lcl_nw.c
@@ -0,0 +1,378 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: lcl_nw.c,v 1.22 2001/05/29 05:49:07 marka Exp $";
+/* from getgrent.c 8.2 (Berkeley) 3/21/94"; */
+/* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */
+#endif /* LIBC_SCCS and not lint */
+
+/* Imports */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <irs.h>
+#include <isc/memcluster.h>
+
+#include "port_after.h"
+
+#include <isc/misc.h>
+#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/usr/src/lib/libresolv2/common/irs/lcl_p.h b/usr/src/lib/libresolv2/common/irs/lcl_p.h
new file mode 100644
index 0000000000..061ec1b8ad
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/lcl_p.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * $Id: lcl_p.h,v 1.7 1999/01/08 19:24:51 vixie Exp $
+ */
+
+/*
+ * lcl_p.h - private include file for the local accessor functions.
+ */
+
+#ifndef _LCL_P_H_INCLUDED
+#define _LCL_P_H_INCLUDED
+
+/*
+ * Object state.
+ */
+struct lcl_p {
+ struct __res_state * res;
+ void (*free_res) __P((void *));
+};
+
+/*
+ * Externs.
+ */
+
+extern struct irs_acc * irs_lcl_acc __P((const char *));
+extern struct irs_gr * irs_lcl_gr __P((struct irs_acc *));
+extern struct irs_pw * irs_lcl_pw __P((struct irs_acc *));
+extern struct irs_sv * irs_lcl_sv __P((struct irs_acc *));
+extern struct irs_pr * irs_lcl_pr __P((struct irs_acc *));
+extern struct irs_ho * irs_lcl_ho __P((struct irs_acc *));
+extern struct irs_nw * irs_lcl_nw __P((struct irs_acc *));
+extern struct irs_ng * irs_lcl_ng __P((struct irs_acc *));
+
+#endif /*_LCL_P_H_INCLUDED*/
diff --git a/usr/src/lib/libresolv2/common/irs/lcl_pr.c b/usr/src/lib/libresolv2/common/irs/lcl_pr.c
new file mode 100644
index 0000000000..f6a8d312c9
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/lcl_pr.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: lcl_pr.c,v 1.18 1999/10/13 17:11:20 vixie Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/* extern */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <irs.h>
+#include <isc/memcluster.h>
+
+#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/usr/src/lib/libresolv2/common/irs/lcl_pw.c b/usr/src/lib/libresolv2/common/irs/lcl_pw.c
new file mode 100644
index 0000000000..5fa0d965e7
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/lcl_pw.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: lcl_pw.c,v 1.20 2001/05/29 05:49:08 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/* Extern */
+
+#include "port_before.h"
+
+#ifndef WANT_IRS_PW
+static int __bind_irs_pw_unneeded;
+#else
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <db.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <utmp.h>
+#include <unistd.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#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/usr/src/lib/libresolv2/common/irs/lcl_sv.c b/usr/src/lib/libresolv2/common/irs/lcl_sv.c
new file mode 100644
index 0000000000..afbdf3f3da
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/lcl_sv.c
@@ -0,0 +1,438 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: lcl_sv.c,v 1.22 2001/06/18 14:43:59 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/* extern */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#ifdef IRS_LCL_SV_DB
+#include <db.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <irs.h>
+#include <isc/memcluster.h>
+
+#include "port_after.h"
+
+#include "irs_p.h"
+#include "lcl_p.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/* Types */
+
+struct pvt {
+#ifdef IRS_LCL_SV_DB
+ DB * dbh;
+ int dbf;
+#endif
+ struct lcl_sv sv;
+};
+
+/* Forward */
+
+static void sv_close(struct irs_sv*);
+static struct servent * sv_next(struct irs_sv *);
+static struct servent * sv_byname(struct irs_sv *, const char *,
+ const char *);
+static struct servent * sv_byport(struct irs_sv *, int, const char *);
+static void sv_rewind(struct irs_sv *);
+static void sv_minimize(struct irs_sv *);
+/*global*/ struct servent * irs_lclsv_fnxt(struct lcl_sv *);
+#ifdef IRS_LCL_SV_DB
+static struct servent * sv_db_rec(struct lcl_sv *, DBT *, DBT *);
+#endif
+
+/* Portability */
+
+#ifndef SEEK_SET
+# define SEEK_SET 0
+#endif
+
+/* Public */
+
+struct irs_sv *
+irs_lcl_sv(struct irs_acc *this) {
+ struct irs_sv *sv;
+ struct pvt *pvt;
+
+ UNUSED(this);
+
+ if ((sv = memget(sizeof *sv)) == NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(sv, 0x5e, sizeof *sv);
+ if ((pvt = memget(sizeof *pvt)) == NULL) {
+ memput(sv, sizeof *sv);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pvt, 0, sizeof *pvt);
+ sv->private = pvt;
+ sv->close = sv_close;
+ sv->next = sv_next;
+ sv->byname = sv_byname;
+ sv->byport = sv_byport;
+ sv->rewind = sv_rewind;
+ sv->minimize = sv_minimize;
+ sv->res_get = NULL;
+ sv->res_set = NULL;
+#ifdef IRS_LCL_SV_DB
+ pvt->dbf = R_FIRST;
+#endif
+ return (sv);
+}
+
+/* Methods */
+
+static void
+sv_close(struct irs_sv *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+#ifdef IRS_LCL_SV_DB
+ if (pvt->dbh != NULL)
+ (*pvt->dbh->close)(pvt->dbh);
+#endif
+ if (pvt->sv.fp)
+ fclose(pvt->sv.fp);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
+}
+
+static struct servent *
+sv_byname(struct irs_sv *this, const char *name, const char *proto) {
+#ifdef IRS_LCL_SV_DB
+ struct pvt *pvt = (struct pvt *)this->private;
+#endif
+ struct servent *p;
+ char **cp;
+
+ sv_rewind(this);
+#ifdef IRS_LCL_SV_DB
+ if (pvt->dbh != NULL) {
+ DBT key, data;
+
+ /* Note that (sizeof "/") == 2. */
+ if ((strlen(name) + sizeof "/" + proto ? strlen(proto) : 0)
+ > sizeof pvt->sv.line)
+ goto try_local;
+ key.data = pvt->sv.line;
+ key.size = SPRINTF((pvt->sv.line, "%s/%s", name,
+ proto ? proto : "")) + 1;
+ if (proto != NULL) {
+ if ((*pvt->dbh->get)(pvt->dbh, &key, &data, 0) != 0)
+ return (NULL);
+ } else if ((*pvt->dbh->seq)(pvt->dbh, &key, &data, R_CURSOR)
+ != 0)
+ return (NULL);
+ return (sv_db_rec(&pvt->sv, &key, &data));
+ }
+ try_local:
+#endif
+
+ while ((p = sv_next(this))) {
+ if (strcmp(name, p->s_name) == 0)
+ goto gotname;
+ for (cp = p->s_aliases; *cp; cp++)
+ if (strcmp(name, *cp) == 0)
+ goto gotname;
+ continue;
+ gotname:
+ if (proto == NULL || strcmp(p->s_proto, proto) == 0)
+ break;
+ }
+ return (p);
+}
+
+static struct servent *
+sv_byport(struct irs_sv *this, int port, const char *proto) {
+#ifdef IRS_LCL_SV_DB
+ struct pvt *pvt = (struct pvt *)this->private;
+#endif
+ struct servent *p;
+
+ sv_rewind(this);
+#ifdef IRS_LCL_SV_DB
+ if (pvt->dbh != NULL) {
+ DBT key, data;
+ u_short *ports;
+
+ ports = (u_short *)pvt->sv.line;
+ ports[0] = 0;
+ ports[1] = port;
+ key.data = ports;
+ key.size = sizeof(u_short) * 2;
+ if (proto && *proto) {
+ strncpy((char *)ports + key.size, proto,
+ BUFSIZ - key.size);
+ key.size += strlen((char *)ports + key.size) + 1;
+ if ((*pvt->dbh->get)(pvt->dbh, &key, &data, 0) != 0)
+ return (NULL);
+ } else {
+ if ((*pvt->dbh->seq)(pvt->dbh, &key, &data, R_CURSOR)
+ != 0)
+ return (NULL);
+ }
+ return (sv_db_rec(&pvt->sv, &key, &data));
+ }
+#endif
+ while ((p = sv_next(this))) {
+ if (p->s_port != port)
+ continue;
+ if (proto == NULL || strcmp(p->s_proto, proto) == 0)
+ break;
+ }
+ return (p);
+}
+
+static void
+sv_rewind(struct irs_sv *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (pvt->sv.fp) {
+ if (fseek(pvt->sv.fp, 0L, SEEK_SET) == 0)
+ return;
+ (void)fclose(pvt->sv.fp);
+ pvt->sv.fp = NULL;
+ }
+#ifdef IRS_LCL_SV_DB
+ pvt->dbf = R_FIRST;
+ if (pvt->dbh != NULL)
+ return;
+ pvt->dbh = dbopen(_PATH_SERVICES_DB, O_RDONLY,O_RDONLY,DB_BTREE, NULL);
+ if (pvt->dbh != NULL) {
+ if (fcntl((*pvt->dbh->fd)(pvt->dbh), F_SETFD, 1) < 0) {
+ (*pvt->dbh->close)(pvt->dbh);
+ pvt->dbh = NULL;
+ }
+ return;
+ }
+#endif
+ if ((pvt->sv.fp = fopen(_PATH_SERVICES, "r")) == NULL)
+ return;
+ if (fcntl(fileno(pvt->sv.fp), F_SETFD, 1) < 0) {
+ (void)fclose(pvt->sv.fp);
+ pvt->sv.fp = NULL;
+ }
+}
+
+static struct servent *
+sv_next(struct irs_sv *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+#ifdef IRS_LCL_SV_DB
+ if (pvt->dbh == NULL && pvt->sv.fp == NULL)
+#else
+ if (pvt->sv.fp == NULL)
+#endif
+ sv_rewind(this);
+
+#ifdef IRS_LCL_SV_DB
+ if (pvt->dbh != NULL) {
+ DBT key, data;
+
+ while ((*pvt->dbh->seq)(pvt->dbh, &key, &data, pvt->dbf) == 0){
+ pvt->dbf = R_NEXT;
+ if (((char *)key.data)[0])
+ continue;
+ return (sv_db_rec(&pvt->sv, &key, &data));
+ }
+ }
+#endif
+
+ if (pvt->sv.fp == NULL)
+ return (NULL);
+ return (irs_lclsv_fnxt(&pvt->sv));
+}
+
+static void
+sv_minimize(struct irs_sv *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+#ifdef IRS_LCL_SV_DB
+ if (pvt->dbh != NULL) {
+ (*pvt->dbh->close)(pvt->dbh);
+ pvt->dbh = NULL;
+ }
+#endif
+ if (pvt->sv.fp != NULL) {
+ (void)fclose(pvt->sv.fp);
+ pvt->sv.fp = NULL;
+ }
+}
+
+/* Quasipublic. */
+
+struct servent *
+irs_lclsv_fnxt(struct lcl_sv *sv) {
+ char *p, *cp, **q;
+
+ again:
+ if ((p = fgets(sv->line, BUFSIZ, sv->fp)) == NULL)
+ return (NULL);
+ if (*p == '#')
+ goto again;
+ sv->serv.s_name = p;
+ while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#')
+ ++p;
+ if (*p == '\0' || *p == '#' || *p == '\n')
+ goto again;
+ *p++ = '\0';
+ while (*p == ' ' || *p == '\t')
+ p++;
+ if (*p == '\0' || *p == '#' || *p == '\n')
+ goto again;
+ sv->serv.s_port = htons((u_short)strtol(p, &cp, 10));
+ if (cp == p || (*cp != '/' && *cp != ','))
+ goto again;
+ p = cp + 1;
+ sv->serv.s_proto = p;
+
+ q = sv->serv.s_aliases = sv->serv_aliases;
+
+ while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#')
+ ++p;
+
+ while (*p == ' ' || *p == '\t') {
+ *p++ = '\0';
+ while (*p == ' ' || *p == '\t')
+ ++p;
+ if (*p == '\0' || *p == '#' || *p == '\n')
+ break;
+ if (q < &sv->serv_aliases[IRS_SV_MAXALIASES - 1])
+ *q++ = p;
+ while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#')
+ ++p;
+ }
+
+ *p = '\0';
+ *q = NULL;
+ return (&sv->serv);
+}
+
+/* Private. */
+
+#ifdef IRS_LCL_SV_DB
+static struct servent *
+sv_db_rec(struct lcl_sv *sv, DBT *key, DBT *data) {
+ char *p, **q;
+ int n;
+
+ p = data->data;
+ p[data->size - 1] = '\0'; /* should be, but we depend on it */
+
+ if (((char *)key->data)[0] == '\0') {
+ if (key->size < sizeof(u_short)*2 || data->size < 2)
+ return (NULL);
+ sv->serv.s_port = ((u_short *)key->data)[1];
+ n = strlen(p) + 1;
+ if ((size_t)n > sizeof(sv->line)) {
+ n = sizeof(sv->line);
+ }
+ memcpy(sv->line, p, n);
+ sv->serv.s_name = sv->line;
+ if ((sv->serv.s_proto = strchr(sv->line, '/')) != NULL)
+ *(sv->serv.s_proto)++ = '\0';
+ p += n;
+ data->size -= n;
+ } else {
+ if (data->size < sizeof(u_short) + 1)
+ return (NULL);
+ if (key->size > sizeof(sv->line))
+ key->size = sizeof(sv->line);
+ ((char *)key->data)[key->size - 1] = '\0';
+ memcpy(sv->line, key->data, key->size);
+ sv->serv.s_name = sv->line;
+ if ((sv->serv.s_proto = strchr(sv->line, '/')) != NULL)
+ *(sv->serv.s_proto)++ = '\0';
+ sv->serv.s_port = *(u_short *)data->data;
+ p += sizeof(u_short);
+ data->size -= sizeof(u_short);
+ }
+ q = sv->serv.s_aliases = sv->serv_aliases;
+ while (data->size > 0 && q < &sv->serv_aliases[IRS_SV_MAXALIASES - 1]) {
+
+ *q++ = p;
+ n = strlen(p) + 1;
+ data->size -= n;
+ p += n;
+ }
+ *q = NULL;
+ return (&sv->serv);
+}
+#endif
diff --git a/usr/src/lib/libresolv2/common/irs/nis.c b/usr/src/lib/libresolv2/common/irs/nis.c
new file mode 100644
index 0000000000..bdac586cc1
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/nis.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: nis.c,v 1.15 2001/05/29 05:49:11 marka Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#ifdef WANT_IRS_NIS
+
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#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/usr/src/lib/libresolv2/common/irs/nis_gr.c b/usr/src/lib/libresolv2/common/irs/nis_gr.c
new file mode 100644
index 0000000000..3f9f059db2
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/nis_gr.c
@@ -0,0 +1,360 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: nis_gr.c,v 1.22 2002/07/08 06:26:11 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 <sys/param.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <isc/memcluster.h>
+
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+
+#include <errno.h>
+#include <grp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/memcluster.h>
+
+#include <irs.h>
+
+#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 = 0;
+ 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/usr/src/lib/libresolv2/common/irs/nis_ho.c b/usr/src/lib/libresolv2/common/irs/nis_ho.c
new file mode 100644
index 0000000000..7a38d12035
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/nis_ho.c
@@ -0,0 +1,537 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: nis_ho.c,v 1.19 2003/04/24 04:09:11 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 <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#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";
+static /*const*/ char ipnode_byname[] = "ipnode.byname";
+static /*const*/ char ipnode_byaddr[] = "ipnode.byaddr";
+static /*const*/ char yp_multi[] = "YP_MULTI_";
+
+/* Forwards */
+
+static void ho_close(struct irs_ho *this);
+static struct hostent * ho_byname(struct irs_ho *this, const char *name);
+static struct hostent * ho_byname2(struct irs_ho *this, const char *name,
+ int af);
+static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr,
+ int len, int af);
+static struct hostent * ho_next(struct irs_ho *this);
+static void ho_rewind(struct irs_ho *this);
+static void ho_minimize(struct irs_ho *this);
+static struct __res_state * ho_res_get(struct irs_ho *this);
+static void ho_res_set(struct irs_ho *this,
+ struct __res_state *res,
+ void (*free_res)(void *));
+static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name,
+ const struct addrinfo *pai);
+
+static struct hostent * makehostent(struct irs_ho *this);
+static void nisfree(struct pvt *, enum do_what);
+static int init(struct irs_ho *this);
+
+/* Public */
+
+struct irs_ho *
+irs_nis_ho(struct irs_acc *this) {
+ struct irs_ho *ho;
+ struct pvt *pvt;
+
+ if (!(pvt = memget(sizeof *pvt))) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pvt, 0, sizeof *pvt);
+ if (!(ho = memget(sizeof *ho))) {
+ memput(pvt, sizeof *pvt);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(ho, 0x5e, sizeof *ho);
+ pvt->needrewind = 1;
+ pvt->nis_domain = ((struct nis_p *)this->private)->domain;
+ ho->private = pvt;
+ ho->close = ho_close;
+ ho->byname = ho_byname;
+ ho->byname2 = ho_byname2;
+ ho->byaddr = ho_byaddr;
+ ho->next = ho_next;
+ ho->rewind = ho_rewind;
+ ho->minimize = ho_minimize;
+ ho->res_set = ho_res_set;
+ ho->res_get = ho_res_get;
+ ho->addrinfo = ho_addrinfo;
+ return (ho);
+}
+
+/* Methods */
+
+static void
+ho_close(struct irs_ho *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ ho_minimize(this);
+ nisfree(pvt, do_all);
+ if (pvt->res && pvt->free_res)
+ (*pvt->free_res)(pvt->res);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
+}
+
+static struct hostent *
+ho_byname(struct irs_ho *this, const char *name) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct hostent *hp;
+
+ if (init(this) == -1)
+ return (NULL);
+
+ if (pvt->res->options & RES_USE_INET6) {
+ hp = ho_byname2(this, name, AF_INET6);
+ if (hp)
+ return (hp);
+ }
+ return (ho_byname2(this, name, AF_INET));
+}
+
+static struct hostent *
+ho_byname2(struct irs_ho *this, const char *name, int af) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ int r;
+ char *tmp;
+
+ UNUSED(af);
+
+ if (init(this) == -1)
+ return (NULL);
+
+ nisfree(pvt, do_val);
+
+ strcpy(pvt->hostbuf, yp_multi);
+ strncat(pvt->hostbuf, name, sizeof(pvt->hostbuf) - sizeof(yp_multi));
+ pvt->hostbuf[sizeof(pvt->hostbuf) - 1] = '\0';
+ for (r = sizeof(yp_multi) - 1; pvt->hostbuf[r] != '\0'; r++)
+ if (isupper((unsigned char)pvt->hostbuf[r]))
+ tolower(pvt->hostbuf[r]);
+
+ tmp = pvt->hostbuf;
+ r = yp_match(pvt->nis_domain, ipnode_byname, tmp,
+ strlen(tmp), &pvt->curval_data, &pvt->curval_len);
+ if (r != 0) {
+ tmp = pvt->hostbuf + sizeof(yp_multi) - 1;
+ r = yp_match(pvt->nis_domain, ipnode_byname, tmp,
+ strlen(tmp), &pvt->curval_data, &pvt->curval_len);
+ }
+ if (r != 0) {
+ tmp = pvt->hostbuf;
+ r = yp_match(pvt->nis_domain, hosts_byname, tmp,
+ strlen(tmp), &pvt->curval_data, &pvt->curval_len);
+ }
+ if (r != 0) {
+ tmp = pvt->hostbuf + sizeof(yp_multi) - 1;
+ r = yp_match(pvt->nis_domain, hosts_byname, tmp,
+ strlen(tmp), &pvt->curval_data, &pvt->curval_len);
+ }
+ if (r != 0) {
+ RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
+ return (NULL);
+ }
+ return (makehostent(this));
+}
+
+static struct hostent *
+ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
+ const u_char *uaddr = addr;
+ int r;
+
+ if (init(this) == -1)
+ return (NULL);
+
+ if (af == AF_INET6 && len == IN6ADDRSZ &&
+ (!memcmp(uaddr, mapped, sizeof mapped) ||
+ !memcmp(uaddr, tunnelled, sizeof tunnelled))) {
+ /* Unmap. */
+ addr = (const u_char *)addr + sizeof mapped;
+ uaddr += sizeof mapped;
+ af = AF_INET;
+ len = INADDRSZ;
+ }
+ if (inet_ntop(af, uaddr, tmp, sizeof tmp) == NULL) {
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
+ return (NULL);
+ }
+ nisfree(pvt, do_val);
+ r = yp_match(pvt->nis_domain, ipnode_byaddr, tmp, strlen(tmp),
+ &pvt->curval_data, &pvt->curval_len);
+ if (r != 0)
+ 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 */
+
+/*
+ipnodes:
+::1 localhost
+127.0.0.1 localhost
+1.2.3.4 FOO bar
+1.2.6.4 FOO bar
+1.2.6.5 host
+
+ipnodes.byname:
+YP_MULTI_localhost ::1,127.0.0.1 localhost
+YP_MULTI_foo 1.2.3.4,1.2.6.4 FOO bar
+YP_MULTI_bar 1.2.3.4,1.2.6.4 FOO bar
+host 1.2.6.5 host
+
+hosts.byname:
+localhost 127.0.0.1 localhost
+host 1.2.6.5 host
+YP_MULTI_foo 1.2.3.4,1.2.6.4 FOO bar
+YP_MULTI_bar 1.2.3.4,1.2.6.4 FOO bar
+*/
+
+static struct hostent *
+makehostent(struct irs_ho *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ static const char spaces[] = " \t";
+ char *cp, **q, *p, *comma, *ap;
+ int af = 0, len = 0;
+ int multi = 0;
+ int addr = 0;
+
+ p = pvt->curval_data;
+ if ((cp = strpbrk(p, "#\n")) != NULL)
+ *cp = '\0';
+ if (!(cp = strpbrk(p, spaces)))
+ return (NULL);
+ *cp++ = '\0';
+ ap = pvt->hostbuf;
+ do {
+ if ((comma = strchr(p, ',')) != NULL) {
+ *comma++ = '\0';
+ multi = 1;
+ }
+ if ((ap + IN6ADDRSZ) > (pvt->hostbuf + sizeof(pvt->hostbuf)))
+ break;
+ if ((pvt->res->options & RES_USE_INET6) &&
+ inet_pton(AF_INET6, p, ap) > 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, ap);
+ af = AF_INET6;
+ len = IN6ADDRSZ;
+ } else {
+ af = AF_INET;
+ len = INADDRSZ;
+ }
+ } else {
+ if (!multi)
+ return (NULL);
+ continue;
+ }
+ if (addr < MAXADDRS) {
+ pvt->h_addr_ptrs[addr++] = ap;
+ pvt->h_addr_ptrs[addr] = NULL;
+ ap += len;
+ }
+ } while ((p = comma) != NULL);
+ if (ap == pvt->hostbuf)
+ return (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/usr/src/lib/libresolv2/common/irs/nis_ng.c b/usr/src/lib/libresolv2/common/irs/nis_ng.c
new file mode 100644
index 0000000000..109e9cde1f
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/nis_ng.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: nis_ng.c,v 1.17 2001/05/29 05:49:14 marka Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#ifndef WANT_IRS_NIS
+static int __bind_irs_nis_unneeded;
+#else
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+
+#include <isc/assertions.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#include "irs_p.h"
+#include "nis_p.h"
+
+/* Definitions */
+
+struct tmpgrp {
+ const char * name;
+ const char * host;
+ const char * user;
+ const char * domain;
+ struct tmpgrp * next;
+};
+
+struct pvt {
+ char * nis_domain;
+ struct tmpgrp * tmp;
+ struct tmpgrp * cur;
+ char * tmpgroup;
+};
+
+enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 };
+
+static /*const*/ char netgroup_map[] = "netgroup";
+
+/* Forward */
+
+static void ng_close(struct irs_ng *);
+static int ng_next(struct irs_ng *, const char **,
+ const char **, const char **);
+static int ng_test(struct irs_ng *,
+ const char *, const char *,
+ const char *, const char *);
+static void ng_rewind(struct irs_ng *, const char *);
+static void ng_minimize(struct irs_ng *);
+
+static void add_group_to_list(struct pvt *, const char *, int);
+static void add_tuple_to_list(struct pvt *, const char *, char *);
+static void tmpfree(struct pvt *);
+
+/* Public */
+
+struct irs_ng *
+irs_nis_ng(struct irs_acc *this) {
+ struct irs_ng *ng;
+ struct pvt *pvt;
+
+ if (!(ng = memget(sizeof *ng))) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(ng, 0x5e, sizeof *ng);
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(ng, sizeof *ng);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pvt, 0, sizeof *pvt);
+ pvt->nis_domain = ((struct nis_p *)this->private)->domain;
+ ng->private = pvt;
+ ng->close = ng_close;
+ ng->next = ng_next;
+ ng->test = ng_test;
+ ng->rewind = ng_rewind;
+ ng->minimize = ng_minimize;
+ return (ng);
+}
+
+/* Methods */
+
+static void
+ng_close(struct irs_ng *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ tmpfree(pvt);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
+}
+
+static int
+ng_next(struct irs_ng *this, const char **host, const char **user, const char **domain) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (!pvt->cur)
+ return (0);
+ *host = pvt->cur->host;
+ *user = pvt->cur->user;
+ *domain = pvt->cur->domain;
+ pvt->cur = pvt->cur->next;
+ return (1);
+}
+
+static int
+ng_test(struct irs_ng *this, const char *name,
+ const char *host, const char *user, const char *domain)
+{
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct tmpgrp *cur;
+
+ tmpfree(pvt);
+ add_group_to_list(pvt, name, strlen(name));
+ for (cur = pvt->tmp; cur; cur = cur->next) {
+ if ((!host || !cur->host || !strcmp(host, cur->host)) &&
+ (!user || !cur->user || !strcmp(user, cur->user)) &&
+ (!domain || !cur->domain || !strcmp(domain, cur->domain)))
+ break;
+ }
+ tmpfree(pvt);
+ return ((cur == NULL) ? 0 : 1);
+}
+
+static void
+ng_rewind(struct irs_ng *this, const char *name) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ /* Either hand back or free the existing list. */
+ if (pvt->tmpgroup) {
+ if (pvt->tmp && !strcmp(pvt->tmpgroup, name))
+ goto reset;
+ tmpfree(pvt);
+ }
+ pvt->tmpgroup = strdup(name);
+ add_group_to_list(pvt, name, strlen(name));
+ reset:
+ pvt->cur = pvt->tmp;
+}
+
+static void
+ng_minimize(struct irs_ng *this) {
+ UNUSED(this);
+ /* NOOP */
+}
+
+/* Private */
+
+static void
+add_group_to_list(struct pvt *pvt, const char *name, int len) {
+ char *vdata, *cp, *np;
+ struct tmpgrp *tmp;
+ int vlen, r;
+ char *nametmp;
+
+ /* Don't add the same group to the list more than once. */
+ for (tmp = pvt->tmp; tmp; tmp = tmp->next)
+ if (!strcmp(tmp->name, name))
+ return;
+
+ DE_CONST(name, nametmp);
+ r = yp_match(pvt->nis_domain, netgroup_map, nametmp, len,
+ &vdata, &vlen);
+ if (r == 0) {
+ cp = vdata;
+ if (*cp && cp[strlen(cp)-1] == '\n')
+ cp[strlen(cp)-1] = '\0';
+ for ( ; cp; cp = np) {
+ np = strchr(cp, ' ');
+ if (np)
+ *np++ = '\0';
+ if (*cp == '(')
+ add_tuple_to_list(pvt, name, cp);
+ else
+ add_group_to_list(pvt, cp, strlen(cp));
+ }
+ free(vdata);
+ }
+}
+
+static void
+add_tuple_to_list(struct pvt *pvt, const char *name, char *cp) {
+ struct tmpgrp *tmp;
+ char *tp, *np;
+
+ INSIST(*cp++ == '(');
+
+ tmp = malloc(sizeof *tmp + strlen(name) + sizeof '\0' +
+ strlen(cp) - sizeof ')');
+ if (!tmp)
+ return;
+ memset(tmp, 0, sizeof *tmp);
+ tp = ((char *)tmp) + sizeof *tmp;
+
+ /* Name */
+ strcpy(tp, name);
+ tmp->name = tp;
+ tp += strlen(tp) + 1;
+
+ /* Host */
+ if (!(np = strchr(cp, ',')))
+ goto cleanup;
+ *np++ = '\0';
+ strcpy(tp, cp);
+ tmp->host = tp;
+ tp += strlen(tp) + 1;
+ cp = np;
+
+ /* User */
+ if (!(np = strchr(cp, ',')))
+ goto cleanup;
+ *np++ = '\0';
+ strcpy(tp, cp);
+ tmp->user = tp;
+ tp += strlen(tp) + 1;
+ cp = np;
+
+ /* Domain */
+ if (!(np = strchr(cp, ')')))
+ goto cleanup;
+ *np++ = '\0';
+ strcpy(tp, cp);
+ tmp->domain = tp;
+
+ /*
+ * Empty string in file means wildcard, but
+ * NULL string in return value means wildcard.
+ */
+ if (!*tmp->host)
+ tmp->host = NULL;
+ if (!*tmp->user)
+ tmp->user = NULL;
+ if (!*tmp->domain)
+ tmp->domain = NULL;
+
+ /* Add to list (LIFO). */
+ tmp->next = pvt->tmp;
+ pvt->tmp = tmp;
+ return;
+
+ cleanup:
+ free(tmp);
+}
+
+static void
+tmpfree(struct pvt *pvt) {
+ struct tmpgrp *cur, *next;
+
+ if (pvt->tmpgroup) {
+ free(pvt->tmpgroup);
+ pvt->tmpgroup = NULL;
+ }
+ for (cur = pvt->tmp; cur; cur = next) {
+ next = cur->next;
+ free(cur);
+ }
+ pvt->tmp = NULL;
+}
+
+#endif /*WANT_IRS_NIS*/
diff --git a/usr/src/lib/libresolv2/common/irs/nis_nw.c b/usr/src/lib/libresolv2/common/irs/nis_nw.c
new file mode 100644
index 0000000000..dae568e54b
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/nis_nw.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: nis_nw.c,v 1.16 2001/05/29 05:49:15 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/* Imports */
+
+#include "port_before.h"
+
+#ifndef WANT_IRS_NIS
+static int __bind_irs_nis_unneeded;
+#else
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#include "irs_p.h"
+#include "nis_p.h"
+
+/* Definitions */
+
+#define MAXALIASES 35
+#define MAXADDRSIZE 4
+
+struct pvt {
+ int needrewind;
+ char * nis_domain;
+ char * curkey_data;
+ int curkey_len;
+ char * curval_data;
+ int curval_len;
+
+ struct nwent nwent;
+ char * nwbuf;
+
+ char * aliases[MAXALIASES + 1];
+ u_char addr[MAXADDRSIZE];
+
+ struct __res_state * res;
+ void (*free_res)(void *);
+};
+
+enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 };
+
+static /*const*/ char networks_byname[] = "networks.byname";
+static /*const*/ char networks_byaddr[] = "networks.byaddr";
+
+/* Forward */
+
+static void nw_close(struct irs_nw *);
+static struct nwent * nw_byname(struct irs_nw *, const char *, int);
+static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int);
+static struct nwent * nw_next(struct irs_nw *);
+static void nw_rewind(struct irs_nw *);
+static void nw_minimize(struct irs_nw *);
+static struct __res_state * nw_res_get(struct irs_nw *this);
+static void nw_res_set(struct irs_nw *this,
+ struct __res_state *res,
+ void (*free_res)(void *));
+
+static struct nwent * makenwent(struct irs_nw *this);
+static void nisfree(struct pvt *, enum do_what);
+static int init(struct irs_nw *this);
+
+/* Public */
+
+struct irs_nw *
+irs_nis_nw(struct irs_acc *this) {
+ struct irs_nw *nw;
+ struct pvt *pvt;
+
+ if (!(pvt = memget(sizeof *pvt))) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pvt, 0, sizeof *pvt);
+ if (!(nw = memget(sizeof *nw))) {
+ memput(pvt, sizeof *pvt);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(nw, 0x5e, sizeof *nw);
+ pvt->needrewind = 1;
+ pvt->nis_domain = ((struct nis_p *)this->private)->domain;
+ nw->private = pvt;
+ nw->close = nw_close;
+ nw->byname = nw_byname;
+ nw->byaddr = nw_byaddr;
+ nw->next = nw_next;
+ nw->rewind = nw_rewind;
+ nw->minimize = nw_minimize;
+ nw->res_get = nw_res_get;
+ nw->res_set = nw_res_set;
+ return (nw);
+}
+
+/* Methods */
+
+static void
+nw_close(struct irs_nw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ nw_minimize(this);
+ if (pvt->res && pvt->free_res)
+ (*pvt->free_res)(pvt->res);
+ if (pvt->nwbuf)
+ free(pvt->nwbuf);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
+}
+
+static struct nwent *
+nw_byaddr(struct irs_nw *this, void *net, int length, int af) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ char tmp[sizeof "255.255.255.255/32"], *t;
+ int r;
+
+ if (init(this) == -1)
+ return (NULL);
+
+ if (af != AF_INET) {
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+ nisfree(pvt, do_val);
+ /* Try it with /CIDR first. */
+ if (inet_net_ntop(AF_INET, net, length, tmp, sizeof tmp) == NULL) {
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
+ return (NULL);
+ }
+ r = yp_match(pvt->nis_domain, networks_byaddr, tmp, strlen(tmp),
+ &pvt->curval_data, &pvt->curval_len);
+ if (r != 0) {
+ /* Give it a shot without the /CIDR. */
+ if ((t = strchr(tmp, '/')) != NULL) {
+ *t = '\0';
+ r = yp_match(pvt->nis_domain, networks_byaddr,
+ tmp, strlen(tmp),
+ &pvt->curval_data, &pvt->curval_len);
+ }
+ if (r != 0) {
+ RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
+ return (NULL);
+ }
+ }
+ return (makenwent(this));
+}
+
+static struct nwent *
+nw_byname(struct irs_nw *this, const char *name, int af) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ int r;
+ char *tmp;
+
+ if (init(this) == -1)
+ return (NULL);
+
+ if (af != AF_INET) {
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+ nisfree(pvt, do_val);
+ DE_CONST(name, tmp);
+ r = yp_match(pvt->nis_domain, networks_byname, tmp,
+ strlen(tmp), &pvt->curval_data, &pvt->curval_len);
+ if (r != 0) {
+ RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
+ return (NULL);
+ }
+ return (makenwent(this));
+}
+
+static void
+nw_rewind(struct irs_nw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ pvt->needrewind = 1;
+}
+
+static struct nwent *
+nw_next(struct irs_nw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct nwent *rval;
+ int r;
+
+ if (init(this) == -1)
+ return (NULL);
+
+ do {
+ if (pvt->needrewind) {
+ nisfree(pvt, do_all);
+ r = yp_first(pvt->nis_domain, networks_byaddr,
+ &pvt->curkey_data, &pvt->curkey_len,
+ &pvt->curval_data, &pvt->curval_len);
+ pvt->needrewind = 0;
+ } else {
+ char *newkey_data;
+ int newkey_len;
+
+ nisfree(pvt, do_val);
+ r = yp_next(pvt->nis_domain, networks_byaddr,
+ pvt->curkey_data, pvt->curkey_len,
+ &newkey_data, &newkey_len,
+ &pvt->curval_data, &pvt->curval_len);
+ nisfree(pvt, do_key);
+ pvt->curkey_data = newkey_data;
+ pvt->curkey_len = newkey_len;
+ }
+ if (r != 0) {
+ RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
+ return (NULL);
+ }
+ rval = makenwent(this);
+ } while (rval == NULL);
+ return (rval);
+}
+
+static void
+nw_minimize(struct irs_nw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (pvt->res)
+ res_nclose(pvt->res);
+}
+
+static struct __res_state *
+nw_res_get(struct irs_nw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (!pvt->res) {
+ struct __res_state *res;
+ res = (struct __res_state *)malloc(sizeof *res);
+ if (!res) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(res, 0, sizeof *res);
+ nw_res_set(this, res, free);
+ }
+
+ return (pvt->res);
+}
+
+static void
+nw_res_set(struct irs_nw *this, struct __res_state *res,
+ void (*free_res)(void *)) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (pvt->res && pvt->free_res) {
+ res_nclose(pvt->res);
+ (*pvt->free_res)(pvt->res);
+ }
+
+ pvt->res = res;
+ pvt->free_res = free_res;
+}
+
+/* Private */
+
+static struct nwent *
+makenwent(struct irs_nw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ static const char spaces[] = " \t";
+ char *t, *cp, **ap;
+
+ if (pvt->nwbuf)
+ free(pvt->nwbuf);
+ pvt->nwbuf = pvt->curval_data;
+ pvt->curval_data = NULL;
+
+ if ((cp = strpbrk(pvt->nwbuf, "#\n")) != NULL)
+ *cp = '\0';
+ cp = pvt->nwbuf;
+
+ /* Name */
+ pvt->nwent.n_name = cp;
+ cp += strcspn(cp, spaces);
+ if (!*cp)
+ goto cleanup;
+ *cp++ = '\0';
+ cp += strspn(cp, spaces);
+
+ /* Network */
+ pvt->nwent.n_addrtype = AF_INET;
+ t = cp + strcspn(cp, spaces);
+ if (*t)
+ *t++ = '\0';
+ pvt->nwent.n_length = inet_net_pton(AF_INET, cp,
+ pvt->addr, sizeof pvt->addr);
+ if (pvt->nwent.n_length < 0)
+ goto cleanup;
+ pvt->nwent.n_addr = pvt->addr;
+ cp = t;
+
+ /* Aliases */
+ ap = pvt->nwent.n_aliases = pvt->aliases;
+ while (*cp) {
+ if (ap >= &pvt->aliases[MAXALIASES])
+ break;
+ *ap++ = cp;
+ cp += strcspn(cp, spaces);
+ if (!*cp)
+ break;
+ *cp++ = '\0';
+ cp += strspn(cp, spaces);
+ }
+ *ap = NULL;
+
+ return (&pvt->nwent);
+
+ cleanup:
+ if (pvt->nwbuf) {
+ free(pvt->nwbuf);
+ pvt->nwbuf = NULL;
+ }
+ return (NULL);
+}
+
+static void
+nisfree(struct pvt *pvt, enum do_what do_what) {
+ if ((do_what & do_key) && pvt->curkey_data) {
+ free(pvt->curkey_data);
+ pvt->curkey_data = NULL;
+ }
+ if ((do_what & do_val) && pvt->curval_data) {
+ free(pvt->curval_data);
+ pvt->curval_data = NULL;
+ }
+}
+
+static int
+init(struct irs_nw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (!pvt->res && !nw_res_get(this))
+ return (-1);
+ if (((pvt->res->options & RES_INIT) == 0) &&
+ res_ninit(pvt->res) == -1)
+ return (-1);
+ return (0);
+}
+
+#endif /*WANT_IRS_NIS*/
diff --git a/usr/src/lib/libresolv2/common/irs/nis_p.h b/usr/src/lib/libresolv2/common/irs/nis_p.h
new file mode 100644
index 0000000000..cd80d19235
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/nis_p.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * $Id: nis_p.h,v 1.6 1999/01/08 19:25:03 vixie Exp $
+ */
+
+/*
+ * nis_p.h - private include file for the NIS functions.
+ */
+
+/*
+ * Object state.
+ */
+struct nis_p {
+ char * domain;
+ struct __res_state * res;
+ void (*free_res) __P((void *));
+};
+
+
+/*
+ * Methods.
+ */
+
+extern struct irs_gr * irs_nis_gr __P((struct irs_acc *));
+extern struct irs_pw * irs_nis_pw __P((struct irs_acc *));
+extern struct irs_sv * irs_nis_sv __P((struct irs_acc *));
+extern struct irs_pr * irs_nis_pr __P((struct irs_acc *));
+extern struct irs_ho * irs_nis_ho __P((struct irs_acc *));
+extern struct irs_nw * irs_nis_nw __P((struct irs_acc *));
+extern struct irs_ng * irs_nis_ng __P((struct irs_acc *));
diff --git a/usr/src/lib/libresolv2/common/irs/nis_pr.c b/usr/src/lib/libresolv2/common/irs/nis_pr.c
new file mode 100644
index 0000000000..c4695f3234
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/nis_pr.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: nis_pr.c,v 1.14 2001/05/29 05:49:16 marka Exp $";
+#endif
+
+/* Imports */
+
+#include "port_before.h"
+
+#ifndef WANT_IRS_NIS
+static int __bind_irs_nis_unneeded;
+#else
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#include "irs_p.h"
+#include "nis_p.h"
+
+/* Definitions */
+
+struct pvt {
+ int needrewind;
+ char * nis_domain;
+ char * curkey_data;
+ int curkey_len;
+ char * curval_data;
+ int curval_len;
+ struct protoent proto;
+ char * prbuf;
+};
+
+enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 };
+
+static /*const*/ char protocols_byname[] = "protocols.byname";
+static /*const*/ char protocols_bynumber[] = "protocols.bynumber";
+
+/* Forward */
+
+static void pr_close(struct irs_pr *);
+static struct protoent * pr_byname(struct irs_pr *, const char *);
+static struct protoent * pr_bynumber(struct irs_pr *, int);
+static struct protoent * pr_next(struct irs_pr *);
+static void pr_rewind(struct irs_pr *);
+static void pr_minimize(struct irs_pr *);
+
+static struct protoent * makeprotoent(struct irs_pr *this);
+static void nisfree(struct pvt *, enum do_what);
+
+/* Public */
+
+struct irs_pr *
+irs_nis_pr(struct irs_acc *this) {
+ struct irs_pr *pr;
+ struct pvt *pvt;
+
+ if (!(pr = memget(sizeof *pr))) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pr, 0x5e, sizeof *pr);
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(pr, sizeof *pr);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pvt, 0, sizeof *pvt);
+ pvt->needrewind = 1;
+ pvt->nis_domain = ((struct nis_p *)this->private)->domain;
+ pr->private = pvt;
+ pr->byname = pr_byname;
+ pr->bynumber = pr_bynumber;
+ pr->next = pr_next;
+ pr->rewind = pr_rewind;
+ pr->close = pr_close;
+ pr->minimize = pr_minimize;
+ pr->res_get = NULL;
+ pr->res_set = NULL;
+ return (pr);
+}
+
+/* Methods. */
+
+static void
+pr_close(struct irs_pr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ nisfree(pvt, do_all);
+ if (pvt->proto.p_aliases)
+ free(pvt->proto.p_aliases);
+ if (pvt->prbuf)
+ free(pvt->prbuf);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
+}
+
+static struct protoent *
+pr_byname(struct irs_pr *this, const char *name) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ int r;
+ char *tmp;
+
+ nisfree(pvt, do_val);
+ DE_CONST(name, tmp);
+ r = yp_match(pvt->nis_domain, protocols_byname, tmp,
+ strlen(tmp), &pvt->curval_data, &pvt->curval_len);
+ if (r != 0) {
+ errno = ENOENT;
+ return (NULL);
+ }
+ return (makeprotoent(this));
+}
+
+static struct protoent *
+pr_bynumber(struct irs_pr *this, int num) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ char tmp[sizeof "-4294967295"];
+ int r;
+
+ nisfree(pvt, do_val);
+ (void) sprintf(tmp, "%d", num);
+ r = yp_match(pvt->nis_domain, protocols_bynumber, tmp, strlen(tmp),
+ &pvt->curval_data, &pvt->curval_len);
+ if (r != 0) {
+ errno = ENOENT;
+ return (NULL);
+ }
+ return (makeprotoent(this));
+}
+
+static struct protoent *
+pr_next(struct irs_pr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct protoent *rval;
+ int r;
+
+ do {
+ if (pvt->needrewind) {
+ nisfree(pvt, do_all);
+ r = yp_first(pvt->nis_domain, protocols_bynumber,
+ &pvt->curkey_data, &pvt->curkey_len,
+ &pvt->curval_data, &pvt->curval_len);
+ pvt->needrewind = 0;
+ } else {
+ char *newkey_data;
+ int newkey_len;
+
+ nisfree(pvt, do_val);
+ r = yp_next(pvt->nis_domain, protocols_bynumber,
+ pvt->curkey_data, pvt->curkey_len,
+ &newkey_data, &newkey_len,
+ &pvt->curval_data, &pvt->curval_len);
+ nisfree(pvt, do_key);
+ pvt->curkey_data = newkey_data;
+ pvt->curkey_len = newkey_len;
+ }
+ if (r != 0) {
+ errno = ENOENT;
+ return (NULL);
+ }
+ rval = makeprotoent(this);
+ } while (rval == NULL);
+ return (rval);
+}
+
+static void
+pr_rewind(struct irs_pr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ pvt->needrewind = 1;
+}
+
+static void
+pr_minimize(struct irs_pr *this) {
+ UNUSED(this);
+ /* NOOP */
+}
+
+/* Private */
+
+static struct protoent *
+makeprotoent(struct irs_pr *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ char *p, **t;
+ int n, m;
+
+ if (pvt->prbuf)
+ free(pvt->prbuf);
+ pvt->prbuf = pvt->curval_data;
+ pvt->curval_data = NULL;
+
+ for (p = pvt->prbuf; *p && *p != '#';)
+ p++;
+ while (p > pvt->prbuf && isspace((unsigned char)(p[-1])))
+ p--;
+ *p = '\0';
+
+ p = pvt->prbuf;
+ n = m = 0;
+
+ pvt->proto.p_name = p;
+ while (*p && !isspace((unsigned char)*p))
+ p++;
+ if (!*p)
+ return (NULL);
+ *p++ = '\0';
+
+ while (*p && isspace((unsigned char)*p))
+ p++;
+ pvt->proto.p_proto = atoi(p);
+ while (*p && !isspace((unsigned char)*p))
+ p++;
+ *p++ = '\0';
+
+ while (*p) {
+ if ((n + 1) >= m || !pvt->proto.p_aliases) {
+ m += 10;
+ t = realloc(pvt->proto.p_aliases,
+ m * sizeof(char *));
+ if (!t) {
+ errno = ENOMEM;
+ goto cleanup;
+ }
+ pvt->proto.p_aliases = t;
+ }
+ pvt->proto.p_aliases[n++] = p;
+ while (*p && !isspace((unsigned char)*p))
+ p++;
+ if (*p)
+ *p++ = '\0';
+ }
+ if (!pvt->proto.p_aliases)
+ pvt->proto.p_aliases = malloc(sizeof(char *));
+ if (!pvt->proto.p_aliases)
+ goto cleanup;
+ pvt->proto.p_aliases[n] = NULL;
+ return (&pvt->proto);
+
+ cleanup:
+ if (pvt->proto.p_aliases) {
+ free(pvt->proto.p_aliases);
+ pvt->proto.p_aliases = NULL;
+ }
+ if (pvt->prbuf) {
+ free(pvt->prbuf);
+ pvt->prbuf = NULL;
+ }
+ return (NULL);
+}
+
+static void
+nisfree(struct pvt *pvt, enum do_what do_what) {
+ if ((do_what & do_key) && pvt->curkey_data) {
+ free(pvt->curkey_data);
+ pvt->curkey_data = NULL;
+ }
+ if ((do_what & do_val) && pvt->curval_data) {
+ free(pvt->curval_data);
+ pvt->curval_data = NULL;
+ }
+}
+
+#endif /*WANT_IRS_NIS*/
diff --git a/usr/src/lib/libresolv2/common/irs/nis_pw.c b/usr/src/lib/libresolv2/common/irs/nis_pw.c
new file mode 100644
index 0000000000..5e8c4e76a2
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/nis_pw.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: nis_pw.c,v 1.17 2001/05/29 05:49:18 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/* Imports */
+
+#include "port_before.h"
+
+#if !defined(WANT_IRS_PW) || !defined(WANT_IRS_NIS)
+static int __bind_irs_pw_unneeded;
+#else
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <isc/memcluster.h>
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/memcluster.h>
+
+#include <irs.h>
+
+#include "port_after.h"
+
+#include "irs_p.h"
+#include "nis_p.h"
+
+/* Definitions */
+
+struct pvt {
+ int needrewind;
+ char * nis_domain;
+ char * curkey_data;
+ int curkey_len;
+ char * curval_data;
+ int curval_len;
+ struct passwd passwd;
+ char * pwbuf;
+};
+
+enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 };
+
+static /*const*/ char passwd_byname[] = "passwd.byname";
+static /*const*/ char passwd_byuid[] = "passwd.byuid";
+
+/* Forward */
+
+static void pw_close(struct irs_pw *);
+static struct passwd * pw_next(struct irs_pw *);
+static struct passwd * pw_byname(struct irs_pw *, const char *);
+static struct passwd * pw_byuid(struct irs_pw *, uid_t);
+static void pw_rewind(struct irs_pw *);
+static void pw_minimize(struct irs_pw *);
+
+static struct passwd * makepasswdent(struct irs_pw *);
+static void nisfree(struct pvt *, enum do_what);
+
+/* Public */
+
+struct irs_pw *
+irs_nis_pw(struct irs_acc *this) {
+ struct irs_pw *pw;
+ struct pvt *pvt;
+
+ if (!(pw = memget(sizeof *pw))) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pw, 0x5e, sizeof *pw);
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(pw, sizeof *pw);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pvt, 0, sizeof *pvt);
+ pvt->needrewind = 1;
+ pvt->nis_domain = ((struct nis_p *)this->private)->domain;
+ pw->private = pvt;
+ pw->close = pw_close;
+ pw->next = pw_next;
+ pw->byname = pw_byname;
+ pw->byuid = pw_byuid;
+ pw->rewind = pw_rewind;
+ pw->minimize = pw_minimize;
+ pw->res_get = NULL;
+ pw->res_set = NULL;
+ return (pw);
+}
+
+/* Methods */
+
+static void
+pw_close(struct irs_pw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (pvt->pwbuf)
+ free(pvt->pwbuf);
+ nisfree(pvt, do_all);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
+}
+
+static struct passwd *
+pw_next(struct irs_pw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct passwd *rval;
+ int r;
+
+ do {
+ if (pvt->needrewind) {
+ nisfree(pvt, do_all);
+ r = yp_first(pvt->nis_domain, passwd_byname,
+ &pvt->curkey_data, &pvt->curkey_len,
+ &pvt->curval_data, &pvt->curval_len);
+ pvt->needrewind = 0;
+ } else {
+ char *newkey_data;
+ int newkey_len;
+
+ nisfree(pvt, do_val);
+ r = yp_next(pvt->nis_domain, passwd_byname,
+ pvt->curkey_data, pvt->curkey_len,
+ &newkey_data, &newkey_len,
+ &pvt->curval_data, &pvt->curval_len);
+ nisfree(pvt, do_key);
+ pvt->curkey_data = newkey_data;
+ pvt->curkey_len = newkey_len;
+ }
+ if (r != 0) {
+ errno = ENOENT;
+ return (NULL);
+ }
+ rval = makepasswdent(this);
+ } while (rval == NULL);
+ return (rval);
+}
+
+static struct passwd *
+pw_byname(struct irs_pw *this, const char *name) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ int r;
+ char *tmp;
+
+ nisfree(pvt, do_val);
+ DE_CONST(name, tmp);
+ r = yp_match(pvt->nis_domain, passwd_byname, tmp, strlen(tmp),
+ &pvt->curval_data, &pvt->curval_len);
+ if (r != 0) {
+ errno = ENOENT;
+ return (NULL);
+ }
+ return (makepasswdent(this));
+}
+
+static struct passwd *
+pw_byuid(struct irs_pw *this, uid_t uid) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ char tmp[sizeof "4294967295"];
+ int r;
+
+ nisfree(pvt, do_val);
+ (void) sprintf(tmp, "%u", (unsigned int)uid);
+ r = yp_match(pvt->nis_domain, passwd_byuid, tmp, strlen(tmp),
+ &pvt->curval_data, &pvt->curval_len);
+ if (r != 0) {
+ errno = ENOENT;
+ return (NULL);
+ }
+ return (makepasswdent(this));
+}
+
+static void
+pw_rewind(struct irs_pw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ pvt->needrewind = 1;
+}
+
+static void
+pw_minimize(struct irs_pw *this) {
+ UNUSED(this);
+ /* NOOP */
+}
+
+/* Private */
+
+static struct passwd *
+makepasswdent(struct irs_pw *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ char *cp;
+
+ memset(&pvt->passwd, 0, sizeof pvt->passwd);
+ if (pvt->pwbuf)
+ free(pvt->pwbuf);
+ pvt->pwbuf = pvt->curval_data;
+ pvt->curval_data = NULL;
+
+ cp = pvt->pwbuf;
+ pvt->passwd.pw_name = cp;
+ if (!(cp = strchr(cp, ':')))
+ goto cleanup;
+#ifdef HAS_PW_CLASS
+ pvt->passwd.pw_class = cp; /* Needs to point at a \0. */
+#endif
+ *cp++ = '\0';
+
+ pvt->passwd.pw_passwd = cp;
+ if (!(cp = strchr(cp, ':')))
+ goto cleanup;
+ *cp++ = '\0';
+
+ pvt->passwd.pw_uid = atoi(cp);
+ if (!(cp = strchr(cp, ':')))
+ goto cleanup;
+ *cp++ = '\0';
+
+ pvt->passwd.pw_gid = atoi(cp);
+ if (!(cp = strchr(cp, ':')))
+ goto cleanup;
+ *cp++ = '\0';
+
+ pvt->passwd.pw_gecos = cp;
+ if (!(cp = strchr(cp, ':')))
+ goto cleanup;
+ *cp++ = '\0';
+
+ pvt->passwd.pw_dir = cp;
+ if (!(cp = strchr(cp, ':')))
+ goto cleanup;
+ *cp++ = '\0';
+
+ pvt->passwd.pw_shell = cp;
+
+ if ((cp = strchr(cp, '\n')) != NULL)
+ *cp = '\0';
+
+ return (&pvt->passwd);
+
+ cleanup:
+ free(pvt->pwbuf);
+ pvt->pwbuf = NULL;
+ return (NULL);
+}
+
+static void
+nisfree(struct pvt *pvt, enum do_what do_what) {
+ if ((do_what & do_key) && pvt->curkey_data) {
+ free(pvt->curkey_data);
+ pvt->curkey_data = NULL;
+ }
+ if ((do_what & do_val) && pvt->curval_data) {
+ free(pvt->curval_data);
+ pvt->curval_data = NULL;
+ }
+}
+
+#endif /* WANT_IRS_PW && WANT_IRS_NIS */
diff --git a/usr/src/lib/libresolv2/common/irs/nis_sv.c b/usr/src/lib/libresolv2/common/irs/nis_sv.c
new file mode 100644
index 0000000000..da5cf57693
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/nis_sv.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: nis_sv.c,v 1.15 2001/05/29 05:49:19 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/* Imports */
+
+#include "port_before.h"
+
+#ifndef WANT_IRS_NIS
+static int __bind_irs_nis_unneeded;
+#else
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <sys/socket.h>
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/memcluster.h>
+#include <irs.h>
+
+#include "port_after.h"
+
+#include "irs_p.h"
+#include "nis_p.h"
+
+/* Definitions */
+
+struct pvt {
+ int needrewind;
+ char * nis_domain;
+ char * curkey_data;
+ int curkey_len;
+ char * curval_data;
+ int curval_len;
+ char line[BUFSIZ+1];
+ struct servent serv;
+ char * svbuf;
+};
+
+enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 };
+
+static /*const*/ char services_byname[] = "services.byname";
+
+/* Forward */
+
+static void sv_close(struct irs_sv*);
+static struct servent * sv_next(struct irs_sv *);
+static struct servent * sv_byname(struct irs_sv *, const char *,
+ const char *);
+static struct servent * sv_byport(struct irs_sv *, int, const char *);
+static void sv_rewind(struct irs_sv *);
+static void sv_minimize(struct irs_sv *);
+
+static struct servent * makeservent(struct irs_sv *this);
+static void nisfree(struct pvt *, enum do_what);
+
+/* Public */
+
+struct irs_sv *
+irs_nis_sv(struct irs_acc *this) {
+ struct irs_sv *sv;
+ struct pvt *pvt;
+
+ if (!(sv = memget(sizeof *sv))) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(sv, 0x5e, sizeof *sv);
+ if (!(pvt = memget(sizeof *pvt))) {
+ memput(sv, sizeof *sv);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(pvt, 0, sizeof *pvt);
+ pvt->needrewind = 1;
+ pvt->nis_domain = ((struct nis_p *)this->private)->domain;
+ sv->private = pvt;
+ sv->close = sv_close;
+ sv->next = sv_next;
+ sv->byname = sv_byname;
+ sv->byport = sv_byport;
+ sv->rewind = sv_rewind;
+ sv->minimize = sv_minimize;
+ sv->res_get = NULL;
+ sv->res_set = NULL;
+ return (sv);
+}
+
+/* Methods */
+
+static void
+sv_close(struct irs_sv *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ nisfree(pvt, do_all);
+ if (pvt->serv.s_aliases)
+ free(pvt->serv.s_aliases);
+ if (pvt->svbuf)
+ free(pvt->svbuf);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
+}
+
+static struct servent *
+sv_byname(struct irs_sv *this, const char *name, const char *proto) {
+ struct servent *serv;
+ char **sap;
+
+ sv_rewind(this);
+ while ((serv = sv_next(this)) != NULL) {
+ if (proto != NULL && strcmp(proto, serv->s_proto))
+ continue;
+ if (!strcmp(name, serv->s_name))
+ break;
+ for (sap = serv->s_aliases; sap && *sap; sap++)
+ if (!strcmp(name, *sap))
+ break;
+ }
+ return (serv);
+}
+
+static struct servent *
+sv_byport(struct irs_sv *this, int port, const char *proto) {
+ struct servent *serv;
+
+ sv_rewind(this);
+ while ((serv = sv_next(this)) != NULL) {
+ if (proto != NULL && strcmp(proto, serv->s_proto))
+ continue;
+ if (serv->s_port == port)
+ break;
+ }
+ return (serv);
+}
+
+static void
+sv_rewind(struct irs_sv *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ pvt->needrewind = 1;
+}
+
+static struct servent *
+sv_next(struct irs_sv *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ struct servent *rval;
+ int r;
+
+ do {
+ if (pvt->needrewind) {
+ nisfree(pvt, do_all);
+ r = yp_first(pvt->nis_domain, services_byname,
+ &pvt->curkey_data, &pvt->curkey_len,
+ &pvt->curval_data, &pvt->curval_len);
+ pvt->needrewind = 0;
+ } else {
+ char *newkey_data;
+ int newkey_len;
+
+ nisfree(pvt, do_val);
+ r = yp_next(pvt->nis_domain, services_byname,
+ pvt->curkey_data, pvt->curkey_len,
+ &newkey_data, &newkey_len,
+ &pvt->curval_data, &pvt->curval_len);
+ nisfree(pvt, do_key);
+ pvt->curkey_data = newkey_data;
+ pvt->curkey_len = newkey_len;
+ }
+ if (r != 0) {
+ errno = ENOENT;
+ return (NULL);
+ }
+ rval = makeservent(this);
+ } while (rval == NULL);
+ return (rval);
+}
+
+static void
+sv_minimize(struct irs_sv *this) {
+ UNUSED(this);
+ /* NOOP */
+}
+
+/* Private */
+
+static struct servent *
+makeservent(struct irs_sv *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+ static const char spaces[] = " \t";
+ char *p, **t;
+ int n, m;
+
+ if (pvt->svbuf)
+ free(pvt->svbuf);
+ pvt->svbuf = pvt->curval_data;
+ pvt->curval_data = NULL;
+
+ if (pvt->serv.s_aliases) {
+ free(pvt->serv.s_aliases);
+ pvt->serv.s_aliases = NULL;
+ }
+
+ if ((p = strpbrk(pvt->svbuf, "#\n")))
+ *p = '\0';
+
+ p = pvt->svbuf;
+
+ pvt->serv.s_name = p;
+ p += strcspn(p, spaces);
+ if (!*p)
+ goto cleanup;
+ *p++ = '\0';
+ p += strspn(p, spaces);
+
+ pvt->serv.s_port = htons((u_short) atoi(p));
+ pvt->serv.s_proto = NULL;
+
+ while (*p && !isspace((unsigned char)*p))
+ if (*p++ == '/')
+ pvt->serv.s_proto = p;
+ if (!pvt->serv.s_proto)
+ goto cleanup;
+ if (*p) {
+ *p++ = '\0';
+ p += strspn(p, spaces);
+ }
+
+ n = m = 0;
+ while (*p) {
+ if ((n + 1) >= m || !pvt->serv.s_aliases) {
+ m += 10;
+ t = realloc(pvt->serv.s_aliases, m * sizeof(char *));
+ if (!t) {
+ errno = ENOMEM;
+ goto cleanup;
+ }
+ pvt->serv.s_aliases = t;
+ }
+ pvt->serv.s_aliases[n++] = p;
+ p += strcspn(p, spaces);
+ if (!*p)
+ break;
+ *p++ = '\0';
+ p += strspn(p, spaces);
+ }
+ if (!pvt->serv.s_aliases)
+ pvt->serv.s_aliases = malloc(sizeof(char *));
+ if (!pvt->serv.s_aliases)
+ goto cleanup;
+ pvt->serv.s_aliases[n] = NULL;
+ return (&pvt->serv);
+
+ cleanup:
+ if (pvt->serv.s_aliases) {
+ free(pvt->serv.s_aliases);
+ pvt->serv.s_aliases = NULL;
+ }
+ if (pvt->svbuf) {
+ free(pvt->svbuf);
+ pvt->svbuf = NULL;
+ }
+ return (NULL);
+}
+
+static void
+nisfree(struct pvt *pvt, enum do_what do_what) {
+ if ((do_what & do_key) && pvt->curkey_data) {
+ free(pvt->curkey_data);
+ pvt->curkey_data = NULL;
+ }
+ if ((do_what & do_val) && pvt->curval_data) {
+ free(pvt->curval_data);
+ pvt->curval_data = NULL;
+ }
+}
+
+#endif /*WANT_IRS_NIS*/
diff --git a/usr/src/lib/libresolv2/common/irs/nul_ng.c b/usr/src/lib/libresolv2/common/irs/nul_ng.c
new file mode 100644
index 0000000000..7aaa760cd3
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/nul_ng.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: nul_ng.c,v 1.11 2001/05/29 05:49:20 marka Exp $";
+#endif
+
+/*
+ * nul_ng.c - the netgroup accessor null map
+ */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <irs.h>
+#include <isc/memcluster.h>
+
+#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/usr/src/lib/libresolv2/common/irs/pathnames.h b/usr/src/lib/libresolv2/common/irs/pathnames.h
new file mode 100644
index 0000000000..c223a6bf53
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/pathnames.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * $Id: pathnames.h,v 1.7 1999/01/08 19:25:10 vixie Exp $
+ */
+
+#ifndef _PATH_IRS_CONF
+#define _PATH_IRS_CONF "/etc/irs.conf"
+#endif
+
+#ifndef _PATH_NETWORKS
+#define _PATH_NETWORKS "/etc/networks"
+#endif
+
+#ifndef _PATH_GROUP
+#define _PATH_GROUP "/etc/group"
+#endif
+
+#ifndef _PATH_NETGROUP
+#define _PATH_NETGROUP "/etc/netgroup"
+#endif
+
+#ifndef _PATH_SERVICES
+#define _PATH_SERVICES "/etc/services"
+#endif
+
+#ifdef IRS_LCL_SV_DB
+#ifndef _PATH_SERVICES_DB
+#define _PATH_SERVICES_DB _PATH_SERVICES ".db"
+#endif
+#endif
+
+#ifndef _PATH_HESIOD_CONF
+#define _PATH_HESIOD_CONF "/etc/hesiod.conf"
+#endif
diff --git a/usr/src/lib/libresolv2/common/irs/util.c b/usr/src/lib/libresolv2/common/irs/util.c
new file mode 100644
index 0000000000..2f27b2ae34
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/irs/util.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: util.c,v 1.12 2001/05/29 05:49:21 marka Exp $";
+#endif
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <irs.h>
+
+#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/usr/src/lib/libresolv2/common/isc/assertions.c b/usr/src/lib/libresolv2/common/isc/assertions.c
new file mode 100644
index 0000000000..1afff62208
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/assertions.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright 1998-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: assertions.c,v 8.4 2001/05/29 05:49:22 marka Exp $";
+#endif
+
+#include "port_before.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/assertions.h>
+
+#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/usr/src/lib/libresolv2/common/isc/base64.c b/usr/src/lib/libresolv2/common/isc/base64.c
new file mode 100644
index 0000000000..3e55d161ce
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/base64.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: base64.c,v 8.7 1999/10/13 16:39:33 vixie Exp $";
+#endif /* not lint */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "port_after.h"
+
+#ifdef ORIGINAL_ISC_CODE
+#else
+#pragma weak __b64_ntop = b64_ntop
+#pragma weak __b64_pton = b64_pton
+#endif /* ORIGINAL_ISC_CODE */
+
+#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/usr/src/lib/libresolv2/common/isc/bitncmp.c b/usr/src/lib/libresolv2/common/isc/bitncmp.c
new file mode 100644
index 0000000000..cc205bdad6
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/bitncmp.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: bitncmp.c,v 1.7 2001/05/29 05:49:23 marka Exp $";
+#endif
+
+#include "port_before.h"
+
+#include <sys/types.h>
+
+#include <string.h>
+
+#include "port_after.h"
+
+#include <isc/misc.h>
+
+/*
+ * 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/usr/src/lib/libresolv2/common/isc/ctl_clnt.c b/usr/src/lib/libresolv2/common/isc/ctl_clnt.c
new file mode 100644
index 0000000000..5da3f30075
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/ctl_clnt.c
@@ -0,0 +1,609 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: ctl_clnt.c,v 8.18 2002/07/08 05:10:23 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* Extern. */
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/assertions.h>
+#include <isc/ctl.h>
+#include <isc/eventlib.h>
+#include <isc/list.h>
+#include <isc/memcluster.h>
+
+#include "ctl_p.h"
+
+#include "port_after.h"
+
+/* Constants. */
+
+
+/* Macros. */
+
+#define donefunc_p(ctx) ((ctx).donefunc != NULL)
+#define arpacode_p(line) (isdigit((unsigned char)(line[0])) && \
+ isdigit((unsigned char)(line[1])) && \
+ isdigit((unsigned char)(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;
+ struct sockaddr *captmp;
+
+ 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));
+ }
+ DE_CONST(cap, captmp);
+ if (bind(ctx->sock, captmp, 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, 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((unsigned char)*pc) ||
+ !isprint((unsigned char)*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/usr/src/lib/libresolv2/common/isc/ctl_p.c b/usr/src/lib/libresolv2/common/isc/ctl_p.c
new file mode 100644
index 0000000000..ef785e70bd
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/ctl_p.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: ctl_p.c,v 8.8 2001/05/29 05:49:26 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* Extern. */
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <isc/assertions.h>
+#include <isc/eventlib.h>
+#include <isc/logging.h>
+#include <isc/memcluster.h>
+#include <isc/ctl.h>
+
+#include "ctl_p.h"
+
+#include "port_after.h"
+
+/* Constants. */
+
+const char * const ctl_sevnames[] = {
+ "debug", "warning", "error"
+};
+
+/* Public. */
+
+/*
+ * ctl_logger()
+ * if ctl_startup()'s caller didn't specify a logger, this one
+ * is used. this pollutes stderr with all kinds of trash so it will
+ * probably never be used in real applications.
+ */
+void
+ctl_logger(enum ctl_severity severity, const char *format, ...) {
+ va_list ap;
+ static const char me[] = "ctl_logger";
+
+ fprintf(stderr, "%s(%s): ", me, ctl_sevnames[severity]);
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+}
+
+int
+ctl_bufget(struct ctl_buf *buf, ctl_logfunc logger) {
+ static const char me[] = "ctl_bufget";
+
+ REQUIRE(!allocated_p(*buf) && buf->used == 0);
+ buf->text = memget(MAX_LINELEN);
+ if (!allocated_p(*buf)) {
+ (*logger)(ctl_error, "%s: getmem: %s", me, strerror(errno));
+ return (-1);
+ }
+ buf->used = 0;
+ return (0);
+}
+
+void
+ctl_bufput(struct ctl_buf *buf) {
+
+ REQUIRE(allocated_p(*buf));
+ memput(buf->text, MAX_LINELEN);
+ buf->text = NULL;
+ buf->used = 0;
+}
+
+const char *
+ctl_sa_ntop(const struct sockaddr *sa,
+ char *buf, size_t size,
+ ctl_logfunc logger)
+{
+ static const char me[] = "ctl_sa_ntop";
+ static const char punt[] = "[0].-1";
+ char tmp[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/usr/src/lib/libresolv2/common/isc/ctl_p.h b/usr/src/lib/libresolv2/common/isc/ctl_p.h
new file mode 100644
index 0000000000..df86107f4d
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/ctl_p.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+struct ctl_buf {
+ char * text;
+ size_t used;
+};
+
+#define MAX_LINELEN 990 /* Like SMTP. */
+#ifndef NO_SOCKADDR_UN
+#define MAX_NTOP PATH_MAX
+#else
+#define MAX_NTOP (sizeof "[255.255.255.255].65535")
+#endif
+
+#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/usr/src/lib/libresolv2/common/isc/ctl_srvr.c b/usr/src/lib/libresolv2/common/isc/ctl_srvr.c
new file mode 100644
index 0000000000..8593ba9a30
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/ctl_srvr.c
@@ -0,0 +1,787 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: ctl_srvr.c,v 8.26 2002/07/08 05:10:25 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* Extern. */
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <isc/assertions.h>
+#include <isc/ctl.h>
+#include <isc/eventlib.h>
+#include <isc/list.h>
+#include <isc/logging.h>
+#include <isc/memcluster.h>
+
+#include "ctl_p.h"
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/* Macros. */
+
+#define lastverb_p(verb) (verb->name == NULL || verb->func == NULL)
+#define address_expr ctl_sa_ntop((struct sockaddr *)&sess->sa, \
+ tmp, sizeof tmp, ctx->logger)
+
+/* Types. */
+
+enum state {
+ available = 0, initializing, writing, reading, reading_data,
+ processing, idling, quitting, closing
+};
+
+union sa_un {
+ struct sockaddr_in in;
+#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, 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((unsigned char)*pc) ||
+ !isprint((unsigned char)*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/usr/src/lib/libresolv2/common/isc/ev_connects.c b/usr/src/lib/libresolv2/common/isc/ev_connects.c
new file mode 100644
index 0000000000..533b544a49
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/ev_connects.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* ev_connects.c - implement asynch connect/accept for the eventlib
+ * vix 16sep96 [initial]
+ */
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: ev_connects.c,v 8.32 2001/07/03 13:26:35 marka Exp $";
+#endif
+
+/* Import. */
+
+#include "port_before.h"
+#include "fd_setsize.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <unistd.h>
+
+#include <isc/eventlib.h>
+#include <isc/assertions.h>
+#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) {
+#ifdef USE_FIONBIO_IOCTL
+ int on = 1;
+ OK(ioctl(fd, FIONBIO, (char *)&on));
+#else
+ OK(fcntl(fd, F_SETFL, mode | PORT_NONBLOCK));
+#endif
+ 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 {
+#ifdef USE_FIONBIO_IOCTL
+ int on = 1;
+ OK(ioctl(this->fd, FIONBIO, (char *)&on));
+#else
+ OK(fcntl(this->fd, F_SETFL, mode | PORT_NONBLOCK));
+#endif
+ }
+ }
+
+ /* 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;
+ ISC_SOCKLEN_T 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;
+ ISC_SOCKLEN_T lalen, ralen;
+ char buf[1];
+ void *conn_uap;
+ evConnFunc conn_func;
+ evConnID id;
+ int socket_errno = 0;
+ ISC_SOCKLEN_T 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/usr/src/lib/libresolv2/common/isc/ev_files.c b/usr/src/lib/libresolv2/common/isc/ev_files.c
new file mode 100644
index 0000000000..8c9b1b22d6
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/ev_files.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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.22 2002/07/08 05:50:07 marka Exp $";
+#endif
+
+#include "port_before.h"
+#include "fd_setsize.h"
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <isc/eventlib.h>
+#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 %p, fd %d, mask 0x%x, func %p, uap %p)\n",
+ ctx, fd, eventmask, func, uap);
+ if (eventmask == 0 || (eventmask & ~EV_MASK_ALL) != 0)
+ EV_ERR(EINVAL);
+#ifdef SUNW_POLL
+#else
+ if (fd > ctx->highestFD)
+ EV_ERR(EINVAL);
+#endif /* SUNW_POLL */
+ 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.
+ */
+#ifdef SUNW_POLL
+ /* Make sure both ctx->pollfds[] and ctx->fdTable[] are large enough */
+ if (fd >= ctx->maxnfds)
+ evPollfdRealloc(ctx, 1, fd);
+#endif /* SUNW_POLL */
+ id = FindFD(ctx, fd, EV_MASK_ALL);
+ if (id == NULL) {
+ if (mode & PORT_NONBLOCK)
+ FD_SET(fd, &ctx->nonblockBefore);
+ else {
+#ifdef USE_FIONBIO_IOCTL
+ int on = 1;
+ OK(ioctl(fd, FIONBIO, (char *)&on));
+#else
+ OK(fcntl(fd, F_SETFL, mode | PORT_NONBLOCK));
+#endif
+ 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)
+ EV_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;
+
+#ifdef SUNW_POLL
+#else
+ 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]);
+#endif /* SUNW_POLL */
+
+ 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)
+ EV_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.
+ */
+#ifdef USE_FIONBIO_IOCTL
+ int off = 1;
+ (void) ioctl(del->fd, FIONBIO, (char *)&off);
+#else
+ (void) fcntl(del->fd, F_SETFL, mode & ~PORT_NONBLOCK);
+#endif
+ }
+
+ /*
+ * 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;
+
+#ifdef SUNW_POLL
+#else
+ 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]);
+#endif /* SUNW_POLL */
+
+ /* 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/usr/src/lib/libresolv2/common/isc/ev_streams.c b/usr/src/lib/libresolv2/common/isc/ev_streams.c
new file mode 100644
index 0000000000..04ac464354
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/ev_streams.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1996-1999 by Internet Software Consortium
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* ev_streams.c - implement asynch stream file IO for the eventlib
+ * vix 04mar96 [initial]
+ */
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: ev_streams.c,v 8.22 2001/05/29 05:49:29 marka Exp $";
+#endif
+
+#include "port_before.h"
+#include "fd_setsize.h"
+
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+
+#include <isc/eventlib.h>
+#include <isc/assertions.h>
+#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 < (size_t)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/usr/src/lib/libresolv2/common/isc/ev_timers.c b/usr/src/lib/libresolv2/common/isc/ev_timers.c
new file mode 100644
index 0000000000..9afc4a0ccd
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/ev_timers.c
@@ -0,0 +1,422 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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.33 2002/07/08 05:50:09 marka Exp $";
+#endif
+
+/* Import. */
+
+#include "port_before.h"
+#include "fd_setsize.h"
+
+#include <errno.h>
+
+#include <isc/assertions.h>
+#include <isc/eventlib.h>
+#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 %p, func %p, uap %p, due %ld.%09ld, inter %ld.%09ld)\n",
+ ctx, func, uap,
+ (long)due.tv_sec, due.tv_nsec,
+ (long)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)
+ EV_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)
+ EV_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 %ld.%09ld, inter %ld.%09ld\n",
+ cur->func, cur->uap,
+ (long)cur->due.tv_sec, cur->due.tv_nsec,
+ (long)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/usr/src/lib/libresolv2/common/isc/ev_waits.c b/usr/src/lib/libresolv2/common/isc/ev_waits.c
new file mode 100644
index 0000000000..223915c853
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/ev_waits.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2003 by Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* ev_waits.c - implement deferred function calls for the eventlib
+ * vix 05dec95 [initial]
+ */
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: ev_waits.c,v 8.12 2002/07/08 05:50:10 marka Exp $";
+#endif
+
+#include "port_before.h"
+#include "fd_setsize.h"
+
+#include <errno.h>
+
+#include <isc/eventlib.h>
+#include <isc/assertions.h>
+#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 %p:", wl->first->tag);
+ for (this = wl->first; this != NULL; this = this->next)
+ evPrintf(ctx, 9, " %p", this);
+ evPrintf(ctx, 9, "\n");
+ }
+ evPrintf(ctx, 9, "wait done:");
+ for (this = ctx->waitDone.first; this != NULL; this = this->next)
+ evPrintf(ctx, 9, " %p", 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/usr/src/lib/libresolv2/common/isc/eventlib.c b/usr/src/lib/libresolv2/common/isc/eventlib.c
new file mode 100644
index 0000000000..8bd1eaf5e0
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/eventlib.c
@@ -0,0 +1,899 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* eventlib.c - implement glue for the eventlib
+ * vix 09sep95 [initial]
+ */
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: eventlib.c,v 1.48 2002/07/17 07:37:34 marka Exp $";
+#endif
+
+#include "port_before.h"
+#include "fd_setsize.h"
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#ifdef SUNW_POLL
+#include <limits.h>
+#endif /* SUNW_POLL */
+
+#include <errno.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/eventlib.h>
+#include <isc/assertions.h>
+#include "eventlib_p.h"
+
+#include "port_after.h"
+
+#ifdef SUNW_POLL
+#define pselect Pselect
+#endif /* SUNW_POLL */
+
+/* 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;
+#ifdef SUNW_POLL
+ ctx->pollfds = 0;
+ ctx->maxnfds = 0;
+ ctx->firstfd = 0;
+ emulMaskInit(ctx, rdLast, EV_READ, 1);
+ emulMaskInit(ctx, rdNext, EV_READ, 0);
+ emulMaskInit(ctx, wrLast, EV_WRITE, 1);
+ emulMaskInit(ctx, wrNext, EV_WRITE, 0);
+ emulMaskInit(ctx, exLast, EV_EXCEPT, 1);
+ emulMaskInit(ctx, exNext, EV_EXCEPT, 0);
+ emulMaskInit(ctx, nonblockBefore, EV_WASNONBLOCKING, 0);
+#endif /* SUNW_POLL */
+ 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. */
+#ifdef SUNW_POLL
+ ctx->highestFD = INT_MAX;
+#else
+ ctx->highestFD = FD_SETSIZE - 1;
+#endif /* SUNW_POLL */
+#ifdef EVENTLIB_TIME_CHECKS
+ ctx->lastFdCount = 0;
+#endif
+#ifdef SUNW_POLL
+ ctx->fdTable = 0;
+#else
+ memset(ctx->fdTable, 0, sizeof ctx->fdTable);
+#endif /* SUNW_POLL */
+
+ /* 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)
+ EV_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)
+ EV_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 {
+#ifdef SUNW_POLL
+ /*
+ * The pollfd structure uses separate fields for
+ * the input and output events (corresponding to
+ * the ??Next and ??Last fd sets), so there's no
+ * need to copy one to the other.
+ */
+#else
+ /* XXX need to copy only the bits we are using. */
+ ctx->rdLast = ctx->rdNext;
+ ctx->wrLast = ctx->wrNext;
+ ctx->exLast = ctx->exNext;
+#endif /* SUNW_POLL */
+
+ if (m == Timer) {
+ INSIST(tp == &t);
+ t = evSubTime(nextTime, ctx->lastEventTime);
+ }
+
+#ifdef SUNW_POLL
+#else
+ evPrintf(ctx, 4,
+ "pselect(%d, 0x%lx, 0x%lx, 0x%lx, %ld.%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 ? (long)tp->tv_sec : -1L,
+ tp ? tp->tv_nsec : -1);
+#endif
+
+ /* XXX should predict system's earliness and adjust. */
+ x = pselect(ctx->fdMax+1,
+ &ctx->rdLast, &ctx->wrLast, &ctx->exLast,
+ tp, NULL);
+ pselect_errno = errno;
+
+#ifdef SUNW_POLL
+ evPrintf(ctx, 4, "poll() returns %d (err: %s)\n",
+ x, (x == -1) ? strerror(errno) : "none");
+#else
+ evPrintf(ctx, 4, "select() returns %d (err: %s)\n",
+ x, (x == -1) ? strerror(errno) : "none");
+#endif /* SUNW_POLL */
+
+ /* 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();
+ }
+ EV_ERR(pselect_errno);
+ }
+ if (x == 0 && (nextTimer == NULL || !timerPast) &&
+ (options & EV_POLL))
+ EV_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 %p, uap %p\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 %p, uap %p\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 %p, uap %p\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 %p, uap %p\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 %p, func %p, uap %p\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;
+#ifdef SUNW_POLL
+ int polltimeout = INFTIM;
+ evContext_p *ctx;
+ struct pollfd *fds;
+ nfds_t pnfds;
+#endif
+
+ if (tsp) {
+ tvp = &tv;
+ tv = evTimeVal(*tsp);
+#ifdef SUNW_POLL
+ polltimeout = 1000*tv.tv_sec + tv.tv_usec/1000;
+#endif
+ } else
+ tvp = NULL;
+ if (sigmask)
+ sigprocmask(SIG_SETMASK, sigmask, &sigs);
+#ifdef SUNW_POLL
+ /*
+ * rfds, wfds, and efds should all be from the same evContext_p,
+ * so any of them will do. If they're all NULL, the caller is
+ * presumably calling us to block.
+ */
+ if (rfds != 0)
+ ctx = ((__evEmulMask *)rfds)->ctx;
+ else if (wfds != 0)
+ ctx = ((__evEmulMask *)wfds)->ctx;
+ else if (efds != 0)
+ ctx = ((__evEmulMask *)efds)->ctx;
+ else
+ ctx = 0;
+ if (ctx != 0) {
+ fds = &(ctx->pollfds[ctx->firstfd]);
+ pnfds = ctx->fdMax - ctx->firstfd + 1;
+ } else {
+ fds = 0;
+ pnfds = 0;
+ }
+ n = poll(fds, pnfds, polltimeout);
+ /*
+ * pselect() should return the total number of events on the file
+ * descriptors, not just the count of fd:s with activity. Hence,
+ * traverse the pollfds array and count the events.
+ */
+ if (n > 0) {
+ int i, e;
+ for (e = 0, i = ctx->firstfd; i <= ctx->fdMax; i++) {
+ if (ctx->pollfds[i].fd < 0)
+ continue;
+ if (FD_ISSET(i, &ctx->rdLast))
+ e++;
+ if (FD_ISSET(i, &ctx->wrLast))
+ e++;
+ if (FD_ISSET(i, &ctx->exLast))
+ e++;
+ }
+ n = e;
+ }
+#else
+ n = select(nfds, rfds, wfds, efds, tvp);
+#endif /* SUNW_POLL */
+ if (sigmask)
+ sigprocmask(SIG_SETMASK, &sigs, NULL);
+ if (tsp)
+ *tsp = evTimeSpec(tv);
+ return (n);
+}
+#endif
+
+#ifdef SUNW_POLL
+void
+evPollfdRealloc(evContext_p *ctx, int pollfd_chunk_size, int fd) {
+
+ int old_maxnfds = ctx->maxnfds;
+ int i;
+
+ if (fd < old_maxnfds)
+ return;
+
+ /* Don't allow ridiculously small values for pollfd_chunk_size */
+ if (pollfd_chunk_size < 20)
+ pollfd_chunk_size = 20;
+
+ ctx->maxnfds = (1 + (fd/pollfd_chunk_size)) * pollfd_chunk_size;
+
+ ctx->pollfds = realloc(ctx->pollfds,
+ ctx->maxnfds * sizeof(*ctx->pollfds));
+ ctx->fdTable = realloc(ctx->fdTable,
+ ctx->maxnfds * sizeof(*ctx->fdTable));
+
+ if (ctx->pollfds == 0 || ctx->fdTable == 0) {
+ evPrintf(ctx, 2, "pollfd() realloc (%lu) failed\n",
+ ctx->maxnfds*sizeof(struct pollfd));
+ exit(1);
+ }
+
+ for (i = old_maxnfds; i < ctx->maxnfds; i++) {
+ ctx->pollfds[i].fd = -1;
+ ctx->pollfds[i].events = 0;
+ ctx->fdTable[i] = 0;
+ }
+}
+
+/*
+ * Neither evPollfdAdd() nor evPollfdDel() are needed anymore. We keep
+ * them as no-ops for now so that the in.named code doesn't have to change.
+ */
+void
+evPollfdAdd(evContext opaqueCtx, int pollfd_chunk_size, int fd, short events)
+{
+}
+
+void
+evPollfdDel(evContext opaqueCtx, int fd)
+{
+}
+
+/* Find the appropriate 'events' or 'revents' field in the pollfds array */
+short *
+__fd_eventfield(int fd, __evEmulMask *maskp) {
+
+ evContext_p *ctx = (evContext_p *)maskp->ctx;
+
+ if (!maskp->result || maskp->type == EV_WASNONBLOCKING)
+ return (&(ctx->pollfds[fd].events));
+ else
+ return (&(ctx->pollfds[fd].revents));
+}
+
+/* Translate to poll(2) event */
+short
+__poll_event(__evEmulMask *maskp) {
+
+ switch ((maskp)->type) {
+ case EV_READ:
+ return (POLLRDNORM);
+ case EV_WRITE:
+ return (POLLWRNORM);
+ case EV_EXCEPT:
+ return (POLLRDBAND | POLLPRI | POLLWRBAND);
+ case EV_WASNONBLOCKING:
+ return (POLLHUP);
+ default:
+ return (0);
+ }
+}
+
+/*
+ * Clear the events corresponding to the specified mask. If this leaves
+ * the events mask empty (apart from the POLLHUP bit), set the fd field
+ * to -1 so that poll(2) will ignore this fd.
+ */
+void
+__fd_clr(int fd, __evEmulMask *maskp) {
+
+ evContext_p *ctx = maskp->ctx;
+
+ *__fd_eventfield(fd, maskp) &= ~__poll_event(maskp);
+ if ((ctx->pollfds[fd].events & ~POLLHUP) == 0) {
+ ctx->pollfds[fd].fd = -1;
+ for ( ; ctx->fdMax > 0 && ctx->pollfds[ctx->fdMax].fd < 0;
+ ctx->fdMax--);
+ for ( ; ctx->firstfd <= ctx->fdMax &&
+ ctx->pollfds[ctx->firstfd].fd < 0;
+ ctx->firstfd++);
+ }
+}
+
+/*
+ * Set the events bit(s) corresponding to the specified mask. If the events
+ * field has any other bits than POLLHUP set, also set the fd field so that
+ * poll(2) will watch this fd.
+ */
+void
+__fd_set(int fd, __evEmulMask *maskp) {
+
+ evContext_p *ctx = maskp->ctx;
+
+ *__fd_eventfield(fd, maskp) |= __poll_event(maskp);
+ if ((ctx->pollfds[fd].events & ~POLLHUP) != 0) {
+ ctx->pollfds[fd].fd = fd;
+ if (fd < ctx->firstfd || ctx->firstfd == 0)
+ ctx->firstfd = fd;
+ if (fd > ctx->fdMax)
+ ctx->fdMax = fd;
+ }
+}
+#endif
diff --git a/usr/src/lib/libresolv2/common/isc/eventlib_p.h b/usr/src/lib/libresolv2/common/isc/eventlib_p.h
new file mode 100644
index 0000000000..28aa9fb25d
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/eventlib_p.h
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* eventlib_p.h - private interfaces for eventlib
+ * vix 09sep95 [initial]
+ *
+ * $Id: eventlib_p.h,v 1.31 2003/04/03 05:37:56 marka Exp $
+ */
+
+#ifndef _EVENTLIB_P_H
+#define _EVENTLIB_P_H
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
+#define EVENTLIB_DEBUG 1
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/heap.h>
+#include <isc/list.h>
+#include <isc/memcluster.h>
+
+#define EV_MASK_ALL (EV_READ | EV_WRITE | EV_EXCEPT)
+#define EV_ERR(e) return (errno = (e), -1)
+#define OK(x) if ((x) < 0) EV_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
+
+#ifdef SUNW_POLL
+#include <stropts.h>
+#include <poll.h>
+#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;
+ ISC_SOCKLEN_T lalen;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in in;
+#ifndef NO_SOCKADDR_UN
+ struct sockaddr_un un;
+#endif
+ } ra;
+ ISC_SOCKLEN_T 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;
+
+#ifdef SUNW_POLL
+typedef struct {
+ void *ctx; /* Pointer to the evContext_p */
+ uint32_t type; /* READ, WRITE, EXCEPT, nonblk */
+ uint32_t result; /* 1 => revents, 0 => events */
+} __evEmulMask;
+
+#define emulMaskInit(ctx, field, ev, lastnext) \
+ ctx->field.ctx = ctx; \
+ ctx->field.type = ev; \
+ ctx->field.result = lastnext;
+
+/* Any value other than EV_* values from <isc/eventlib.h> will do */
+#define EV_WASNONBLOCKING 4000000001
+
+extern short *__fd_eventfield(int fd, __evEmulMask *maskp);
+extern short __poll_event(__evEmulMask *maskp);
+extern void __fd_clr(int fd, __evEmulMask *maskp);
+extern void __fd_set(int fd, __evEmulMask *maskp);
+
+#undef FD_ZERO
+#define FD_ZERO(maskp)
+
+#undef FD_SET
+#define FD_SET(fd, maskp) \
+ __fd_set(fd, maskp)
+
+#undef FD_CLR
+#define FD_CLR(fd, maskp) \
+ __fd_clr(fd, maskp)
+
+#undef FD_ISSET
+#define FD_ISSET(fd, maskp) \
+ ((*__fd_eventfield(fd, maskp) & __poll_event(maskp)) != 0)
+
+#endif /* SUNW_POLL */
+
+typedef struct {
+ /* Global. */
+ const evEvent_p *cur;
+ /* Debugging. */
+ int debug;
+ FILE *output;
+ /* Connections. */
+ evConn *conns;
+ LIST(evAccept) accepts;
+ /* Files. */
+ evFile *files, *fdNext;
+#ifdef SUNW_POLL
+ struct pollfd *pollfds; /* Allocated as needed */
+ evFile **fdTable; /* Ditto */
+ int maxnfds; /* # elements in above */
+ int firstfd; /* First active fd */
+ int fdMax; /* Last active fd */
+ int fdCount; /* # fd:s with I/O */
+ int highestFD; /* Max fd allowed by OS */
+ __evEmulMask rdLast, rdNext;
+ __evEmulMask wrLast, wrNext;
+ __evEmulMask exLast, exNext;
+ __evEmulMask nonblockBefore;
+#else
+ fd_set rdLast, rdNext;
+ fd_set wrLast, wrNext;
+ fd_set exLast, exNext;
+ fd_set nonblockBefore;
+ int fdMax, fdCount, highestFD;
+ evFile *fdTable[FD_SETSIZE];
+#endif
+#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, ...)
+ ISC_FORMAT_PRINTF(3, 4);
+
+#ifdef SUNW_POLL
+extern void evPollfdRealloc(evContext_p *ctx, int pollfd_chunk_size, int fd);
+#endif /* SUNW_POLL */
+
+/* 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/usr/src/lib/libresolv2/common/isc/heap.c b/usr/src/lib/libresolv2/common/isc/heap.c
new file mode 100644
index 0000000000..72c823d9d8
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/heap.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Heap implementation of priority queues adapted from the following:
+ *
+ * _Introduction to Algorithms_, Cormen, Leiserson, and Rivest,
+ * MIT Press / McGraw Hill, 1990, ISBN 0-262-03141-8, chapter 7.
+ *
+ * _Algorithms_, Second Edition, Sedgewick, Addison-Wesley, 1988,
+ * ISBN 0-201-06673-4, chapter 11.
+ */
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: heap.c,v 8.7 1999/10/13 16:39:34 vixie Exp $";
+#endif /* not lint */
+
+#include "port_before.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "port_after.h"
+
+#include <isc/heap.h>
+
+/*
+ * 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/usr/src/lib/libresolv2/common/isc/hex.c b/usr/src/lib/libresolv2/common/isc/hex.c
new file mode 100644
index 0000000000..5e1f6e8364
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/hex.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 2001 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <port_before.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <isc/misc.h>
+#include <port_after.h>
+
+static const char hex[17] = "0123456789abcdef";
+
+int
+isc_gethexstring(unsigned char *buf, size_t len, int count, FILE *fp,
+ int *multiline)
+{
+ int c, n;
+ unsigned char x;
+ char *s;
+ int result = count;
+
+ x = 0; /* silence compiler */
+ n = 0;
+ while (count > 0) {
+ c = fgetc(fp);
+
+ if ((c == EOF) ||
+ (c == '\n' && !*multiline) ||
+ (c == '(' && *multiline) ||
+ (c == ')' && !*multiline))
+ goto formerr;
+ /* comment */
+ if (c == ';') {
+ while ((c = fgetc(fp)) != EOF && c != '\n')
+ /* empty */
+ if (c == '\n' && *multiline)
+ continue;
+ goto formerr;
+ }
+ /* white space */
+ if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
+ continue;
+ /* multiline */
+ if ('(' == c || c == ')') {
+ *multiline = (c == '(' /*)*/);
+ continue;
+ }
+ if ((s = strchr(hex, tolower(c))) == NULL)
+ goto formerr;
+ x = (x<<4) | (s - hex);
+ if (++n == 2) {
+ if (len > 0) {
+ *buf++ = x;
+ len--;
+ } else
+ result = -1;
+ count--;
+ n = 0;
+ }
+ }
+ return (result);
+
+ formerr:
+ if (c == '\n')
+ ungetc(c, fp);
+ return (-1);
+}
+
+void
+isc_puthexstring(FILE *fp, const unsigned char *buf, size_t buflen,
+ size_t len1, size_t len2, const char *sep)
+{
+ size_t i = 0;
+
+ if (len1 < 4)
+ len1 = 4;
+ if (len2 < 4)
+ len2 = 4;
+ while (buflen > 0) {
+ fputc(hex[(buf[0]>>4)&0xf], fp);
+ fputc(hex[buf[0]&0xf], fp);
+ i += 2;
+ buflen--;
+ buf++;
+ if (i >= len1 && sep != NULL) {
+ fputs(sep, fp);
+ i = 0;
+ len1 = len2;
+ }
+ }
+}
+
+void
+isc_tohex(const unsigned char *buf, size_t buflen, char *t) {
+ while (buflen > 0) {
+ *t++ = hex[(buf[0]>>4)&0xf];
+ *t++ = hex[buf[0]&0xf];
+ buf++;
+ buflen--;
+ }
+ *t = '\0';
+}
diff --git a/usr/src/lib/libresolv2/common/isc/logging.c b/usr/src/lib/libresolv2/common/isc/logging.c
new file mode 100644
index 0000000000..13fc49259d
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/logging.c
@@ -0,0 +1,727 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: logging.c,v 8.32 2003/01/02 00:35:42 marka Exp $";
+#endif /* not lint */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <syslog.h>
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/assertions.h>
+#include <isc/logging.h>
+#include <isc/memcluster.h>
+#include <isc/misc.h>
+
+#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)rename(old_name, new_name);
+ }
+ sprintf(new_name, "%s.0", chan->out.file.name);
+ (void)rename(chan->out.file.name, new_name);
+}
+
+FILE *
+log_open_stream(log_channel chan) {
+ FILE *stream;
+ int fd, flags;
+ struct stat sb;
+ int regular;
+
+ if (chan == NULL || chan->type != log_file) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /*
+ * Don't open already open streams
+ */
+ if (chan->out.file.stream != NULL)
+ return (chan->out.file.stream);
+
+ if (stat(chan->out.file.name, &sb) < 0) {
+ if (errno != ENOENT) {
+ syslog(LOG_ERR,
+ "log_open_stream: stat of %s failed: %s",
+ chan->out.file.name, strerror(errno));
+ chan->flags |= LOG_CHANNEL_BROKEN;
+ return (NULL);
+ }
+ regular = 1;
+ } else
+ regular = (sb.st_mode & S_IFREG);
+
+ if (chan->out.file.versions) {
+ if (!regular) {
+ syslog(LOG_ERR,
+ "log_open_stream: want versions but %s isn't a regular file",
+ chan->out.file.name);
+ chan->flags |= LOG_CHANNEL_BROKEN;
+ errno = EINVAL;
+ return (NULL);
+ }
+ }
+
+ flags = O_WRONLY|O_CREAT|O_APPEND;
+
+ if ((chan->flags & LOG_TRUNCATE) != 0) {
+ if (regular) {
+ (void)unlink(chan->out.file.name);
+ flags |= O_EXCL;
+ } else {
+ syslog(LOG_ERR,
+ "log_open_stream: want truncation but %s isn't a regular file",
+ chan->out.file.name);
+ chan->flags |= LOG_CHANNEL_BROKEN;
+ errno = EINVAL;
+ return (NULL);
+ }
+ }
+
+ fd = open(chan->out.file.name, flags,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+ if (fd < 0) {
+ syslog(LOG_ERR, "log_open_stream: open(%s) failed: %s",
+ chan->out.file.name, strerror(errno));
+ chan->flags |= LOG_CHANNEL_BROKEN;
+ return (NULL);
+ }
+ stream = fdopen(fd, "a");
+ if (stream == NULL) {
+ syslog(LOG_ERR, "log_open_stream: fdopen() failed");
+ chan->flags |= LOG_CHANNEL_BROKEN;
+ return (NULL);
+ }
+ (void) fchown(fd, chan->out.file.owner, chan->out.file.group);
+
+ chan->out.file.stream = stream;
+ return (stream);
+}
+
+int
+log_close_stream(log_channel chan) {
+ FILE *stream;
+
+ if (chan == NULL || chan->type != log_file) {
+ errno = EINVAL;
+ return (0);
+ }
+ stream = chan->out.file.stream;
+ chan->out.file.stream = NULL;
+ if (stream != NULL && fclose(stream) == EOF)
+ return (-1);
+ return (0);
+}
+
+void
+log_close_debug_channels(log_context lc) {
+ log_channel_list lcl;
+ int i;
+
+ for (i = 0; i < lc->num_categories; i++)
+ for (lcl = lc->categories[i]; lcl != NULL; lcl = lcl->next)
+ if (lcl->channel->type == log_file &&
+ lcl->channel->out.file.stream != NULL &&
+ lcl->channel->flags & LOG_REQUIRE_DEBUG)
+ (void)log_close_stream(lcl->channel);
+}
+
+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;
+#ifdef HAVE_TIME_R
+ struct tm tm_tmp;
+#endif
+ time_t tt;
+ 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 {
+ tt = tv.tv_sec;
+#ifdef HAVE_TIME_R
+ local_tm = localtime_r(&tt, &tm_tmp);
+#else
+ local_tm = localtime(&tt);
+#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,
+ const 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/usr/src/lib/libresolv2/common/isc/logging_p.h b/usr/src/lib/libresolv2/common/isc/logging_p.h
new file mode 100644
index 0000000000..d85af6f2fc
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/logging_p.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1997-2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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/usr/src/lib/libresolv2/common/isc/memcluster.c b/usr/src/lib/libresolv2/common/isc/memcluster.c
new file mode 100644
index 0000000000..03fb6d3c8b
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/memcluster.c
@@ -0,0 +1,588 @@
+/*
+ * Copyright 1998-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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 8.23 2001/06/18 14:44:05 marka Exp $";
+#endif /* not lint */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <isc/memcluster.h>
+#include <isc/assertions.h>
+
+#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
+ size_t 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. */
+
+#ifdef SUNW_MT_RESOLVER
+#include <thread.h>
+#include <synch.h>
+static mutex_t memlock = DEFAULTMUTEX;
+#define SUNW_MEMLOCK (void)mutex_lock(&memlock)
+#define SUNW_MEMUNLOCK (void)mutex_unlock(&memlock)
+#define SUNW_MEMLOCKBLOCK_BEGIN {
+#define SUNW_MEMLOCKBLOCK_END }
+#else
+#define SUNW_MEMLOCK
+#define SUNW_MEMUNLOCK
+#define SUNW_MEMLOCKBLOCK_BEGIN
+#define SUNW_MEMLOCKBLOCK_END
+#endif /* SUNW_MT_RESOLVER */
+
+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;
+
+ SUNW_MEMLOCK;
+
+#if !defined(MEMCLUSTER_RECORD)
+ UNUSED(file);
+ UNUSED(line);
+#endif
+ if (freelists == NULL)
+ if (meminit(0, 0) == -1)
+SUNW_MEMLOCKBLOCK_BEGIN
+ SUNW_MEMUNLOCK;
+ return (NULL);
+SUNW_MEMLOCKBLOCK_END
+ if (size == 0) {
+ SUNW_MEMUNLOCK;
+ 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) {
+ SUNW_MEMUNLOCK;
+ 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
+ SUNW_MEMUNLOCK;
+ e->fencepost = FRONT_FENCEPOST;
+ p = (char *)e + sizeof *e + size;
+ memcpy(p, &fp, sizeof fp);
+ return ((char *)e + sizeof *e);
+#else
+ SUNW_MEMUNLOCK;
+ 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) {
+ SUNW_MEMUNLOCK;
+ 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) {
+ SUNW_MEMUNLOCK;
+ 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--;
+ SUNW_MEMUNLOCK;
+#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;
+ memcluster_element *el;
+#ifdef MEMCLUSTER_RECORD
+ memcluster_element *prev;
+#endif
+ fence_t fp;
+ char *p;
+#endif
+
+ SUNW_MEMLOCK;
+
+#if !defined (MEMCLUSTER_RECORD)
+ UNUSED(file);
+ UNUSED(line);
+#endif
+
+ REQUIRE(freelists != NULL);
+
+ if (size == 0) {
+ SUNW_MEMUNLOCK;
+ 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--;
+ SUNW_MEMUNLOCK;
+ 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++;
+ SUNW_MEMUNLOCK;
+}
+
+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
+
+ SUNW_MEMLOCK;
+ if (freelists == NULL)
+SUNW_MEMLOCKBLOCK_BEGIN
+ SUNW_MEMUNLOCK;
+ return;
+SUNW_MEMLOCKBLOCK_END
+ 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 :
+ "<UNKNOWN>", e->line,
+ (char *)e + sizeof *e, e->size);
+ e = e->next;
+ }
+ }
+#endif
+ SUNW_MEMUNLOCK;
+}
+
+int
+memactive(void) {
+ size_t i;
+
+ if (stats == NULL)
+ return (0);
+ for (i = 1; i <= max_size; i++)
+ if (stats[i].gets != 0)
+ return (1);
+ return (0);
+}
+
+/* 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) {
+ size_t i;
+ for (i = 0; i < len; i++)
+ INSIST(a[i] == value);
+}
+#endif
diff --git a/usr/src/lib/libresolv2/common/isc/tree.c b/usr/src/lib/libresolv2/common/isc/tree.c
new file mode 100644
index 0000000000..fea38085e0
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/isc/tree.c
@@ -0,0 +1,543 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef LINT
+static const char rcsid[] = "$Id: tree.c,v 8.10 2001/11/01 05:33:46 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*#define DEBUG "tree"*/
+
+#include "port_before.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "port_after.h"
+
+#include <isc/memcluster.h>
+#include <isc/tree.h>
+
+#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, tree_t), 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, tree_t),
+ 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, tree_t),
+ 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)(tree_t)) {
+ 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)(tree_t)) {
+ 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)(tree_t, tree_t), void (*pfv_delete)(tree_t))
+{
+ 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;
+ }
+#ifdef ORIGINAL_ISC_CODE
+ RET(*ppr);
+#else
+ RET(*ppr)
+#endif
+ }
+
+ /* 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, tree_t), tree_t p_user,
+ void (*pfv_uar)(tree_t), 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)(tree_t), 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/usr/src/lib/libresolv2/common/llib-lresolv b/usr/src/lib/libresolv2/common/llib-lresolv
new file mode 100644
index 0000000000..aedd06a0fa
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/llib-lresolv
@@ -0,0 +1,59 @@
+/* LINTLIBRARY */
+/* PROTOLIB1 */
+
+/*
+ * Copyright (c) 1997-1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+/*
+ * usr/src/lib/libresolv2 routines
+ */
+
+int dn_skipname(const uchar_t *, const uchar_t *);
+void fp_query(const u_char *, FILE *);
+const uchar_t * p_cdname(const uchar_t *, const uchar_t *, FILE *);
+const char * p_class(int);
+void p_query(const u_char *);
+const char * p_time(unsigned int);
+const char * p_type(int);
+void putlong(unsigned int, uchar_t *);
+uint32_t _getlong(const u_char *);
+uint16_t _getshort(const u_char *);
+const char * hstrerror(int);
+int res_init(void);
+int res_mkquery(int, const char *, int, int, const u_char *,
+ int, const u_char *, u_char *, int);
+int res_query(const char *, int, int, u_char *, int);
+int res_querydomain(const char *, const char *, int, int,
+ u_char *, int);
+int res_search(const char *, int, int, u_char *, int);
+int res_send(const u_char *, int, u_char *, int);
+int res_update(ns_updrec *);
+int res_ninit(res_state);
+void fp_resstat(const res_state, FILE *);
+const char * res_hostalias(const res_state, const char *, char *, size_t);
+int res_nquery(res_state, const char *, int, int, u_char *, int);
+int res_nsearch(res_state, const char *, int, int, u_char *, int);
+int res_nquerydomain(res_state, const char *, const char *,
+ int, int, u_char *, int);
+int res_nmkquery(res_state, int, const char *, int, int,
+ const u_char *, int, const u_char *,
+ u_char *, int);
+int res_nsend(res_state, const u_char *, int, u_char *, int);
+int res_nmkupdate(res_state, ns_updrec *, u_char *, int);
+void res_nclose(res_state);
+int res_nsendsigned(res_state, const u_char *, int, ns_tsig_key *,
+ u_char *, int);
+int dn_comp(const char *, u_char *, int, u_char **, u_char **);
+int dn_expand(const u_char *, const u_char *, const u_char *,
+ char *, int);
diff --git a/usr/src/lib/libresolv2/common/mapfile-vers b/usr/src/lib/libresolv2/common/mapfile-vers
new file mode 100644
index 0000000000..e700b09635
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/mapfile-vers
@@ -0,0 +1,15 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# Special mapfile to establish h_errno as a filter on libnsl. As a filtered
+# symbol, this isn't visible to apptrace, and thus doesn't have to be defined
+# from the specfiles. To ensure the symbol remains in .bss, with the correct
+# size, its filtering capabilities are assigned here rather than via a specfile.
+
+SUNW_2.1 {
+ global:
+ h_errno = FILTER libnsl.so.1;
+};
diff --git a/usr/src/lib/libresolv2/common/nameser/ns_date.c b/usr/src/lib/libresolv2/common/nameser/ns_date.c
new file mode 100644
index 0000000000..b089063c71
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/nameser/ns_date.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_date.c,v 1.3 2001/05/29 05:49:34 marka Exp $";
+#endif
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* Import. */
+
+#include "port_before.h"
+
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/* Forward. */
+
+static int datepart(const char *, int, int, int, int *);
+
+/* Public. */
+
+/* Convert a date in ASCII into the number of seconds since
+ 1 January 1970 (GMT assumed). Format is yyyymmddhhmmss, all
+ digits required, no spaces allowed. */
+
+u_int32_t
+ns_datetosecs(const char *cp, int *errp) {
+ struct tm time;
+ u_int32_t result;
+ int mdays, i;
+ static const int days_per_month[12] =
+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+ if (strlen(cp) != 14) {
+ *errp = 1;
+ return (0);
+ }
+ *errp = 0;
+
+ memset(&time, 0, sizeof time);
+ time.tm_year = datepart(cp + 0, 4, 1990, 9999, errp) - 1900;
+ time.tm_mon = datepart(cp + 4, 2, 01, 12, errp) - 1;
+ time.tm_mday = datepart(cp + 6, 2, 01, 31, errp);
+ time.tm_hour = datepart(cp + 8, 2, 00, 23, errp);
+ time.tm_min = datepart(cp + 10, 2, 00, 59, errp);
+ time.tm_sec = datepart(cp + 12, 2, 00, 59, errp);
+ if (*errp) /* Any parse errors? */
+ return (0);
+
+ /*
+ * OK, now because timegm() is not available in all environments,
+ * we will do it by hand. Roll up sleeves, curse the gods, begin!
+ */
+
+#define SECS_PER_DAY ((u_int32_t)24*60*60)
+#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
+
+ result = time.tm_sec; /* Seconds */
+ result += time.tm_min * 60; /* Minutes */
+ result += time.tm_hour * (60*60); /* Hours */
+ result += (time.tm_mday - 1) * SECS_PER_DAY; /* Days */
+
+ /* Months are trickier. Look without leaping, then leap */
+ mdays = 0;
+ for (i = 0; i < time.tm_mon; i++)
+ mdays += days_per_month[i];
+ result += mdays * SECS_PER_DAY; /* Months */
+ if (time.tm_mon > 1 && isleap(1900+time.tm_year))
+ result += SECS_PER_DAY; /* Add leapday for this year */
+
+ /* First figure years without leapdays, then add them in. */
+ /* The loop is slow, FIXME, but simple and accurate. */
+ result += (time.tm_year - 70) * (SECS_PER_DAY*365); /* Years */
+ for (i = 70; i < time.tm_year; i++)
+ if (isleap(1900+i))
+ result += SECS_PER_DAY; /* Add leapday for prev year */
+
+ return (result);
+}
+
+/* Private. */
+
+/*
+ * Parse part of a date. Set error flag if any error.
+ * Don't reset the flag if there is no error.
+ */
+static int
+datepart(const char *buf, int size, int min, int max, int *errp) {
+ int result = 0;
+ int i;
+
+ for (i = 0; i < size; i++) {
+ if (!isdigit((unsigned char)(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/usr/src/lib/libresolv2/common/nameser/ns_name.c b/usr/src/lib/libresolv2/common/nameser/ns_name.c
new file mode 100644
index 0000000000..fbe2c5ccc7
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/nameser/ns_name.c
@@ -0,0 +1,970 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_name.c,v 8.20 2003/04/03 06:00:07 marka Exp $";
+#endif
+
+#include "port_before.h"
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+#define NS_TYPE_ELT 0x40 /* EDNS0 extended label type */
+#define DNS_LABELTYPE_BITSTRING 0x41
+
+/* Data. */
+
+static const char digits[] = "0123456789";
+
+static const char digitvalue[256] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
+};
+
+/* Forward. */
+
+static int special(int);
+static int printable(int);
+static int dn_find(const u_char *, const u_char *,
+ const u_char * const *,
+ const u_char * const *);
+static int encode_bitsring(const char **, const char *,
+ char **, char **, const char *);
+static int labellen(const u_char *);
+static int decode_bitstring(const char **, char *, const char *);
+
+/* Public. */
+
+/*
+ * ns_name_ntop(src, dst, dstsiz)
+ * Convert an encoded domain name to printable ascii as per RFC1035.
+ * return:
+ * Number of bytes written to buffer, or -1 (with errno set)
+ * notes:
+ * The root is returned as "."
+ * All other domains are returned in non absolute form
+ */
+int
+ns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
+{
+ const u_char *cp;
+ char *dn, *eom;
+ u_char c;
+ u_int n;
+ int l;
+
+ cp = src;
+ dn = dst;
+ eom = dst + dstsiz;
+
+ while ((n = *cp++) != 0) {
+ if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+ /* Some kind of compression pointer. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (dn != dst) {
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '.';
+ }
+ if ((l = labellen(cp - 1)) < 0) {
+ errno = EMSGSIZE; /* XXX */
+ return(-1);
+ }
+ if (dn + l >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) {
+ int m;
+
+ if (n != DNS_LABELTYPE_BITSTRING) {
+ /* XXX: labellen should reject this case */
+ errno = EINVAL;
+ return(-1);
+ }
+ if ((m = decode_bitstring((const char **)&cp, dn, eom)) < 0)
+ {
+ errno = EMSGSIZE;
+ return(-1);
+ }
+ dn += m;
+ continue;
+ }
+ for ((void)NULL; l > 0; l--) {
+ c = *cp++;
+ if (special(c)) {
+ if (dn + 1 >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '\\';
+ *dn++ = (char)c;
+ } else if (!printable(c)) {
+ if (dn + 3 >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '\\';
+ *dn++ = digits[c / 100];
+ *dn++ = digits[(c % 100) / 10];
+ *dn++ = digits[c % 10];
+ } else {
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = (char)c;
+ }
+ }
+ }
+ if (dn == dst) {
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '.';
+ }
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '\0';
+ return (dn - dst);
+}
+
+/*
+ * ns_name_pton(src, dst, dstsiz)
+ * Convert a ascii string into an encoded domain name as per RFC1035.
+ * return:
+ * -1 if it fails
+ * 1 if string was fully qualified
+ * 0 is string was not fully qualified
+ * notes:
+ * Enforces label and domain length limits.
+ */
+
+int
+ns_name_pton(const char *src, u_char *dst, size_t dstsiz)
+{
+ u_char *label, *bp, *eom;
+ int c, n, escaped, e = 0;
+ char *cp;
+
+ escaped = 0;
+ bp = dst;
+ eom = dst + dstsiz;
+ label = bp++;
+
+ while ((c = *src++) != 0) {
+ if (escaped) {
+ if (c == '[') { /* start a bit string label */
+ if ((cp = strchr(src, ']')) == NULL) {
+ errno = EINVAL; /* ??? */
+ return(-1);
+ }
+ if ((e = encode_bitsring(&src,
+ cp + 2,
+ (char **)&label,
+ (char **)&bp,
+ (const char *)eom))
+ != 0) {
+ errno = e;
+ return(-1);
+ }
+ escaped = 0;
+ label = bp++;
+ if ((c = *src++) == 0)
+ goto done;
+ else if (c != '.') {
+ errno = EINVAL;
+ return(-1);
+ }
+ continue;
+ }
+ else if ((cp = strchr(digits, c)) != NULL) {
+ n = (cp - digits) * 100;
+ if ((c = *src++) == 0 ||
+ (cp = strchr(digits, c)) == NULL) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ n += (cp - digits) * 10;
+ if ((c = *src++) == 0 ||
+ (cp = strchr(digits, c)) == NULL) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ n += (cp - digits);
+ if (n > 255) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ c = n;
+ }
+ escaped = 0;
+ } else if (c == '\\') {
+ escaped = 1;
+ continue;
+ } else if (c == '.') {
+ c = (bp - label - 1);
+ if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (label >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *label = c;
+ /* Fully qualified ? */
+ if (*src == '\0') {
+ if (c != 0) {
+ if (bp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *bp++ = '\0';
+ }
+ if ((bp - dst) > MAXCDNAME) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ return (1);
+ }
+ if (c == 0 || *src == '.') {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ label = bp++;
+ continue;
+ }
+ if (bp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *bp++ = (u_char)c;
+ }
+ c = (bp - label - 1);
+ if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ done:
+ if (label >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *label = c;
+ if (c != 0) {
+ if (bp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *bp++ = 0;
+ }
+ if ((bp - dst) > MAXCDNAME) { /* src too big */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * ns_name_ntol(src, dst, dstsiz)
+ * Convert a network strings labels into all lowercase.
+ * return:
+ * Number of bytes written to buffer, or -1 (with errno set)
+ * notes:
+ * Enforces label and domain length limits.
+ */
+
+int
+ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz)
+{
+ const u_char *cp;
+ u_char *dn, *eom;
+ u_char c;
+ u_int n;
+ int l;
+
+ cp = src;
+ dn = dst;
+ eom = dst + dstsiz;
+
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ while ((n = *cp++) != 0) {
+ if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+ /* Some kind of compression pointer. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = n;
+ if ((l = labellen(cp - 1)) < 0) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (dn + l >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ for ((void)NULL; l > 0; l--) {
+ c = *cp++;
+ if (isupper(c))
+ *dn++ = tolower(c);
+ else
+ *dn++ = c;
+ }
+ }
+ *dn++ = '\0';
+ return (dn - dst);
+}
+
+/*
+ * ns_name_unpack(msg, eom, src, dst, dstsiz)
+ * Unpack a domain name from a message, source may be compressed.
+ * return:
+ * -1 if it fails, or consumed octets if it succeeds.
+ */
+int
+ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
+ u_char *dst, size_t dstsiz)
+{
+ const u_char *srcp, *dstlim;
+ u_char *dstp;
+ int n, len, checked, l;
+
+ len = -1;
+ checked = 0;
+ dstp = dst;
+ srcp = src;
+ dstlim = dst + dstsiz;
+ if (srcp < msg || srcp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ /* Fetch next label in domain name. */
+ while ((n = *srcp++) != 0) {
+ /* Check for indirection. */
+ switch (n & NS_CMPRSFLGS) {
+ case 0:
+ case NS_TYPE_ELT:
+ /* Limit checks. */
+ if ((l = labellen(srcp - 1)) < 0) {
+ errno = EMSGSIZE;
+ return(-1);
+ }
+ if (dstp + l + 1 >= dstlim || srcp + l >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ checked += l + 1;
+ *dstp++ = n;
+ memcpy(dstp, srcp, l);
+ dstp += l;
+ srcp += l;
+ break;
+
+ case NS_CMPRSFLGS:
+ if (srcp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (len < 0)
+ len = srcp - src + 1;
+ srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
+ if (srcp < msg || srcp >= eom) { /* Out of range. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ checked += 2;
+ /*
+ * Check for loops in the compressed name;
+ * if we've looked at the whole message,
+ * there must be a loop.
+ */
+ if (checked >= eom - msg) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ break;
+
+ default:
+ errno = EMSGSIZE;
+ return (-1); /* flag error */
+ }
+ }
+ *dstp = '\0';
+ if (len < 0)
+ len = srcp - src;
+ return (len);
+}
+
+/*
+ * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
+ * Pack domain name 'domain' into 'comp_dn'.
+ * return:
+ * Size of the compressed name, or -1.
+ * notes:
+ * 'dnptrs' is an array of pointers to previous compressed names.
+ * dnptrs[0] is a pointer to the beginning of the message. The array
+ * ends with NULL.
+ * 'lastdnptr' is a pointer to the end of the array pointed to
+ * by 'dnptrs'.
+ * Side effects:
+ * The list of pointers in dnptrs is updated for labels inserted into
+ * the message as we compress the name. If 'dnptr' is NULL, we don't
+ * try to compress names. If 'lastdnptr' is NULL, we don't update the
+ * list.
+ */
+int
+ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
+ const u_char **dnptrs, const u_char **lastdnptr)
+{
+ u_char *dstp;
+ const u_char **cpp, **lpp, *eob, *msg;
+ const u_char *srcp;
+ int n, l, first = 1;
+
+ srcp = src;
+ dstp = dst;
+ eob = dstp + dstsiz;
+ lpp = cpp = NULL;
+ if (dnptrs != NULL) {
+ if ((msg = *dnptrs++) != NULL) {
+ for (cpp = dnptrs; *cpp != NULL; cpp++)
+ (void)NULL;
+ lpp = cpp; /* end of list to search */
+ }
+ } else
+ msg = NULL;
+
+ /* make sure the domain we are about to add is legal */
+ l = 0;
+ do {
+ int l0;
+
+ n = *srcp;
+ if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if ((l0 = labellen(srcp)) < 0) {
+ errno = EINVAL;
+ return(-1);
+ }
+ l += l0 + 1;
+ if (l > MAXCDNAME) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ srcp += l0 + 1;
+ } while (n != 0);
+
+ /* from here on we need to reset compression pointer array on error */
+ srcp = src;
+ do {
+ /* Look to see if we can use pointers. */
+ n = *srcp;
+ if (n != 0 && msg != NULL) {
+ l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
+ (const u_char * const *)lpp);
+ if (l >= 0) {
+ if (dstp + 1 >= eob) {
+ goto cleanup;
+ }
+ *dstp++ = (l >> 8) | NS_CMPRSFLGS;
+ *dstp++ = l % 256;
+ return (dstp - dst);
+ }
+ /* Not found, save it. */
+ if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
+ (dstp - msg) < 0x4000 && first) {
+ *cpp++ = dstp;
+ *cpp = NULL;
+ first = 0;
+ }
+ }
+ /* copy label to buffer */
+ if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+ /* Should not happen. */
+ goto cleanup;
+ }
+ n = labellen(srcp);
+ if (dstp + 1 + n >= eob) {
+ goto cleanup;
+ }
+ memcpy(dstp, srcp, n + 1);
+ srcp += n + 1;
+ dstp += n + 1;
+ } while (n != 0);
+
+ if (dstp > eob) {
+cleanup:
+ if (msg != NULL)
+ *lpp = NULL;
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ return (dstp - dst);
+}
+
+/*
+ * ns_name_uncompress(msg, eom, src, dst, dstsiz)
+ * Expand compressed domain name to presentation format.
+ * return:
+ * Number of bytes read out of `src', or -1 (with errno set).
+ * note:
+ * Root domain returns as "." not "".
+ */
+int
+ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
+ char *dst, size_t dstsiz)
+{
+ u_char tmp[NS_MAXCDNAME];
+ int n;
+
+ if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
+ return (-1);
+ if (ns_name_ntop(tmp, dst, dstsiz) == -1)
+ return (-1);
+ return (n);
+}
+
+/*
+ * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr)
+ * Compress a domain name into wire format, using compression pointers.
+ * return:
+ * Number of bytes consumed in `dst' or -1 (with errno set).
+ * notes:
+ * 'dnptrs' is an array of pointers to previous compressed names.
+ * dnptrs[0] is a pointer to the beginning of the message.
+ * The list ends with NULL. 'lastdnptr' is a pointer to the end of the
+ * array pointed to by 'dnptrs'. Side effect is to update the list of
+ * pointers for labels inserted into the message as we compress the name.
+ * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
+ * is NULL, we don't update the list.
+ */
+int
+ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
+ const u_char **dnptrs, const u_char **lastdnptr)
+{
+ u_char tmp[NS_MAXCDNAME];
+
+ if (ns_name_pton(src, tmp, sizeof tmp) == -1)
+ return (-1);
+ return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
+}
+
+/*
+ * Reset dnptrs so that there are no active references to pointers at or
+ * after src.
+ */
+void
+ns_name_rollback(const u_char *src, const u_char **dnptrs,
+ const u_char **lastdnptr)
+{
+ while (dnptrs < lastdnptr && *dnptrs != NULL) {
+ if (*dnptrs >= src) {
+ *dnptrs = NULL;
+ break;
+ }
+ dnptrs++;
+ }
+}
+
+/*
+ * ns_name_skip(ptrptr, eom)
+ * Advance *ptrptr to skip over the compressed name it points at.
+ * return:
+ * 0 on success, -1 (with errno set) on failure.
+ */
+int
+ns_name_skip(const u_char **ptrptr, const u_char *eom)
+{
+ const u_char *cp;
+ u_int n;
+ int l;
+
+ cp = *ptrptr;
+ while (cp < eom && (n = *cp++) != 0) {
+ /* Check for indirection. */
+ switch (n & NS_CMPRSFLGS) {
+ case 0: /* normal case, n == len */
+ cp += n;
+ continue;
+ case NS_TYPE_ELT: /* EDNS0 extended label */
+ if ((l = labellen(cp - 1)) < 0) {
+ errno = EMSGSIZE; /* XXX */
+ return(-1);
+ }
+ cp += l;
+ continue;
+ case NS_CMPRSFLGS: /* indirection */
+ cp++;
+ break;
+ default: /* illegal type */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ break;
+ }
+ if (cp > eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *ptrptr = cp;
+ return (0);
+}
+
+/* Private. */
+
+/*
+ * special(ch)
+ * Thinking in noninternationalized USASCII (per the DNS spec),
+ * is this characted special ("in need of quoting") ?
+ * return:
+ * boolean.
+ */
+static int
+special(int ch) {
+ switch (ch) {
+ case 0x22: /* '"' */
+ case 0x2E: /* '.' */
+ case 0x3B: /* ';' */
+ case 0x5C: /* '\\' */
+ case 0x28: /* '(' */
+ case 0x29: /* ')' */
+ /* Special modifiers in zone files. */
+ case 0x40: /* '@' */
+ case 0x24: /* '$' */
+ return (1);
+ default:
+ return (0);
+ }
+}
+
+/*
+ * printable(ch)
+ * Thinking in noninternationalized USASCII (per the DNS spec),
+ * is this character visible and not a space when printed ?
+ * return:
+ * boolean.
+ */
+static int
+printable(int ch) {
+ return (ch > 0x20 && ch < 0x7f);
+}
+
+/*
+ * Thinking in noninternationalized USASCII (per the DNS spec),
+ * convert this character to lower case if it's upper case.
+ */
+static int
+mklower(int ch) {
+ if (ch >= 0x41 && ch <= 0x5A)
+ return (ch + 0x20);
+ return (ch);
+}
+
+/*
+ * dn_find(domain, msg, dnptrs, lastdnptr)
+ * Search for the counted-label name in an array of compressed names.
+ * return:
+ * offset from msg if found, or -1.
+ * notes:
+ * dnptrs is the pointer to the first name on the list,
+ * not the pointer to the start of the message.
+ */
+static int
+dn_find(const u_char *domain, const u_char *msg,
+ const u_char * const *dnptrs,
+ const u_char * const *lastdnptr)
+{
+ const u_char *dn, *cp, *sp;
+ const u_char * const *cpp;
+ u_int n;
+
+ for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
+ sp = *cpp;
+ /*
+ * terminate search on:
+ * root label
+ * compression pointer
+ * unusable offset
+ */
+ while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
+ (sp - msg) < 0x4000) {
+ dn = domain;
+ cp = sp;
+ while ((n = *cp++) != 0) {
+ /*
+ * check for indirection
+ */
+ switch (n & NS_CMPRSFLGS) {
+ case 0: /* normal case, n == len */
+ n = labellen(cp - 1); /* XXX */
+
+ if (n != *dn++)
+ goto next;
+
+ for ((void)NULL; n > 0; n--)
+ if (mklower(*dn++) !=
+ mklower(*cp++))
+ goto next;
+ /* Is next root for both ? */
+ if (*dn == '\0' && *cp == '\0')
+ return (sp - msg);
+ if (*dn)
+ continue;
+ goto next;
+ case NS_CMPRSFLGS: /* indirection */
+ cp = msg + (((n & 0x3f) << 8) | *cp);
+ break;
+
+ default: /* illegal type */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ }
+ next: ;
+ sp += *sp + 1;
+ }
+ }
+ errno = ENOENT;
+ return (-1);
+}
+
+static int
+decode_bitstring(const char **cpp, char *dn, const char *eom)
+{
+ const char *cp = *cpp;
+ char *beg = dn, tc;
+ int b, blen, plen, i;
+
+ 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++;
+ i = SPRINTF((dn, "\\[x"));
+ if (i < 0)
+ return (-1);
+ dn += i;
+ for (b = blen; b > 7; b -= 8, cp++) {
+ i = SPRINTF((dn, "%02x", *cp & 0xff));
+ if (i < 0)
+ return (-1);
+ dn += i;
+ }
+ if (b > 4) {
+ tc = *cp++;
+ i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b))));
+ if (i < 0)
+ return (-1);
+ dn += i;
+ } else if (b > 0) {
+ tc = *cp++;
+ i = SPRINTF((dn, "%1x",
+ ((tc >> 4) & 0x0f) & (0x0f << (4 - b))));
+ if (i < 0)
+ return (-1);
+ dn += i;
+ }
+ i = SPRINTF((dn, "/%d]", blen));
+ if (i < 0)
+ return (-1);
+ dn += i;
+
+ *cpp = cp;
+ return(dn - beg);
+}
+
+static int
+encode_bitsring(const char **bp, const char *end, char **labelp,
+ char ** dst, const char *eom)
+{
+ int afterslash = 0;
+ const char *cp = *bp;
+ char *tp, c;
+ const char *beg_blen;
+ char *end_blen = NULL;
+ int value = 0, count = 0, tbcount = 0, blen = 0;
+
+ beg_blen = end_blen = NULL;
+
+ /* a bitstring must contain at least 2 characters */
+ if (end - cp < 2)
+ return(EINVAL);
+
+ /* XXX: currently, only hex strings are supported */
+ if (*cp++ != 'x')
+ return(EINVAL);
+ if (!isxdigit((*cp) & 0xff)) /* reject '\[x/BLEN]' */
+ return(EINVAL);
+
+ for (tp = *dst + 1; cp < end && tp < eom; cp++) {
+ switch((c = *cp)) {
+ case ']': /* end of the bitstring */
+ if (afterslash) {
+ if (beg_blen == NULL)
+ return(EINVAL);
+ blen = (int)strtol(beg_blen, &end_blen, 10);
+ if (*end_blen != ']')
+ return(EINVAL);
+ }
+ if (count)
+ *tp++ = ((value << 4) & 0xff);
+ cp++; /* skip ']' */
+ goto done;
+ case '/':
+ afterslash = 1;
+ break;
+ default:
+ if (afterslash) {
+ if (!isdigit(c&0xff))
+ return(EINVAL);
+ if (beg_blen == NULL) {
+
+ if (c == '0') {
+ /* blen never begings with 0 */
+ return(EINVAL);
+ }
+ beg_blen = cp;
+ }
+ } else {
+ if (!isxdigit(c&0xff))
+ return(EINVAL);
+ value <<= 4;
+ value += digitvalue[(int)c];
+ count += 4;
+ tbcount += 4;
+ if (tbcount > 256)
+ return(EINVAL);
+ if (count == 8) {
+ *tp++ = value;
+ count = 0;
+ }
+ }
+ break;
+ }
+ }
+ done:
+ if (cp >= end || tp >= eom)
+ return(EMSGSIZE);
+
+ /*
+ * bit length validation:
+ * If a <length> is present, the number of digits in the <bit-data>
+ * MUST be just sufficient to contain the number of bits specified
+ * by the <length>. 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/usr/src/lib/libresolv2/common/nameser/ns_netint.c b/usr/src/lib/libresolv2/common/nameser/ns_netint.c
new file mode 100644
index 0000000000..e753ce9809
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/nameser/ns_netint.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_netint.c,v 8.4 1999/10/13 16:39:35 vixie Exp $";
+#endif
+
+/* Import. */
+
+#include "port_before.h"
+
+#include <arpa/nameser.h>
+
+#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/usr/src/lib/libresolv2/common/nameser/ns_parse.c b/usr/src/lib/libresolv2/common/nameser/ns_parse.c
new file mode 100644
index 0000000000..65476deeb2
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/nameser/ns_parse.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_parse.c,v 8.18 2003/04/03 06:10:10 marka Exp $";
+#endif
+
+/* Import. */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <string.h>
+
+#include "port_after.h"
+
+/* Forward. */
+
+static void setsection(ns_msg *msg, ns_sect sect);
+
+/* Macros. */
+
+#ifdef ORIGINAL_ISC_CODE
+#define RETERR(err) do { errno = (err); return (-1); } while (0)
+#else
+#define RETERR(err) { errno = (err); return (-1); }
+#endif
+
+/* 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;
+ int tmp;
+
+ /* Make section right. */
+ if ((tmp = section) < 0 || section >= ns_s_max)
+ RETERR(ENODEV);
+ if (section != handle->_sect)
+ setsection(handle, section);
+
+ /* Make rrnum right. */
+ if (rrnum == -1)
+ rrnum = handle->_rrnum;
+ if (rrnum < 0 || rrnum >= handle->_counts[(int)section])
+ RETERR(ENODEV);
+ if (rrnum < handle->_rrnum)
+ setsection(handle, section);
+ if (rrnum > handle->_rrnum) {
+ b = ns_skiprr(handle->_msg_ptr, handle->_eom, section,
+ rrnum - handle->_rrnum);
+
+ if (b < 0)
+ return (-1);
+ handle->_msg_ptr += b;
+ handle->_rrnum = rrnum;
+ }
+
+ /* Do the parse. */
+ b = dn_expand(handle->_msg, handle->_eom,
+ handle->_msg_ptr, rr->name, NS_MAXDNAME);
+ if (b < 0)
+ return (-1);
+ handle->_msg_ptr += b;
+ if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom)
+ RETERR(EMSGSIZE);
+ NS_GET16(rr->type, handle->_msg_ptr);
+ NS_GET16(rr->rr_class, handle->_msg_ptr);
+ if (section == ns_s_qd) {
+ rr->ttl = 0;
+ rr->rdlength = 0;
+ rr->rdata = NULL;
+ } else {
+ if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom)
+ RETERR(EMSGSIZE);
+ NS_GET32(rr->ttl, handle->_msg_ptr);
+ NS_GET16(rr->rdlength, handle->_msg_ptr);
+ if (handle->_msg_ptr + rr->rdlength > handle->_eom)
+ RETERR(EMSGSIZE);
+ rr->rdata = handle->_msg_ptr;
+ handle->_msg_ptr += rr->rdlength;
+ }
+ if (++handle->_rrnum > handle->_counts[(int)section])
+ setsection(handle, (ns_sect)((int)section + 1));
+
+ /* All done. */
+ return (0);
+}
+
+/* Private. */
+
+static void
+setsection(ns_msg *msg, ns_sect sect) {
+ msg->_sect = sect;
+ if (sect == ns_s_max) {
+ msg->_rrnum = -1;
+ msg->_msg_ptr = NULL;
+ } else {
+ msg->_rrnum = 0;
+ msg->_msg_ptr = msg->_sections[(int)sect];
+ }
+}
diff --git a/usr/src/lib/libresolv2/common/nameser/ns_print.c b/usr/src/lib/libresolv2/common/nameser/ns_print.c
new file mode 100644
index 0000000000..ced16b0828
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/nameser/ns_print.c
@@ -0,0 +1,913 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_print.c,v 8.26 2003/02/24 23:56:35 vixie Exp $";
+#endif
+
+/* Import. */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <isc/assertions.h>
+#include <isc/dst.h>
+#include <errno.h>
+#include <resolv.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/* Forward. */
+
+static 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);
+
+#ifdef ORIGINAL_ISC_CODE
+#else
+/* Proto. */
+
+u_int16_t dst_s_dns_key_id(const u_char *, const int);
+#endif
+
+/* Macros. */
+
+#define T(x) \
+ do { \
+ if ((x) < 0) \
+ return (-1); \
+ } while (0)
+
+/* Public. */
+
+/*
+ * int
+ * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen)
+ * Convert an RR to presentation format.
+ * return:
+ * Number of characters written to buf, or -1 (check errno).
+ */
+int
+ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
+ const char *name_ctx, const char *origin,
+ char *buf, size_t buflen)
+{
+ int n;
+
+ n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
+ ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
+ ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
+ name_ctx, origin, buf, buflen);
+ return (n);
+}
+
+/*
+ * int
+ * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen,
+ * name_ctx, origin, buf, buflen)
+ * Convert the fields of an RR into presentation format.
+ * return:
+ * Number of characters written to buf, or -1 (check errno).
+ */
+int
+ns_sprintrrf(const u_char *msg, size_t msglen,
+ const char *name, ns_class class, ns_type type,
+ u_long ttl, const u_char *rdata, size_t rdlen,
+ const char *name_ctx, const char *origin,
+ char *buf, size_t buflen)
+{
+ const char *obuf = buf;
+ const u_char *edata = rdata + rdlen;
+ int spaced = 0;
+
+ const char *comment;
+ char tmp[100];
+ int len, x;
+
+ /*
+ * Owner.
+ */
+ if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
+ T(addstr("\t\t\t", 3, &buf, &buflen));
+ } else {
+ len = prune_origin(name, origin);
+ if (*name == '\0') {
+ goto root;
+ } else if (len == 0) {
+ T(addstr("@\t\t\t", 4, &buf, &buflen));
+ } else {
+ T(addstr(name, len, &buf, &buflen));
+ /* Origin not used or not root, and no trailing dot? */
+ if (((origin == NULL || origin[0] == '\0') ||
+ (origin[0] != '.' && origin[1] != '\0' &&
+ name[len] == '\0')) && name[len - 1] != '.') {
+ root:
+ T(addstr(".", 1, &buf, &buflen));
+ len++;
+ }
+ T(spaced = addtab(len, 24, spaced, &buf, &buflen));
+ }
+ }
+
+ /*
+ * TTL, Class, Type.
+ */
+ T(x = ns_format_ttl(ttl, buf, buflen));
+ addlen(x, &buf, &buflen);
+ len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
+ T(addstr(tmp, len, &buf, &buflen));
+ if (rdlen == 0)
+ return (buf - obuf);
+ T(spaced = addtab(x + len, 16, spaced, &buf, &buflen));
+
+ /*
+ * RData.
+ */
+ switch (type) {
+ case ns_t_a:
+ if (rdlen != NS_INADDRSZ)
+ goto formerr;
+ (void) inet_ntop(AF_INET, rdata, buf, buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ break;
+
+ case ns_t_cname:
+ case ns_t_mb:
+ case ns_t_mg:
+ case ns_t_mr:
+ case ns_t_ns:
+ case ns_t_ptr:
+ case ns_t_dname:
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ break;
+
+ case ns_t_hinfo:
+ case ns_t_isdn:
+ /* First word. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+
+ /* Second word, optional in ISDN records. */
+ if (type == ns_t_isdn && rdata == edata)
+ break;
+
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ break;
+
+ case ns_t_soa: {
+ u_long t;
+
+ /* Server name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Administrator name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" (\n", 3, &buf, &buflen));
+ spaced = 0;
+
+ if ((edata - rdata) != 5*NS_INT32SZ)
+ goto formerr;
+
+ /* Serial number. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ len = SPRINTF((tmp, "%lu", t));
+ T(addstr(tmp, len, &buf, &buflen));
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; serial\n", 9, &buf, &buflen));
+ spaced = 0;
+
+ /* Refresh interval. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; refresh\n", 10, &buf, &buflen));
+ spaced = 0;
+
+ /* Retry interval. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; retry\n", 8, &buf, &buflen));
+ spaced = 0;
+
+ /* Expiry. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; expiry\n", 9, &buf, &buflen));
+ spaced = 0;
+
+ /* Minimum TTL. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(addstr(" )", 2, &buf, &buflen));
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; minimum\n", 10, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_mx:
+ case ns_t_afsdb:
+ case ns_t_rt: {
+ u_int t;
+
+ if (rdlen < NS_INT16SZ)
+ goto formerr;
+
+ /* Priority. */
+ t = ns_get16(rdata);
+ rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u ", t));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Target. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_px: {
+ u_int t;
+
+ if (rdlen < NS_INT16SZ)
+ goto formerr;
+
+ /* Priority. */
+ t = ns_get16(rdata);
+ rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u ", t));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Name1. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Name2. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_x25:
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ break;
+
+ case ns_t_txt:
+ while (rdata < edata) {
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ if (rdata < edata)
+ T(addstr(" ", 1, &buf, &buflen));
+ }
+ break;
+
+ case ns_t_nsap: {
+ char t[2+255*3];
+
+ (void) inet_nsap_ntoa(rdlen, rdata, t);
+ T(addstr(t, strlen(t), &buf, &buflen));
+ break;
+ }
+
+ case ns_t_aaaa:
+ if (rdlen != NS_IN6ADDRSZ)
+ goto formerr;
+ (void) inet_ntop(AF_INET6, rdata, buf, buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ break;
+
+ case ns_t_loc: {
+ char t[255];
+
+ /* XXX protocol format checking? */
+ (void) loc_ntoa(rdata, t);
+ T(addstr(t, strlen(t), &buf, &buflen));
+ break;
+ }
+
+ case ns_t_naptr: {
+ u_int order, preference;
+ char t[50];
+
+ if (rdlen < 2*NS_INT16SZ)
+ goto formerr;
+
+ /* Order, Precedence. */
+ order = ns_get16(rdata); rdata += NS_INT16SZ;
+ preference = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((t, "%u %u ", order, preference));
+ T(addstr(t, len, &buf, &buflen));
+
+ /* Flags. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Service. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Regexp. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len < 0)
+ return (-1);
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Server. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ break;
+ }
+
+ case ns_t_srv: {
+ u_int priority, weight, port;
+ char t[50];
+
+ if (rdlen < NS_INT16SZ*3)
+ goto formerr;
+
+ /* Priority, Weight, Port. */
+ priority = ns_get16(rdata); rdata += NS_INT16SZ;
+ weight = ns_get16(rdata); rdata += NS_INT16SZ;
+ port = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((t, "%u %u %u ", priority, weight, port));
+ T(addstr(t, len, &buf, &buflen));
+
+ /* Server. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ break;
+ }
+
+ case ns_t_minfo:
+ case ns_t_rp:
+ /* Name1. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Name2. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+
+ case ns_t_wks: {
+ int n, lcnt;
+
+ if (rdlen < NS_INT32SZ + 1)
+ goto formerr;
+
+ /* Address. */
+ (void) inet_ntop(AF_INET, rdata, buf, buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ rdata += NS_INADDRSZ;
+
+ /* Protocol. */
+ len = SPRINTF((tmp, " %u ( ", *rdata));
+ T(addstr(tmp, len, &buf, &buflen));
+ rdata += NS_INT8SZ;
+
+ /* Bit map. */
+ n = 0;
+ lcnt = 0;
+ while (rdata < edata) {
+ u_int c = *rdata++;
+ do {
+ if (c & 0200) {
+ if (lcnt == 0) {
+ T(addstr("\n\t\t\t\t", 5,
+ &buf, &buflen));
+ lcnt = 10;
+ spaced = 0;
+ }
+ len = SPRINTF((tmp, "%d ", n));
+ T(addstr(tmp, len, &buf, &buflen));
+ lcnt--;
+ }
+ c <<= 1;
+ } while (++n & 07);
+ }
+ T(addstr(")", 1, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_key: {
+ char base64_key[NS_MD5RSA_MAX_BASE64];
+ u_int keyflags, protocol, algorithm, key_id;
+ const char *leader;
+ int n;
+
+ if (rdlen < NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
+ goto formerr;
+
+ /* Key flags, Protocol, Algorithm. */
+ key_id = dst_s_dns_key_id(rdata, edata-rdata);
+ keyflags = ns_get16(rdata); rdata += NS_INT16SZ;
+ protocol = *rdata++;
+ algorithm = *rdata++;
+ len = SPRINTF((tmp, "0x%04x %u %u",
+ keyflags, protocol, algorithm));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Public key data. */
+ len = b64_ntop(rdata, edata - rdata,
+ base64_key, sizeof base64_key);
+ if (len < 0)
+ goto formerr;
+ if (len > 15) {
+ T(addstr(" (", 2, &buf, &buflen));
+ leader = "\n\t\t";
+ spaced = 0;
+ } else
+ leader = " ";
+ for (n = 0; n < len; n += 48) {
+ T(addstr(leader, strlen(leader), &buf, &buflen));
+ T(addstr(base64_key + n, MIN(len - n, 48),
+ &buf, &buflen));
+ }
+ if (len > 15)
+ T(addstr(" )", 2, &buf, &buflen));
+ n = SPRINTF((tmp, " ; key_tag= %u", key_id));
+ T(addstr(tmp, n, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_sig: {
+ char base64_key[NS_MD5RSA_MAX_BASE64];
+ u_int type, algorithm, labels, footprint;
+ const char *leader;
+ u_long t;
+ int n;
+
+ if (rdlen < 22)
+ goto formerr;
+
+ /* Type covered, Algorithm, Label count, Original TTL. */
+ type = ns_get16(rdata); rdata += NS_INT16SZ;
+ algorithm = *rdata++;
+ labels = *rdata++;
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s %d %d %lu ",
+ p_type(type), algorithm, labels, t));
+ T(addstr(tmp, len, &buf, &buflen));
+ if (labels > (u_int)dn_count_labels(name))
+ goto formerr;
+
+ /* Signature expiry. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Time signed. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Signature Footprint. */
+ footprint = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u ", footprint));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Signer's name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ /* Signature. */
+ len = b64_ntop(rdata, edata - rdata,
+ base64_key, sizeof base64_key);
+ if (len > 15) {
+ T(addstr(" (", 2, &buf, &buflen));
+ leader = "\n\t\t";
+ spaced = 0;
+ } else
+ leader = " ";
+ if (len < 0)
+ goto formerr;
+ for (n = 0; n < len; n += 48) {
+ T(addstr(leader, strlen(leader), &buf, &buflen));
+ T(addstr(base64_key + n, MIN(len - n, 48),
+ &buf, &buflen));
+ }
+ if (len > 15)
+ T(addstr(" )", 2, &buf, &buflen));
+ break;
+ }
+
+ case ns_t_nxt: {
+ int n, c;
+
+ /* Next domain name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ /* Type bit map. */
+ n = edata - rdata;
+ for (c = 0; c < n*8; c++)
+ if (NS_NXT_BIT_ISSET(c, rdata)) {
+ len = SPRINTF((tmp, " %s", p_type(c)));
+ T(addstr(tmp, len, &buf, &buflen));
+ }
+ break;
+ }
+
+ case ns_t_cert: {
+ u_int c_type, key_tag, alg;
+ int n;
+ unsigned int siz;
+ char base64_cert[8192], tmp[40];
+ const char *leader;
+
+ c_type = ns_get16(rdata); rdata += NS_INT16SZ;
+ key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
+ alg = (u_int) *rdata++;
+
+ len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg));
+ T(addstr(tmp, len, &buf, &buflen));
+ siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
+ if (siz > sizeof(base64_cert) * 3/4) {
+ const char *str = "record too long to print";
+ T(addstr(str, strlen(str), &buf, &buflen));
+ }
+ else {
+ len = b64_ntop(rdata, edata-rdata, base64_cert, siz);
+
+ if (len < 0)
+ goto formerr;
+ else if (len > 15) {
+ T(addstr(" (", 2, &buf, &buflen));
+ leader = "\n\t\t";
+ spaced = 0;
+ }
+ else
+ leader = " ";
+
+ for (n = 0; n < len; n += 48) {
+ T(addstr(leader, strlen(leader),
+ &buf, &buflen));
+ T(addstr(base64_cert + n, MIN(len - n, 48),
+ &buf, &buflen));
+ }
+ if (len > 15)
+ T(addstr(" )", 2, &buf, &buflen));
+ }
+ break;
+ }
+
+ case ns_t_tkey: {
+ /* KJD - need to complete this */
+ u_long t;
+ int mode, err, keysize;
+
+ /* Algorithm name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Inception. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Experation. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Mode , Error, Key Size. */
+ /* Priority, Weight, Port. */
+ mode = ns_get16(rdata); rdata += NS_INT16SZ;
+ err = ns_get16(rdata); rdata += NS_INT16SZ;
+ keysize = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* need to dump key, print otherdata length & other data */
+ break;
+ }
+
+ case ns_t_tsig: {
+ /* BEW - need to complete this */
+ int n;
+
+ T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+ rdata += 8; /* time */
+ n = ns_get16(rdata); rdata += INT16SZ;
+ rdata += n; /* sig */
+ n = ns_get16(rdata); rdata += INT16SZ; /* original id */
+ sprintf(buf, "%d", ns_get16(rdata));
+ rdata += INT16SZ;
+ addlen(strlen(buf), &buf, &buflen);
+ break;
+ }
+
+ case ns_t_a6: {
+ struct in6_addr a;
+ int pbyte, pbit;
+
+ /* prefix length */
+ if (rdlen == 0) goto formerr;
+ len = SPRINTF((tmp, "%d ", *rdata));
+ T(addstr(tmp, len, &buf, &buflen));
+ pbit = *rdata;
+ if (pbit > 128) goto formerr;
+ pbyte = (pbit & ~7) / 8;
+ rdata++;
+
+ /* address suffix: provided only when prefix len != 128 */
+ if (pbit < 128) {
+ if (rdata + pbyte >= edata) goto formerr;
+ memset(&a, 0, sizeof(a));
+ memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte);
+ (void) inet_ntop(AF_INET6, &a, buf, buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ rdata += sizeof(a) - pbyte;
+ }
+
+ /* prefix name: provided only when prefix len > 0 */
+ if (pbit == 0)
+ break;
+ if (rdata >= edata) goto formerr;
+ T(addstr(" ", 1, &buf, &buflen));
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_opt: {
+ len = SPRINTF((tmp, "%u bytes", class));
+ T(addstr(tmp, len, &buf, &buflen));
+ break;
+ }
+
+ default:
+ comment = "unknown RR type";
+ goto hexify;
+ }
+ return (buf - obuf);
+ formerr:
+ comment = "RR format error";
+ hexify: {
+ int n, m;
+ char *p;
+
+ len = SPRINTF((tmp, "\\# %u (\t; %s", edata - rdata, comment));
+ T(addstr(tmp, len, &buf, &buflen));
+ while (rdata < edata) {
+ p = tmp;
+ p += SPRINTF((p, "\n\t"));
+ spaced = 0;
+ n = MIN(16, edata - rdata);
+ for (m = 0; m < n; m++)
+ p += SPRINTF((p, "%02x ", rdata[m]));
+ T(addstr(tmp, p - tmp, &buf, &buflen));
+ if (n < 16) {
+ T(addstr(")", 1, &buf, &buflen));
+ T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen));
+ }
+ p = tmp;
+ p += SPRINTF((p, "; "));
+ for (m = 0; m < n; m++)
+ *p++ = (isascii(rdata[m]) && isprint(rdata[m]))
+ ? rdata[m]
+ : '.';
+ T(addstr(tmp, p - tmp, &buf, &buflen));
+ rdata += n;
+ }
+ return (buf - obuf);
+ }
+}
+
+/* Private. */
+
+/*
+ * size_t
+ * prune_origin(name, origin)
+ * Find out if the name is at or under the current origin.
+ * return:
+ * Number of characters in name before start of origin,
+ * or length of name if origin does not match.
+ * notes:
+ * This function should share code with samedomain().
+ */
+static size_t
+prune_origin(const char *name, const char *origin) {
+ const char *oname = name;
+
+ while (*name != '\0') {
+ if (origin != NULL && ns_samename(name, origin) == 1)
+ return (name - oname - (name > oname));
+ while (*name != '\0') {
+ if (*name == '\\') {
+ name++;
+ /* XXX need to handle \nnn form. */
+ if (*name == '\0')
+ break;
+ } else if (*name == '.') {
+ name++;
+ break;
+ }
+ name++;
+ }
+ }
+ return (name - oname);
+}
+
+/*
+ * int
+ * charstr(rdata, edata, buf, buflen)
+ * Format a <character-string> 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/usr/src/lib/libresolv2/common/nameser/ns_samedomain.c b/usr/src/lib/libresolv2/common/nameser/ns_samedomain.c
new file mode 100644
index 0000000000..9ae0195f27
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/nameser/ns_samedomain.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1995,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_samedomain.c,v 8.11 2003/04/14 14:52:48 vixie Exp $";
+#endif
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <arpa/nameser.h>
+#include <errno.h>
+#include <string.h>
+
+#include "port_after.h"
+
+/*
+ * int
+ * ns_samedomain(a, b)
+ * Check whether a name belongs to a domain.
+ * Inputs:
+ * a - the domain whose ancestory is being verified
+ * b - the potential ancestor we're checking against
+ * Return:
+ * boolean - is a at or below b?
+ * Notes:
+ * Trailing dots are first removed from name and domain.
+ * Always compare complete subdomains, not only whether the
+ * domain name is the trailing string of the given name.
+ *
+ * "host.foobar.top" lies in "foobar.top" and in "top" and in ""
+ * but NOT in "bar.top"
+ */
+
+int
+ns_samedomain(const char *a, const char *b) {
+ size_t la, lb;
+ int diff, i, escaped;
+ const char *cp;
+
+ la = strlen(a);
+ lb = strlen(b);
+
+ /* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */
+ if (la != 0 && a[la - 1] == '.') {
+ escaped = 0;
+ /* Note this loop doesn't get executed if la==1. */
+ for (i = la - 2; i >= 0; i--)
+ if (a[i] == '\\') {
+ if (escaped)
+ escaped = 0;
+ else
+ escaped = 1;
+ } else
+ break;
+ if (!escaped)
+ la--;
+ }
+
+ /* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */
+ if (lb != 0 && b[lb - 1] == '.') {
+ escaped = 0;
+ /* note this loop doesn't get executed if lb==1 */
+ for (i = lb - 2; i >= 0; i--)
+ if (b[i] == '\\') {
+ if (escaped)
+ escaped = 0;
+ else
+ escaped = 1;
+ } else
+ break;
+ if (!escaped)
+ lb--;
+ }
+
+ /* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */
+ if (lb == 0)
+ return (1);
+
+ /* 'b' longer than 'a' means 'a' can't be in 'b'. */
+ if (lb > la)
+ return (0);
+
+ /* 'a' and 'b' being equal at this point indicates sameness. */
+ if (lb == la)
+ return (strncasecmp(a, b, lb) == 0);
+
+ /* Ok, we know la > lb. */
+
+ diff = la - lb;
+
+ /*
+ * If 'a' is only 1 character longer than 'b', then it can't be
+ * a subdomain of 'b' (because of the need for the '.' label
+ * separator).
+ */
+ if (diff < 2)
+ return (0);
+
+ /*
+ * If the character before the last 'lb' characters of 'b'
+ * isn't '.', then it can't be a match (this lets us avoid
+ * having "foobar.com" match "bar.com").
+ */
+ if (a[diff - 1] != '.')
+ return (0);
+
+ /*
+ * We're not sure about that '.', however. It could be escaped
+ * and thus not a really a label separator.
+ */
+ escaped = 0;
+ for (i = diff - 2; i >= 0; i--)
+ if (a[i] == '\\') {
+ if (escaped)
+ escaped = 0;
+ else
+ escaped = 1;
+ } else
+ break;
+ if (escaped)
+ return (0);
+
+ /* Now compare aligned trailing substring. */
+ cp = a + diff;
+ return (strncasecmp(cp, b, lb) == 0);
+}
+
+/*
+ * int
+ * ns_subdomain(a, b)
+ * is "a" a subdomain of "b"?
+ */
+int
+ns_subdomain(const char *a, const char *b) {
+ return (ns_samename(a, b) != 1 && ns_samedomain(a, b));
+}
+
+/*
+ * int
+ * ns_makecanon(src, dst, dstsize)
+ * make a canonical copy of domain name "src"
+ * notes:
+ * foo -> foo.
+ * foo. -> foo.
+ * foo.. -> foo.
+ * foo\. -> foo\..
+ * foo\\. -> foo\\.
+ */
+
+int
+ns_makecanon(const char *src, char *dst, size_t dstsize) {
+ size_t n = strlen(src);
+
+ if (n + sizeof "." > dstsize) { /* Note: sizeof == 2 */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ strcpy(dst, src);
+ while (n >= 1 && dst[n - 1] == '.') /* Ends in "." */
+ if (n >= 2 && dst[n - 2] == '\\' && /* Ends in "\." */
+ (n < 3 || 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/usr/src/lib/libresolv2/common/nameser/ns_sign.c b/usr/src/lib/libresolv2/common/nameser/ns_sign.c
new file mode 100644
index 0000000000..74674134c5
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/nameser/ns_sign.c
@@ -0,0 +1,387 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1999 by Internet Software Consortium, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_sign.c,v 8.12 2002/10/01 06:48:37 marka Exp $";
+#endif
+
+/* Import. */
+
+#include "port_before.h"
+#include "fd_setsize.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/dst.h>
+#include <isc/assertions.h>
+
+#include "port_after.h"
+
+#define BOUNDS_CHECK(ptr, count) \
+ do { \
+ if ((ptr) + (count) > eob) { \
+ errno = EMSGSIZE; \
+ return(NS_TSIG_ERROR_NO_SPACE); \
+ } \
+ } while (0)
+
+/* ns_sign
+ * Parameters:
+ * msg message to be sent
+ * msglen input - length of message
+ * output - length of signed message
+ * msgsize length of buffer containing message
+ * error value to put in the error field
+ * key tsig key used for signing
+ * querysig (response), the signature in the query
+ * querysiglen (response), the length of the signature in the query
+ * sig a buffer to hold the generated signature
+ * siglen input - length of signature buffer
+ * output - length of signature
+ *
+ * Errors:
+ * - bad input data (-1)
+ * - bad key / sign failed (-BADKEY)
+ * - not enough space (NS_TSIG_ERROR_NO_SPACE)
+ */
+int
+ns_sign(u_char *msg, int *msglen, int msgsize, int error, void *k,
+ const u_char *querysig, int querysiglen, u_char *sig, int *siglen,
+ time_t in_timesigned)
+{
+ return(ns_sign2(msg, msglen, msgsize, error, k,
+ querysig, querysiglen, sig, siglen,
+ in_timesigned, NULL, NULL));
+}
+
+int
+ns_sign2(u_char *msg, int *msglen, int msgsize, int error, void *k,
+ const u_char *querysig, int querysiglen, u_char *sig, int *siglen,
+ time_t in_timesigned, u_char **dnptrs, u_char **lastdnptr)
+{
+ HEADER *hp = (HEADER *)msg;
+ DST_KEY *key = (DST_KEY *)k;
+ u_char *cp = msg + *msglen, *eob = msg + msgsize;
+ u_char *lenp;
+ u_char *alg;
+ int n;
+ time_t timesigned;
+ u_char name[NS_MAXCDNAME];
+
+ 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 = ns_name_pton(key->dk_key_name, name, sizeof name);
+ if (n != -1)
+ n = ns_name_pack(name, cp, eob - cp,
+ (const u_char **)dnptrs,
+ (const u_char **)lastdnptr);
+
+ } else {
+ n = ns_name_pton("", name, sizeof name);
+ if (n != -1)
+ n = ns_name_pack(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. */
+ 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[NS_MAXCDNAME], *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));
+ INSIST(n > 0);
+ 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));
+ INSIST(n > 0);
+ dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0);
+
+ /* Digest the time signed, fudge, error, and other data */
+ cp2 = buf;
+ PUTSHORT(0, cp2); /* Top 16 bits of time */
+ if (error != ns_r_badtime)
+ PUTLONG(timesigned, cp2);
+ else
+ PUTLONG(in_timesigned, cp2);
+ PUTSHORT(NS_TSIG_FUDGE, cp2);
+ PUTSHORT(error, cp2); /* Error */
+ if (error != ns_r_badtime)
+ PUTSHORT(0, cp2); /* Other data length */
+ else {
+ PUTSHORT(INT16SZ+INT32SZ, cp2); /* Other data length */
+ PUTSHORT(0, cp2); /* Top 16 bits of time */
+ PUTLONG(timesigned, cp2);
+ }
+ dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, cp2-buf,
+ NULL, 0);
+
+ n = dst_sign_data(SIG_MODE_FINAL, key, &ctx, NULL, 0,
+ sig, *siglen);
+ if (n < 0)
+ return (-ns_r_badkey);
+ *siglen = n;
+ } else
+ *siglen = 0;
+
+ /* Add the signature. */
+ BOUNDS_CHECK(cp, INT16SZ + (*siglen));
+ PUTSHORT(*siglen, cp);
+ memcpy(cp, sig, *siglen);
+ cp += (*siglen);
+
+ /* The original message ID & error. */
+ BOUNDS_CHECK(cp, INT16SZ + INT16SZ);
+ PUTSHORT(ntohs(hp->id), cp); /* already in network order */
+ PUTSHORT(error, cp);
+
+ /* Other data. */
+ BOUNDS_CHECK(cp, INT16SZ);
+ if (error != ns_r_badtime)
+ PUTSHORT(0, cp); /* Other data length */
+ else {
+ PUTSHORT(INT16SZ+INT32SZ, cp); /* Other data length */
+ BOUNDS_CHECK(cp, INT32SZ+INT16SZ);
+ PUTSHORT(0, cp); /* Top 16 bits of time */
+ PUTLONG(timesigned, cp);
+ }
+
+ /* Go back and fill in the length. */
+ PUTSHORT(cp - lenp - INT16SZ, lenp);
+
+ hp->arcount = htons(ntohs(hp->arcount) + 1);
+ *msglen = (cp - msg);
+ return (0);
+}
+
+int
+ns_sign_tcp_init(void *k, const u_char *querysig, int querysiglen,
+ ns_tcp_tsig_state *state)
+{
+ dst_init();
+ if (state == NULL || k == NULL || querysig == NULL || querysiglen < 0)
+ return (-1);
+ state->counter = -1;
+ state->key = k;
+ if (state->key->dk_alg != KEY_HMAC_MD5)
+ return (-ns_r_badkey);
+ if (querysiglen > (int)sizeof(state->sig))
+ return (-1);
+ memcpy(state->sig, querysig, querysiglen);
+ state->siglen = querysiglen;
+ return (0);
+}
+
+int
+ns_sign_tcp(u_char *msg, int *msglen, int msgsize, int error,
+ ns_tcp_tsig_state *state, int done)
+{
+ return (ns_sign_tcp2(msg, msglen, msgsize, error, state,
+ done, NULL, NULL));
+}
+
+int
+ns_sign_tcp2(u_char *msg, int *msglen, int msgsize, int error,
+ ns_tcp_tsig_state *state, int done,
+ u_char **dnptrs, u_char **lastdnptr)
+{
+ u_char *cp, *eob, *lenp;
+ u_char buf[MAXDNAME], *cp2;
+ HEADER *hp = (HEADER *)msg;
+ time_t timesigned;
+ int n;
+
+ if (msg == NULL || msglen == NULL || state == NULL)
+ return (-1);
+
+ state->counter++;
+ if (state->counter == 0)
+ return (ns_sign2(msg, msglen, msgsize, error, state->key,
+ state->sig, state->siglen,
+ state->sig, &state->siglen, 0,
+ dnptrs, lastdnptr));
+
+ if (state->siglen > 0) {
+ u_int16_t siglen_n = htons(state->siglen);
+ dst_sign_data(SIG_MODE_INIT, state->key, &state->ctx,
+ NULL, 0, NULL, 0);
+ dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx,
+ (u_char *)&siglen_n, INT16SZ, NULL, 0);
+ dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx,
+ state->sig, state->siglen, NULL, 0);
+ state->siglen = 0;
+ }
+
+ dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, msg, *msglen,
+ NULL, 0);
+
+ if (done == 0 && (state->counter % 100 != 0))
+ return (0);
+
+ cp = msg + *msglen;
+ eob = msg + msgsize;
+
+ /* Name. */
+ n = dn_comp(state->key->dk_key_name, cp, eob - cp, dnptrs, lastdnptr);
+ if (n < 0)
+ return (NS_TSIG_ERROR_NO_SPACE);
+ cp += n;
+
+ /* Type, class, ttl, length (not filled in yet). */
+ BOUNDS_CHECK(cp, INT16SZ + INT16SZ + INT32SZ + INT16SZ);
+ PUTSHORT(ns_t_tsig, cp);
+ PUTSHORT(ns_c_any, cp);
+ PUTLONG(0, cp); /* TTL */
+ lenp = cp;
+ cp += 2;
+
+ /* Alg. */
+ n = dn_comp(NS_TSIG_ALG_HMAC_MD5, cp, eob - cp, NULL, NULL);
+ if (n < 0)
+ return (NS_TSIG_ERROR_NO_SPACE);
+ cp += n;
+
+ /* Time. */
+ BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ);
+ PUTSHORT(0, cp);
+ timesigned = time(NULL);
+ PUTLONG(timesigned, cp);
+ PUTSHORT(NS_TSIG_FUDGE, cp);
+
+ /*
+ * Compute the signature.
+ */
+
+ /* Digest the time signed and fudge. */
+ cp2 = buf;
+ PUTSHORT(0, cp2); /* Top 16 bits of time */
+ PUTLONG(timesigned, cp2);
+ PUTSHORT(NS_TSIG_FUDGE, cp2);
+
+ dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx,
+ buf, cp2 - buf, NULL, 0);
+
+ n = dst_sign_data(SIG_MODE_FINAL, state->key, &state->ctx, NULL, 0,
+ state->sig, sizeof(state->sig));
+ if (n < 0)
+ return (-ns_r_badkey);
+ state->siglen = n;
+
+ /* Add the signature. */
+ BOUNDS_CHECK(cp, INT16SZ + state->siglen);
+ PUTSHORT(state->siglen, cp);
+ memcpy(cp, state->sig, state->siglen);
+ cp += state->siglen;
+
+ /* The original message ID & error. */
+ BOUNDS_CHECK(cp, INT16SZ + INT16SZ);
+ PUTSHORT(ntohs(hp->id), cp); /* already in network order */
+ PUTSHORT(error, cp);
+
+ /* Other data. */
+ BOUNDS_CHECK(cp, INT16SZ);
+ PUTSHORT(0, cp);
+
+ /* Go back and fill in the length. */
+ PUTSHORT(cp - lenp - INT16SZ, lenp);
+
+ hp->arcount = htons(ntohs(hp->arcount) + 1);
+ *msglen = (cp - msg);
+ return (0);
+}
diff --git a/usr/src/lib/libresolv2/common/nameser/ns_ttl.c b/usr/src/lib/libresolv2/common/nameser/ns_ttl.c
new file mode 100644
index 0000000000..274359036f
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/nameser/ns_ttl.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_ttl.c,v 8.8 1999/10/13 16:39:36 vixie Exp $";
+#endif
+
+/* Import. */
+
+#include "port_before.h"
+
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/* Forward. */
+
+static int 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/usr/src/lib/libresolv2/common/nameser/ns_verify.c b/usr/src/lib/libresolv2/common/nameser/ns_verify.c
new file mode 100644
index 0000000000..c8ccf219d5
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/nameser/ns_verify.c
@@ -0,0 +1,487 @@
+/*
+ * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1999 by Internet Software Consortium, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_verify.c,v 8.14 2001/05/29 05:49:40 marka Exp $";
+#endif
+
+/* Import. */
+
+#include "port_before.h"
+#include "fd_setsize.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/dst.h>
+
+#include "port_after.h"
+
+/* Private. */
+
+#define BOUNDS_CHECK(ptr, count) \
+ do { \
+ if ((ptr) + (count) > eom) { \
+ return (NS_TSIG_ERROR_FORMERR); \
+ } \
+ } while (0)
+
+/* Public. */
+
+u_char *
+ns_find_tsig(u_char *msg, u_char *eom) {
+ HEADER *hp = (HEADER *)msg;
+ int n, type;
+ u_char *cp = msg, *start;
+
+ if (msg == NULL || eom == NULL || msg > eom)
+ return (NULL);
+
+ if (cp + HFIXEDSZ >= eom)
+ return (NULL);
+
+ if (hp->arcount == 0)
+ return (NULL);
+
+ cp += HFIXEDSZ;
+
+ n = ns_skiprr(cp, eom, ns_s_qd, ntohs(hp->qdcount));
+ if (n < 0)
+ return (NULL);
+ cp += n;
+
+ n = ns_skiprr(cp, eom, ns_s_an, ntohs(hp->ancount));
+ if (n < 0)
+ return (NULL);
+ cp += n;
+
+ n = ns_skiprr(cp, eom, ns_s_ns, ntohs(hp->nscount));
+ if (n < 0)
+ return (NULL);
+ cp += n;
+
+ n = ns_skiprr(cp, eom, ns_s_ar, ntohs(hp->arcount) - 1);
+ if (n < 0)
+ return (NULL);
+ cp += n;
+
+ start = cp;
+ n = dn_skipname(cp, eom);
+ if (n < 0)
+ return (NULL);
+ cp += n;
+ if (cp + INT16SZ >= eom)
+ return (NULL);
+
+ GETSHORT(type, cp);
+ if (type != ns_t_tsig)
+ return (NULL);
+ return (start);
+}
+
+/* ns_verify
+ * Parameters:
+ * statp res stuff
+ * msg received message
+ * msglen length of message
+ * key tsig key used for verifying.
+ * querysig (response), the signature in the query
+ * querysiglen (response), the length of the signature in the query
+ * sig (query), a buffer to hold the signature
+ * siglen (query), input - length of signature buffer
+ * output - length of signature
+ *
+ * Errors:
+ * - bad input (-1)
+ * - invalid dns message (NS_TSIG_ERROR_FORMERR)
+ * - TSIG is not present (NS_TSIG_ERROR_NO_TSIG)
+ * - key doesn't match (-ns_r_badkey)
+ * - TSIG verification fails with BADKEY (-ns_r_badkey)
+ * - TSIG verification fails with BADSIG (-ns_r_badsig)
+ * - TSIG verification fails with BADTIME (-ns_r_badtime)
+ * - TSIG verification succeeds, error set to BAKEY (ns_r_badkey)
+ * - TSIG verification succeeds, error set to BADSIG (ns_r_badsig)
+ * - TSIG verification succeeds, error set to BADTIME (ns_r_badtime)
+ */
+int
+ns_verify(u_char *msg, int *msglen, void *k,
+ const u_char *querysig, int querysiglen, u_char *sig, int *siglen,
+ time_t *timesigned, int nostrip)
+{
+ HEADER *hp = (HEADER *)msg;
+ DST_KEY *key = (DST_KEY *)k;
+ u_char *cp = msg, *eom;
+ char name[MAXDNAME], alg[MAXDNAME];
+ u_char *recstart, *rdatastart;
+ u_char *sigstart, *otherstart;
+ int n;
+ int error;
+ u_int16_t type, length;
+ u_int16_t fudge, sigfieldlen, id, otherfieldlen;
+
+ dst_init();
+ if (msg == NULL || msglen == NULL || *msglen < 0)
+ return (-1);
+
+ eom = msg + *msglen;
+
+ recstart = ns_find_tsig(msg, eom);
+ if (recstart == NULL)
+ return (NS_TSIG_ERROR_NO_TSIG);
+
+ cp = recstart;
+
+ /* Read the key name. */
+ n = dn_expand(msg, eom, cp, name, MAXDNAME);
+ if (n < 0)
+ return (NS_TSIG_ERROR_FORMERR);
+ cp += n;
+
+ /* Read the type. */
+ BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ);
+ GETSHORT(type, cp);
+ if (type != ns_t_tsig)
+ return (NS_TSIG_ERROR_NO_TSIG);
+
+ /* Skip the class and TTL, save the length. */
+ cp += INT16SZ + INT32SZ;
+ GETSHORT(length, cp);
+ if (eom - cp != length)
+ return (NS_TSIG_ERROR_FORMERR);
+
+ /* Read the algorithm name. */
+ rdatastart = cp;
+ n = dn_expand(msg, eom, cp, alg, MAXDNAME);
+ if (n < 0)
+ return (NS_TSIG_ERROR_FORMERR);
+ if (ns_samename(alg, NS_TSIG_ALG_HMAC_MD5) != 1)
+ return (-ns_r_badkey);
+ cp += n;
+
+ /* Read the time signed and fudge. */
+ BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ);
+ cp += INT16SZ;
+ GETLONG((*timesigned), cp);
+ GETSHORT(fudge, cp);
+
+ /* Read the signature. */
+ BOUNDS_CHECK(cp, INT16SZ);
+ GETSHORT(sigfieldlen, cp);
+ BOUNDS_CHECK(cp, sigfieldlen);
+ sigstart = cp;
+ cp += sigfieldlen;
+
+ /* Read the original id and error. */
+ BOUNDS_CHECK(cp, 2*INT16SZ);
+ GETSHORT(id, cp);
+ GETSHORT(error, cp);
+
+ /* Parse the other data. */
+ BOUNDS_CHECK(cp, INT16SZ);
+ GETSHORT(otherfieldlen, cp);
+ BOUNDS_CHECK(cp, otherfieldlen);
+ otherstart = cp;
+ cp += otherfieldlen;
+
+ if (cp != eom)
+ return (NS_TSIG_ERROR_FORMERR);
+
+ /* Verify that the key used is OK. */
+ if (key != NULL) {
+ if (key->dk_alg != KEY_HMAC_MD5)
+ return (-ns_r_badkey);
+ if (error != ns_r_badsig && error != ns_r_badkey) {
+ if (ns_samename(key->dk_key_name, name) != 1)
+ return (-ns_r_badkey);
+ }
+ }
+
+ hp->arcount = htons(ntohs(hp->arcount) - 1);
+
+ /*
+ * Do the verification.
+ */
+
+ if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) {
+ void *ctx;
+ u_char buf[MAXDNAME];
+ 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, &timesigned, 0));
+
+ if (state->siglen > 0) {
+ u_int16_t siglen_n = htons(state->siglen);
+
+ dst_verify_data(SIG_MODE_INIT, state->key, &state->ctx,
+ NULL, 0, NULL, 0);
+ dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx,
+ (u_char *)&siglen_n, INT16SZ, NULL, 0);
+ dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx,
+ state->sig, state->siglen, NULL, 0);
+ state->siglen = 0;
+ }
+
+ cp = recstart = ns_find_tsig(msg, eom);
+
+ if (recstart == NULL) {
+ if (required)
+ return (NS_TSIG_ERROR_NO_TSIG);
+ dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx,
+ msg, *msglen, NULL, 0);
+ return (0);
+ }
+
+ hp->arcount = htons(ntohs(hp->arcount) - 1);
+ dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx,
+ msg, recstart - msg, NULL, 0);
+
+ /* Read the key name. */
+ n = dn_expand(msg, eom, cp, name, MAXDNAME);
+ if (n < 0)
+ return (NS_TSIG_ERROR_FORMERR);
+ cp += n;
+
+ /* Read the type. */
+ BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ);
+ GETSHORT(type, cp);
+ if (type != ns_t_tsig)
+ return (NS_TSIG_ERROR_NO_TSIG);
+
+ /* Skip the class and TTL, save the length. */
+ cp += INT16SZ + INT32SZ;
+ GETSHORT(length, cp);
+ if (eom - cp != length)
+ return (NS_TSIG_ERROR_FORMERR);
+
+ /* Read the algorithm name. */
+ rdatastart = cp;
+ n = dn_expand(msg, eom, cp, alg, MAXDNAME);
+ if (n < 0)
+ return (NS_TSIG_ERROR_FORMERR);
+ if (ns_samename(alg, NS_TSIG_ALG_HMAC_MD5) != 1)
+ return (-ns_r_badkey);
+ cp += n;
+
+ /* Verify that the key used is OK. */
+ if ((ns_samename(state->key->dk_key_name, name) != 1 ||
+ state->key->dk_alg != KEY_HMAC_MD5))
+ return (-ns_r_badkey);
+
+ /* Read the time signed and fudge. */
+ BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ);
+ cp += INT16SZ;
+ GETLONG(timesigned, cp);
+ GETSHORT(fudge, cp);
+
+ /* Read the signature. */
+ BOUNDS_CHECK(cp, INT16SZ);
+ GETSHORT(sigfieldlen, cp);
+ BOUNDS_CHECK(cp, sigfieldlen);
+ sigstart = cp;
+ cp += sigfieldlen;
+
+ /* Read the original id and error. */
+ BOUNDS_CHECK(cp, 2*INT16SZ);
+ GETSHORT(id, cp);
+ GETSHORT(error, cp);
+
+ /* Parse the other data. */
+ BOUNDS_CHECK(cp, INT16SZ);
+ GETSHORT(otherfieldlen, cp);
+ BOUNDS_CHECK(cp, otherfieldlen);
+ cp += otherfieldlen;
+
+ if (cp != eom)
+ return (NS_TSIG_ERROR_FORMERR);
+
+ /*
+ * Do the verification.
+ */
+
+ /* Digest the time signed and fudge. */
+ cp2 = buf;
+ PUTSHORT(0, cp2); /* Top 16 bits of time. */
+ PUTLONG(timesigned, cp2);
+ PUTSHORT(NS_TSIG_FUDGE, cp2);
+
+ dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx,
+ buf, cp2 - buf, NULL, 0);
+
+ n = dst_verify_data(SIG_MODE_FINAL, state->key, &state->ctx, NULL, 0,
+ sigstart, sigfieldlen);
+ if (n < 0)
+ return (-ns_r_badsig);
+
+ if (sigfieldlen > sizeof(state->sig))
+ return (NS_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/usr/src/lib/libresolv2/common/resolv/herror.c b/usr/src/lib/libresolv2/common/resolv/herror.c
new file mode 100644
index 0000000000..1101057748
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/resolv/herror.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: herror.c,v 8.13 2001/06/18 14:44:06 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/uio.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <netdb.h>
+#include <resolv.h>
+#include <string.h>
+#include <unistd.h>
+#include <irs.h>
+
+#include "port_after.h"
+#undef h_errno
+
+const char *h_errlist[] = {
+ "Resolver Error 0 (no error)",
+ "Unknown host", /* 1 HOST_NOT_FOUND */
+ "Host name lookup failure", /* 2 TRY_AGAIN */
+ "Unknown server error", /* 3 NO_RECOVERY */
+ "No address associated with name", /* 4 NO_ADDRESS */
+};
+int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
+
+int h_errno;
+
+/*
+ * herror --
+ * print the error indicated by the h_errno value.
+ */
+void
+herror(const char *s) {
+ struct iovec iov[4], *v = iov;
+ char *t;
+
+ if (s != NULL && *s != '\0') {
+ DE_CONST(s, t);
+ v->iov_base = t;
+ v->iov_len = strlen(t);
+ v++;
+ DE_CONST(": ", t);
+ v->iov_base = t;
+ v->iov_len = 2;
+ v++;
+ }
+ DE_CONST(hstrerror(*__h_errno()), t);
+ v->iov_base = t;
+ v->iov_len = strlen(v->iov_base);
+ v++;
+ DE_CONST("\n", t);
+ v->iov_base = t;
+ v->iov_len = 1;
+ writev(STDERR_FILENO, iov, (v - iov) + 1);
+}
+
+/*
+ * hstrerror --
+ * return the string associated with a given "host" errno value.
+ */
+const char *
+hstrerror(int err) {
+ if (err < 0)
+ return ("Resolver internal error");
+ else if (err < h_nerr)
+ return (h_errlist[err]);
+ return ("Unknown resolver error");
+}
diff --git a/usr/src/lib/libresolv2/common/resolv/res_comp.c b/usr/src/lib/libresolv2/common/resolv/res_comp.c
new file mode 100644
index 0000000000..a0a3d9abb2
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/resolv/res_comp.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2003 by Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_comp.c,v 8.16 2002/08/07 03:47:34 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include "port_before.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <ctype.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "port_after.h"
+
+#ifdef ORIGINAL_ISC_CODE
+#else
+#pragma weak __dn_skipname = dn_skipname
+#pragma weak __res_dnok = res_dnok
+#pragma weak __res_hnok = res_hnok
+#pragma weak __res_mailok = res_mailok
+#pragma weak __res_ownok = res_ownok
+#endif /* ORIGINAL_ISC_CODE */
+/*
+ * Expand compressed domain name 'src' to full domain name.
+ * 'msg' is a pointer to the begining of the message,
+ * 'eom' points to the first location after the message,
+ * 'dst' is a pointer to a buffer of size 'dstsiz' 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)
+#ifdef SUNW_HNOK_UNDERSCORE
+#define underscorechar(c) ((c) == 0x5f)
+#endif /* SUNW_HNOK_UNDERSCORE */
+#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))
+#ifdef SUNW_HNOK_UNDERSCORE
+#define middlechar(c) (borderchar(c) || hyphenchar(c) || underscorechar(c))
+#else
+#define middlechar(c) (borderchar(c) || hyphenchar(c))
+#endif /* SUNW_HNOK_UNDERSCORE */
+#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 <label>.<hostname> */
+ while ((ch = *dn++) != '\0') {
+ if (!domainchar(ch))
+ return (0);
+ if (!escaped && periodchar(ch))
+ break;
+ if (escaped)
+ escaped = 0;
+ else if (bslashchar(ch))
+ escaped = 1;
+ }
+ if (periodchar(ch))
+ return (res_hnok(dn));
+ return (0);
+}
+
+/*
+ * This function is quite liberal, since RFC 1034's character sets are only
+ * recommendations.
+ */
+int
+res_dnok(const char *dn) {
+ int ch;
+
+ while ((ch = *dn++) != '\0')
+ if (!domainchar(ch))
+ return (0);
+ return (1);
+}
+
+#ifdef BIND_4_COMPAT
+/*
+ * This module must export the following externally-visible symbols:
+ * ___putlong
+ * ___putshort
+ * __getlong
+ * __getshort
+ * Note that one _ comes from C and the others come from us.
+ */
+#ifdef ORIGINAL_ISC_CODE
+#else
+#ifdef __putlong
+#undef __putlong
+#endif
+#ifdef __putshort
+#undef __putshort
+#endif
+#pragma weak putlong = __putlong
+#pragma weak putshort = __putshort
+#endif /* ORIGINAL_ISC_CODE */
+void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); }
+void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); }
+#ifndef __ultrix__
+u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); }
+u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); }
+#endif /*__ultrix__*/
+#endif /*BIND_4_COMPAT*/
diff --git a/usr/src/lib/libresolv2/common/resolv/res_data.c b/usr/src/lib/libresolv2/common/resolv/res_data.c
new file mode 100644
index 0000000000..50368f6600
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/resolv/res_data.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright 2003 by Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: res_data.c,v 8.18 2000/12/23 08:14:58 vixie Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <res_update.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "port_after.h"
+#undef _res
+
+#ifdef ORIGINAL_ISC_CODE
+#else
+#pragma weak __fp_nquery = fp_nquery
+#pragma weak __fp_query = fp_query
+#pragma weak __p_query = p_query
+#pragma weak __hostalias = hostalias
+#endif
+
+const char *_res_opcodes[] = {
+ "QUERY",
+ "IQUERY",
+ "CQUERYM",
+ "CQUERYU", /* experimental */
+ "NOTIFY", /* experimental */
+ "UPDATE",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "11",
+ "12",
+ "13",
+ "ZONEINIT",
+ "ZONEREF",
+};
+
+#ifdef BIND_UPDATE
+const char *_res_sectioncodes[] = {
+ "ZONE",
+ "PREREQUISITES",
+ "UPDATE",
+ "ADDITIONAL",
+};
+#endif
+
+#ifndef __BIND_NOSTATIC
+struct __res_state _res
+# if defined(__BIND_RES_TEXT)
+ = { RES_TIMEOUT, } /* Motorola, et al. */
+# endif
+ ;
+
+/* Proto. */
+
+int res_ourserver_p(const res_state, const struct sockaddr_in *);
+
+int
+res_init(void) {
+ extern int __res_vinit(res_state, int);
+
+ /*
+ * These three fields used to be statically initialized. This made
+ * it hard to use this code in a shared library. It is necessary,
+ * now that we're doing dynamic initialization here, that we preserve
+ * the old semantics: if an application modifies one of these three
+ * fields of _res before res_init() is called, res_init() will not
+ * alter them. Of course, if an application is setting them to
+ * _zero_ before calling res_init(), hoping to override what used
+ * to be the static default, we can't detect it and unexpected results
+ * will follow. Zero for any of these fields would make no sense,
+ * so one can safely assume that the applications were already getting
+ * unexpected results.
+ *
+ * _res.options is tricky since some apps were known to diddle the bits
+ * before res_init() was first called. We can't replicate that semantic
+ * with dynamic initialization (they may have turned bits off that are
+ * set in RES_DEFAULT). Our solution is to declare such applications
+ * "broken". They could fool us by setting RES_INIT but none do (yet).
+ */
+ if (!_res.retrans)
+ _res.retrans = RES_TIMEOUT;
+ if (!_res.retry)
+ _res.retry = 4;
+ if (!(_res.options & RES_INIT))
+ _res.options = RES_DEFAULT;
+
+ /*
+ * This one used to initialize implicitly to zero, so unless the app
+ * has set it to something in particular, we can randomize it now.
+ */
+ if (!_res.id)
+ _res.id = res_randomid();
+
+ return (__res_vinit(&_res, 1));
+}
+
+void
+p_query(const u_char *msg) {
+ fp_query(msg, stdout);
+}
+
+void
+fp_query(const u_char *msg, FILE *file) {
+ fp_nquery(msg, PACKETSZ, file);
+}
+
+void
+fp_nquery(const u_char *msg, int len, FILE *file) {
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ return;
+
+ res_pquery(&_res, msg, len, file);
+}
+
+int
+res_mkquery(int op, /* opcode of query */
+ const char *dname, /* domain name */
+ int class, int type, /* class and type of query */
+ const u_char *data, /* resource record data */
+ int datalen, /* length of data */
+ const u_char *newrr_in, /* new rr for modify or append */
+ u_char *buf, /* buffer to put query */
+ int buflen) /* size of buffer */
+{
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+ return (res_nmkquery(&_res, op, dname, class, type,
+ data, datalen,
+ newrr_in, buf, buflen));
+}
+
+int
+res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nmkupdate(&_res, rrecp_in, buf, buflen));
+}
+
+int
+res_query(const char *name, /* domain name */
+ int class, int type, /* class and type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen) /* size of answer buffer */
+{
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+ return (res_nquery(&_res, name, class, type, answer, anslen));
+}
+
+void
+res_send_setqhook(res_send_qhook hook) {
+ _res.qhook = hook;
+}
+
+void
+res_send_setrhook(res_send_rhook hook) {
+ _res.rhook = hook;
+}
+
+int
+res_isourserver(const struct sockaddr_in *inp) {
+ return (res_ourserver_p(&_res, inp));
+}
+
+int
+res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ /* errno should have been set by res_init() in this case. */
+ return (-1);
+ }
+
+ return (res_nsend(&_res, buf, buflen, ans, anssiz));
+}
+
+int
+res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key,
+ u_char *ans, int anssiz)
+{
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ /* errno should have been set by res_init() in this case. */
+ return (-1);
+ }
+
+ return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz));
+}
+
+void
+res_close(void) {
+ res_nclose(&_res);
+}
+
+int
+res_update(ns_updrec *rrecp_in) {
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nupdate(&_res, rrecp_in, NULL));
+}
+
+int
+res_search(const char *name, /* domain name */
+ int class, int type, /* class and type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen) /* size of answer */
+{
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nsearch(&_res, name, class, type, answer, anslen));
+}
+
+int
+res_querydomain(const char *name,
+ const char *domain,
+ int class, int type, /* class and type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen) /* size of answer */
+{
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nquerydomain(&_res, name, domain,
+ class, type,
+ answer, anslen));
+}
+
+const char *
+hostalias(const char *name) {
+ static char abuf[MAXDNAME];
+
+ return (res_hostalias(&_res, name, abuf, sizeof abuf));
+}
+
+#ifdef ultrix
+int
+local_hostname_length(const char *hostname) {
+ int len_host, len_domain;
+
+ if (!*_res.defdname)
+ res_init();
+ len_host = strlen(hostname);
+ len_domain = strlen(_res.defdname);
+ if (len_host > len_domain &&
+ !strcasecmp(hostname + len_host - len_domain, _res.defdname) &&
+ hostname[len_host - len_domain - 1] == '.')
+ return (len_host - len_domain - 1);
+ return (0);
+}
+#endif /*ultrix*/
+
+#endif
diff --git a/usr/src/lib/libresolv2/common/resolv/res_debug.c b/usr/src/lib/libresolv2/common/resolv/res_debug.c
new file mode 100644
index 0000000000..838ed3fd8a
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/resolv/res_debug.c
@@ -0,0 +1,1222 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1985
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_debug.c,v 8.50 2003/04/16 04:55:40 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <math.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) sprintf x
+#endif
+
+extern const char *_res_opcodes[];
+extern const char *_res_sectioncodes[];
+
+#ifdef ORIGINAL_ISC_CODE
+#else
+#pragma weak __dn_count_labels = dn_count_labels
+#pragma weak __fp_resstat = fp_resstat
+#pragma weak __loc_aton = loc_aton
+#pragma weak __loc_ntoa = loc_ntoa
+#pragma weak __p_cdname = p_cdname
+#pragma weak __p_class = p_class
+#pragma weak __p_secstodate = p_secstodate
+#pragma weak __p_section = p_section
+#pragma weak __p_time = p_time
+#pragma weak __p_type = p_type
+#pragma weak __sym_ntop = sym_ntop
+#pragma weak __sym_ntos = sym_ntos
+#pragma weak __sym_ston = sym_ston
+#endif /* ORIGINAL_ISC_CODE */
+
+/*
+ * Print the current options.
+ */
+void
+fp_resstat(const res_state statp, FILE *file) {
+ u_long mask;
+
+ fprintf(file, ";; res options:");
+ for (mask = 1; mask != 0; mask <<= 1)
+ if (statp->options & mask)
+ fprintf(file, " %s", p_option(mask));
+ putc('\n', file);
+}
+
+static void
+do_section(const res_state statp,
+ ns_msg *handle, ns_sect section,
+ int pflag, FILE *file)
+{
+ int n, sflag, rrnum;
+ static int buflen = 2048;
+ char *buf;
+ ns_opcode opcode;
+ ns_rr rr;
+
+ /*
+ * Print answer records.
+ */
+ sflag = (statp->pfcode & pflag);
+ if (statp->pfcode && !sflag)
+ return;
+
+ buf = malloc(buflen);
+ if (buf == NULL) {
+ fprintf(file, ";; memory allocation failure\n");
+ return;
+ }
+
+ opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode);
+ rrnum = 0;
+ for (;;) {
+ if (ns_parserr(handle, section, rrnum, &rr)) {
+ if (errno != ENODEV)
+ fprintf(file, ";; ns_parserr: %s\n",
+ strerror(errno));
+ else if (rrnum > 0 && sflag != 0 &&
+ (statp->pfcode & RES_PRF_HEAD1))
+ putc('\n', file);
+ goto cleanup;
+ }
+ if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1))
+ fprintf(file, ";; %s SECTION:\n",
+ p_section(section, opcode));
+ if (section == ns_s_qd)
+ fprintf(file, ";;\t%s, type = %s, class = %s\n",
+ ns_rr_name(rr),
+ p_type(ns_rr_type(rr)),
+ p_class(ns_rr_class(rr)));
+ else if (section == ns_s_ar && ns_rr_type(rr) == ns_t_opt) {
+ u_int32_t ttl = ns_rr_ttl(rr);
+ fprintf(file,
+ "; EDNS: version: %u, udp=%u, flags=%04x\n",
+ (ttl>>16)&0xff, ns_rr_class(rr), ttl&0xffff);
+ } else {
+ n = ns_sprintrr(handle, &rr, NULL, NULL,
+ buf, buflen);
+ if (n < 0) {
+ if (errno == ENOSPC) {
+ free(buf);
+ buf = NULL;
+ if (buflen < 131072)
+ buf = malloc(buflen += 1024);
+ if (buf == NULL) {
+ fprintf(file,
+ ";; memory allocation failure\n");
+ return;
+ }
+ continue;
+ }
+ fprintf(file, ";; ns_sprintrr: %s\n",
+ strerror(errno));
+ goto cleanup;
+ }
+ fputs(buf, file);
+ fputc('\n', file);
+ }
+ rrnum++;
+ }
+ cleanup:
+ if (buf != NULL)
+ free(buf);
+}
+
+/*
+ * Print the contents of a query.
+ * This is intended to be primarily a debugging routine.
+ */
+void
+res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
+ ns_msg handle;
+ int qdcount, ancount, nscount, arcount;
+ u_int opcode, rcode, id;
+
+ if (ns_initparse(msg, len, &handle) < 0) {
+ fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
+ return;
+ }
+ opcode = ns_msg_getflag(handle, ns_f_opcode);
+ rcode = ns_msg_getflag(handle, ns_f_rcode);
+ id = ns_msg_id(handle);
+ qdcount = ns_msg_count(handle, ns_s_qd);
+ ancount = ns_msg_count(handle, ns_s_an);
+ nscount = ns_msg_count(handle, ns_s_ns);
+ arcount = ns_msg_count(handle, ns_s_ar);
+
+ /*
+ * Print header fields.
+ */
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode)
+ fprintf(file,
+ ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
+ _res_opcodes[opcode], p_rcode(rcode), id);
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX))
+ putc(';', file);
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) {
+ fprintf(file, "; flags:");
+ if (ns_msg_getflag(handle, ns_f_qr))
+ fprintf(file, " qr");
+ if (ns_msg_getflag(handle, ns_f_aa))
+ fprintf(file, " aa");
+ if (ns_msg_getflag(handle, ns_f_tc))
+ fprintf(file, " tc");
+ if (ns_msg_getflag(handle, ns_f_rd))
+ fprintf(file, " rd");
+ if (ns_msg_getflag(handle, ns_f_ra))
+ fprintf(file, " ra");
+ if (ns_msg_getflag(handle, ns_f_z))
+ fprintf(file, " ??");
+ if (ns_msg_getflag(handle, ns_f_ad))
+ fprintf(file, " ad");
+ if (ns_msg_getflag(handle, ns_f_cd))
+ fprintf(file, " cd");
+ }
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) {
+ fprintf(file, "; %s: %d",
+ p_section(ns_s_qd, opcode), qdcount);
+ fprintf(file, ", %s: %d",
+ p_section(ns_s_an, opcode), ancount);
+ fprintf(file, ", %s: %d",
+ p_section(ns_s_ns, opcode), nscount);
+ fprintf(file, ", %s: %d",
+ p_section(ns_s_ar, opcode), arcount);
+ }
+ if ((!statp->pfcode) || (statp->pfcode &
+ (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
+ putc('\n',file);
+ }
+ /*
+ * Print the various sections.
+ */
+ do_section(statp, &handle, ns_s_qd, RES_PRF_QUES, file);
+ do_section(statp, &handle, ns_s_an, RES_PRF_ANS, file);
+ do_section(statp, &handle, ns_s_ns, RES_PRF_AUTH, file);
+ do_section(statp, &handle, ns_s_ar, RES_PRF_ADD, file);
+ if (qdcount == 0 && ancount == 0 &&
+ nscount == 0 && arcount == 0)
+ putc('\n', file);
+}
+
+const u_char *
+p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {
+ char name[MAXDNAME];
+ int n;
+
+ if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
+ return (NULL);
+ if (name[0] == '\0')
+ putc('.', file);
+ else
+ fputs(name, file);
+ return (cp + n);
+}
+
+const u_char *
+p_cdname(const u_char *cp, const u_char *msg, FILE *file) {
+ return (p_cdnname(cp, msg, PACKETSZ, file));
+}
+
+/* Return a fully-qualified domain name from a compressed name (with
+ length supplied). */
+
+const u_char *
+p_fqnname(cp, msg, msglen, name, namelen)
+ const u_char *cp, *msg;
+ int msglen;
+ char *name;
+ int namelen;
+{
+ int n, newlen;
+
+ if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
+ return (NULL);
+ newlen = strlen(name);
+ if (newlen == 0 || name[newlen - 1] != '.') {
+ if (newlen + 1 >= namelen) /* Lack space for final dot */
+ return (NULL);
+ else
+ strcpy(name + newlen, ".");
+ }
+ return (cp + n);
+}
+
+/* XXX: the rest of these functions need to become length-limited, too. */
+
+const u_char *
+p_fqname(const u_char *cp, const u_char *msg, FILE *file) {
+ char name[MAXDNAME];
+ const u_char *n;
+
+ n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
+ if (n == NULL)
+ return (NULL);
+ fputs(name, file);
+ return (n);
+}
+
+/*
+ * Names of RR classes and qclasses. Classes and qclasses are the same, except
+ * that C_ANY is a qclass but not a class. (You can ask for records of class
+ * C_ANY, but you can't have any records of that class in the database.)
+ */
+const struct res_sym __p_class_syms[] = {
+ {C_IN, "IN", (char *)0},
+ {C_CHAOS, "CHAOS", (char *)0},
+ {C_HS, "HS", (char *)0},
+ {C_HS, "HESIOD", (char *)0},
+ {C_ANY, "ANY", (char *)0},
+ {C_NONE, "NONE", (char *)0},
+ {C_IN, (char *)0, (char *)0}
+};
+
+/*
+ * Names of message sections.
+ */
+const struct res_sym __p_default_section_syms[] = {
+ {ns_s_qd, "QUERY", (char *)0},
+ {ns_s_an, "ANSWER", (char *)0},
+ {ns_s_ns, "AUTHORITY", (char *)0},
+ {ns_s_ar, "ADDITIONAL", (char *)0},
+ {0, (char *)0, (char *)0}
+};
+
+const struct res_sym __p_update_section_syms[] = {
+ {S_ZONE, "ZONE", (char *)0},
+ {S_PREREQ, "PREREQUISITE", (char *)0},
+ {S_UPDATE, "UPDATE", (char *)0},
+ {S_ADDT, "ADDITIONAL", (char *)0},
+ {0, (char *)0, (char *)0}
+};
+
+const struct res_sym __p_key_syms[] = {
+ {NS_ALG_MD5RSA, "RSA", "RSA KEY with MD5 hash"},
+ {NS_ALG_DH, "DH", "Diffie Hellman"},
+ {NS_ALG_DSA, "DSA", "Digital Signature Algorithm"},
+ {NS_ALG_EXPIRE_ONLY, "EXPIREONLY", "No algorithm"},
+ {NS_ALG_PRIVATE_OID, "PRIVATE", "Algorithm obtained from OID"},
+ {0, NULL, NULL}
+};
+
+const struct res_sym __p_cert_syms[] = {
+ {cert_t_pkix, "PKIX", "PKIX (X.509v3) Certificate"},
+ {cert_t_spki, "SPKI", "SPKI certificate"},
+ {cert_t_pgp, "PGP", "PGP certificate"},
+ {cert_t_url, "URL", "URL Private"},
+ {cert_t_oid, "OID", "OID Private"},
+ {0, NULL, NULL}
+};
+
+/*
+ * Names of RR types and qtypes. Types and qtypes are the same, except
+ * that T_ANY is a qtype but not a type. (You can ask for records of type
+ * T_ANY, but you can't have any records of that type in the database.)
+ */
+const struct res_sym __p_type_syms[] = {
+ {ns_t_a, "A", "address"},
+ {ns_t_ns, "NS", "name server"},
+ {ns_t_md, "MD", "mail destination (deprecated)"},
+ {ns_t_mf, "MF", "mail forwarder (deprecated)"},
+ {ns_t_cname, "CNAME", "canonical name"},
+ {ns_t_soa, "SOA", "start of authority"},
+ {ns_t_mb, "MB", "mailbox"},
+ {ns_t_mg, "MG", "mail group member"},
+ {ns_t_mr, "MR", "mail rename"},
+ {ns_t_null, "NULL", "null"},
+ {ns_t_wks, "WKS", "well-known service (deprecated)"},
+ {ns_t_ptr, "PTR", "domain name pointer"},
+ {ns_t_hinfo, "HINFO", "host information"},
+ {ns_t_minfo, "MINFO", "mailbox information"},
+ {ns_t_mx, "MX", "mail exchanger"},
+ {ns_t_txt, "TXT", "text"},
+ {ns_t_rp, "RP", "responsible person"},
+ {ns_t_afsdb, "AFSDB", "DCE or AFS server"},
+ {ns_t_x25, "X25", "X25 address"},
+ {ns_t_isdn, "ISDN", "ISDN address"},
+ {ns_t_rt, "RT", "router"},
+ {ns_t_nsap, "NSAP", "nsap address"},
+ {ns_t_nsap_ptr, "NSAP_PTR", "domain name pointer"},
+ {ns_t_sig, "SIG", "signature"},
+ {ns_t_key, "KEY", "key"},
+ {ns_t_px, "PX", "mapping information"},
+ {ns_t_gpos, "GPOS", "geographical position (withdrawn)"},
+ {ns_t_aaaa, "AAAA", "IPv6 address"},
+ {ns_t_loc, "LOC", "location"},
+ {ns_t_nxt, "NXT", "next valid name (unimplemented)"},
+ {ns_t_eid, "EID", "endpoint identifier (unimplemented)"},
+ {ns_t_nimloc, "NIMLOC", "NIMROD locator (unimplemented)"},
+ {ns_t_srv, "SRV", "server selection"},
+ {ns_t_atma, "ATMA", "ATM address (unimplemented)"},
+ {ns_t_tkey, "TKEY", "tkey"},
+ {ns_t_tsig, "TSIG", "transaction signature"},
+ {ns_t_ixfr, "IXFR", "incremental zone transfer"},
+ {ns_t_axfr, "AXFR", "zone transfer"},
+ {ns_t_zxfr, "ZXFR", "compressed zone transfer"},
+ {ns_t_mailb, "MAILB", "mailbox-related data (deprecated)"},
+ {ns_t_maila, "MAILA", "mail agent (deprecated)"},
+ {ns_t_naptr, "NAPTR", "URN Naming Authority"},
+ {ns_t_kx, "KX", "Key Exchange"},
+ {ns_t_cert, "CERT", "Certificate"},
+ {ns_t_a6, "A6", "IPv6 Address"},
+ {ns_t_dname, "DNAME", "dname"},
+ {ns_t_sink, "SINK", "Kitchen Sink (experimental)"},
+ {ns_t_opt, "OPT", "EDNS Options"},
+ {ns_t_any, "ANY", "\"any\""},
+ {0, NULL, NULL}
+};
+
+/*
+ * Names of DNS rcodes.
+ */
+const struct res_sym __p_rcode_syms[] = {
+ {ns_r_noerror, "NOERROR", "no error"},
+ {ns_r_formerr, "FORMERR", "format error"},
+ {ns_r_servfail, "SERVFAIL", "server failed"},
+ {ns_r_nxdomain, "NXDOMAIN", "no such domain name"},
+ {ns_r_notimpl, "NOTIMP", "not implemented"},
+ {ns_r_refused, "REFUSED", "refused"},
+ {ns_r_yxdomain, "YXDOMAIN", "domain name exists"},
+ {ns_r_yxrrset, "YXRRSET", "rrset exists"},
+ {ns_r_nxrrset, "NXRRSET", "rrset doesn't exist"},
+ {ns_r_notauth, "NOTAUTH", "not authoritative"},
+ {ns_r_notzone, "NOTZONE", "Not in zone"},
+ {ns_r_max, "", ""},
+ {ns_r_badsig, "BADSIG", "bad signature"},
+ {ns_r_badkey, "BADKEY", "bad key"},
+ {ns_r_badtime, "BADTIME", "bad time"},
+ {0, NULL, NULL}
+};
+
+int
+sym_ston(const struct res_sym *syms, const char *name, int *success) {
+ for ((void)NULL; syms->name != 0; syms++) {
+ if (strcasecmp (name, syms->name) == 0) {
+ if (success)
+ *success = 1;
+ return (syms->number);
+ }
+ }
+ if (success)
+ *success = 0;
+ return (syms->number); /* The default value. */
+}
+
+const char *
+sym_ntos(const struct res_sym *syms, int number, int *success) {
+#ifdef SUNW_MT_RESOLVER
+ char *unname = sym_ntos_unname;
+#else
+ static char unname[20];
+#endif /* SUNW_MT_RESOLVER */
+
+ for ((void)NULL; syms->name != 0; syms++) {
+ if (number == syms->number) {
+ if (success)
+ *success = 1;
+ return (syms->name);
+ }
+ }
+
+ sprintf(unname, "%d", number); /* XXX nonreentrant */
+ if (success)
+ *success = 0;
+ return (unname);
+}
+
+const char *
+sym_ntop(const struct res_sym *syms, int number, int *success) {
+#ifdef SUNW_MT_RESOLVER
+ char *unname = sym_ntop_unname;
+#else
+ static char unname[20];
+#endif /* SUNW_MT_RESOLVER */
+
+ for ((void)NULL; syms->name != 0; syms++) {
+ if (number == syms->number) {
+ if (success)
+ *success = 1;
+ return (syms->humanname);
+ }
+ }
+ sprintf(unname, "%d", number); /* XXX nonreentrant */
+ if (success)
+ *success = 0;
+ return (unname);
+}
+
+/*
+ * Return a string for the type.
+ */
+const char *
+p_type(int type) {
+ int success;
+ const char *result;
+ static char typebuf[20];
+
+ result = sym_ntos(__p_type_syms, type, &success);
+ if (success)
+ return (result);
+ if (type < 0 || type > 0xfff)
+ return ("BADTYPE");
+ sprintf(typebuf, "TYPE%d", type);
+ return (typebuf);
+}
+
+/*
+ * Return a string for the type.
+ */
+const char *
+p_section(int section, int opcode) {
+ const struct res_sym *symbols;
+
+ switch (opcode) {
+ case ns_o_update:
+ symbols = __p_update_section_syms;
+ break;
+ default:
+ symbols = __p_default_section_syms;
+ break;
+ }
+ return (sym_ntos(symbols, section, (int *)0));
+}
+
+/*
+ * Return a mnemonic for class.
+ */
+const char *
+p_class(int class) {
+ int success;
+ const char *result;
+ static char classbuf[20];
+
+ result = sym_ntos(__p_class_syms, class, &success);
+ if (success)
+ return (result);
+ if (class < 0 || class > 0xfff)
+ return ("BADCLASS");
+ sprintf(classbuf, "CLASS%d", class);
+ return (classbuf);
+}
+
+/*
+ * Return a mnemonic for an option
+ */
+const char *
+#ifdef ORIGINAL_ISC_CODE
+p_option(u_long option) {
+#else
+p_option(u_int option) {
+#endif
+#ifdef SUNW_MT_RESOLVER
+ char *nbuf = p_option_nbuf;
+#else
+ static char nbuf[40];
+#endif /* SUNW_MT_RESOLVER */
+
+ switch (option) {
+ case RES_INIT: return "init";
+ case RES_DEBUG: return "debug";
+ case RES_AAONLY: return "aaonly(unimpl)";
+ case RES_USEVC: return "usevc";
+ case RES_PRIMARY: return "primry(unimpl)";
+ case RES_IGNTC: return "igntc";
+ case RES_RECURSE: return "recurs";
+ case RES_DEFNAMES: return "defnam";
+ case RES_STAYOPEN: return "styopn";
+ case RES_DNSRCH: return "dnsrch";
+ case RES_INSECURE1: return "insecure1";
+ case RES_INSECURE2: return "insecure2";
+ case RES_NOALIASES: return "noaliases";
+ case RES_USE_INET6: return "inet6";
+#ifdef RES_USE_EDNS0 /* KAME extension */
+ case RES_USE_EDNS0: return "edns0";
+#endif
+#ifdef RES_USE_DNAME
+ case RES_USE_DNAME: return "dname";
+#endif
+#ifdef RES_USE_DNSSEC
+ case RES_USE_DNSSEC: return "dnssec";
+#endif
+#ifdef RES_NOTLDQUERY
+ case RES_NOTLDQUERY: return "no-tld-query";
+#endif
+#ifdef ORIGINAL_ISC_CODE
+ /* XXX nonreentrant */
+ default: sprintf(nbuf, "?0x%lx?", (u_long)option);
+#else
+ default: sprintf(nbuf, "?0x%x?", (u_int)option);
+#endif
+ return (nbuf);
+ }
+}
+
+/*
+ * Return a mnemonic for a time to live.
+ */
+const char *
+p_time(u_int32_t value) {
+#ifdef SUNW_MT_RESOLVER
+ char *nbuf = p_time_nbuf;
+#else
+ static char nbuf[40]; /* XXX nonreentrant */
+#endif /* SUNW_MT_RESOLVER */
+
+ if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0)
+ sprintf(nbuf, "%u", value);
+ return (nbuf);
+}
+
+/*
+ * Return a string for the rcode.
+ */
+const char *
+p_rcode(int rcode) {
+ return (sym_ntos(__p_rcode_syms, rcode, (int *)0));
+}
+
+/*
+ * Return a string for a res_sockaddr_union.
+ */
+const char *
+p_sockun(union res_sockaddr_union u, char *buf, size_t size) {
+ char ret[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:123.123.123.123"];
+
+ switch (u.sin.sin_family) {
+ case AF_INET:
+ inet_ntop(AF_INET, &u.sin.sin_addr, ret, sizeof ret);
+ break;
+#ifdef HAS_INET6_STRUCTS
+ case AF_INET6:
+ inet_ntop(AF_INET6, &u.sin6.sin6_addr, ret, sizeof ret);
+ break;
+#endif
+ default:
+ sprintf(ret, "[af%d]", u.sin.sin_family);
+ break;
+ }
+ if (size > 0) {
+ strncpy(buf, ret, size - 1);
+ buf[size - 1] = '0';
+ }
+ return (buf);
+}
+
+/*
+ * routines to convert between on-the-wire RR format and zone file format.
+ * Does not contain conversion to/from decimal degrees; divide or multiply
+ * by 60*60*1000 for that.
+ */
+
+static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
+ 1000000,10000000,100000000,1000000000};
+
+/* takes an XeY precision/size value, returns a string representation. */
+static const char *
+precsize_ntoa(prec)
+ u_int8_t prec;
+{
+#ifdef SUNW_MT_RESOLVER
+ char *retbuf = precsize_ntoa_retbuf;
+#else
+ static char retbuf[sizeof "90000000.00"]; /* XXX nonreentrant */
+#endif /* SUNW_MT_RESOLVER */
+ unsigned long val;
+ int mantissa, exponent;
+
+ mantissa = (int)((prec >> 4) & 0x0f) % 10;
+ exponent = (int)((prec >> 0) & 0x0f) % 10;
+
+ val = mantissa * poweroften[exponent];
+
+ (void) sprintf(retbuf, "%lu.%.2lu", val/100, val%100);
+ return (retbuf);
+}
+
+/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
+static u_int8_t
+precsize_aton(const char **strptr) {
+ unsigned int mval = 0, cmval = 0;
+ u_int8_t retval = 0;
+ const char *cp;
+ int exponent;
+ int mantissa;
+
+ cp = *strptr;
+
+ while (isdigit((unsigned char)*cp))
+ mval = mval * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /* centimeters */
+ cp++;
+ if (isdigit((unsigned char)*cp)) {
+ cmval = (*cp++ - '0') * 10;
+ if (isdigit((unsigned char)*cp)) {
+ cmval += (*cp++ - '0');
+ }
+ }
+ }
+ cmval = (mval * 100) + cmval;
+
+ for (exponent = 0; exponent < 9; exponent++)
+ if (cmval < poweroften[exponent+1])
+ break;
+
+ mantissa = cmval / poweroften[exponent];
+ if (mantissa > 9)
+ mantissa = 9;
+
+ retval = (mantissa << 4) | exponent;
+
+ *strptr = cp;
+
+ return (retval);
+}
+
+/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
+static u_int32_t
+latlon2ul(const char **latlonstrptr, int *which) {
+ const char *cp;
+ u_int32_t retval;
+ int deg = 0, min = 0, secs = 0, secsfrac = 0;
+
+ cp = *latlonstrptr;
+
+ while (isdigit((unsigned char)*cp))
+ deg = deg * 10 + (*cp++ - '0');
+
+ while (isspace((unsigned char)*cp))
+ cp++;
+
+ if (!(isdigit((unsigned char)*cp)))
+ goto fndhemi;
+
+ while (isdigit((unsigned char)*cp))
+ min = min * 10 + (*cp++ - '0');
+
+ while (isspace((unsigned char)*cp))
+ cp++;
+
+ if (!(isdigit((unsigned char)*cp)))
+ goto fndhemi;
+
+ while (isdigit((unsigned char)*cp))
+ secs = secs * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /* decimal seconds */
+ cp++;
+ if (isdigit((unsigned char)*cp)) {
+ secsfrac = (*cp++ - '0') * 100;
+ if (isdigit((unsigned char)*cp)) {
+ secsfrac += (*cp++ - '0') * 10;
+ if (isdigit((unsigned char)*cp)) {
+ secsfrac += (*cp++ - '0');
+ }
+ }
+ }
+ }
+
+ while (!isspace((unsigned char)*cp)) /* if any trailing garbage */
+ cp++;
+
+ while (isspace((unsigned char)*cp))
+ cp++;
+
+ fndhemi:
+ switch (*cp) {
+ case 'N': case 'n':
+ case 'E': case 'e':
+ retval = ((unsigned)1<<31)
+ + (((((deg * 60) + min) * 60) + secs) * 1000)
+ + secsfrac;
+ break;
+ case 'S': case 's':
+ case 'W': case 'w':
+ retval = ((unsigned)1<<31)
+ - (((((deg * 60) + min) * 60) + secs) * 1000)
+ - secsfrac;
+ break;
+ default:
+ retval = 0; /* invalid value -- indicates error */
+ break;
+ }
+
+ switch (*cp) {
+ case 'N': case 'n':
+ case 'S': case 's':
+ *which = 1; /* latitude */
+ break;
+ case 'E': case 'e':
+ case 'W': case 'w':
+ *which = 2; /* longitude */
+ break;
+ default:
+ *which = 0; /* error */
+ break;
+ }
+
+ cp++; /* skip the hemisphere */
+
+ while (!isspace((unsigned char)*cp)) /* if any trailing garbage */
+ cp++;
+
+ while (isspace((unsigned char)*cp)) /* move to next field */
+ cp++;
+
+ *latlonstrptr = cp;
+
+ return (retval);
+}
+
+/* converts a zone file representation in a string to an RDATA on-the-wire
+ * representation. */
+int
+loc_aton(ascii, binary)
+ const char *ascii;
+ u_char *binary;
+{
+ const char *cp, *maxcp;
+ u_char *bcp;
+
+ u_int32_t latit = 0, longit = 0, alt = 0;
+ u_int32_t lltemp1 = 0, lltemp2 = 0;
+ int altmeters = 0, altfrac = 0, altsign = 1;
+ u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
+ u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
+ u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
+ int which1 = 0, which2 = 0;
+
+ cp = ascii;
+ maxcp = cp + strlen(ascii);
+
+ lltemp1 = latlon2ul(&cp, &which1);
+
+ lltemp2 = latlon2ul(&cp, &which2);
+
+ switch (which1 + which2) {
+ case 3: /* 1 + 2, the only valid combination */
+ if ((which1 == 1) && (which2 == 2)) { /* normal case */
+ latit = lltemp1;
+ longit = lltemp2;
+ } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
+ longit = lltemp1;
+ latit = lltemp2;
+ } else { /* some kind of brokenness */
+ return (0);
+ }
+ break;
+ default: /* we didn't get one of each */
+ return (0);
+ }
+
+ /* altitude */
+ if (*cp == '-') {
+ altsign = -1;
+ cp++;
+ }
+
+ if (*cp == '+')
+ cp++;
+
+ while (isdigit((unsigned char)*cp))
+ altmeters = altmeters * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /* decimal meters */
+ cp++;
+ if (isdigit((unsigned char)*cp)) {
+ altfrac = (*cp++ - '0') * 10;
+ if (isdigit((unsigned char)*cp)) {
+ altfrac += (*cp++ - '0');
+ }
+ }
+ }
+
+ alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
+
+ while (!isspace((unsigned char)*cp) && (cp < maxcp)) /* if trailing garbage or m */
+ cp++;
+
+ while (isspace((unsigned char)*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ siz = precsize_aton(&cp);
+
+ while (!isspace((unsigned char)*cp) && (cp < maxcp)) /* if trailing garbage or m */
+ cp++;
+
+ while (isspace((unsigned char)*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ hp = precsize_aton(&cp);
+
+ while (!isspace((unsigned char)*cp) && (cp < maxcp)) /* if trailing garbage or m */
+ cp++;
+
+ while (isspace((unsigned char)*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ vp = precsize_aton(&cp);
+
+ defaults:
+
+ bcp = binary;
+ *bcp++ = (u_int8_t) 0; /* version byte */
+ *bcp++ = siz;
+ *bcp++ = hp;
+ *bcp++ = vp;
+ PUTLONG(latit,bcp);
+ PUTLONG(longit,bcp);
+ PUTLONG(alt,bcp);
+
+ return (16); /* size of RR in octets */
+}
+
+/* takes an on-the-wire LOC RR and formats it in a human readable format. */
+const char *
+loc_ntoa(binary, ascii)
+ const u_char *binary;
+ char *ascii;
+{
+ static const char *error = "?";
+#ifdef SUNW_MT_RESOLVER
+ char *tmpbuf = loc_ntoa_tmpbuf;
+#else
+ static char tmpbuf[sizeof
+"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
+#endif /* SUNW_MT_RESOLVER */
+ const u_char *cp = binary;
+
+ int latdeg, latmin, latsec, latsecfrac;
+ int longdeg, longmin, longsec, longsecfrac;
+ char northsouth, eastwest;
+ const char *altsign;
+ int altmeters, altfrac;
+
+ const u_int32_t referencealt = 100000 * 100;
+
+ int32_t latval, longval, altval;
+ u_int32_t templ;
+ u_int8_t sizeval, hpval, vpval, versionval;
+
+ char *sizestr, *hpstr, *vpstr;
+
+ versionval = *cp++;
+
+ if (ascii == NULL)
+ ascii = tmpbuf;
+
+ if (versionval) {
+ (void) sprintf(ascii, "; error: unknown LOC RR version");
+ return (ascii);
+ }
+
+ sizeval = *cp++;
+
+ hpval = *cp++;
+ vpval = *cp++;
+
+ GETLONG(templ, cp);
+ latval = (templ - ((unsigned)1<<31));
+
+ GETLONG(templ, cp);
+ longval = (templ - ((unsigned)1<<31));
+
+ GETLONG(templ, cp);
+ if (templ < referencealt) { /* below WGS 84 spheroid */
+ altval = referencealt - templ;
+ altsign = "-";
+ } else {
+ altval = templ - referencealt;
+ altsign = "";
+ }
+
+ if (latval < 0) {
+ northsouth = 'S';
+ latval = -latval;
+ } else
+ northsouth = 'N';
+
+ latsecfrac = latval % 1000;
+ latval = latval / 1000;
+ latsec = latval % 60;
+ latval = latval / 60;
+ latmin = latval % 60;
+ latval = latval / 60;
+ latdeg = latval;
+
+ if (longval < 0) {
+ eastwest = 'W';
+ longval = -longval;
+ } else
+ eastwest = 'E';
+
+ longsecfrac = longval % 1000;
+ longval = longval / 1000;
+ longsec = longval % 60;
+ longval = longval / 60;
+ longmin = longval % 60;
+ longval = longval / 60;
+ longdeg = longval;
+
+ altfrac = altval % 100;
+ altmeters = (altval / 100);
+
+ sizestr = strdup(precsize_ntoa(sizeval));
+ hpstr = strdup(precsize_ntoa(hpval));
+ vpstr = strdup(precsize_ntoa(vpval));
+
+ sprintf(ascii,
+ "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %s%d.%.2dm %sm %sm %sm",
+ latdeg, latmin, latsec, latsecfrac, northsouth,
+ longdeg, longmin, longsec, longsecfrac, eastwest,
+ altsign, altmeters, altfrac,
+ (sizestr != NULL) ? sizestr : error,
+ (hpstr != NULL) ? hpstr : error,
+ (vpstr != NULL) ? vpstr : error);
+
+ if (sizestr != NULL)
+ free(sizestr);
+ if (hpstr != NULL)
+ free(hpstr);
+ if (vpstr != NULL)
+ free(vpstr);
+
+ return (ascii);
+}
+
+
+/* Return the number of DNS hierarchy levels in the name. */
+int
+dn_count_labels(const char *name) {
+ int i, len, count;
+
+ len = strlen(name);
+ for (i = 0, count = 0; i < len; i++) {
+ /* XXX need to check for \. or use named's nlabels(). */
+ if (name[i] == '.')
+ count++;
+ }
+
+ /* don't count initial wildcard */
+ if (name[0] == '*')
+ if (count)
+ count--;
+
+ /* don't count the null label for root. */
+ /* if terminating '.' not found, must adjust */
+ /* count to include last label */
+ if (len > 0 && name[len-1] != '.')
+ count++;
+ return (count);
+}
+
+
+/*
+ * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
+ * SIG records are required to be printed like this, by the Secure DNS RFC.
+ */
+char *
+#ifdef ORIGINAL_ISC_CODE
+p_secstodate (u_long secs) {
+#else
+p_secstodate (u_int secs) {
+#endif
+#ifdef SUNW_MT_RESOLVER
+ char *output = p_secstodate_output;
+#else
+ /* XXX nonreentrant */
+ static char output[15]; /* YYYYMMDDHHMMSS and null */
+#endif /* SUNW_MT_RESOLVER */
+ time_t clock = secs;
+ struct tm *time;
+
+#ifdef HAVE_TIME_R
+ gmtime_r(&clock, &time);
+#else
+ time = gmtime(&clock);
+#endif
+ time->tm_year += 1900;
+ time->tm_mon += 1;
+ sprintf(output, "%04d%02d%02d%02d%02d%02d",
+ time->tm_year, time->tm_mon, time->tm_mday,
+ time->tm_hour, time->tm_min, time->tm_sec);
+ return (output);
+}
+
+u_int16_t
+res_nametoclass(const char *buf, int *successp) {
+ unsigned long result;
+ char *endptr;
+ int success;
+
+ result = sym_ston(__p_class_syms, buf, &success);
+ if (success)
+ goto done;
+
+ if (strncasecmp(buf, "CLASS", 5) != 0 ||
+ !isdigit((unsigned char)buf[5]))
+ goto done;
+ errno = 0;
+ result = strtoul(buf + 5, &endptr, 10);
+ if (errno == 0 && *endptr == '\0' && result <= 0xffff)
+ success = 1;
+ done:
+ if (successp)
+ *successp = success;
+ return (result);
+}
+
+u_int16_t
+res_nametotype(const char *buf, int *successp) {
+ unsigned long result;
+ char *endptr;
+ int success;
+
+ result = sym_ston(__p_type_syms, buf, &success);
+ if (success)
+ goto done;
+
+ if (strncasecmp(buf, "type", 4) != 0 ||
+ !isdigit((unsigned char)buf[4]))
+ goto done;
+ errno = 0;
+ result = strtoul(buf + 4, &endptr, 10);
+ if (errno == 0 && *endptr == '\0' && result <= 0xffff)
+ success = 1;
+ done:
+ if (successp)
+ *successp = success;
+ return (result);
+}
diff --git a/usr/src/lib/libresolv2/common/resolv/res_debug.h b/usr/src/lib/libresolv2/common/resolv/res_debug.h
new file mode 100644
index 0000000000..1395d7a207
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/resolv/res_debug.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef _RES_DEBUG_H_
+#define _RES_DEBUG_H_
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef DEBUG
+# define Dprint(cond, args) /*empty*/
+# define DprintQ(cond, args, query, size) /*empty*/
+# define Aerror(statp, file, string, error, address) /*empty*/
+# define Perror(statp, file, string, error) /*empty*/
+#else
+# define Dprint(cond, args) if (cond) {fprintf args;} else {}
+# define DprintQ(cond, args, query, size) if (cond) {\
+ fprintf args;\
+ res_pquery(statp, query, size, stdout);\
+ } else {}
+#endif
+
+#endif /* _RES_DEBUG_H_ */
diff --git a/usr/src/lib/libresolv2/common/resolv/res_findzonecut.c b/usr/src/lib/libresolv2/common/resolv/res_findzonecut.c
new file mode 100644
index 0000000000..65be96235b
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/resolv/res_findzonecut.c
@@ -0,0 +1,729 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: res_findzonecut.c,v 8.20 2003/05/27 23:36:53 marka Exp $";
+#endif /* not lint */
+
+/*
+ * Copyright (c) 1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/* Import. */
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/list.h>
+
+#include "port_after.h"
+
+#include <resolv.h>
+
+/* Data structures. */
+
+typedef struct rr_a {
+ LINK(struct rr_a) link;
+ union res_sockaddr_union addr;
+} rr_a;
+typedef LIST(rr_a) rrset_a;
+
+typedef struct rr_ns {
+ LINK(struct rr_ns) link;
+ const char * name;
+ unsigned int flags;
+ rrset_a addrs;
+} rr_ns;
+typedef LIST(rr_ns) rrset_ns;
+
+#define RR_NS_HAVE_V4 0x01
+#define RR_NS_HAVE_V6 0x02
+
+/* Forward. */
+
+static int satisfy(res_state, const char *, rrset_ns *,
+ union res_sockaddr_union *, int);
+static int add_addrs(res_state, rr_ns *,
+ union res_sockaddr_union *, int);
+static int get_soa(res_state, const char *, ns_class, int,
+ char *, size_t, char *, size_t,
+ rrset_ns *);
+static int get_ns(res_state, const char *, ns_class, int, rrset_ns *);
+static int get_glue(res_state, ns_class, int, rrset_ns *);
+static int save_ns(res_state, ns_msg *, ns_sect,
+ const char *, ns_class, int, rrset_ns *);
+static int save_a(res_state, ns_msg *, ns_sect,
+ const char *, ns_class, int, rr_ns *);
+static void free_nsrrset(rrset_ns *);
+static void free_nsrr(rrset_ns *, rr_ns *);
+static rr_ns * find_ns(rrset_ns *, const char *);
+static int do_query(res_state, const char *, ns_class, ns_type,
+ u_char *, ns_msg *);
+static void res_dprintf(const char *, ...) ISC_FORMAT_PRINTF(1, 2);
+
+/* Macros. */
+
+#define DPRINTF(x) do {\
+ int save_errno = errno; \
+ if ((statp->options & RES_DEBUG) != 0) res_dprintf x; \
+ errno = save_errno; \
+ } while (0)
+
+/* Public. */
+
+/*
+ * int
+ * res_findzonecut(res, dname, class, zname, zsize, addrs, naddrs)
+ * find enclosing zone for a <dname,class>, and some server addresses
+ * parameters:
+ * res - resolver context to work within (is modified)
+ * dname - domain name whose enclosing zone is desired
+ * class - class of dname (and its enclosing zone)
+ * zname - found zone name
+ * zsize - allocated size of zname
+ * addrs - found server addresses
+ * naddrs - max number of addrs
+ * return values:
+ * < 0 - an error occurred (check errno)
+ * = 0 - zname is now valid, but addrs[] wasn't changed
+ * > 0 - zname is now valid, and return value is number of addrs[] found
+ * notes:
+ * this function calls res_nsend() which means it depends on correctly
+ * functioning recursive nameservers (usually defined in /etc/resolv.conf
+ * or its local equivilent).
+ *
+ * we start by asking for an SOA<dname,class>. if we get one as an
+ * answer, that just means <dname,class> is a zone top, which is fine.
+ * more than likely we'll be told to go pound sand, in the form of a
+ * negative answer.
+ *
+ * note that we are not prepared to deal with referrals since that would
+ * only come from authority servers and our correctly functioning local
+ * recursive server would have followed the referral and got us something
+ * more definite.
+ *
+ * if the authority section contains an SOA, this SOA should also be the
+ * closest enclosing zone, since any intermediary zone cuts would've been
+ * returned as referrals and dealt with by our correctly functioning local
+ * recursive name server. but an SOA in the authority section should NOT
+ * match our dname (since that would have been returned in the answer
+ * section). an authority section SOA has to be "above" our dname.
+ *
+ * however, since authority section SOA's were once optional, it's
+ * possible that we'll have to go hunting for the enclosing SOA by
+ * ripping labels off the front of our dname -- this is known as "doing
+ * it the hard way."
+ *
+ * ultimately we want some server addresses, which are ideally the ones
+ * pertaining to the SOA.MNAME, but only if there is a matching NS RR.
+ * so the second phase (after we find an SOA) is to go looking for the
+ * NS RRset for that SOA's zone.
+ *
+ * no answer section processed by this code is allowed to contain CNAME
+ * or DNAME RR's. for the SOA query this means we strip a label and
+ * keep going. for the NS and A queries this means we just give up.
+ */
+
+int
+res_findzonecut(res_state statp, const char *dname, ns_class class, int opts,
+ char *zname, size_t zsize, struct in_addr *addrs, int naddrs)
+{
+ int result, i;
+ union res_sockaddr_union *u;
+
+
+ opts |= RES_IPV4ONLY;
+ opts &= ~RES_IPV6ONLY;
+
+ u = calloc(naddrs, sizeof(*u));
+ if (u == NULL)
+ return(-1);
+
+ result = res_findzonecut2(statp, dname, class, opts, zname, zsize,
+ u, naddrs);
+
+ for (i = 0; i < result; i++) {
+ addrs[i] = u[i].sin.sin_addr;
+ }
+ free(u);
+ return (result);
+}
+
+int
+res_findzonecut2(res_state statp, const char *dname, ns_class class, int opts,
+ char *zname, size_t zsize, union res_sockaddr_union *addrs,
+ int naddrs)
+{
+ char mname[NS_MAXDNAME];
+ u_long save_pfcode;
+ rrset_ns nsrrs;
+ int n;
+
+ DPRINTF(("START dname='%s' class=%s, zsize=%ld, naddrs=%d",
+ dname, p_class(class), (long)zsize, naddrs));
+ save_pfcode = statp->pfcode;
+ statp->pfcode |= RES_PRF_HEAD2 | RES_PRF_HEAD1 | RES_PRF_HEADX |
+ RES_PRF_QUES | RES_PRF_ANS |
+ RES_PRF_AUTH | RES_PRF_ADD;
+ INIT_LIST(nsrrs);
+
+ DPRINTF(("get the soa, and see if it has enough glue"));
+ if ((n = get_soa(statp, dname, class, opts, zname, zsize,
+ mname, sizeof mname, &nsrrs)) < 0 ||
+ ((opts & RES_EXHAUSTIVE) == 0 &&
+ (n = satisfy(statp, mname, &nsrrs, addrs, naddrs)) > 0))
+ goto done;
+
+ DPRINTF(("get the ns rrset and see if it has enough glue"));
+ if ((n = get_ns(statp, zname, class, opts, &nsrrs)) < 0 ||
+ ((opts & RES_EXHAUSTIVE) == 0 &&
+ (n = satisfy(statp, mname, &nsrrs, addrs, naddrs)) > 0))
+ goto done;
+
+ DPRINTF(("get the missing glue and see if it's finally enough"));
+ if ((n = get_glue(statp, class, opts, &nsrrs)) >= 0)
+ n = satisfy(statp, mname, &nsrrs, addrs, naddrs);
+
+ done:
+ DPRINTF(("FINISH n=%d (%s)", n, (n < 0) ? strerror(errno) : "OK"));
+ free_nsrrset(&nsrrs);
+ statp->pfcode = save_pfcode;
+ return (n);
+}
+
+/* Private. */
+
+static int
+satisfy(res_state statp, const char *mname, rrset_ns *nsrrsp,
+ union res_sockaddr_union *addrs, int naddrs)
+{
+ rr_ns *nsrr;
+ int n, x;
+
+ n = 0;
+ nsrr = find_ns(nsrrsp, mname);
+ if (nsrr != NULL) {
+ x = add_addrs(statp, nsrr, addrs, naddrs);
+ addrs += x;
+ naddrs -= x;
+ n += x;
+ }
+ for (nsrr = HEAD(*nsrrsp);
+ nsrr != NULL && naddrs > 0;
+ nsrr = NEXT(nsrr, link))
+ if (ns_samename(nsrr->name, mname) != 1) {
+ x = add_addrs(statp, nsrr, addrs, naddrs);
+ addrs += x;
+ naddrs -= x;
+ n += x;
+ }
+ DPRINTF(("satisfy(%s): %d", mname, n));
+ return (n);
+}
+
+static int
+add_addrs(res_state statp, rr_ns *nsrr,
+ union res_sockaddr_union *addrs, int naddrs)
+{
+ rr_a *arr;
+ int n = 0;
+
+ for (arr = HEAD(nsrr->addrs); arr != NULL; arr = NEXT(arr, link)) {
+ if (naddrs <= 0)
+ return (0);
+ *addrs++ = arr->addr;
+ naddrs--;
+ n++;
+ }
+ DPRINTF(("add_addrs: %d", n));
+ return (n);
+}
+
+static int
+get_soa(res_state statp, const char *dname, ns_class class, int opts,
+ char *zname, size_t zsize, char *mname, size_t msize,
+ rrset_ns *nsrrsp)
+{
+ char tname[NS_MAXDNAME];
+ u_char *resp = NULL;
+ int n, i, ancount, nscount;
+ ns_sect sect;
+ ns_msg msg;
+ u_int rcode;
+
+ /*
+ * Find closest enclosing SOA, even if it's for the root zone.
+ */
+
+ /* First canonicalize dname (exactly one unescaped trailing "."). */
+ if (ns_makecanon(dname, tname, sizeof tname) < 0)
+ goto cleanup;
+ dname = tname;
+
+ resp = malloc(NS_MAXMSG);
+ if (resp == NULL)
+ goto cleanup;
+
+ /* Now grovel the subdomains, hunting for an SOA answer or auth. */
+ for (;;) {
+ /* Leading or inter-label '.' are skipped here. */
+ while (*dname == '.')
+ dname++;
+
+ /* Is there an SOA? */
+ n = do_query(statp, dname, class, ns_t_soa, resp, &msg);
+ if (n < 0) {
+ DPRINTF(("get_soa: do_query('%s', %s) failed (%d)",
+ dname, p_class(class), n));
+ goto cleanup;
+ }
+ if (n > 0) {
+ DPRINTF(("get_soa: CNAME or DNAME found"));
+ sect = ns_s_max, n = 0;
+ } else {
+ rcode = ns_msg_getflag(msg, ns_f_rcode);
+ ancount = ns_msg_count(msg, ns_s_an);
+ nscount = ns_msg_count(msg, ns_s_ns);
+ if (ancount > 0 && rcode == ns_r_noerror)
+ sect = ns_s_an, n = ancount;
+ else if (nscount > 0)
+ sect = ns_s_ns, n = nscount;
+ else
+ sect = ns_s_max, n = 0;
+ }
+ for (i = 0; i < n; i++) {
+ const char *t;
+ const u_char *rdata;
+ int rdlen;
+ ns_rr rr;
+
+ if (ns_parserr(&msg, sect, i, &rr) < 0) {
+ DPRINTF(("get_soa: ns_parserr(%s, %d) failed",
+ p_section(sect, ns_o_query), i));
+ goto cleanup;
+ }
+ if (ns_rr_type(rr) == ns_t_cname ||
+ ns_rr_type(rr) == ns_t_dname)
+ break;
+ if (ns_rr_type(rr) != ns_t_soa ||
+ ns_rr_class(rr) != class)
+ continue;
+ t = ns_rr_name(rr);
+ switch (sect) {
+ case ns_s_an:
+ if (ns_samedomain(dname, t) == 0) {
+ DPRINTF(
+ ("get_soa: ns_samedomain('%s', '%s') == 0",
+ dname, t)
+ );
+ errno = EPROTOTYPE;
+ goto cleanup;
+ }
+ break;
+ case ns_s_ns:
+ if (ns_samename(dname, t) == 1 ||
+ ns_samedomain(dname, t) == 0) {
+ DPRINTF(
+ ("get_soa: ns_samename() || !ns_samedomain('%s', '%s')",
+ dname, t)
+ );
+ errno = EPROTOTYPE;
+ goto cleanup;
+ }
+ break;
+ default:
+ abort();
+ }
+ if (strlen(t) + 1 > zsize) {
+ DPRINTF(("get_soa: zname(%d) too small (%d)",
+ zsize, strlen(t) + 1));
+ errno = EMSGSIZE;
+ goto cleanup;
+ }
+ strcpy(zname, t);
+ rdata = ns_rr_rdata(rr);
+ rdlen = ns_rr_rdlen(rr);
+ if (ns_name_uncompress(resp, ns_msg_end(msg), rdata,
+ mname, msize) < 0) {
+ DPRINTF(("get_soa: ns_name_uncompress failed")
+ );
+ goto cleanup;
+ }
+ if (save_ns(statp, &msg, ns_s_ns,
+ zname, class, opts, nsrrsp) < 0) {
+ DPRINTF(("get_soa: save_ns failed"));
+ goto cleanup;
+ }
+ free(resp);
+ return (0);
+ }
+
+ /* If we're out of labels, then not even "." has an SOA! */
+ if (*dname == '\0')
+ break;
+
+ /* Find label-terminating "."; top of loop will skip it. */
+ while (*dname != '.') {
+ if (*dname == '\\')
+ if (*++dname == '\0') {
+ errno = EMSGSIZE;
+ goto cleanup;
+ }
+ dname++;
+ }
+ }
+ DPRINTF(("get_soa: out of labels"));
+ errno = EDESTADDRREQ;
+ cleanup:
+ if (resp != NULL)
+ free(resp);
+ return (-1);
+}
+
+static int
+get_ns(res_state statp, const char *zname, ns_class class, int opts,
+ rrset_ns *nsrrsp)
+{
+ u_char *resp;
+ ns_msg msg;
+ int n;
+
+ resp = malloc(NS_MAXMSG);
+ if (resp == NULL)
+ return (-1);
+
+ /* Go and get the NS RRs for this zone. */
+ n = do_query(statp, zname, class, ns_t_ns, resp, &msg);
+ if (n != 0) {
+ DPRINTF(("get_ns: do_query('%s', %s) failed (%d)",
+ zname, p_class(class), n));
+ free(resp);
+ return (-1);
+ }
+
+ /* Remember the NS RRs and associated A RRs that came back. */
+ if (save_ns(statp, &msg, ns_s_an, zname, class, opts, nsrrsp) < 0) {
+ DPRINTF(("get_ns save_ns('%s', %s) failed",
+ zname, p_class(class)));
+ free(resp);
+ return (-1);
+ }
+
+ free(resp);
+ return (0);
+}
+
+static int
+get_glue(res_state statp, ns_class class, int opts, rrset_ns *nsrrsp) {
+ rr_ns *nsrr, *nsrr_n;
+ u_char *resp;
+
+ resp = malloc(NS_MAXMSG);
+ if (resp == NULL)
+ return(-1);
+
+ /* Go and get the A RRs for each empty NS RR on our list. */
+ for (nsrr = HEAD(*nsrrsp); nsrr != NULL; nsrr = nsrr_n) {
+ ns_msg msg;
+ int n;
+
+ nsrr_n = NEXT(nsrr, link);
+
+ if ((nsrr->flags & RR_NS_HAVE_V4) == 0) {
+ n = do_query(statp, nsrr->name, class, ns_t_a,
+ resp, &msg);
+ if (n < 0) {
+ DPRINTF(
+ ("get_glue: do_query('%s', %s') failed",
+ nsrr->name, p_class(class)));
+ goto cleanup;
+ }
+ if (n > 0) {
+ DPRINTF((
+ "get_glue: do_query('%s', %s') CNAME or DNAME found",
+ nsrr->name, p_class(class)));
+ }
+ if (save_a(statp, &msg, ns_s_an, nsrr->name, class,
+ opts, nsrr) < 0) {
+ DPRINTF(("get_glue: save_r('%s', %s) failed",
+ nsrr->name, p_class(class)));
+ goto cleanup;
+ }
+ }
+
+ if ((nsrr->flags & RR_NS_HAVE_V6) == 0) {
+ n = do_query(statp, nsrr->name, class, ns_t_aaaa,
+ resp, &msg);
+ if (n < 0) {
+ DPRINTF(
+ ("get_glue: do_query('%s', %s') failed",
+ nsrr->name, p_class(class)));
+ goto cleanup;
+ }
+ if (n > 0) {
+ DPRINTF((
+ "get_glue: do_query('%s', %s') CNAME or DNAME found",
+ nsrr->name, p_class(class)));
+ }
+ if (save_a(statp, &msg, ns_s_an, nsrr->name, class,
+ opts, nsrr) < 0) {
+ DPRINTF(("get_glue: save_r('%s', %s) failed",
+ nsrr->name, p_class(class)));
+ goto cleanup;
+ }
+ }
+
+ /* If it's still empty, it's just chaff. */
+ if (EMPTY(nsrr->addrs)) {
+ DPRINTF(("get_glue: removing empty '%s' NS",
+ nsrr->name));
+ free_nsrr(nsrrsp, nsrr);
+ }
+ }
+ free(resp);
+ return (0);
+
+ cleanup:
+ free(resp);
+ return (-1);
+}
+
+static int
+save_ns(res_state statp, ns_msg *msg, ns_sect sect,
+ const char *owner, ns_class class, int opts,
+ rrset_ns *nsrrsp)
+{
+ int i;
+
+ for (i = 0; i < ns_msg_count(*msg, sect); i++) {
+ char tname[MAXDNAME];
+ const u_char *rdata;
+ rr_ns *nsrr;
+ ns_rr rr;
+ int rdlen;
+
+ if (ns_parserr(msg, sect, i, &rr) < 0) {
+ DPRINTF(("save_ns: ns_parserr(%s, %d) failed",
+ p_section(sect, ns_o_query), i));
+ return (-1);
+ }
+ if (ns_rr_type(rr) != ns_t_ns ||
+ ns_rr_class(rr) != class ||
+ ns_samename(ns_rr_name(rr), owner) != 1)
+ continue;
+ nsrr = find_ns(nsrrsp, ns_rr_name(rr));
+ if (nsrr == NULL) {
+ nsrr = malloc(sizeof *nsrr);
+ if (nsrr == NULL) {
+ DPRINTF(("save_ns: malloc failed"));
+ return (-1);
+ }
+ rdata = ns_rr_rdata(rr);
+ rdlen = ns_rr_rdlen(rr);
+ if (ns_name_uncompress(ns_msg_base(*msg),
+ ns_msg_end(*msg), rdata,
+ tname, sizeof tname) < 0) {
+ DPRINTF(("save_ns: ns_name_uncompress failed")
+ );
+ free(nsrr);
+ return (-1);
+ }
+ nsrr->name = strdup(tname);
+ if (nsrr->name == NULL) {
+ DPRINTF(("save_ns: strdup failed"));
+ free(nsrr);
+ return (-1);
+ }
+ INIT_LINK(nsrr, link);
+ INIT_LIST(nsrr->addrs);
+ nsrr->flags = 0;
+ APPEND(*nsrrsp, nsrr, link);
+ }
+ if (save_a(statp, msg, ns_s_ar,
+ nsrr->name, class, opts, nsrr) < 0) {
+ DPRINTF(("save_ns: save_r('%s', %s) failed",
+ nsrr->name, p_class(class)));
+ return (-1);
+ }
+ }
+ return (0);
+}
+
+static int
+save_a(res_state statp, ns_msg *msg, ns_sect sect,
+ const char *owner, ns_class class, int opts,
+ rr_ns *nsrr)
+{
+ int i;
+
+ for (i = 0; i < ns_msg_count(*msg, sect); i++) {
+ ns_rr rr;
+ rr_a *arr;
+
+ if (ns_parserr(msg, sect, i, &rr) < 0) {
+ DPRINTF(("save_a: ns_parserr(%s, %d) failed",
+ p_section(sect, ns_o_query), i));
+ return (-1);
+ }
+ if ((ns_rr_type(rr) != ns_t_a &&
+ ns_rr_type(rr) != ns_t_aaaa) ||
+ ns_rr_class(rr) != class ||
+ ns_samename(ns_rr_name(rr), owner) != 1 ||
+ ns_rr_rdlen(rr) != NS_INADDRSZ)
+ continue;
+ if ((opts & RES_IPV6ONLY) != 0 && ns_rr_type(rr) != ns_t_aaaa)
+ continue;
+ if ((opts & RES_IPV4ONLY) != 0 && ns_rr_type(rr) != ns_t_a)
+ continue;
+ arr = malloc(sizeof *arr);
+ if (arr == NULL) {
+ DPRINTF(("save_a: malloc failed"));
+ return (-1);
+ }
+ INIT_LINK(arr, link);
+ memset(&arr->addr, 0, sizeof(arr->addr));
+ switch (ns_rr_type(rr)) {
+ case ns_t_a:
+ arr->addr.sin.sin_family = AF_INET;
+#ifdef HAVE_SA_LEN
+ arr->addr.sin.sin_len = sizeof(arr->addr.sin);
+#endif
+ memcpy(&arr->addr.sin.sin_addr, ns_rr_rdata(rr),
+ NS_INADDRSZ);
+ arr->addr.sin.sin_port = htons(NAMESERVER_PORT);
+ nsrr->flags |= RR_NS_HAVE_V4;
+ break;
+ case ns_t_aaaa:
+ arr->addr.sin6.sin6_family = AF_INET6;
+#ifdef HAVE_SA_LEN
+ arr->addr.sin6.sin6_len = sizeof(arr->addr.sin6);
+#endif
+ memcpy(&arr->addr.sin6.sin6_addr, ns_rr_rdata(rr), 16);
+ arr->addr.sin.sin_port = htons(NAMESERVER_PORT);
+ nsrr->flags |= RR_NS_HAVE_V6;
+ break;
+ default:
+ abort();
+ }
+ APPEND(nsrr->addrs, arr, link);
+ }
+ return (0);
+}
+
+static void
+free_nsrrset(rrset_ns *nsrrsp) {
+ rr_ns *nsrr;
+
+ while ((nsrr = HEAD(*nsrrsp)) != NULL)
+ free_nsrr(nsrrsp, nsrr);
+}
+
+static void
+free_nsrr(rrset_ns *nsrrsp, rr_ns *nsrr) {
+ rr_a *arr;
+ char *tmp;
+
+ while ((arr = HEAD(nsrr->addrs)) != NULL) {
+ UNLINK(nsrr->addrs, arr, link);
+ free(arr);
+ }
+ DE_CONST(nsrr->name, tmp);
+ free(tmp);
+ UNLINK(*nsrrsp, nsrr, link);
+ free(nsrr);
+}
+
+static rr_ns *
+find_ns(rrset_ns *nsrrsp, const char *dname) {
+ rr_ns *nsrr;
+
+ for (nsrr = HEAD(*nsrrsp); nsrr != NULL; nsrr = NEXT(nsrr, link))
+ if (ns_samename(nsrr->name, dname) == 1)
+ return (nsrr);
+ return (NULL);
+}
+
+static int
+do_query(res_state statp, const char *dname, ns_class class, ns_type qtype,
+ u_char *resp, ns_msg *msg)
+{
+ u_char req[NS_PACKETSZ];
+ int i, n;
+
+ n = res_nmkquery(statp, ns_o_query, dname, class, qtype,
+ NULL, 0, NULL, req, NS_PACKETSZ);
+ if (n < 0) {
+ DPRINTF(("do_query: res_nmkquery failed"));
+ return (-1);
+ }
+ n = res_nsend(statp, req, n, resp, NS_MAXMSG);
+ if (n < 0) {
+ DPRINTF(("do_query: res_nsend failed"));
+ return (-1);
+ }
+ if (n == 0) {
+ DPRINTF(("do_query: res_nsend returned 0"));
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (ns_initparse(resp, n, msg) < 0) {
+ DPRINTF(("do_query: ns_initparse failed"));
+ return (-1);
+ }
+ n = 0;
+ for (i = 0; i < ns_msg_count(*msg, ns_s_an); i++) {
+ ns_rr rr;
+
+ if (ns_parserr(msg, ns_s_an, i, &rr) < 0) {
+ DPRINTF(("do_query: ns_parserr failed"));
+ return (-1);
+ }
+ n += (ns_rr_class(rr) == class &&
+ (ns_rr_type(rr) == ns_t_cname ||
+ ns_rr_type(rr) == ns_t_dname));
+ }
+ return (n);
+}
+
+static void
+res_dprintf(const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ fputs(";; res_findzonecut: ", stderr);
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ va_end(ap);
+}
diff --git a/usr/src/lib/libresolv2/common/resolv/res_init.c b/usr/src/lib/libresolv2/common/resolv/res_init.c
new file mode 100644
index 0000000000..06b35591b1
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/resolv/res_init.c
@@ -0,0 +1,897 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1985, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
+static const char rcsid[] = "$Id: res_init.c,v 8.32 2003/04/03 06:31:10 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+
+#include "port_after.h"
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+#include "../../../libnsl/include/nsl_stdio_prv.h"
+#endif
+
+/* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */
+#include <resolv.h>
+
+#include "res_private.h"
+
+/* Options. Should all be left alone. */
+#define RESOLVSORT
+#define DEBUG
+
+#ifdef SUNW_INITCHKIF
+#include <net/if.h>
+#include <netinet/if_ether.h>
+#include <sys/sockio.h>
+#define MAXIFS 8192
+#endif /* SUNW_INITCHKIF */
+
+#ifdef SUNW_DOMAINFROMNIS
+#include <sys/systeminfo.h>
+#include <string.h>
+#endif /* SUNW_DOMAINFROMNIS */
+
+#ifdef ORIGINAL_ISC_CODE
+#else
+#pragma weak __res_randomid = res_randomid
+#endif /* ORIGINAL_ISC_CODE */
+
+static void res_setoptions __P((res_state, const char *, const char *));
+
+#ifdef RESOLVSORT
+static const char sort_mask[] = "/&";
+#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
+static u_int32_t net_mask __P((struct in_addr));
+#endif
+
+#if !defined(isascii) /* XXX - could be a function */
+# define isascii(c) (!(c & 0200))
+#endif
+
+/*
+ * Resolver state default settings.
+ */
+
+/*
+ * Set up default settings. If the configuration file exist, the values
+ * there will have precedence. Otherwise, the server address is set to
+ * INADDR_ANY and the default domain name comes from the gethostname().
+ *
+ * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
+ * rather than INADDR_ANY ("0.0.0.0") as the default name server address
+ * since it was noted that INADDR_ANY actually meant ``the first interface
+ * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
+ * it had to be "up" in order for you to reach your own name server. It
+ * was later decided that since the recommended practice is to always
+ * install local static routes through 127.0.0.1 for all your network
+ * interfaces, that we could solve this problem without a code change.
+ *
+ * The configuration file should always be used, since it is the only way
+ * to specify a default domain. If you are running a server on your local
+ * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
+ * in the configuration file.
+ *
+ * Return 0 if completes successfully, -1 on error
+ */
+int
+res_ninit(res_state statp) {
+ extern int __res_vinit(res_state, int);
+
+ return (__res_vinit(statp, 0));
+}
+
+/* This function has to be reachable by res_data.c but not publically. */
+int
+__res_vinit(res_state statp, int preinit) {
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+ register __NSL_FILE *fp;
+#else
+ register FILE *fp;
+#endif
+ register char *cp, **pp;
+ register int n;
+ char buf[BUFSIZ];
+ int nserv = 0; /* number of nameserver records read from file */
+ int haveenv = 0;
+ int havesearch = 0;
+#ifdef RESOLVSORT
+ int nsort = 0;
+ char *net;
+#endif
+ int dots;
+ union res_sockaddr_union u[2];
+
+ if (!preinit) {
+ statp->retrans = RES_TIMEOUT;
+ statp->retry = RES_DFLRETRY;
+ statp->options = RES_DEFAULT;
+ statp->id = res_randomid();
+ }
+
+ if ((statp->options & RES_INIT) != 0)
+ res_ndestroy(statp);
+
+ memset(u, 0, sizeof(u));
+#ifdef USELOOPBACK
+ u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
+#else
+ u[nserv].sin.sin_addr.s_addr = INADDR_ANY;
+#endif
+ u[nserv].sin.sin_family = AF_INET;
+ u[nserv].sin.sin_port = htons(NAMESERVER_PORT);
+#ifdef HAVE_SA_LEN
+ u[nserv].sin.sin_len = sizeof(struct sockaddr_in);
+#endif
+ nserv++;
+#ifdef HAS_INET6_STRUCTS
+#ifdef USELOOPBACK
+ u[nserv].sin6.sin6_addr = in6addr_loopback;
+#else
+ u[nserv].sin6.sin6_addr = in6addr_any;
+#endif
+ u[nserv].sin6.sin6_family = AF_INET6;
+ u[nserv].sin6.sin6_port = htons(NAMESERVER_PORT);
+#ifdef HAVE_SA_LEN
+ u[nserv].sin6.sin6_len = sizeof(struct sockaddr_in6);
+#endif
+ nserv++;
+#endif
+ statp->nscount = 0;
+ statp->ndots = 1;
+ statp->pfcode = 0;
+ statp->_vcsock = -1;
+ statp->_flags = 0;
+ statp->qhook = NULL;
+ statp->rhook = NULL;
+ statp->_u._ext.nscount = 0;
+ statp->_u._ext.ext = malloc(sizeof(*statp->_u._ext.ext));
+ if (statp->_u._ext.ext != NULL) {
+ memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext));
+ statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr;
+ strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa");
+ strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int");
+ }
+#ifdef RESOLVSORT
+ statp->nsort = 0;
+#endif
+ res_setservers(statp, u, nserv);
+
+#ifdef SUNW_INITCHKIF
+/*
+ * Short circuit res_init() if no non-loopback interfaces are up. This is
+ * done to avoid boot delays if "dns" comes before "files" in nsswitch.conf.
+ * An additional fix has been added to this code, to count all external
+ * interfaces, which includes the IPv6 interfaces. If no external interfaces
+ * are found, an additional check is carried out to determine if any deprecated
+ * interfaces are up.
+ */
+ {
+ int s;
+ struct lifnum lifn;
+
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("res_init: socket");
+ return (-1);
+ }
+ lifn.lifn_family = AF_UNSPEC;
+ lifn.lifn_flags = LIFC_EXTERNAL_SOURCE;
+ if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0) {
+ close(s);
+ return (-1);
+ }
+ if (lifn.lifn_count == 0) {
+ /*
+ * Check if there are any deprecated interfaces up
+ */
+ struct lifconf lifc;
+ uchar_t *buf;
+ int buflen, i, int_up = 0;
+
+ lifn.lifn_flags = 0;
+ if ((ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0) ||
+ (lifn.lifn_count < 1)) {
+ close(s);
+ return (-1);
+ }
+
+ buflen = lifn.lifn_count * sizeof (struct lifreq);
+ buf = (uchar_t *)malloc(buflen);
+ if (buf == NULL) {
+ close(s);
+ return (-1);
+ }
+
+ lifc.lifc_family = AF_UNSPEC;
+ lifc.lifc_flags = 0;
+ lifc.lifc_len = buflen;
+ lifc.lifc_lifcu.lifcu_buf = (caddr_t)buf;
+ if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) {
+ close(s);
+ free(buf);
+ return (-1);
+ }
+
+ for (i = 0; i < lifn.lifn_count; ++i) {
+ struct lifreq *lreqp, lreq;
+
+ lreqp = (struct lifreq *)&lifc.lifc_req[i];
+ strlcpy(lreq.lifr_name, lreqp->lifr_name,
+ sizeof (lreq.lifr_name));
+ if (ioctl(s, SIOCGLIFFLAGS, &lreq) < 0) {
+ close(s);
+ free(buf);
+ return (-1);
+ }
+ if ((lreq.lifr_flags & IFF_UP) &&
+ !(lreq.lifr_flags & IFF_NOLOCAL) &&
+ !(lreq.lifr_flags & IFF_NOXMIT) &&
+ !(lreq.lifr_flags & IFF_LOOPBACK)) {
+ int_up = 1;
+ break;
+ }
+ }
+ free(buf);
+
+ if (!int_up) {
+ close(s);
+ return (-1);
+ }
+ }
+ close(s);
+ }
+#endif /* SUNW_INITCHKIF */
+
+#ifdef SUNW_DOMAINFROMNIS
+/*
+ * The old (4.8.3) libresolv derived the default domainname from NIS/NIS+.
+ */
+ {
+ char buf[sizeof(statp->defdname)], *cp;
+ int ret;
+ if ((ret = sysinfo(SI_SRPC_DOMAIN, buf, sizeof(buf))) > 0 &&
+ ret <= sizeof(buf)) {
+ if (buf[0] == '+')
+ buf[0] = '.';
+ cp = strchr(buf, '.');
+ if (cp == 0)
+ strcpy(statp->defdname, buf);
+ else
+ strcpy(statp->defdname, cp+1);
+ }
+ }
+#endif /* SUNW_DOMAINFROMNIS */
+
+ /* Allow user to override the local domain definition */
+ if ((cp = getenv("LOCALDOMAIN")) != NULL) {
+ (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
+ statp->defdname[sizeof(statp->defdname) - 1] = '\0';
+ haveenv++;
+
+ /*
+ * Set search list to be blank-separated strings
+ * from rest of env value. Permits users of LOCALDOMAIN
+ * to still have a search list, and anyone to set the
+ * one that they want to use as an individual (even more
+ * important now that the rfc1535 stuff restricts searches)
+ */
+ cp = statp->defdname;
+ pp = statp->dnsrch;
+ *pp++ = cp;
+ for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
+ if (*cp == '\n') /* silly backwards compat */
+ break;
+ else if (*cp == ' ' || *cp == '\t') {
+ *cp = 0;
+ n = 1;
+ } else if (n) {
+ *pp++ = cp;
+ n = 0;
+ havesearch = 1;
+ }
+ }
+ /* null terminate last domain if there are excess */
+ while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
+ cp++;
+ *cp = '\0';
+ *pp++ = 0;
+ }
+
+#define MATCH(line, name) \
+ (!strncmp(line, name, sizeof(name) - 1) && \
+ (line[sizeof(name) - 1] == ' ' || \
+ line[sizeof(name) - 1] == '\t'))
+
+ nserv = 0;
+
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+ if ((fp = __nsl_fopen(_PATH_RESCONF, "r")) != NULL) {
+ /* read the config file */
+ while (__nsl_fgets(buf, sizeof(buf), fp) != NULL) {
+#else
+ if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
+ /* read the config file */
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+#endif
+ /* skip comments */
+ if (*buf == ';' || *buf == '#')
+ continue;
+ /* read default domain name */
+ if (MATCH(buf, "domain")) {
+ if (haveenv) /* skip if have from environ */
+ continue;
+ cp = buf + sizeof("domain") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp == '\0') || (*cp == '\n'))
+ continue;
+ strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
+ statp->defdname[sizeof(statp->defdname) - 1] = '\0';
+ if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL)
+ *cp = '\0';
+ havesearch = 0;
+ continue;
+ }
+ /* set search list */
+ if (MATCH(buf, "search")) {
+ if (haveenv) /* skip if have from environ */
+ continue;
+ cp = buf + sizeof("search") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp == '\0') || (*cp == '\n'))
+ continue;
+ strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
+ statp->defdname[sizeof(statp->defdname) - 1] = '\0';
+ if ((cp = strchr(statp->defdname, '\n')) != NULL)
+ *cp = '\0';
+ /*
+ * Set search list to be blank-separated strings
+ * on rest of line.
+ */
+ cp = statp->defdname;
+ pp = statp->dnsrch;
+ *pp++ = cp;
+ for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
+ if (*cp == ' ' || *cp == '\t') {
+ *cp = 0;
+ n = 1;
+ } else if (n) {
+ *pp++ = cp;
+ n = 0;
+ }
+ }
+ /* null terminate last domain if there are excess */
+ while (*cp != '\0' && *cp != ' ' && *cp != '\t')
+ cp++;
+ *cp = '\0';
+ *pp++ = 0;
+ havesearch = 1;
+ continue;
+ }
+ /* read nameservers to query */
+ if (MATCH(buf, "nameserver") && nserv < MAXNS) {
+ struct addrinfo hints, *ai;
+ char sbuf[NI_MAXSERV];
+ const size_t minsiz =
+ sizeof(statp->_u._ext.ext->nsaddrs[0]);
+
+ cp = buf + sizeof("nameserver") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ cp[strcspn(cp, ";# \t\n")] = '\0';
+ if ((*cp != '\0') && (*cp != '\n')) {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+ hints.ai_flags = AI_NUMERICHOST;
+ sprintf(sbuf, "%u", NAMESERVER_PORT);
+ if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 &&
+ ai->ai_addrlen <= minsiz) {
+ if (statp->_u._ext.ext != NULL) {
+ memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
+ ai->ai_addr, ai->ai_addrlen);
+ }
+ if (ai->ai_addrlen <=
+ sizeof(statp->nsaddr_list[nserv])) {
+ memcpy(&statp->nsaddr_list[nserv],
+ ai->ai_addr, ai->ai_addrlen);
+ } else
+ statp->nsaddr_list[nserv].sin_family = 0;
+ freeaddrinfo(ai);
+ nserv++;
+ }
+ }
+ continue;
+ }
+#ifdef RESOLVSORT
+ if (MATCH(buf, "sortlist")) {
+ struct in_addr a;
+
+ cp = buf + sizeof("sortlist") - 1;
+ while (nsort < MAXRESOLVSORT) {
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if (*cp == '\0' || *cp == '\n' || *cp == ';')
+ break;
+ net = cp;
+ while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
+ isascii(*cp) && !isspace((unsigned char)*cp))
+ cp++;
+ n = *cp;
+ *cp = 0;
+ if (inet_aton(net, &a)) {
+ statp->sort_list[nsort].addr = a;
+ if (ISSORTMASK(n)) {
+ *cp++ = n;
+ net = cp;
+ while (*cp && *cp != ';' &&
+ isascii(*cp) &&
+ !isspace((unsigned char)*cp))
+ cp++;
+ n = *cp;
+ *cp = 0;
+ if (inet_aton(net, &a)) {
+ statp->sort_list[nsort].mask = a.s_addr;
+ } else {
+ statp->sort_list[nsort].mask =
+ net_mask(statp->sort_list[nsort].addr);
+ }
+ } else {
+ statp->sort_list[nsort].mask =
+ net_mask(statp->sort_list[nsort].addr);
+ }
+ nsort++;
+ }
+ *cp = n;
+ }
+ continue;
+ }
+#endif
+ if (MATCH(buf, "options")) {
+ res_setoptions(statp, buf + sizeof("options") - 1, "conf");
+ continue;
+ }
+ }
+ if (nserv > 0)
+ statp->nscount = nserv;
+#ifdef RESOLVSORT
+ statp->nsort = nsort;
+#endif
+
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+ (void) __nsl_fclose(fp);
+#else
+ (void) fclose(fp);
+#endif
+ }
+/*
+ * Last chance to get a nameserver. This should not normally
+ * be necessary
+ */
+#ifdef NO_RESOLV_CONF
+ if(nserv == 0)
+ nserv = get_nameservers(statp);
+#endif
+
+ if (statp->defdname[0] == 0 &&
+ gethostname(buf, sizeof(statp->defdname) - 1) == 0 &&
+ (cp = strchr(buf, '.')) != NULL)
+ strcpy(statp->defdname, cp + 1);
+
+ /* find components of local domain that might be searched */
+ if (havesearch == 0) {
+ pp = statp->dnsrch;
+ *pp++ = statp->defdname;
+ *pp = NULL;
+
+ dots = 0;
+ for (cp = statp->defdname; *cp; cp++)
+ dots += (*cp == '.');
+
+ cp = statp->defdname;
+ while (pp < statp->dnsrch + MAXDFLSRCH) {
+ if (dots < LOCALDOMAINPARTS)
+ break;
+ cp = strchr(cp, '.') + 1; /* we know there is one */
+ *pp++ = cp;
+ dots--;
+ }
+ *pp = NULL;
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG) {
+ printf(";; res_init()... default dnsrch list:\n");
+ for (pp = statp->dnsrch; *pp; pp++)
+ printf(";;\t%s\n", *pp);
+ printf(";;\t..END..\n");
+ }
+#endif
+ }
+
+ if ((cp = getenv("RES_OPTIONS")) != NULL)
+ res_setoptions(statp, cp, "env");
+ statp->options |= RES_INIT;
+ return (0);
+}
+
+static void
+res_setoptions(res_state statp, const char *options, const char *source)
+{
+ const char *cp = options;
+ int i;
+ struct __res_state_ext *ext = statp->_u._ext.ext;
+
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_setoptions(\"%s\", \"%s\")...\n",
+ options, source);
+#endif
+ while (*cp) {
+ /* skip leading and inner runs of spaces */
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ /* search for and process individual options */
+ if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
+ i = atoi(cp + sizeof("ndots:") - 1);
+ if (i <= RES_MAXNDOTS)
+ statp->ndots = i;
+ else
+ statp->ndots = RES_MAXNDOTS;
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";;\tndots=%d\n", statp->ndots);
+#endif
+ } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
+ i = atoi(cp + sizeof("timeout:") - 1);
+ if (i <= RES_MAXRETRANS)
+ statp->retrans = i;
+ else
+ statp->retrans = RES_MAXRETRANS;
+ } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){
+ i = atoi(cp + sizeof("attempts:") - 1);
+ if (i <= RES_MAXRETRY)
+ statp->retry = i;
+ else
+ statp->retry = RES_MAXRETRY;
+#ifdef ORIGINAL_ISC_CODE
+#else
+ } else if (!strncmp(cp, "retrans:", sizeof("retrans:") - 1)) {
+ /*
+ * For backward compatibility, 'retrans' is
+ * supported as an alias for 'timeout', though
+ * without an imposed maximum.
+ */
+ statp->retrans = atoi(cp + sizeof("retrans:") - 1);
+ } else if (!strncmp(cp, "retry:", sizeof("retry:") - 1)){
+ /*
+ * For backward compatibility, 'retry' is
+ * supported as an alias for 'attempts', though
+ * without an imposed maximum.
+ */
+ statp->retry = atoi(cp + sizeof("retry:") - 1);
+#endif /* ORIGINAL_ISC_CODE */
+ } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
+#ifdef DEBUG
+ if (!(statp->options & RES_DEBUG)) {
+ printf(";; res_setoptions(\"%s\", \"%s\")..\n",
+ options, source);
+ statp->options |= RES_DEBUG;
+ }
+ printf(";;\tdebug\n");
+#endif
+ } else if (!strncmp(cp, "no_tld_query",
+ sizeof("no_tld_query") - 1) ||
+ !strncmp(cp, "no-tld-query",
+ sizeof("no-tld-query") - 1)) {
+ statp->options |= RES_NOTLDQUERY;
+ } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
+ statp->options |= RES_USE_INET6;
+ } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
+ statp->options |= RES_ROTATE;
+ } else if (!strncmp(cp, "no-check-names",
+ sizeof("no-check-names") - 1)) {
+ statp->options |= RES_NOCHECKNAME;
+ }
+#ifdef RES_USE_EDNS0
+ else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
+ statp->options |= RES_USE_EDNS0;
+ }
+#endif
+ else if (!strncmp(cp, "dname", sizeof("dname") - 1)) {
+ statp->options |= RES_USE_DNAME;
+ }
+ else if (!strncmp(cp, "nibble:", sizeof("nibble:") - 1)) {
+ if (ext == NULL)
+ goto skip;
+ cp += sizeof("nibble:") - 1;
+ i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix) - 1);
+ strncpy(ext->nsuffix, cp, i);
+ ext->nsuffix[i] = '\0';
+ }
+ else if (!strncmp(cp, "nibble2:", sizeof("nibble2:") - 1)) {
+ if (ext == NULL)
+ goto skip;
+ cp += sizeof("nibble2:") - 1;
+ i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix2) - 1);
+ strncpy(ext->nsuffix2, cp, i);
+ ext->nsuffix2[i] = '\0';
+ }
+ else if (!strncmp(cp, "v6revmode:", sizeof("v6revmode:") - 1)) {
+ cp += sizeof("v6revmode:") - 1;
+ /* "nibble" and "bitstring" used to be valid */
+ if (!strncmp(cp, "single", sizeof("single") - 1)) {
+ statp->options |= RES_NO_NIBBLE2;
+ } else if (!strncmp(cp, "both", sizeof("both") - 1)) {
+ statp->options &=
+ ~RES_NO_NIBBLE2;
+ }
+ }
+ else {
+ /* XXX - print a warning here? */
+ }
+ skip:
+ /* skip to next run of spaces */
+ while (*cp && *cp != ' ' && *cp != '\t')
+ cp++;
+ }
+}
+
+#ifdef RESOLVSORT
+/* XXX - should really support CIDR which means explicit masks always. */
+static u_int32_t
+net_mask(in) /* XXX - should really use system's version of this */
+ struct in_addr in;
+{
+ register u_int32_t i = ntohl(in.s_addr);
+
+ if (IN_CLASSA(i))
+ return (htonl(IN_CLASSA_NET));
+ else if (IN_CLASSB(i))
+ return (htonl(IN_CLASSB_NET));
+ return (htonl(IN_CLASSC_NET));
+}
+#endif
+
+u_int
+res_randomid(void) {
+ struct timeval now;
+
+ gettimeofday(&now, NULL);
+ return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid()));
+}
+
+/*
+ * This routine is for closing the socket if a virtual circuit is used and
+ * the program wants to close it. This provides support for endhostent()
+ * which expects to close the socket.
+ *
+ * This routine is not expected to be user visible.
+ */
+void
+res_nclose(res_state statp) {
+ int ns;
+
+ if (statp->_vcsock >= 0) {
+ (void) close(statp->_vcsock);
+ statp->_vcsock = -1;
+ statp->_flags &= ~(RES_F_VC | RES_F_CONN);
+ }
+ for (ns = 0; ns < statp->_u._ext.nscount; ns++) {
+ if (statp->_u._ext.nssocks[ns] != -1) {
+ (void) close(statp->_u._ext.nssocks[ns]);
+ statp->_u._ext.nssocks[ns] = -1;
+ }
+ }
+}
+
+void
+res_ndestroy(res_state statp) {
+ res_nclose(statp);
+ if (statp->_u._ext.ext != NULL)
+ free(statp->_u._ext.ext);
+ statp->options &= ~RES_INIT;
+ statp->_u._ext.ext = NULL;
+}
+
+const char *
+res_get_nibblesuffix(res_state statp) {
+ if (statp->_u._ext.ext)
+ return (statp->_u._ext.ext->nsuffix);
+ return ("ip6.arpa");
+}
+
+const char *
+res_get_nibblesuffix2(res_state statp) {
+ if (statp->_u._ext.ext)
+ return (statp->_u._ext.ext->nsuffix2);
+ return ("ip6.int");
+}
+
+void
+res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) {
+ int i, nserv;
+ size_t size;
+
+ /* close open servers */
+ res_nclose(statp);
+
+ /* cause rtt times to be forgotten */
+ statp->_u._ext.nscount = 0;
+
+ nserv = 0;
+ for (i = 0; i < cnt && nserv < MAXNS; i++) {
+ switch (set->sin.sin_family) {
+ case AF_INET:
+ size = sizeof(set->sin);
+ if (statp->_u._ext.ext)
+ memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
+ &set->sin, size);
+ if (size <= sizeof(statp->nsaddr_list[nserv]))
+ memcpy(&statp->nsaddr_list[nserv],
+ &set->sin, size);
+ else
+ statp->nsaddr_list[nserv].sin_family = 0;
+ nserv++;
+ break;
+
+#ifdef HAS_INET6_STRUCTS
+ case AF_INET6:
+ size = sizeof(set->sin6);
+ if (statp->_u._ext.ext)
+ memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
+ &set->sin6, size);
+ if (size <= sizeof(statp->nsaddr_list[nserv]))
+ memcpy(&statp->nsaddr_list[nserv],
+ &set->sin6, size);
+ else
+ statp->nsaddr_list[nserv].sin_family = 0;
+ nserv++;
+ break;
+#endif
+
+ default:
+ break;
+ }
+ set++;
+ }
+ statp->nscount = nserv;
+
+}
+
+int
+res_getservers(res_state statp, union res_sockaddr_union *set, int cnt) {
+ int i;
+ size_t size;
+ u_int16_t family;
+
+ for (i = 0; i < statp->nscount && i < cnt; i++) {
+ if (statp->_u._ext.ext)
+ family = statp->_u._ext.ext->nsaddrs[i].sin.sin_family;
+ else
+ family = statp->nsaddr_list[i].sin_family;
+
+ switch (family) {
+ case AF_INET:
+ size = sizeof(set->sin);
+ if (statp->_u._ext.ext)
+ memcpy(&set->sin,
+ &statp->_u._ext.ext->nsaddrs[i],
+ size);
+ else
+ memcpy(&set->sin, &statp->nsaddr_list[i],
+ size);
+ break;
+
+#ifdef HAS_INET6_STRUCTS
+ case AF_INET6:
+ size = sizeof(set->sin6);
+ if (statp->_u._ext.ext)
+ memcpy(&set->sin6,
+ &statp->_u._ext.ext->nsaddrs[i],
+ size);
+ else
+ memcpy(&set->sin6, &statp->nsaddr_list[i],
+ size);
+ break;
+#endif
+
+ default:
+ set->sin.sin_family = 0;
+ break;
+ }
+ set++;
+ }
+ return (statp->nscount);
+}
diff --git a/usr/src/lib/libresolv2/common/resolv/res_mkquery.c b/usr/src/lib/libresolv2/common/resolv/res_mkquery.c
new file mode 100644
index 0000000000..c81e9eba32
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/resolv/res_mkquery.c
@@ -0,0 +1,359 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_mkquery.c,v 8.16 2003/04/29 02:13:08 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include "port_before.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#ifdef SUNW_CONFCHECK
+#include <sys/socket.h>
+#include <errno.h>
+#include <sys/stat.h>
+#endif
+
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+#include "port_after.h"
+
+/* Options. Leave them on. */
+#define DEBUG
+
+extern const char *_res_opcodes[];
+
+#ifdef SUNW_CONFCHECK
+static int _confcheck(res_state statp);
+#endif
+
+/*
+ * Form all types of queries.
+ * Returns the size of the result or -1.
+ */
+int
+res_nmkquery(res_state statp,
+ int op, /* opcode of query */
+ const char *dname, /* domain name */
+ int class, int type, /* class and type of query */
+ const u_char *data, /* resource record data */
+ int datalen, /* length of data */
+ const u_char *newrr_in, /* new rr for modify or append */
+ u_char *buf, /* buffer to put query */
+ int buflen) /* size of buffer */
+{
+ register HEADER *hp;
+ register u_char *cp, *ep;
+ register int n;
+ u_char *dnptrs[20], **dpp, **lastdnptr;
+
+ UNUSED(newrr_in);
+
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_nmkquery(%s, %s, %s, %s)\n",
+ _res_opcodes[op], dname, p_class(class), p_type(type));
+#endif
+
+#ifdef SUNW_CONFCHECK
+ /*
+ * 1247019, 1265838, and 4034368: Check to see if we can
+ * bailout quickly.
+ */
+ if (_confcheck(statp) == -1) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return(-1);
+ }
+#endif
+
+ /*
+ * Initialize header fields.
+ */
+ if ((buf == NULL) || (buflen < HFIXEDSZ))
+ return (-1);
+ memset(buf, 0, HFIXEDSZ);
+ hp = (HEADER *) buf;
+ hp->id = htons(++statp->id);
+ hp->opcode = op;
+ hp->rd = (statp->options & RES_RECURSE) != 0;
+ hp->rcode = NOERROR;
+ cp = buf + HFIXEDSZ;
+ ep = buf + buflen;
+ dpp = dnptrs;
+ *dpp++ = buf;
+ *dpp++ = NULL;
+ lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
+ /*
+ * perform opcode specific processing
+ */
+ switch (op) {
+ case QUERY: /*FALLTHROUGH*/
+ case NS_NOTIFY_OP:
+ if (ep - cp < QFIXEDSZ)
+ return (-1);
+ if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs,
+ lastdnptr)) < 0)
+ return (-1);
+ cp += n;
+ ns_put16(type, cp);
+ cp += INT16SZ;
+ ns_put16(class, cp);
+ cp += INT16SZ;
+ hp->qdcount = htons(1);
+ if (op == QUERY || data == NULL)
+ break;
+ /*
+ * Make an additional record for completion domain.
+ */
+ if ((ep - cp) < RRFIXEDSZ)
+ return (-1);
+ n = dn_comp((const char *)data, cp, ep - cp - RRFIXEDSZ,
+ dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ns_put16(T_NULL, cp);
+ cp += INT16SZ;
+ ns_put16(class, cp);
+ cp += INT16SZ;
+ ns_put32(0, cp);
+ cp += INT32SZ;
+ ns_put16(0, cp);
+ cp += INT16SZ;
+ hp->arcount = htons(1);
+ break;
+
+ case IQUERY:
+ /*
+ * Initialize answer section
+ */
+ if (ep - cp < 1 + RRFIXEDSZ + datalen)
+ return (-1);
+ *cp++ = '\0'; /* no domain name */
+ ns_put16(type, cp);
+ cp += INT16SZ;
+ ns_put16(class, cp);
+ cp += INT16SZ;
+ ns_put32(0, cp);
+ cp += INT32SZ;
+ ns_put16(datalen, cp);
+ cp += INT16SZ;
+ if (datalen) {
+ memcpy(cp, data, datalen);
+ cp += datalen;
+ }
+ hp->ancount = htons(1);
+ break;
+
+ default:
+ return (-1);
+ }
+ return (cp - buf);
+}
+
+#ifdef RES_USE_EDNS0
+/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
+#ifndef T_OPT
+#define T_OPT 41
+#endif
+
+int
+res_nopt(res_state statp,
+ int n0, /* current offset in buffer */
+#ifdef ORIGINAL_ISC_CODE
+ u_char *buf, /* buffer to put query */
+#else
+ uchar_t *buf, /* buffer to put query */
+#endif
+ int buflen, /* size of buffer */
+ int anslen) /* UDP answer buffer size */
+{
+ register HEADER *hp;
+ register u_char *cp, *ep;
+ u_int16_t flags = 0;
+
+#ifdef DEBUG
+ if ((statp->options & RES_DEBUG) != 0)
+ printf(";; res_nopt()\n");
+#endif
+
+ hp = (HEADER *) buf;
+ cp = buf + n0;
+ ep = buf + buflen;
+
+ if ((ep - cp) < 1 + RRFIXEDSZ)
+ return (-1);
+
+ *cp++ = 0; /* "." */
+
+ ns_put16(T_OPT, cp); /* TYPE */
+ cp += INT16SZ;
+ ns_put16(anslen & 0xffff, cp); /* CLASS = UDP payload size */
+ cp += INT16SZ;
+ *cp++ = NOERROR; /* extended RCODE */
+ *cp++ = 0; /* EDNS version */
+ if (statp->options & RES_USE_DNSSEC) {
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_opt()... ENDS0 DNSSEC\n");
+#endif
+ flags |= NS_OPT_DNSSEC_OK;
+ }
+ ns_put16(flags, cp);
+ cp += INT16SZ;
+ ns_put16(0, cp); /* RDLEN */
+ cp += INT16SZ;
+ hp->arcount = htons(ntohs(hp->arcount) + 1);
+
+ return (cp - buf);
+}
+#endif
+
+#ifdef SUNW_CONFCHECK
+/*
+ * Kludge to time out quickly if there is no /etc/resolv.conf
+ * and a TCP connection to the local DNS server fails.
+ *
+ * Moved function from res_send.c to res_mkquery.c. This
+ * solves a long timeout problem with nslookup.
+ *
+ * __areweinnamed is needed because there is a possibility that the
+ * user might do bad things to resolv.conf and cause in.named to call
+ * _confcheck and deadlock the server.
+ */
+
+#ifdef SUNW_AREWEINNAMED
+int __areweinnamed()
+{
+ return (0);
+}
+#endif /* SUNW_AREWEINNAMED */
+
+static int _confcheck(res_state statp)
+{
+ int ns;
+ struct stat rc_stat;
+ struct sockaddr_in ns_sin;
+
+
+ if (__areweinnamed())
+ return (0);
+
+ /* First, we check to see if /etc/resolv.conf exists.
+ * If it doesn't, then it is likely that the localhost is
+ * the nameserver.
+ */
+ if (stat(_PATH_RESCONF, &rc_stat) == -1 && errno == ENOENT) {
+
+ /* Next, we check to see if _res.nsaddr is set to loopback.
+ * If it isn't, it has been altered by the application
+ * explicitly and we then want to bail with success.
+ */
+ if (statp->nsaddr.sin_addr.S_un.S_addr ==
+ htonl(INADDR_LOOPBACK)) {
+
+ /* Lastly, we try to connect to the TCP port of the
+ * nameserver. If this fails, then we know that
+ * DNS is misconfigured and we can quickly exit.
+ */
+ ns = socket(AF_INET, SOCK_STREAM, 0);
+ IN_SET_LOOPBACK_ADDR(&ns_sin);
+ ns_sin.sin_port = htons(NAMESERVER_PORT);
+ if (connect(ns, (struct sockaddr *) &ns_sin,
+ sizeof ns_sin) == -1) {
+ close(ns);
+ return(-1);
+ }
+ else {
+ close(ns);
+
+ return(0);
+ }
+ }
+
+ return(0);
+ }
+
+ return (0);
+}
+#endif
diff --git a/usr/src/lib/libresolv2/common/resolv/res_mkupdate.c b/usr/src/lib/libresolv2/common/resolv/res_mkupdate.c
new file mode 100644
index 0000000000..d66f0b91ed
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/resolv/res_mkupdate.c
@@ -0,0 +1,1165 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Based on the Dynamic DNS reference implementation by Viraj Bais
+ * <viraj_bais@ccm.fm.intel.com>
+ */
+
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: res_mkupdate.c,v 1.30 2003/08/14 07:54:50 marka Exp $";
+#endif /* not lint */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <res_update.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include "port_after.h"
+
+/* Options. Leave them on. */
+#define DEBUG
+#define MAXPORT 1024
+
+static int getnum_str(u_char **, u_char *);
+static int gethexnum_str(u_char **, u_char *);
+static int getword_str(char *, int, u_char **, u_char *);
+static int getstr_str(char *, int, u_char **, u_char *);
+
+#define ShrinkBuffer(x) if ((buflen -= x) < 0) return (-2);
+
+/* Forward. */
+
+int res_protocolnumber(const char *);
+int res_servicenumber(const char *);
+
+/*
+ * Form update packets.
+ * Returns the size of the resulting packet if no error
+ * On error,
+ * returns -1 if error in reading a word/number in rdata
+ * portion for update packets
+ * -2 if length of buffer passed is insufficient
+ * -3 if zone section is not the first section in
+ * the linked list, or section order has a problem
+ * -4 on a number overflow
+ * -5 unknown operation or no records
+ */
+int
+res_nmkupdate(res_state statp, ns_updrec *rrecp_in, u_char *buf, int buflen) {
+ ns_updrec *rrecp_start = rrecp_in;
+ HEADER *hp;
+ u_char *cp, *sp1, *sp2, *startp, *endp;
+ int n, i, soanum, multiline;
+ ns_updrec *rrecp;
+ struct in_addr ina;
+ struct in6_addr in6a;
+ char buf2[MAXDNAME];
+ u_char buf3[MAXDNAME];
+ int section, numrrs = 0, counts[ns_s_max];
+ u_int16_t rtype, rclass;
+ u_int32_t n1, rttl;
+ u_char *dnptrs[20], **dpp, **lastdnptr;
+ int siglen, keylen, certlen;
+
+ /*
+ * Initialize header fields.
+ */
+ if ((buf == NULL) || (buflen < HFIXEDSZ))
+ return (-1);
+ memset(buf, 0, HFIXEDSZ);
+ hp = (HEADER *) buf;
+ hp->id = htons(++statp->id);
+ hp->opcode = ns_o_update;
+ hp->rcode = NOERROR;
+ sp1 = buf + 2*INT16SZ; /* save pointer to zocount */
+ cp = buf + HFIXEDSZ;
+ buflen -= HFIXEDSZ;
+ dpp = dnptrs;
+ *dpp++ = buf;
+ *dpp++ = NULL;
+ lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
+
+ if (rrecp_start == NULL)
+ return (-5);
+ else if (rrecp_start->r_section != S_ZONE)
+ return (-3);
+
+ memset(counts, 0, sizeof counts);
+ for (rrecp = rrecp_start; rrecp; rrecp = NEXT(rrecp, r_glink)) {
+ numrrs++;
+ section = rrecp->r_section;
+ if (section < 0 || section >= ns_s_max)
+ return (-1);
+ counts[section]++;
+ for (i = section + 1; i < ns_s_max; i++)
+ if (counts[i])
+ return (-3);
+ rtype = rrecp->r_type;
+ rclass = rrecp->r_class;
+ rttl = rrecp->r_ttl;
+ /* overload class and type */
+ if (section == S_PREREQ) {
+ rttl = 0;
+ switch (rrecp->r_opcode) {
+ case YXDOMAIN:
+ rclass = C_ANY;
+ rtype = T_ANY;
+ rrecp->r_size = 0;
+ break;
+ case NXDOMAIN:
+ rclass = C_NONE;
+ rtype = T_ANY;
+ rrecp->r_size = 0;
+ break;
+ case NXRRSET:
+ rclass = C_NONE;
+ rrecp->r_size = 0;
+ break;
+ case YXRRSET:
+ if (rrecp->r_size == 0)
+ rclass = C_ANY;
+ break;
+ default:
+ fprintf(stderr,
+ "res_mkupdate: incorrect opcode: %d\n",
+ rrecp->r_opcode);
+ fflush(stderr);
+ return (-1);
+ }
+ } else if (section == S_UPDATE) {
+ switch (rrecp->r_opcode) {
+ case DELETE:
+ rclass = rrecp->r_size == 0 ? C_ANY : C_NONE;
+ break;
+ case ADD:
+ break;
+ default:
+ fprintf(stderr,
+ "res_mkupdate: incorrect opcode: %d\n",
+ rrecp->r_opcode);
+ fflush(stderr);
+ return (-1);
+ }
+ }
+
+ /*
+ * XXX appending default domain to owner name is omitted,
+ * fqdn must be provided
+ */
+ if ((n = dn_comp(rrecp->r_dname, cp, buflen, dnptrs,
+ lastdnptr)) < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n + 2*INT16SZ);
+ PUTSHORT(rtype, cp);
+ PUTSHORT(rclass, cp);
+ if (section == S_ZONE) {
+ if (numrrs != 1 || rrecp->r_type != T_SOA)
+ return (-3);
+ continue;
+ }
+ ShrinkBuffer(INT32SZ + INT16SZ);
+ PUTLONG(rttl, cp);
+ sp2 = cp; /* save pointer to length byte */
+ cp += INT16SZ;
+ if (rrecp->r_size == 0) {
+ if (section == S_UPDATE && rclass != C_ANY)
+ return (-1);
+ else {
+ PUTSHORT(0, sp2);
+ continue;
+ }
+ }
+ startp = rrecp->r_data;
+ endp = startp + rrecp->r_size - 1;
+ /* XXX this should be done centrally. */
+ switch (rrecp->r_type) {
+ case T_A:
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ if (!inet_aton(buf2, &ina))
+ return (-1);
+ n1 = ntohl(ina.s_addr);
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(n1, cp);
+ break;
+ case T_CNAME:
+ case T_MB:
+ case T_MG:
+ case T_MR:
+ case T_NS:
+ case T_PTR:
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ break;
+ case T_MINFO:
+ case T_SOA:
+ case T_RP:
+ for (i = 0; i < 2; i++) {
+ if (!getword_str(buf2, sizeof buf2, &startp,
+ endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen,
+ dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ }
+ if (rrecp->r_type == T_SOA) {
+ ShrinkBuffer(5 * INT32SZ);
+ while (isspace(*startp) || !*startp)
+ startp++;
+ if (*startp == '(') {
+ multiline = 1;
+ startp++;
+ } else
+ multiline = 0;
+ /* serial, refresh, retry, expire, minimum */
+ for (i = 0; i < 5; i++) {
+ soanum = getnum_str(&startp, endp);
+ if (soanum < 0)
+ return (-1);
+ PUTLONG(soanum, cp);
+ }
+ if (multiline) {
+ while (isspace(*startp) || !*startp)
+ startp++;
+ if (*startp != ')')
+ return (-1);
+ }
+ }
+ break;
+ case T_MX:
+ case T_AFSDB:
+ case T_RT:
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ break;
+ case T_SRV:
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, NULL, NULL);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ break;
+ case T_PX:
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ PUTSHORT(n, cp);
+ ShrinkBuffer(INT16SZ);
+ for (i = 0; i < 2; i++) {
+ if (!getword_str(buf2, sizeof buf2, &startp,
+ endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs,
+ lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ }
+ break;
+ case T_WKS: {
+ char bm[MAXPORT/8];
+ unsigned int maxbm = 0;
+
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ if (!inet_aton(buf2, &ina))
+ return (-1);
+ n1 = ntohl(ina.s_addr);
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(n1, cp);
+
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ if ((i = res_protocolnumber(buf2)) < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = i & 0xff;
+
+ for (i = 0; i < MAXPORT/8 ; i++)
+ bm[i] = 0;
+
+ while (getword_str(buf2, sizeof buf2, &startp, endp)) {
+ if ((n1 = res_servicenumber(buf2)) <= 0)
+ return (-1);
+
+ if (n1 < MAXPORT) {
+ bm[n1/8] |= (0x80>>(n1%8));
+ if (n1 > maxbm)
+ maxbm = n1;
+ } else
+ return (-1);
+ }
+ maxbm = maxbm/8 + 1;
+ ShrinkBuffer(maxbm);
+ memcpy(cp, bm, maxbm);
+ cp += maxbm;
+ break;
+ }
+ case T_HINFO:
+ for (i = 0; i < 2; i++) {
+ if ((n = getstr_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ }
+ break;
+ case T_TXT:
+ while (1) {
+ if ((n = getstr_str(buf2, sizeof buf2,
+ &startp, endp)) < 0) {
+ if (cp != (sp2 + INT16SZ))
+ break;
+ return (-1);
+ }
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ }
+ break;
+ case T_X25:
+ /* RFC 1183 */
+ if ((n = getstr_str(buf2, sizeof buf2, &startp,
+ endp)) < 0)
+ return (-1);
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ break;
+ case T_ISDN:
+ /* RFC 1183 */
+ if ((n = getstr_str(buf2, sizeof buf2, &startp,
+ endp)) < 0)
+ return (-1);
+ if ((n > 255) || (n == 0))
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ if ((n = getstr_str(buf2, sizeof buf2, &startp,
+ endp)) < 0)
+ n = 0;
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ break;
+ case T_NSAP:
+ if ((n = inet_nsap_addr((char *)startp, (u_char *)buf2, sizeof(buf2))) != 0) {
+ ShrinkBuffer(n);
+ memcpy(cp, buf2, n);
+ cp += n;
+ } else {
+ return (-1);
+ }
+ break;
+ case T_LOC:
+ if ((n = loc_aton((char *)startp, (u_char *)buf2)) != 0) {
+ ShrinkBuffer(n);
+ memcpy(cp, buf2, n);
+ cp += n;
+ } else
+ return (-1);
+ break;
+ case ns_t_sig:
+ {
+ int sig_type, success, dateerror;
+ u_int32_t exptime, timesigned;
+
+ /* type */
+ if ((n = getword_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ sig_type = sym_ston(__p_type_syms, buf2, &success);
+ if (!success || sig_type == ns_t_any)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(sig_type, cp);
+ /* alg */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* labels */
+ n = getnum_str(&startp, endp);
+ if (n <= 0 || n > 255)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* ottl & expire */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ exptime = ns_datetosecs(buf2, &dateerror);
+ if (!dateerror) {
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(rttl, cp);
+ }
+ else {
+ char *ulendp;
+ u_int32_t ottl;
+
+ errno = 0;
+ ottl = strtoul(buf2, &ulendp, 10);
+ if (errno != 0 ||
+ (ulendp != NULL && *ulendp != '\0'))
+ return (-1);
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(ottl, cp);
+ if (!getword_str(buf2, sizeof buf2, &startp,
+ endp))
+ return (-1);
+ exptime = ns_datetosecs(buf2, &dateerror);
+ if (dateerror)
+ return (-1);
+ }
+ /* expire */
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(exptime, cp);
+ /* timesigned */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ timesigned = ns_datetosecs(buf2, &dateerror);
+ if (!dateerror) {
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(timesigned, cp);
+ }
+ else
+ return (-1);
+ /* footprint */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* signer name */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ /* sig */
+ if ((n = getword_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ siglen = b64_pton(buf2, buf3, sizeof(buf3));
+ if (siglen < 0)
+ return (-1);
+ ShrinkBuffer(siglen);
+ memcpy(cp, buf3, siglen);
+ cp += siglen;
+ break;
+ }
+ case ns_t_key:
+ /* flags */
+ n = gethexnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* proto */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* alg */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* key */
+ if ((n = getword_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ keylen = b64_pton(buf2, buf3, sizeof(buf3));
+ if (keylen < 0)
+ return (-1);
+ ShrinkBuffer(keylen);
+ memcpy(cp, buf3, keylen);
+ cp += keylen;
+ break;
+ case ns_t_nxt:
+ {
+ int success, nxt_type;
+ u_char data[32];
+ int maxtype;
+
+ /* next name */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, NULL, NULL);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ maxtype = 0;
+ memset(data, 0, sizeof data);
+ while (1) {
+ if (!getword_str(buf2, sizeof buf2, &startp,
+ endp))
+ break;
+ nxt_type = sym_ston(__p_type_syms, buf2,
+ &success);
+ if (!success || !ns_t_rr_p(nxt_type))
+ return (-1);
+ NS_NXT_BIT_SET(nxt_type, data);
+ if (nxt_type > maxtype)
+ maxtype = nxt_type;
+ }
+ n = maxtype/NS_NXT_BITS+1;
+ ShrinkBuffer(n);
+ memcpy(cp, data, n);
+ cp += n;
+ break;
+ }
+ case ns_t_cert:
+ /* type */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* key tag */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* alg */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* cert */
+ if ((n = getword_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ certlen = b64_pton(buf2, buf3, sizeof(buf3));
+ if (certlen < 0)
+ return (-1);
+ ShrinkBuffer(certlen);
+ memcpy(cp, buf3, certlen);
+ cp += certlen;
+ break;
+ case ns_t_aaaa:
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ if (inet_pton(AF_INET6, buf2, &in6a) <= 0)
+ return (-1);
+ ShrinkBuffer(NS_IN6ADDRSZ);
+ memcpy(cp, &in6a, NS_IN6ADDRSZ);
+ cp += NS_IN6ADDRSZ;
+ break;
+ case ns_t_naptr:
+ /* Order Preference Flags Service Replacement Regexp */
+ /* Order */
+ n = getnum_str(&startp, endp);
+ if (n < 0 || n > 65535)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* Preference */
+ n = getnum_str(&startp, endp);
+ if (n < 0 || n > 65535)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* Flags */
+ if ((n = getstr_str(buf2, sizeof buf2,
+ &startp, endp)) < 0) {
+ return (-1);
+ }
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ /* Service Classes */
+ if ((n = getstr_str(buf2, sizeof buf2,
+ &startp, endp)) < 0) {
+ return (-1);
+ }
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ /* Pattern */
+ if ((n = getstr_str(buf2, sizeof buf2,
+ &startp, endp)) < 0) {
+ return (-1);
+ }
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ /* Replacement */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, NULL, NULL);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ break;
+ default:
+ return (-1);
+ } /*switch*/
+ n = (u_int16_t)((cp - sp2) - INT16SZ);
+ PUTSHORT(n, sp2);
+ } /*for*/
+
+ hp->qdcount = htons(counts[0]);
+ hp->ancount = htons(counts[1]);
+ hp->nscount = htons(counts[2]);
+ hp->arcount = htons(counts[3]);
+ return (cp - buf);
+}
+
+/*
+ * Get a whitespace delimited word from a string (not file)
+ * into buf. modify the start pointer to point after the
+ * word in the string.
+ */
+static int
+getword_str(char *buf, int size, u_char **startpp, u_char *endp) {
+ char *cp;
+ int c;
+
+ for (cp = buf; *startpp <= endp; ) {
+ c = **startpp;
+ if (isspace(c) || c == '\0') {
+ if (cp != buf) /* trailing whitespace */
+ break;
+ else { /* leading whitespace */
+ (*startpp)++;
+ continue;
+ }
+ }
+ (*startpp)++;
+ if (cp >= buf+size-1)
+ break;
+ *cp++ = (u_char)c;
+ }
+ *cp = '\0';
+ return (cp != buf);
+}
+
+/*
+ * get a white spae delimited string from memory. Process quoted strings
+ * and \DDD escapes. Return length or -1 on error. Returned string may
+ * contain nulls.
+ */
+static char digits[] = "0123456789";
+static int
+getstr_str(char *buf, int size, u_char **startpp, u_char *endp) {
+ char *cp;
+ int c, c1 = 0;
+ int inquote = 0;
+ int seen_quote = 0;
+ int escape = 0;
+ int dig = 0;
+
+ for (cp = buf; *startpp <= endp; ) {
+ if ((c = **startpp) == '\0')
+ break;
+ /* leading white space */
+ if ((cp == buf) && !seen_quote && isspace(c)) {
+ (*startpp)++;
+ continue;
+ }
+
+ switch (c) {
+ case '\\':
+ if (!escape) {
+ escape = 1;
+ dig = 0;
+ c1 = 0;
+ (*startpp)++;
+ continue;
+ }
+ goto do_escape;
+ case '"':
+ if (!escape) {
+ inquote = !inquote;
+ seen_quote = 1;
+ (*startpp)++;
+ continue;
+ }
+ /* fall through */
+ default:
+ do_escape:
+ if (escape) {
+ switch (c) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ c1 = c1 * 10 +
+ (strchr(digits, c) - digits);
+
+ if (++dig == 3) {
+ c = c1 &0xff;
+ break;
+ }
+ (*startpp)++;
+ continue;
+ }
+ escape = 0;
+ } else if (!inquote && isspace(c))
+ goto done;
+ if (cp >= buf+size-1)
+ goto done;
+ *cp++ = (u_char)c;
+ (*startpp)++;
+ }
+ }
+ done:
+ *cp = '\0';
+ return ((cp == buf)? (seen_quote? 0: -1): (cp - buf));
+}
+/*
+ * Get a whitespace delimited base 16 number from a string (not file) into buf
+ * update the start pointer to point after the number in the string.
+ */
+static int
+gethexnum_str(u_char **startpp, u_char *endp) {
+ int c, n;
+ int seendigit = 0;
+ int m = 0;
+
+ if (*startpp + 2 >= endp || strncasecmp((char *)*startpp, "0x", 2) != 0)
+ return getnum_str(startpp, endp);
+ (*startpp)+=2;
+ for (n = 0; *startpp <= endp; ) {
+ c = **startpp;
+ if (isspace(c) || c == '\0') {
+ if (seendigit) /* trailing whitespace */
+ break;
+ else { /* leading whitespace */
+ (*startpp)++;
+ continue;
+ }
+ }
+ if (c == ';') {
+ while ((*startpp <= endp) &&
+ ((c = **startpp) != '\n'))
+ (*startpp)++;
+ if (seendigit)
+ break;
+ continue;
+ }
+ if (!isxdigit(c)) {
+ if (c == ')' && seendigit) {
+ (*startpp)--;
+ break;
+ }
+ return (-1);
+ }
+ (*startpp)++;
+ if (isdigit(c))
+ n = n * 16 + (c - '0');
+ else
+ n = n * 16 + (tolower(c) - 'a' + 10);
+ seendigit = 1;
+ }
+ return (n + m);
+}
+
+/*
+ * Get a whitespace delimited base 10 number from a string (not file) into buf
+ * update the start pointer to point after the number in the string.
+ */
+static int
+getnum_str(u_char **startpp, u_char *endp) {
+ int c, n;
+ int seendigit = 0;
+ int m = 0;
+
+ for (n = 0; *startpp <= endp; ) {
+ c = **startpp;
+ if (isspace(c) || c == '\0') {
+ if (seendigit) /* trailing whitespace */
+ break;
+ else { /* leading whitespace */
+ (*startpp)++;
+ continue;
+ }
+ }
+ if (c == ';') {
+ while ((*startpp <= endp) &&
+ ((c = **startpp) != '\n'))
+ (*startpp)++;
+ if (seendigit)
+ break;
+ continue;
+ }
+ if (!isdigit(c)) {
+ if (c == ')' && seendigit) {
+ (*startpp)--;
+ break;
+ }
+ return (-1);
+ }
+ (*startpp)++;
+ n = n * 10 + (c - '0');
+ seendigit = 1;
+ }
+ return (n + m);
+}
+
+/*
+ * Allocate a resource record buffer & save rr info.
+ */
+ns_updrec *
+res_mkupdrec(int section, const char *dname,
+ u_int class, u_int type, u_long ttl) {
+ ns_updrec *rrecp = (ns_updrec *)calloc(1, sizeof(ns_updrec));
+
+ if (!rrecp || !(rrecp->r_dname = strdup(dname))) {
+ if (rrecp)
+ free((char *)rrecp);
+ return (NULL);
+ }
+ INIT_LINK(rrecp, r_link);
+ INIT_LINK(rrecp, r_glink);
+ rrecp->r_class = class;
+ rrecp->r_type = type;
+ rrecp->r_ttl = ttl;
+ rrecp->r_section = section;
+ return (rrecp);
+}
+
+/*
+ * Free a resource record buffer created by res_mkupdrec.
+ */
+void
+res_freeupdrec(ns_updrec *rrecp) {
+ /* Note: freeing r_dp is the caller's responsibility. */
+ if (rrecp->r_dname != NULL)
+ free(rrecp->r_dname);
+ free(rrecp);
+}
+
+struct valuelist {
+ struct valuelist * next;
+ struct valuelist * prev;
+ char * name;
+ char * proto;
+ int port;
+};
+static struct valuelist *servicelist, *protolist;
+
+static void
+res_buildservicelist() {
+ struct servent *sp;
+ struct valuelist *slp;
+
+#ifdef MAYBE_HESIOD
+ setservent(0);
+#else
+ setservent(1);
+#endif
+ while ((sp = getservent()) != NULL) {
+ slp = (struct valuelist *)malloc(sizeof(struct valuelist));
+ if (!slp)
+ break;
+ slp->name = strdup(sp->s_name);
+ slp->proto = strdup(sp->s_proto);
+ if ((slp->name == NULL) || (slp->proto == NULL)) {
+ if (slp->name) free(slp->name);
+ if (slp->proto) free(slp->proto);
+ free(slp);
+ break;
+ }
+ slp->port = ntohs((u_int16_t)sp->s_port); /* host byt order */
+ slp->next = servicelist;
+ slp->prev = NULL;
+ if (servicelist)
+ servicelist->prev = slp;
+ servicelist = slp;
+ }
+ endservent();
+}
+
+void
+res_destroyservicelist() {
+ struct valuelist *slp, *slp_next;
+
+ for (slp = servicelist; slp != NULL; slp = slp_next) {
+ slp_next = slp->next;
+ free(slp->name);
+ free(slp->proto);
+ free(slp);
+ }
+ servicelist = (struct valuelist *)0;
+}
+
+void
+res_buildprotolist(void) {
+ struct protoent *pp;
+ struct valuelist *slp;
+
+#ifdef MAYBE_HESIOD
+ setprotoent(0);
+#else
+ setprotoent(1);
+#endif
+ while ((pp = getprotoent()) != NULL) {
+ slp = (struct valuelist *)malloc(sizeof(struct valuelist));
+ if (!slp)
+ break;
+ slp->name = strdup(pp->p_name);
+ if (slp->name == NULL) {
+ free(slp);
+ break;
+ }
+ slp->port = pp->p_proto; /* host byte order */
+ slp->next = protolist;
+ slp->prev = NULL;
+ if (protolist)
+ protolist->prev = slp;
+ protolist = slp;
+ }
+ endprotoent();
+}
+
+void
+res_destroyprotolist(void) {
+ struct valuelist *plp, *plp_next;
+
+ for (plp = protolist; plp != NULL; plp = plp_next) {
+ plp_next = plp->next;
+ free(plp->name);
+ free(plp);
+ }
+ protolist = (struct valuelist *)0;
+}
+
+static int
+findservice(const char *s, struct valuelist **list) {
+ struct valuelist *lp = *list;
+ int n;
+
+ for (; lp != NULL; lp = lp->next)
+ if (strcasecmp(lp->name, s) == 0) {
+ if (lp != *list) {
+ lp->prev->next = lp->next;
+ if (lp->next)
+ lp->next->prev = lp->prev;
+ (*list)->prev = lp;
+ lp->next = *list;
+ *list = lp;
+ }
+ return (lp->port); /* host byte order */
+ }
+ if (sscanf(s, "%d", &n) != 1 || n <= 0)
+ n = -1;
+ return (n);
+}
+
+/*
+ * Convert service name or (ascii) number to int.
+ */
+int
+res_servicenumber(const char *p) {
+ if (servicelist == (struct valuelist *)0)
+ res_buildservicelist();
+ return (findservice(p, &servicelist));
+}
+
+/*
+ * Convert protocol name or (ascii) number to int.
+ */
+int
+res_protocolnumber(const char *p) {
+ if (protolist == (struct valuelist *)0)
+ res_buildprotolist();
+ return (findservice(p, &protolist));
+}
+
+static struct servent *
+cgetservbyport(u_int16_t port, const char *proto) { /* Host byte order. */
+ struct valuelist **list = &servicelist;
+ struct valuelist *lp = *list;
+ static struct servent serv;
+
+ port = ntohs(port);
+ for (; lp != NULL; lp = lp->next) {
+ if (port != (u_int16_t)lp->port) /* Host byte order. */
+ continue;
+ if (strcasecmp(lp->proto, proto) == 0) {
+ if (lp != *list) {
+ lp->prev->next = lp->next;
+ if (lp->next)
+ lp->next->prev = lp->prev;
+ (*list)->prev = lp;
+ lp->next = *list;
+ *list = lp;
+ }
+ serv.s_name = lp->name;
+ serv.s_port = htons((u_int16_t)lp->port);
+ serv.s_proto = lp->proto;
+ return (&serv);
+ }
+ }
+ return (0);
+}
+
+static struct protoent *
+cgetprotobynumber(int proto) { /* Host byte order. */
+ struct valuelist **list = &protolist;
+ struct valuelist *lp = *list;
+ static struct protoent prot;
+
+ for (; lp != NULL; lp = lp->next)
+ if (lp->port == proto) { /* Host byte order. */
+ if (lp != *list) {
+ lp->prev->next = lp->next;
+ if (lp->next)
+ lp->next->prev = lp->prev;
+ (*list)->prev = lp;
+ lp->next = *list;
+ *list = lp;
+ }
+ prot.p_name = lp->name;
+ prot.p_proto = lp->port; /* Host byte order. */
+ return (&prot);
+ }
+ return (0);
+}
+
+const char *
+res_protocolname(int num) {
+ static char number[8];
+ struct protoent *pp;
+
+ if (protolist == (struct valuelist *)0)
+ res_buildprotolist();
+ pp = cgetprotobynumber(num);
+ if (pp == 0) {
+ (void) sprintf(number, "%d", num);
+ return (number);
+ }
+ return (pp->p_name);
+}
+
+const char *
+res_servicename(u_int16_t port, const char *proto) { /* Host byte order. */
+ static char number[8];
+ struct servent *ss;
+
+ if (servicelist == (struct valuelist *)0)
+ res_buildservicelist();
+ ss = cgetservbyport(htons(port), proto);
+ if (ss == 0) {
+ (void) sprintf(number, "%d", port);
+ return (number);
+ }
+ return (ss->s_name);
+}
diff --git a/usr/src/lib/libresolv2/common/resolv/res_mkupdate.h b/usr/src/lib/libresolv2/common/resolv/res_mkupdate.h
new file mode 100644
index 0000000000..97a7518ee8
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/resolv/res_mkupdate.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1998,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef _RES_MKUPDATE_H_
+#define _RES_MKUPDATE_H_
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+__BEGIN_DECLS
+__END_DECLS
+
+#endif /* _RES_MKUPDATE_H_ */
diff --git a/usr/src/lib/libresolv2/common/resolv/res_private.h b/usr/src/lib/libresolv2/common/resolv/res_private.h
new file mode 100644
index 0000000000..0ee5617541
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/resolv/res_private.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef res_private_h
+#define res_private_h
+
+struct __res_state_ext {
+ union res_sockaddr_union nsaddrs[MAXNS];
+ struct sort_list {
+ int af;
+ union {
+ struct in_addr ina;
+ struct in6_addr in6a;
+ } addr, mask;
+ } sort_list[MAXRESOLVSORT];
+ char nsuffix[64];
+ char nsuffix2[64];
+};
+
+extern int
+res_ourserver_p(const res_state statp, const struct sockaddr *sa);
+
+#endif
diff --git a/usr/src/lib/libresolv2/common/resolv/res_query.c b/usr/src/lib/libresolv2/common/resolv/res_query.c
new file mode 100644
index 0000000000..55746f572f
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/resolv/res_query.c
@@ -0,0 +1,464 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_query.c,v 8.24 2003/01/31 15:25:58 vixie Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include "port_before.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "port_after.h"
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+#include "../../../libnsl/include/nsl_stdio_prv.h"
+#endif
+
+/* Options. Leave them on. */
+#define DEBUG
+
+#if PACKETSZ > 1024
+#define MAXPACKET PACKETSZ
+#else
+#define MAXPACKET 1024
+#endif
+
+/*
+ * Formulate a normal query, send, and await answer.
+ * Returned answer is placed in supplied buffer "answer".
+ * Perform preliminary check of answer, returning success only
+ * if no error is indicated and the answer count is nonzero.
+ * Return the size of the response on success, -1 on error.
+ * Error number is left in H_ERRNO.
+ *
+ * Caller must parse answer and determine whether it answers the question.
+ */
+int
+res_nquery(res_state statp,
+ const char *name, /* domain name */
+ int class, int type, /* class and type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen) /* size of answer buffer */
+{
+ u_char buf[MAXPACKET];
+ HEADER *hp = (HEADER *) answer;
+ int n;
+ u_int oflags;
+
+ oflags = statp->_flags;
+
+again:
+ hp->rcode = NOERROR; /* default */
+
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_query(%s, %d, %d)\n", name, class, type);
+#endif
+
+ n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
+ buf, sizeof(buf));
+#ifdef RES_USE_EDNS0
+ if (n > 0 && (statp->_flags & RES_F_EDNS0ERR) == 0 &&
+ (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
+ n = res_nopt(statp, n, buf, sizeof(buf), anslen);
+#endif
+ if (n <= 0) {
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_query: mkquery failed\n");
+#endif
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (n);
+ }
+ n = res_nsend(statp, buf, n, answer, anslen);
+ if (n < 0) {
+#ifdef RES_USE_EDNS0
+ /* if the query choked with EDNS0, retry without EDNS0 */
+ if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0 &&
+ ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) {
+ statp->_flags |= RES_F_EDNS0ERR;
+ if (statp->options & RES_DEBUG)
+ printf(";; res_nquery: retry without EDNS0\n");
+ goto again;
+ }
+#endif
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_query: send error\n");
+#endif
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ return (n);
+ }
+
+ if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; rcode = (%s), counts = an:%d ns:%d ar:%d\n",
+ p_rcode(hp->rcode),
+ ntohs(hp->ancount),
+ ntohs(hp->nscount),
+ ntohs(hp->arcount));
+#endif
+ switch (hp->rcode) {
+ case NXDOMAIN:
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ break;
+ case SERVFAIL:
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ break;
+ case NOERROR:
+ RES_SET_H_ERRNO(statp, NO_DATA);
+ break;
+ case FORMERR:
+ case NOTIMP:
+ case REFUSED:
+ default:
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ break;
+ }
+ return (-1);
+ }
+ return (n);
+}
+
+/*
+ * Formulate a normal query, send, and retrieve answer in supplied buffer.
+ * Return the size of the response on success, -1 on error.
+ * If enabled, implement search rules until answer or unrecoverable failure
+ * is detected. Error code, if any, is left in H_ERRNO.
+ */
+int
+res_nsearch(res_state statp,
+ const char *name, /* domain name */
+ int class, int type, /* class and type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen) /* size of answer */
+{
+ const char *cp, * const *domain;
+ HEADER *hp = (HEADER *) answer;
+ char tmp[NS_MAXDNAME];
+ u_int dots;
+ int trailing_dot, ret, saved_herrno;
+ int got_nodata = 0, got_servfail = 0, root_on_list = 0;
+ int tried_as_is = 0;
+ int searched = 0;
+
+ errno = 0;
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /* True if we never query. */
+
+ dots = 0;
+ for (cp = name; *cp != '\0'; cp++)
+ dots += (*cp == '.');
+ trailing_dot = 0;
+ if (cp > name && *--cp == '.')
+ trailing_dot++;
+
+ /* If there aren't any dots, it could be a user-level alias. */
+ if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL)
+ return (res_nquery(statp, cp, class, type, answer, anslen));
+
+ /*
+ * If there are enough dots in the name, let's just give it a
+ * try 'as is'. The threshold can be set with the "ndots" option.
+ * Also, query 'as is', if there is a trailing dot in the name.
+ */
+ saved_herrno = -1;
+ if (dots >= statp->ndots || trailing_dot) {
+ ret = res_nquerydomain(statp, name, NULL, class, type,
+ answer, anslen);
+ if (ret > 0 || trailing_dot)
+ return (ret);
+ saved_herrno = statp->res_h_errno;
+ tried_as_is++;
+ }
+
+ /*
+ * We do at least one level of search if
+ * - there is no dot and RES_DEFNAME is set, or
+ * - there is at least one dot, there is no trailing dot,
+ * and RES_DNSRCH is set.
+ */
+ if ((!dots && (statp->options & RES_DEFNAMES) != 0) ||
+ (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0)) {
+ int done = 0;
+
+ for (domain = (const char * const *)statp->dnsrch;
+ *domain && !done;
+ domain++) {
+ searched = 1;
+
+ if (domain[0][0] == '\0' ||
+ (domain[0][0] == '.' && domain[0][1] == '\0'))
+ root_on_list++;
+
+ ret = res_nquerydomain(statp, name, *domain,
+ class, type,
+ answer, anslen);
+ if (ret > 0)
+ return (ret);
+
+ /*
+ * If no server present, give up.
+ * If name isn't found in this domain,
+ * keep trying higher domains in the search list
+ * (if that's enabled).
+ * On a NO_DATA error, keep trying, otherwise
+ * a wildcard entry of another type could keep us
+ * from finding this entry higher in the domain.
+ * If we get some other error (negative answer or
+ * server failure), then stop searching up,
+ * but try the input name below in case it's
+ * fully-qualified.
+ */
+ if (errno == ECONNREFUSED) {
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ return (-1);
+ }
+
+ switch (statp->res_h_errno) {
+ case NO_DATA:
+ got_nodata++;
+ /* FALLTHROUGH */
+ case HOST_NOT_FOUND:
+ /* keep trying */
+ break;
+ case TRY_AGAIN:
+ if (hp->rcode == SERVFAIL) {
+ /* try next search element, if any */
+ got_servfail++;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ /* anything else implies that we're done */
+ done++;
+ }
+
+ /* if we got here for some reason other than DNSRCH,
+ * we only wanted one iteration of the loop, so stop.
+ */
+ if ((statp->options & RES_DNSRCH) == 0)
+ done++;
+ }
+ }
+
+ /*
+ * If the query has not already been tried as is then try it
+ * unless RES_NOTLDQUERY is set and there were no dots.
+ */
+ if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0) &&
+ !(tried_as_is || root_on_list)) {
+ ret = res_nquerydomain(statp, name, NULL, class, type,
+ answer, anslen);
+ if (ret > 0)
+ return (ret);
+ }
+
+ /* if we got here, we didn't satisfy the search.
+ * if we did an initial full query, return that query's H_ERRNO
+ * (note that we wouldn't be here if that query had succeeded).
+ * else if we ever got a nodata, send that back as the reason.
+ * else send back meaningless H_ERRNO, that being the one from
+ * the last DNSRCH we did.
+ */
+ if (saved_herrno != -1)
+ RES_SET_H_ERRNO(statp, saved_herrno);
+ else if (got_nodata)
+ RES_SET_H_ERRNO(statp, NO_DATA);
+ else if (got_servfail)
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ return (-1);
+}
+
+/*
+ * Perform a call on res_query on the concatenation of name and domain,
+ * removing a trailing dot from name if domain is NULL.
+ */
+int
+res_nquerydomain(res_state statp,
+ const char *name,
+ const char *domain,
+ int class, int type, /* class and type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen) /* size of answer */
+{
+ char nbuf[MAXDNAME];
+ const char *longname = nbuf;
+ int n, d;
+
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_nquerydomain(%s, %s, %d, %d)\n",
+ name, domain?domain:"<Nil>", class, type);
+#endif
+ if (domain == NULL) {
+ /*
+ * Check for trailing '.';
+ * copy without '.' if present.
+ */
+ n = strlen(name);
+ if (n >= MAXDNAME) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ n--;
+ if (n >= 0 && name[n] == '.') {
+ strncpy(nbuf, name, n);
+ nbuf[n] = '\0';
+ } else
+ longname = name;
+ } else {
+ n = strlen(name);
+ d = strlen(domain);
+ if (n + d + 1 >= MAXDNAME) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ sprintf(nbuf, "%s.%s", name, domain);
+ }
+ return (res_nquery(statp, longname, class, type, answer, anslen));
+}
+
+const char *
+res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) {
+ char *file, *cp1, *cp2;
+ char buf[BUFSIZ];
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+ __NSL_FILE *fp;
+#else
+ FILE *fp;
+#endif
+
+ if (statp->options & RES_NOALIASES)
+ return (NULL);
+ file = getenv("HOSTALIASES");
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+ if (file == NULL || (fp = __nsl_fopen(file, "r")) == NULL)
+#else
+ if (file == NULL || (fp = fopen(file, "r")) == NULL)
+#endif
+ return (NULL);
+#ifndef SUNW_AVOIDSTDIO_FDLIMIT
+ setbuf(fp, NULL);
+#endif
+ buf[sizeof(buf) - 1] = '\0';
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+ while (__nsl_fgets(buf, sizeof(buf), fp)) {
+#else
+ while (fgets(buf, sizeof(buf), fp)) {
+#endif
+ for (cp1 = buf; *cp1 && !isspace((unsigned char)*cp1); ++cp1)
+ ;
+ if (!*cp1)
+ break;
+ *cp1 = '\0';
+ if (ns_samename(buf, name) == 1) {
+ while (isspace((unsigned char)*++cp1))
+ ;
+ if (!*cp1)
+ break;
+ for (cp2 = cp1 + 1; *cp2 &&
+ !isspace((unsigned char)*cp2); ++cp2)
+ ;
+ *cp2 = '\0';
+ strncpy(dst, cp1, siz - 1);
+ dst[siz - 1] = '\0';
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+ __nsl_fclose(fp);
+#else
+ fclose(fp);
+#endif
+ return (dst);
+ }
+ }
+#ifdef SUNW_AVOIDSTDIO_FDLIMIT
+ __nsl_fclose(fp);
+#else
+ fclose(fp);
+#endif
+ return (NULL);
+}
diff --git a/usr/src/lib/libresolv2/common/resolv/res_send.c b/usr/src/lib/libresolv2/common/resolv/res_send.c
new file mode 100644
index 0000000000..90ea5dad84
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/resolv/res_send.c
@@ -0,0 +1,1087 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1985, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_send.c,v 8.52 2003/04/29 02:13:08 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Send query to name server and wait for reply.
+ */
+
+#include "port_before.h"
+#include "fd_setsize.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/eventlib.h>
+
+#include "port_after.h"
+
+#ifdef SUNW_POLL
+#include <stropts.h>
+#include <poll.h>
+#define pselect Pselect
+#endif /* SUNW_POLL */
+
+/* Options. Leave them on. */
+#define DEBUG
+#include "res_debug.h"
+#include "res_private.h"
+
+#define EXT(res) ((res)->_u._ext)
+
+#ifdef ORIGINAL_ISC_CODE
+static const int highestFD = FD_SETSIZE - 1;
+#else
+static int highestFD = 0;
+#endif
+
+/* Forward. */
+
+static int get_salen __P((const struct sockaddr *));
+static struct sockaddr * get_nsaddr __P((res_state, size_t));
+static int send_vc(res_state, const u_char *, int,
+ u_char *, int, int *, int);
+static int send_dg(res_state, const u_char *, int,
+ u_char *, int, int *, int,
+ int *, int *);
+static void Aerror(const res_state, FILE *, const char *, int,
+ const struct sockaddr *, int);
+static void Perror(const res_state, FILE *, const char *, int);
+static int sock_eq(struct sockaddr *, struct sockaddr *);
+#ifdef NEED_PSELECT
+static int pselect(int, void *, void *, void *,
+ struct timespec *,
+ const sigset_t *);
+#endif
+void res_pquery(const res_state, const u_char *, int, FILE *);
+
+#ifdef ORIGINAL_ISC_CODE
+#else
+#pragma weak __res_nameinquery = res_nameinquery
+#pragma weak __res_queriesmatch = res_queriesmatch
+#pragma weak res_nisourserver = res_ourserver_p
+#endif /* ORIGINAL_ISC_CODE */
+
+static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
+
+/* Public. */
+
+/* int
+ * res_isourserver(ina)
+ * looks up "ina" in _res.ns_addr_list[]
+ * returns:
+ * 0 : not found
+ * >0 : found
+ * author:
+ * paul vixie, 29may94
+ */
+int
+res_ourserver_p(const res_state statp, const struct sockaddr *sa) {
+ const struct sockaddr_in *inp, *srv;
+ const struct sockaddr_in6 *in6p, *srv6;
+ int ns;
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ inp = (const struct sockaddr_in *)sa;
+ for (ns = 0; ns < statp->nscount; ns++) {
+ srv = (struct sockaddr_in *)get_nsaddr(statp, ns);
+ if (srv->sin_family == inp->sin_family &&
+ srv->sin_port == inp->sin_port &&
+ (srv->sin_addr.s_addr == INADDR_ANY ||
+ srv->sin_addr.s_addr == inp->sin_addr.s_addr))
+ return (1);
+ }
+ break;
+ case AF_INET6:
+ if (EXT(statp).ext == NULL)
+ break;
+ in6p = (const struct sockaddr_in6 *)sa;
+ for (ns = 0; ns < statp->nscount; ns++) {
+ srv6 = (struct sockaddr_in6 *)get_nsaddr(statp, ns);
+ if (srv6->sin6_family == in6p->sin6_family &&
+ srv6->sin6_port == in6p->sin6_port &&
+#ifdef HAVE_SIN6_SCOPE_ID
+ (srv6->sin6_scope_id == 0 ||
+ srv6->sin6_scope_id == in6p->sin6_scope_id) &&
+#endif
+ (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
+ IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
+ return (1);
+ }
+ break;
+ default:
+ break;
+ }
+ return (0);
+}
+
+/* int
+ * res_nameinquery(name, type, class, buf, eom)
+ * look for (name,type,class) in the query section of packet (buf,eom)
+ * requires:
+ * buf + HFIXEDSZ <= eom
+ * returns:
+ * -1 : format error
+ * 0 : not found
+ * >0 : found
+ * author:
+ * paul vixie, 29may94
+ */
+int
+res_nameinquery(const char *name, int type, int class,
+ const u_char *buf, const u_char *eom)
+{
+ const u_char *cp = buf + HFIXEDSZ;
+ int qdcount = ntohs(((const HEADER*)buf)->qdcount);
+
+ while (qdcount-- > 0) {
+ char tname[MAXDNAME+1];
+ int n, ttype, tclass;
+
+ n = dn_expand(buf, eom, cp, tname, sizeof tname);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ if (cp + 2 * INT16SZ > eom)
+ return (-1);
+ ttype = ns_get16(cp); cp += INT16SZ;
+ tclass = ns_get16(cp); cp += INT16SZ;
+ if (ttype == type && tclass == class &&
+ ns_samename(tname, name) == 1)
+ return (1);
+ }
+ return (0);
+}
+
+/* int
+ * res_queriesmatch(buf1, eom1, buf2, eom2)
+ * is there a 1:1 mapping of (name,type,class)
+ * in (buf1,eom1) and (buf2,eom2)?
+ * returns:
+ * -1 : format error
+ * 0 : not a 1:1 mapping
+ * >0 : is a 1:1 mapping
+ * author:
+ * paul vixie, 29may94
+ */
+int
+res_queriesmatch(const u_char *buf1, const u_char *eom1,
+ const u_char *buf2, const u_char *eom2)
+{
+ const u_char *cp = buf1 + HFIXEDSZ;
+ int qdcount = ntohs(((const HEADER*)buf1)->qdcount);
+
+ if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
+ return (-1);
+
+ /*
+ * Only header section present in replies to
+ * dynamic update packets.
+ */
+ if ((((const HEADER *)buf1)->opcode == ns_o_update) &&
+ (((const HEADER *)buf2)->opcode == ns_o_update))
+ return (1);
+
+ if (qdcount != ntohs(((const HEADER*)buf2)->qdcount))
+ return (0);
+ while (qdcount-- > 0) {
+ char tname[MAXDNAME+1];
+ int n, ttype, tclass;
+
+ n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ if (cp + 2 * INT16SZ > eom1)
+ return (-1);
+ ttype = ns_get16(cp); cp += INT16SZ;
+ tclass = ns_get16(cp); cp += INT16SZ;
+ if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
+ return (0);
+ }
+ return (1);
+}
+
+int
+res_nsend(res_state statp,
+ const u_char *buf, int buflen, u_char *ans, int anssiz)
+{
+ int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
+ char abuf[NI_MAXHOST];
+
+#ifdef SUNW_POLL
+ highestFD = sysconf(_SC_OPEN_MAX) - 1;
+#endif
+
+ if (statp->nscount == 0) {
+ errno = ESRCH;
+ return (-1);
+ }
+ if (anssiz < HFIXEDSZ) {
+ errno = EINVAL;
+ return (-1);
+ }
+ DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
+ (stdout, ";; res_send()\n"), buf, buflen);
+ v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
+ gotsomewhere = 0;
+ terrno = ETIMEDOUT;
+
+ /*
+ * If the ns_addr_list in the resolver context has changed, then
+ * invalidate our cached copy and the associated timing data.
+ */
+ if (EXT(statp).nscount != 0) {
+ int needclose = 0;
+ struct sockaddr_storage peer;
+ ISC_SOCKLEN_T peerlen;
+
+ if (EXT(statp).nscount != statp->nscount)
+ needclose++;
+ else
+ for (ns = 0; ns < statp->nscount; ns++) {
+ if (statp->nsaddr_list[ns].sin_family &&
+ !sock_eq((struct sockaddr *)&statp->nsaddr_list[ns],
+ (struct sockaddr *)&EXT(statp).ext->nsaddrs[ns])) {
+ needclose++;
+ break;
+ }
+
+ if (EXT(statp).nssocks[ns] == -1)
+ continue;
+ peerlen = sizeof(peer);
+ if (getsockname(EXT(statp).nssocks[ns],
+ (struct sockaddr *)&peer, &peerlen) < 0) {
+ needclose++;
+ break;
+ }
+ if (!sock_eq((struct sockaddr *)&peer,
+ get_nsaddr(statp, ns))) {
+ needclose++;
+ break;
+ }
+ }
+ if (needclose) {
+ res_nclose(statp);
+ EXT(statp).nscount = 0;
+ }
+ }
+
+ /*
+ * Maybe initialize our private copy of the ns_addr_list.
+ */
+ if (EXT(statp).nscount == 0) {
+ for (ns = 0; ns < statp->nscount; ns++) {
+ EXT(statp).nstimes[ns] = RES_MAXTIME;
+ EXT(statp).nssocks[ns] = -1;
+ if (!statp->nsaddr_list[ns].sin_family)
+ continue;
+ EXT(statp).ext->nsaddrs[ns].sin =
+ statp->nsaddr_list[ns];
+ }
+ EXT(statp).nscount = statp->nscount;
+ }
+
+ /*
+ * Some resolvers want to even out the load on their nameservers.
+ * Note that RES_BLAST overrides RES_ROTATE.
+ */
+ if ((statp->options & RES_ROTATE) != 0 &&
+ (statp->options & RES_BLAST) == 0) {
+ union res_sockaddr_union inu;
+ struct sockaddr_in ina;
+ int lastns = statp->nscount - 1;
+ int fd;
+ u_int16_t nstime;
+
+ if (EXT(statp).ext != NULL)
+ inu = EXT(statp).ext->nsaddrs[0];
+ ina = statp->nsaddr_list[0];
+ fd = EXT(statp).nssocks[0];
+ nstime = EXT(statp).nstimes[0];
+ for (ns = 0; ns < lastns; ns++) {
+ if (EXT(statp).ext != NULL)
+ EXT(statp).ext->nsaddrs[ns] =
+ EXT(statp).ext->nsaddrs[ns + 1];
+ statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
+ EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
+ EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1];
+ }
+ if (EXT(statp).ext != NULL)
+ EXT(statp).ext->nsaddrs[lastns] = inu;
+ statp->nsaddr_list[lastns] = ina;
+ EXT(statp).nssocks[lastns] = fd;
+ EXT(statp).nstimes[lastns] = nstime;
+ }
+
+ /*
+ * Send request, RETRY times, or until successful.
+ */
+ for (try = 0; try < statp->retry; try++) {
+ for (ns = 0; ns < statp->nscount; ns++) {
+ struct sockaddr *nsap;
+ int nsaplen;
+ nsap = get_nsaddr(statp, ns);
+ nsaplen = get_salen(nsap);
+ statp->_flags &= ~RES_F_LASTMASK;
+ statp->_flags |= (ns << RES_F_LASTSHIFT);
+ same_ns:
+ if (statp->qhook) {
+ int done = 0, loops = 0;
+
+ do {
+ res_sendhookact act;
+
+ act = (*statp->qhook)(&nsap, &buf, &buflen,
+ ans, anssiz, &resplen);
+ switch (act) {
+ case res_goahead:
+ done = 1;
+ break;
+ case res_nextns:
+ res_nclose(statp);
+ goto next_ns;
+ case res_done:
+ return (resplen);
+ case res_modified:
+ /* give the hook another try */
+ if (++loops < 42) /*doug adams*/
+ break;
+ /*FALLTHROUGH*/
+ case res_error:
+ /*FALLTHROUGH*/
+ default:
+ goto fail;
+ }
+ } while (!done);
+ }
+
+ Dprint(((statp->options & RES_DEBUG) &&
+ getnameinfo(nsap, nsaplen, abuf, sizeof(abuf),
+ NULL, 0, niflags) == 0),
+ (stdout, ";; Querying server (# %d) address = %s\n",
+ ns + 1, abuf));
+
+
+ if (v_circuit) {
+ /* Use VC; at most one attempt per server. */
+ try = statp->retry;
+ n = send_vc(statp, buf, buflen, ans, anssiz, &terrno,
+ ns);
+ if (n < 0)
+ goto fail;
+ if (n == 0)
+ goto next_ns;
+ resplen = n;
+ } else {
+ /* Use datagrams. */
+ n = send_dg(statp, buf, buflen, ans, anssiz, &terrno,
+ ns, &v_circuit, &gotsomewhere);
+ if (n < 0)
+ goto fail;
+ if (n == 0)
+ goto next_ns;
+ if (v_circuit)
+ goto same_ns;
+ resplen = n;
+ }
+
+ Dprint((statp->options & RES_DEBUG) ||
+ ((statp->pfcode & RES_PRF_REPLY) &&
+ (statp->pfcode & RES_PRF_HEAD1)),
+ (stdout, ";; got answer:\n"));
+
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, "%s", ""),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+
+ /*
+ * If we have temporarily opened a virtual circuit,
+ * or if we haven't been asked to keep a socket open,
+ * close the socket.
+ */
+ if ((v_circuit && (statp->options & RES_USEVC) == 0) ||
+ (statp->options & RES_STAYOPEN) == 0) {
+ res_nclose(statp);
+ }
+ if (statp->rhook) {
+ int done = 0, loops = 0;
+
+ do {
+ res_sendhookact act;
+
+ act = (*statp->rhook)(nsap, buf, buflen,
+ ans, anssiz, &resplen);
+ switch (act) {
+ case res_goahead:
+ case res_done:
+ done = 1;
+ break;
+ case res_nextns:
+ res_nclose(statp);
+ goto next_ns;
+ case res_modified:
+ /* give the hook another try */
+ if (++loops < 42) /*doug adams*/
+ break;
+ /*FALLTHROUGH*/
+ case res_error:
+ /*FALLTHROUGH*/
+ default:
+ goto fail;
+ }
+ } while (!done);
+
+ }
+ return (resplen);
+ next_ns: ;
+ } /*foreach ns*/
+ } /*foreach retry*/
+ res_nclose(statp);
+ if (!v_circuit) {
+ if (!gotsomewhere)
+ errno = ECONNREFUSED; /* no nameservers found */
+ else
+ errno = ETIMEDOUT; /* no answer obtained */
+ } else
+ errno = terrno;
+ return (-1);
+ fail:
+ res_nclose(statp);
+ return (-1);
+}
+
+/* Private */
+
+static int
+get_salen(sa)
+ const struct sockaddr *sa;
+{
+
+#ifdef HAVE_SA_LEN
+ /* There are people do not set sa_len. Be forgiving to them. */
+ if (sa->sa_len)
+ return (sa->sa_len);
+#endif
+
+ if (sa->sa_family == AF_INET)
+ return (sizeof(struct sockaddr_in));
+ else if (sa->sa_family == AF_INET6)
+ return (sizeof(struct sockaddr_in6));
+ else
+ return (0); /* unknown, die on connect */
+}
+
+/*
+ * pick appropriate nsaddr_list for use. see res_init() for initialization.
+ */
+static struct sockaddr *
+get_nsaddr(statp, n)
+ res_state statp;
+ size_t n;
+{
+
+ if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {
+ /*
+ * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
+ * than struct sockaddr, and
+ * - user code did not update statp->nsaddr_list[n].
+ */
+ return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n];
+ } else {
+ /*
+ * - user code updated statp->nsaddr_list[n], or
+ * - statp->nsaddr_list[n] has the same content as
+ * EXT(statp).ext->nsaddrs[n].
+ */
+ return (struct sockaddr *)(void *)&statp->nsaddr_list[n];
+ }
+}
+
+static int
+send_vc(res_state statp,
+ const u_char *buf, int buflen, u_char *ans, int anssiz,
+ int *terrno, int ns)
+{
+ const HEADER *hp = (const HEADER *) buf;
+ HEADER *anhp = (HEADER *) ans;
+ struct sockaddr *nsap;
+ int nsaplen;
+ int truncating, connreset, resplen, n;
+ struct iovec iov[2];
+ u_short len;
+ u_char *cp;
+ void *tmp;
+
+ nsap = get_nsaddr(statp, ns);
+ nsaplen = get_salen(nsap);
+
+ connreset = 0;
+ same_ns:
+ truncating = 0;
+
+ /* Are we still talking to whom we want to talk to? */
+ if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
+ struct sockaddr_storage peer;
+ ISC_SOCKLEN_T size = sizeof peer;
+
+ if (getpeername(statp->_vcsock,
+ (struct sockaddr *)&peer, &size) < 0 ||
+ !sock_eq((struct sockaddr *)&peer, nsap)) {
+ res_nclose(statp);
+ statp->_flags &= ~RES_F_VC;
+ }
+ }
+
+ if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
+ if (statp->_vcsock >= 0)
+ res_nclose(statp);
+
+ statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
+ if (statp->_vcsock > highestFD) {
+ res_nclose(statp);
+ errno = ENOTSOCK;
+ }
+ if (statp->_vcsock < 0) {
+ *terrno = errno;
+ Perror(statp, stderr, "socket(vc)", errno);
+ return (-1);
+ }
+ errno = 0;
+ if (connect(statp->_vcsock, nsap, nsaplen) < 0) {
+ *terrno = errno;
+ Aerror(statp, stderr, "connect/vc", errno, nsap,
+ nsaplen);
+ res_nclose(statp);
+ return (0);
+ }
+ statp->_flags |= RES_F_VC;
+ }
+
+ /*
+ * Send length & message
+ */
+ ns_put16((u_short)buflen, (u_char*)&len);
+ iov[0] = evConsIovec(&len, INT16SZ);
+ DE_CONST(buf, tmp);
+ iov[1] = evConsIovec(tmp, buflen);
+ if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
+ *terrno = errno;
+ Perror(statp, stderr, "write failed", errno);
+ res_nclose(statp);
+ return (0);
+ }
+ /*
+ * Receive length & response
+ */
+ read_len:
+ cp = ans;
+ len = INT16SZ;
+ while ((n = read(statp->_vcsock, (char *)cp, (int)len)) > 0) {
+ cp += n;
+ if ((len -= n) <= 0)
+ break;
+ }
+ if (n <= 0) {
+ *terrno = errno;
+ Perror(statp, stderr, "read failed", errno);
+ res_nclose(statp);
+ /*
+ * A long running process might get its TCP
+ * connection reset if the remote server was
+ * restarted. Requery the server instead of
+ * trying a new one. When there is only one
+ * server, this means that a query might work
+ * instead of failing. We only allow one reset
+ * per query to prevent looping.
+ */
+ if (*terrno == ECONNRESET && !connreset) {
+ connreset = 1;
+ res_nclose(statp);
+ goto same_ns;
+ }
+ res_nclose(statp);
+ return (0);
+ }
+ resplen = ns_get16(ans);
+ if (resplen > anssiz) {
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; response truncated\n")
+ );
+ truncating = 1;
+ len = anssiz;
+ } else
+ len = resplen;
+ if (len < HFIXEDSZ) {
+ /*
+ * Undersized message.
+ */
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; undersized: %d\n", len));
+ *terrno = EMSGSIZE;
+ res_nclose(statp);
+ return (0);
+ }
+ cp = ans;
+ while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){
+ cp += n;
+ len -= n;
+ }
+ if (n <= 0) {
+ *terrno = errno;
+ Perror(statp, stderr, "read(vc)", errno);
+ res_nclose(statp);
+ return (0);
+ }
+ if (truncating) {
+ /*
+ * Flush rest of answer so connection stays in synch.
+ */
+ anhp->tc = 1;
+ len = resplen - anssiz;
+ /*
+ * Reset the value of resplen to anssiz,
+ * this is done because the caller assumes
+ * resplen contains the size of message read
+ * into the "ans" buffer passed in.
+ */
+ resplen = anssiz;
+
+ while (len != 0) {
+ char junk[PACKETSZ];
+
+ n = read(statp->_vcsock, junk,
+ (len > sizeof junk) ? sizeof junk : len);
+ if (n > 0)
+ len -= n;
+ else
+ break;
+ }
+ }
+ /*
+ * If the calling applicating has bailed out of
+ * a previous call and failed to arrange to have
+ * the circuit closed or the server has got
+ * itself confused, then drop the packet and
+ * wait for the correct one.
+ */
+ if (hp->id != anhp->id) {
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, ";; old answer (unexpected):\n"),
+ ans, (resplen > anssiz) ? anssiz: resplen);
+ goto read_len;
+ }
+
+ /*
+ * All is well, or the error is fatal. Signal that the
+ * next nameserver ought not be tried.
+ */
+ return (resplen);
+}
+
+static int
+send_dg(res_state statp,
+ const u_char *buf, int buflen, u_char *ans, int anssiz,
+ int *terrno, int ns, int *v_circuit, int *gotsomewhere)
+{
+ const HEADER *hp = (const HEADER *) buf;
+ HEADER *anhp = (HEADER *) ans;
+ const struct sockaddr *nsap;
+ int nsaplen;
+ struct timespec now, timeout, finish;
+ fd_set dsmask;
+ struct sockaddr_storage from;
+ ISC_SOCKLEN_T fromlen;
+ int resplen, seconds, n, s;
+#ifdef SUNW_POLL
+ int polltimeout;
+ struct pollfd pollfd;
+#endif
+
+ nsap = get_nsaddr(statp, ns);
+ nsaplen = get_salen(nsap);
+ if (EXT(statp).nssocks[ns] == -1) {
+ EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0);
+ if (EXT(statp).nssocks[ns] > highestFD) {
+ res_nclose(statp);
+ errno = ENOTSOCK;
+ }
+ if (EXT(statp).nssocks[ns] < 0) {
+ *terrno = errno;
+ Perror(statp, stderr, "socket(dg)", errno);
+ return (-1);
+ }
+#ifndef CANNOT_CONNECT_DGRAM
+ /*
+ * On a 4.3BSD+ machine (client and server,
+ * actually), sending to a nameserver datagram
+ * port with no nameserver will cause an
+ * ICMP port unreachable message to be returned.
+ * If our datagram socket is "connected" to the
+ * server, we get an ECONNREFUSED error on the next
+ * socket operation, and select returns if the
+ * error message is received. We can thus detect
+ * the absence of a nameserver without timing out.
+ */
+ if (connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) {
+ Aerror(statp, stderr, "connect(dg)", errno, nsap,
+ nsaplen);
+ res_nclose(statp);
+ return (0);
+ }
+#endif /* !CANNOT_CONNECT_DGRAM */
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; new DG socket\n"))
+ }
+ s = EXT(statp).nssocks[ns];
+#ifndef CANNOT_CONNECT_DGRAM
+ if (send(s, (const char*)buf, buflen, 0) != buflen) {
+ Perror(statp, stderr, "send", errno);
+ res_nclose(statp);
+ return (0);
+ }
+#else /* !CANNOT_CONNECT_DGRAM */
+ if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
+ {
+ Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
+ res_nclose(statp);
+ return (0);
+ }
+#endif /* !CANNOT_CONNECT_DGRAM */
+
+ /*
+ * Wait for reply.
+ */
+ seconds = (statp->retrans << ns);
+ if (ns > 0)
+ seconds /= statp->nscount;
+ if (seconds <= 0)
+ seconds = 1;
+ now = evNowTime();
+ timeout = evConsTime(seconds, 0);
+ finish = evAddTime(now, timeout);
+ goto nonow;
+ wait:
+ now = evNowTime();
+ nonow:
+#ifdef SUNW_POLL
+ timeout = evSubTime(finish, now);
+ if (timeout.tv_sec < 0)
+ timeout = evConsTime(0, 0);
+ polltimeout = 1000*timeout.tv_sec +
+ timeout.tv_nsec/1000000;
+ pollfd.fd = s;
+ pollfd.events = POLLRDNORM;
+ n = poll(&pollfd, 1, polltimeout);
+#else
+ FD_ZERO(&dsmask);
+ FD_SET(s, &dsmask);
+ if (evCmpTime(finish, now) > 0)
+ timeout = evSubTime(finish, now);
+ else
+ timeout = evConsTime(0, 0);
+ n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL);
+#endif
+ if (n == 0) {
+ Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
+ *gotsomewhere = 1;
+ return (0);
+ }
+ if (n < 0) {
+ if (errno == EINTR)
+ goto wait;
+#ifdef SUNW_POLL
+ Perror(statp, stderr, "poll", errno);
+#else
+ Perror(statp, stderr, "select", errno);
+#endif
+ res_nclose(statp);
+ return (0);
+ }
+ errno = 0;
+ fromlen = sizeof(from);
+ resplen = recvfrom(s, (char*)ans, anssiz,0,
+ (struct sockaddr *)&from, &fromlen);
+ if (resplen <= 0) {
+ Perror(statp, stderr, "recvfrom", errno);
+ res_nclose(statp);
+ return (0);
+ }
+ *gotsomewhere = 1;
+ if (resplen < HFIXEDSZ) {
+ /*
+ * Undersized message.
+ */
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; undersized: %d\n",
+ resplen));
+ *terrno = EMSGSIZE;
+ res_nclose(statp);
+ return (0);
+ }
+ if (hp->id != anhp->id) {
+ /*
+ * response from old query, ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, ";; old answer:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+ goto wait;
+ }
+ if (!(statp->options & RES_INSECURE1) &&
+ !res_ourserver_p(statp, (struct sockaddr *)&from)) {
+ /*
+ * response from wrong server? ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, ";; not our server:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+ goto wait;
+ }
+#ifdef RES_USE_EDNS0
+ if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0) {
+ /*
+ * Do not retry if the server do not understand EDNS0.
+ * The case has to be captured here, as FORMERR packet do not
+ * carry query section, hence res_queriesmatch() returns 0.
+ */
+ DprintQ(statp->options & RES_DEBUG,
+ (stdout, "server rejected query with EDNS0:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+ /* record the error */
+ statp->_flags |= RES_F_EDNS0ERR;
+ res_nclose(statp);
+ return (0);
+ }
+#endif
+ if (!(statp->options & RES_INSECURE2) &&
+ !res_queriesmatch(buf, buf + buflen,
+ ans, ans + anssiz)) {
+ /*
+ * response contains wrong query? ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, ";; wrong query name:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+ goto wait;
+ }
+ if (anhp->rcode == SERVFAIL ||
+ anhp->rcode == NOTIMP ||
+ anhp->rcode == REFUSED) {
+ DprintQ(statp->options & RES_DEBUG,
+ (stdout, "server rejected query:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+ res_nclose(statp);
+ /* don't retry if called from dig */
+ if (!statp->pfcode)
+ return (0);
+ }
+ if (!(statp->options & RES_IGNTC) && anhp->tc) {
+ /*
+ * To get the rest of answer,
+ * use TCP with same server.
+ */
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; truncated answer\n"));
+ *v_circuit = 1;
+ res_nclose(statp);
+ return (1);
+ }
+ /*
+ * All is well, or the error is fatal. Signal that the
+ * next nameserver ought not be tried.
+ */
+ return (resplen);
+}
+
+static void
+Aerror(const res_state statp, FILE *file, const char *string, int error,
+ const struct sockaddr *address, int alen)
+{
+ int save = errno;
+ char hbuf[NI_MAXHOST];
+ char sbuf[NI_MAXSERV];
+
+ alen = alen;
+
+ if ((statp->options & RES_DEBUG) != 0) {
+ if (getnameinfo(address, alen, hbuf, sizeof(hbuf),
+ sbuf, sizeof(sbuf), niflags)) {
+ strncpy(hbuf, "?", sizeof(hbuf) - 1);
+ hbuf[sizeof(hbuf) - 1] = '\0';
+ strncpy(sbuf, "?", sizeof(sbuf) - 1);
+ sbuf[sizeof(sbuf) - 1] = '\0';
+ }
+ fprintf(file, "res_send: %s ([%s].%s): %s\n",
+ string, hbuf, sbuf, strerror(error));
+ }
+ errno = save;
+}
+
+static void
+Perror(const res_state statp, FILE *file, const char *string, int error) {
+ int save = errno;
+
+ if ((statp->options & RES_DEBUG) != 0)
+ fprintf(file, "res_send: %s: %s\n",
+ string, strerror(error));
+ errno = save;
+}
+
+static int
+sock_eq(struct sockaddr *a, struct sockaddr *b) {
+ struct sockaddr_in *a4, *b4;
+ struct sockaddr_in6 *a6, *b6;
+
+ if (a->sa_family != b->sa_family)
+ return 0;
+ switch (a->sa_family) {
+ case AF_INET:
+ a4 = (struct sockaddr_in *)a;
+ b4 = (struct sockaddr_in *)b;
+ return a4->sin_port == b4->sin_port &&
+ a4->sin_addr.s_addr == b4->sin_addr.s_addr;
+ case AF_INET6:
+ a6 = (struct sockaddr_in6 *)a;
+ b6 = (struct sockaddr_in6 *)b;
+ return a6->sin6_port == b6->sin6_port &&
+#ifdef HAVE_SIN6_SCOPE_ID
+ a6->sin6_scope_id == b6->sin6_scope_id &&
+#endif
+ IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
+ default:
+ return 0;
+ }
+}
+
+#ifdef NEED_PSELECT
+/* XXX needs to move to the porting library. */
+static int
+pselect(int nfds, void *rfds, void *wfds, void *efds,
+ struct timespec *tsp, const sigset_t *sigmask)
+{
+ struct timeval tv, *tvp;
+ sigset_t sigs;
+ int n;
+
+ if (tsp) {
+ tvp = &tv;
+ tv = evTimeVal(*tsp);
+ } else
+ tvp = NULL;
+ if (sigmask)
+ sigprocmask(SIG_SETMASK, sigmask, &sigs);
+ n = select(nfds, rfds, wfds, efds, tvp);
+ if (sigmask)
+ sigprocmask(SIG_SETMASK, &sigs, NULL);
+ if (tsp)
+ *tsp = evTimeSpec(tv);
+ return (n);
+}
+#endif
diff --git a/usr/src/lib/libresolv2/common/resolv/res_sendsigned.c b/usr/src/lib/libresolv2/common/resolv/res_sendsigned.c
new file mode 100644
index 0000000000..63fe5cc2d9
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/resolv/res_sendsigned.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * No ISC copyright for this file.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+#include "fd_setsize.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <isc/dst.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "port_after.h"
+
+#define DEBUG
+#include "res_debug.h"
+
+
+/* res_nsendsigned */
+int
+res_nsendsigned(res_state statp, const u_char *msg, int msglen,
+ ns_tsig_key *key, u_char *answer, int anslen)
+{
+ res_state nstatp;
+ DST_KEY *dstkey;
+ int usingTCP = 0;
+ u_char *newmsg;
+ int newmsglen, bufsize, siglen;
+ u_char sig[64];
+ HEADER *hp;
+ time_t tsig_time;
+ int ret;
+
+ dst_init();
+
+ nstatp = (res_state) malloc(sizeof(*statp));
+ if (nstatp == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ memcpy(nstatp, statp, sizeof(*statp));
+
+ bufsize = msglen + 1024;
+ newmsg = (u_char *) malloc(bufsize);
+ if (newmsg == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ memcpy(newmsg, msg, msglen);
+ newmsglen = msglen;
+
+ if (ns_samename(key->alg, NS_TSIG_ALG_HMAC_MD5) != 1)
+ dstkey = NULL;
+ else
+ dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5,
+ NS_KEY_TYPE_AUTH_ONLY,
+ NS_KEY_PROT_ANY,
+ key->data, key->len);
+ if (dstkey == NULL) {
+ errno = EINVAL;
+ free(nstatp);
+ free(newmsg);
+ return (-1);
+ }
+
+ nstatp->nscount = 1;
+ siglen = sizeof(sig);
+ ret = ns_sign(newmsg, &newmsglen, bufsize, NOERROR, dstkey, NULL, 0,
+ sig, &siglen, 0);
+ if (ret < 0) {
+ free (nstatp);
+ free (newmsg);
+ dst_free_key(dstkey);
+ if (ret == NS_TSIG_ERROR_NO_SPACE)
+ errno = EMSGSIZE;
+ else if (ret == -1)
+ errno = EINVAL;
+ return (ret);
+ }
+
+ if (newmsglen > PACKETSZ || (nstatp->options & RES_IGNTC))
+ usingTCP = 1;
+ if (usingTCP == 0)
+ nstatp->options |= RES_IGNTC;
+ else
+ nstatp->options |= RES_USEVC;
+
+retry:
+
+ ret = res_nsend(nstatp, newmsg, newmsglen, answer, anslen);
+ if (ret < 0) {
+ free (nstatp);
+ free (newmsg);
+ dst_free_key(dstkey);
+ return (ret);
+ }
+
+ anslen = ret;
+ ret = ns_verify(answer, &anslen, dstkey, sig, siglen,
+ NULL, NULL, &tsig_time, nstatp->options & RES_KEEPTSIG);
+ if (ret != 0) {
+#ifdef ORIGINAL_ISC_CODE
+ Dprint(nstatp->pfcode & RES_PRF_REPLY,
+ (stdout, ";; TSIG invalid (%s)\n", p_rcode(ret)));
+#else
+ Dprint(nstatp->pfcode & RES_PRF_REPLY,
+ (stdout, ";; TSIG invalid (%s)\n", p_rcode(-ret)));
+#endif
+ free (nstatp);
+ free (newmsg);
+ dst_free_key(dstkey);
+ if (ret == -1)
+ errno = EINVAL;
+ else
+ errno = ENOTTY;
+ return (-1);
+ }
+ Dprint(nstatp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG ok\n"));
+
+ hp = (HEADER *) answer;
+ if (hp->tc && usingTCP == 0) {
+ nstatp->options &= ~RES_IGNTC;
+ usingTCP = 1;
+ goto retry;
+ }
+
+ free (nstatp);
+ free (newmsg);
+ dst_free_key(dstkey);
+ return (anslen);
+}
diff --git a/usr/src/lib/libresolv2/common/resolv/res_update.c b/usr/src/lib/libresolv2/common/resolv/res_update.c
new file mode 100644
index 0000000000..8983dee245
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/resolv/res_update.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: res_update.c,v 1.38 2003/05/27 23:36:53 marka Exp $";
+#endif /* not lint */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Based on the Dynamic DNS reference implementation by Viraj Bais
+ * <viraj_bais@ccm.fm.intel.com>
+ */
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <res_update.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/list.h>
+#include <resolv.h>
+
+#include "port_after.h"
+#include "res_private.h"
+
+/*
+ * Separate a linked list of records into groups so that all records
+ * in a group will belong to a single zone on the nameserver.
+ * Create a dynamic update packet for each zone and send it to the
+ * nameservers for that zone, and await answer.
+ * Abort if error occurs in updating any zone.
+ * Return the number of zones updated on success, < 0 on error.
+ *
+ * On error, caller must deal with the unsynchronized zones
+ * eg. an A record might have been successfully added to the forward
+ * zone but the corresponding PTR record would be missing if error
+ * was encountered while updating the reverse zone.
+ */
+
+struct zonegrp {
+ char z_origin[MAXDNAME];
+ ns_class z_class;
+ union res_sockaddr_union z_nsaddrs[MAXNS];
+ int z_nscount;
+ int z_flags;
+ LIST(ns_updrec) z_rrlist;
+ LINK(struct zonegrp) z_link;
+};
+
+#define ZG_F_ZONESECTADDED 0x0001
+
+/* Forward. */
+
+static void res_dprintf(const char *, ...) ISC_FORMAT_PRINTF(1, 2);
+
+/* Macros. */
+
+#define DPRINTF(x) do {\
+ int save_errno = errno; \
+ if ((statp->options & RES_DEBUG) != 0) res_dprintf x; \
+ errno = save_errno; \
+ } while (0)
+
+/* Public. */
+
+int
+res_nupdate(res_state statp, ns_updrec *rrecp_in, ns_tsig_key *key) {
+ ns_updrec *rrecp;
+ u_char answer[PACKETSZ];
+ u_char *packet;
+ struct zonegrp *zptr, tgrp;
+ LIST(struct zonegrp) zgrps;
+ int nzones = 0, nscount = 0, n;
+ union res_sockaddr_union nsaddrs[MAXNS];
+
+ packet = malloc(NS_MAXMSG);
+ if (packet == NULL) {
+ DPRINTF(("malloc failed"));
+ return (0);
+ }
+ /* Thread all of the updates onto a list of groups. */
+ INIT_LIST(zgrps);
+ memset(&tgrp, 0, sizeof (tgrp));
+ for (rrecp = rrecp_in; rrecp;
+ rrecp = LINKED(rrecp, r_link) ? NEXT(rrecp, r_link) : NULL) {
+ int nscnt;
+ /* Find the origin for it if there is one. */
+ tgrp.z_class = rrecp->r_class;
+ nscnt = res_findzonecut2(statp, rrecp->r_dname, tgrp.z_class,
+ RES_EXHAUSTIVE, tgrp.z_origin,
+ sizeof tgrp.z_origin,
+ tgrp.z_nsaddrs, MAXNS);
+ if (nscnt <= 0) {
+ DPRINTF(("res_findzonecut failed (%d)", nscnt));
+ goto done;
+ }
+ tgrp.z_nscount = nscnt;
+ /* Find the group for it if there is one. */
+ for (zptr = HEAD(zgrps); zptr != NULL; zptr = NEXT(zptr, z_link))
+ if (ns_samename(tgrp.z_origin, zptr->z_origin) == 1 &&
+ tgrp.z_class == zptr->z_class)
+ break;
+ /* Make a group for it if there isn't one. */
+ if (zptr == NULL) {
+ zptr = malloc(sizeof *zptr);
+ if (zptr == NULL) {
+ DPRINTF(("malloc failed"));
+ goto done;
+ }
+ *zptr = tgrp;
+ zptr->z_flags = 0;
+ INIT_LINK(zptr, z_link);
+ INIT_LIST(zptr->z_rrlist);
+ APPEND(zgrps, zptr, z_link);
+ }
+ /* Thread this rrecp onto the right group. */
+ APPEND(zptr->z_rrlist, rrecp, r_glink);
+ }
+
+ for (zptr = HEAD(zgrps); zptr != NULL; zptr = NEXT(zptr, z_link)) {
+ /* Construct zone section and prepend it. */
+ rrecp = res_mkupdrec(ns_s_zn, zptr->z_origin,
+ zptr->z_class, ns_t_soa, 0);
+ if (rrecp == NULL) {
+ DPRINTF(("res_mkupdrec failed"));
+ goto done;
+ }
+ PREPEND(zptr->z_rrlist, rrecp, r_glink);
+ zptr->z_flags |= ZG_F_ZONESECTADDED;
+
+ /* Marshall the update message. */
+ n = res_nmkupdate(statp, HEAD(zptr->z_rrlist),
+ packet, NS_MAXMSG);
+ DPRINTF(("res_mkupdate -> %d", n));
+ if (n < 0)
+ goto done;
+
+ /* Temporarily replace the resolver's nameserver set. */
+ nscount = res_getservers(statp, nsaddrs, MAXNS);
+ res_setservers(statp, zptr->z_nsaddrs, zptr->z_nscount);
+
+ /* Send the update and remember the result. */
+ if (key != NULL)
+ n = res_nsendsigned(statp, packet, n, key,
+ answer, sizeof answer);
+ else
+ n = res_nsend(statp, packet, n, answer, sizeof answer);
+ if (n < 0) {
+ DPRINTF(("res_nsend: send error, n=%d (%s)\n",
+ n, strerror(errno)));
+ goto done;
+ }
+ if (((HEADER *)answer)->rcode == NOERROR)
+ nzones++;
+
+ /* Restore resolver's nameserver set. */
+ res_setservers(statp, nsaddrs, nscount);
+ nscount = 0;
+ }
+ done:
+ while (!EMPTY(zgrps)) {
+ zptr = HEAD(zgrps);
+ if ((zptr->z_flags & ZG_F_ZONESECTADDED) != 0)
+ res_freeupdrec(HEAD(zptr->z_rrlist));
+ UNLINK(zgrps, zptr, z_link);
+ free(zptr);
+ }
+ if (nscount != 0)
+ res_setservers(statp, nsaddrs, nscount);
+
+ free(packet);
+ return (nzones);
+}
+
+/* Private. */
+
+static void
+res_dprintf(const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ fputs(";; res_nupdate: ", stderr);
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ va_end(ap);
+}
diff --git a/usr/src/lib/libresolv2/common/sunw/sunw_dst_init.c b/usr/src/lib/libresolv2/common/sunw/sunw_dst_init.c
new file mode 100644
index 0000000000..9d299a6f90
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/sunw/sunw_dst_init.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#define __SUNW_DST_INIT_NODEFINE
+
+#include <port_before.h>
+
+#include <dlfcn.h>
+
+#include <isc/dst.h>
+
+#include <port_after.h>
+
+
+static int
+genInit(char *library, char *symbol, int (**initFunc)(void)) {
+
+ void *dlHandle;
+
+ if (*initFunc == 0) {
+ if ((dlHandle = dlopen(library, RTLD_LAZY|RTLD_GLOBAL)) == 0)
+ return (0);
+ if ((*(initFunc) = (int (*)(void))dlsym(dlHandle,
+ symbol)) == 0) {
+ /*
+ * Can't close the library, since it may be in use
+ * as a result of a previous, successful, call to
+ * this function.
+ */
+ return (0);
+ }
+ }
+
+ return ((**initFunc)());
+}
+
+
+int
+sunw_dst_bsafe_init(void) {
+
+ static int (*initFunc)(void);
+
+ return (genInit("/usr/lib/dns/dnssafe.so.1", "dst_bsafe_init",
+ &initFunc) ||
+ genInit("/usr/lib/dns/sparcv9/dnssafe.so.1", "dst_bsafe_init",
+ &initFunc));
+}
+
+
+int
+sunw_dst_eay_dss_init(void) {
+
+ static int (*initFunc)(void);
+
+ return (genInit("/usr/lib/dns/cylink.so.1", "dst_eay_dss_init",
+ &initFunc) ||
+ genInit("/usr/lib/dns/sparcv9/cylink.so.1", "dst_eay_dss_init",
+ &initFunc));
+}
+
+
+int
+sunw_dst_cylink_init(void) {
+
+ static int (*initFunc)(void);
+
+ return (genInit("/usr/lib/dns/cylink.so.1", "dst_cylink_init",
+ &initFunc) ||
+ genInit("/usr/lib/dns/sparcv9/cylink.so.1", "dst_cylink_init",
+ &initFunc));
+}
+
+
+int
+sunw_dst_hmac_md5_init(void) {
+
+ static int (*initFunc)(void);
+
+ return (genInit("/usr/lib/dns/dnssafe.so.1", "dst_md5_hmac_init",
+ &initFunc) ||
+ genInit("/usr/lib/dns/sparcv9/dnssafe.so.1",
+ "dst_hmac_md5_init",
+ &initFunc));
+}
+
+
+int
+sunw_dst_rsaref_init(void) {
+
+ static int (*initFunc)(void);
+
+ return (genInit("/usr/lib/dns/dnssafe.so.1", "dst_rsaref_init",
+ &initFunc) ||
+ genInit("/usr/lib/dns/sparcv9/dnssafe.so.1", "dst_rsaref_init",
+ &initFunc));
+}
diff --git a/usr/src/lib/libresolv2/common/sunw/sunw_irs_init.c b/usr/src/lib/libresolv2/common/sunw/sunw_irs_init.c
new file mode 100644
index 0000000000..542172cf25
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/sunw/sunw_irs_init.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#define __SUNW_IRS_INIT_NODEFINE
+
+#include <port_before.h>
+
+#include <dlfcn.h>
+
+#include <port_after.h>
+
+
+static struct irs_acc *
+genInit(char *library, char *symbol,
+ struct irs_acc *(**initFunc)(const char *), const char *options) {
+
+ void *dlHandle;
+
+ if (*initFunc == 0) {
+ if ((dlHandle = dlopen(library, RTLD_LAZY|RTLD_GLOBAL)) == 0)
+ return (0);
+ if ((*(initFunc) =
+ (struct irs_acc *(*)(const char *))dlsym(dlHandle,
+ symbol)) == 0) {
+ /*
+ * Can't close the library, since it may be in use
+ * as a result of a previous, successful, call to
+ * this function.
+ */
+ return (0);
+ }
+ }
+
+ return ((**initFunc)(options));
+}
+
+
+#ifdef WANT_IRS_NIS
+struct irs_acc *
+sunw_irs_nis_acc(const char *options) {
+
+ static struct irs_acc *(*initFunc)(const char *);
+ struct irs_acc *ret;
+
+ ret = genInit("/usr/lib/dns/irs.so.1", "irs_nis_acc", &initFunc,
+ options);
+ if (ret == 0)
+ ret = genInit("/usr/lib/dns/sparcv9/irs.so.1", "irs_nis_acc",
+ &initFunc, options);
+ return (ret);
+}
+#else
+struct irs_acc *
+sunw_irs_nis_acc(const char *options) {
+ return (0);
+}
+#endif /* WANT_IRS_NIS */
+
+struct irs_acc *
+sunw_irs_irp_acc(const char *options) {
+
+ static struct irs_acc *(*initFunc)(const char *);
+ struct irs_acc *ret;
+
+ ret = genInit("/usr/lib/dns/irs.so.1", "irs_irp_acc", &initFunc,
+ options);
+ if (ret == 0)
+ ret = genInit("/usr/lib/dns/sparcv9/irs.so.1", "irs_irp_acc",
+ &initFunc, options);
+ return (ret);
+}
diff --git a/usr/src/lib/libresolv2/common/sunw/sunw_irs_nis_acc.c b/usr/src/lib/libresolv2/common/sunw/sunw_irs_nis_acc.c
new file mode 100644
index 0000000000..0b5422b991
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/sunw/sunw_irs_nis_acc.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <port_before.h>
+
+#include <irs.h>
+
+#include <port_after.h>
+
+#ifdef WANT_IRS_NIS
+static int __deliberately_empty;
+#else
+/*
+ * Never called; defined here so that the mapfile doesn't have to change
+ * depending on WANT_IRS_NIS.
+ */
+struct irs_acc *
+irs_nis_acc(const char *options) {
+ return (0);
+}
+#endif /* WANT_IRS_NIS */
diff --git a/usr/src/lib/libresolv2/common/sunw/sunw_mtctxres.c b/usr/src/lib/libresolv2/common/sunw/sunw_mtctxres.c
new file mode 100644
index 0000000000..c77e103e22
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/sunw/sunw_mtctxres.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 1998-2000 by Sun Microsystems, Inc.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <port_before.h>
+#include <thread.h>
+#include <errno.h>
+#include <netdb.h>
+#include <malloc.h>
+#include <string.h>
+#include <resolv_mt.h>
+#include <irs.h>
+#include <port_after.h>
+
+static int thr_keycreate_ret = 0;
+
+static thread_key_t key;
+static int mt_key_initialized = 0;
+
+static mtctxres_t sharedctx;
+
+static int __res_init_ctx(thread_key_t);
+static void __res_destroy_ctx(void *);
+
+#pragma init (_mtctxres_init)
+
+/*
+ * Initialize the TSD key. By doing this at library load time, we're
+ * implicitly running without interference from other threads, so there's
+ * no need for locking.
+ */
+static void
+_mtctxres_init(void) {
+
+ if ((thr_keycreate_ret = thr_keycreate(&key, __res_destroy_ctx)) == 0) {
+ mt_key_initialized = 1;
+ }
+}
+
+
+/*
+ * To support binaries that used the private MT-safe interface in
+ * on998 or on28, we still need to provide the __res_enable_mt()
+ * and __res_disable_mt() entry points. They're do-nothing routines.
+ */
+int
+__res_enable_mt(void) {
+ return (-1);
+}
+
+int
+__res_disable_mt(void) {
+ return (0);
+}
+
+
+static int
+__res_init_ctx(thread_key_t key) {
+
+ mtctxres_t *mt;
+ int ret;
+
+
+ if (thr_getspecific(key, (void **)&mt) == 0 && mt != 0) {
+ /* Already exists */
+ return (0);
+ }
+
+ if ((mt = malloc(sizeof (mtctxres_t))) == 0) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ memset(mt, 0, sizeof (*mt));
+
+ if ((ret = thr_setspecific(key, mt)) != 0) {
+ errno = ret;
+ free(mt);
+ return (-1);
+ }
+
+ return (0);
+
+}
+
+
+static void
+__res_destroy_ctx(void *value) {
+
+ mtctxres_t *mt = (mtctxres_t *)value;
+
+ if (mt != 0) {
+ free(mt);
+ }
+}
+
+
+mtctxres_t *
+___mtctxres() {
+
+ mtctxres_t *mt;
+
+
+ if (mt_key_initialized) {
+ if ((thr_getspecific(key, (void **)&mt) == 0 && mt != 0) ||
+ (__res_init_ctx(key) == 0 &&
+ thr_getspecific(key, (void **)&mt) == 0 && mt != 0)) {
+ return (mt);
+ }
+ }
+
+ return (&sharedctx);
+}
+
+
+/*
+ * There used to be a private, MT-safe resolver interface that used TSD
+ * to store per-thread _res, h_errno, etc. We continue to provide the
+ * access functions __res_get_res() and __res_get_h_errno() so that binaries
+ * that used the private interface will continue to work.
+ */
+
+#ifdef _res
+#undef _res
+#endif
+
+extern struct __res_state *__res_state(void);
+
+struct __res_state *
+__res_get_res(void) {
+ return (__res_state());
+}
+
+
+#ifdef h_errno
+#undef h_errno
+#endif
+
+extern int *__h_errno(void);
+
+int *
+__res_get_h_errno(void) {
+ return (__h_errno());
+}
+
+
+#ifdef SUNW_HOSTS_FALLBACK
+
+/*
+ * When the name service switch calls libresolv, it doesn't want fallback
+ * to /etc/hosts, so we provide a method to turn it off.
+ */
+
+void
+__res_set_no_hosts_fallback(void) {
+ ___mtctxres()->no_hosts_fallback_private = 1;
+}
+
+void
+__res_unset_no_hosts_fallback(void) {
+ ___mtctxres()->no_hosts_fallback_private = 0;
+}
+
+int
+__res_no_hosts_fallback(void) {
+ return (___mtctxres()->no_hosts_fallback_private);
+}
+
+#endif /* SUNW_HOSTS_FALLBACK */
+
+#ifdef SUNW_OVERRIDE_RETRY
+
+/*
+ * The NS switch wants to be able to override the number of retries.
+ */
+
+int
+__res_override_retry(int retry) {
+ ___mtctxres()->retry_private = retry;
+ /*
+ * This function doesn't really need a return value; saving the
+ * old retry setting, and restoring it, is handled by __res_retry()
+ * and __res_retry_reset() below. However, the nss_dns library
+ * must have a private version of this function to be used when
+ * running with an old libresolv. That private nss_dns function
+ * needs a return value, and a function pointer is used to select
+ * the right function at runtime. Thus, __res_override_retry
+ * must have a function prototype consistent with the private
+ * nss_dns function, i.e., one that returns an int.
+ *
+ * Given that we do have a return value, that value must be zero.
+ * That's because retry_private == 0 is used to indicate that
+ * no override retry value is in effect, and the way we expect
+ * nss_dns to call us is:
+ *
+ * int oldretry = __res_override_retry(N);
+ * <whatever>
+ * (void)__res_override_retry(old_retry);
+ */
+ return (0);
+}
+
+int
+__res_retry(int retry) {
+ mtctxres_t *mt = ___mtctxres();
+
+ mt->retry_save = retry;
+ return ((mt->retry_private != 0) ? mt->retry_private : retry);
+}
+
+int
+__res_retry_reset(void) {
+ mtctxres_t *mt = ___mtctxres();
+
+ return (mt->retry_save);
+}
+
+#endif /* SUNW_OVERRIDE_RETRY */
diff --git a/usr/src/lib/libresolv2/common/sunw/sunw_updrec.c b/usr/src/lib/libresolv2/common/sunw/sunw_updrec.c
new file mode 100644
index 0000000000..c9bc2b2038
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/sunw/sunw_updrec.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * As of BIND 8.2.2, ISC (a) removed res_mkupdate(), res_update(), and
+ * res_mkupdrec() from what they consider the supported interface. The
+ * functions still exist, but their calling interface has changed, since
+ * the ns_updrec structure has changed.
+ *
+ * It seems probable that res_mkupdate() etc. will return, though possibly
+ * with other changes, in some future BIND release. In order to avoid
+ * going to PSARC twice (once to remove the functions, and then again to
+ * add them back), we retain the old interface as a wrapper around the
+ * new one.
+ */
+
+#include <port_before.h>
+
+#include <malloc.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include <res_update.h>
+#undef ns_updrec
+#undef res_mkupdate
+#undef res_update
+#undef res_mkupdrec
+#undef res_freeupdrec
+#include <arpa/nameser.h>
+
+#include <port_after.h>
+
+void res_freeupdrec(ns_updrec *);
+
+
+static int
+old2new(ns_updrec *old, __ISC_ns_updrec *new) {
+
+ if (old->r_dname != 0) {
+ if ((new->r_dname = strdup(old->r_dname)) == 0)
+ return (-1);
+ } else {
+ new->r_dname = 0;
+ }
+
+ new->r_glink.prev =
+ new->r_glink.next =
+ new->r_link.prev =
+ new->r_link.next = 0;
+
+ new->r_section = old->r_section;
+ new->r_class = old->r_class;
+ new->r_type = old->r_type;
+ new->r_ttl = old->r_ttl;
+ new->r_data = old->r_data;
+ new->r_size = old->r_size;
+ new->r_opcode = old->r_opcode;
+ new->r_dp = old->r_dp;
+ new->r_deldp = old->r_deldp;
+ new->r_zone = old->r_zone;
+
+ return (0);
+}
+
+
+static int
+new2old(__ISC_ns_updrec *new, ns_updrec *old) {
+ /* XXX r_prev and r_next unchanged */
+ if (new->r_dname != 0) {
+ if ((old->r_dname = strdup(new->r_dname)) == 0)
+ return (-1);
+ } else {
+ old->r_dname = 0;
+ }
+ old->r_section = new->r_section;
+ old->r_class = new->r_class;
+ old->r_type = new->r_type;
+ old->r_ttl = new->r_ttl;
+ old->r_data = new->r_data;
+ old->r_size = new->r_size;
+ old->r_opcode = new->r_opcode;
+ old->r_grpnext = 0; /* XXX */
+ old->r_dp = new->r_dp;
+ old->r_deldp = new->r_deldp;
+ old->r_zone = new->r_zone;
+
+ return (0);
+}
+
+
+static void
+delete_list(__ISC_ns_updrec *list) {
+
+ __ISC_ns_updrec *next;
+
+ for (; list != 0; list = next) {
+ next = list->r_link.next;
+ __ISC_res_freeupdrec(list);
+ }
+}
+
+
+static __ISC_ns_updrec *
+copy_list(ns_updrec *old) {
+
+ __ISC_ns_updrec *list = 0, *r, *p;
+
+ if (old == 0)
+ return (0);
+
+ for (p = 0; old != 0; old = old->r_next, p = r) {
+ if ((r = calloc(1, sizeof (*r))) == 0 ||
+ old2new(old, r) != 0) {
+ free(r);
+ delete_list(list);
+ return (0);
+ }
+ r->r_link.prev = p;
+ r->r_link.next = 0;
+ if (p != 0)
+ p->r_link.next = r;
+ else
+ list = r;
+ }
+
+ return (list);
+}
+
+
+int
+res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int length) {
+
+ __ISC_ns_updrec *r;
+ int ret;
+
+ if ((r = copy_list(rrecp_in)) == 0)
+ return (-1);
+
+ ret = __ISC_res_mkupdate(r, buf, length);
+
+ delete_list(r);
+
+ return (ret);
+}
+
+
+int
+res_update(ns_updrec *rrecp_in) {
+
+ __ISC_ns_updrec *r;
+ int ret;
+
+ if ((r = copy_list(rrecp_in)) == 0)
+ return (-1);
+
+ ret = __ISC_res_update(r);
+
+ delete_list(r);
+
+ return (ret);
+}
+
+
+
+ns_updrec *
+res_mkupdrec(int section, const char *dname, uint_t class, uint_t type,
+ uint_t ttl) {
+
+ __ISC_ns_updrec *n;
+ ns_updrec *o;
+
+ n = __ISC_res_mkupdrec(section, dname, class, type, ttl);
+ if (n == 0)
+ return (0);
+
+ if ((o = calloc(1, sizeof (*o))) != 0) {
+ if (new2old(n, o) != 0) {
+ res_freeupdrec(o);
+ o = 0;
+ }
+ }
+
+ __ISC_res_freeupdrec(n);
+
+ return (o);
+}
+
+
+void
+res_freeupdrec(ns_updrec *rrecp) {
+ if (rrecp == 0)
+ return;
+ /* Note: freeing r_dp is the caller's responsibility. */
+ if (rrecp->r_dname != NULL)
+ free(rrecp->r_dname);
+ free(rrecp);
+}
diff --git a/usr/src/lib/libresolv2/cylink/Makefile b/usr/src/lib/libresolv2/cylink/Makefile
new file mode 100644
index 0000000000..cb38b82b0a
--- /dev/null
+++ b/usr/src/lib/libresolv2/cylink/Makefile
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/cylink/Makefile
+
+include ../../../Makefile.master
+include ../../Makefile.lib
+
+SUBDIRS= spec $(MACH) $(BUILD64) $(MACH64)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+delete := TARGET= delete
+install := TARGET= install
+lint := TARGET= lint
+_msg := TARGET= _msg
+package := TARGET= package
+
+LIBRARY= cylink.a
+TEXT_DOMAIN= SUNW_OST_OSLIB
+XGETFLAGS= -a
+POFILE= $(LIBRARY:.a=.po)
+POFILES= generic.po
+
+SED= sed
+GREP= grep
+CP= cp
+
+.KEEP_STATE:
+
+all clean clobber delete install lint package: $(SUBDIRS)
+
+# install rule for install_h target
+$(ROOTHDRDIR)/%: %
+ $(INS.file)
+
+install_h: $(ROOTHDRS)
+
+check: $(CHECKHDRS)
+
+$(MACH) $(MACH64) spec: FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+_msg: $(MSGDOMAIN) $(POFILE)
+ $(RM) $(MSGDOMAIN)/$(POFILE)
+ $(CP) $(POFILE) $(MSGDOMAIN)
+
+$(POFILE): $(POFILES)
+ $(RM) $@
+ $(CAT) $(POFILES) > $@
+
+$(POFILES):
+ $(RM) messages.po
+ $(XGETTEXT) $(XGETFLAGS) *.[ch]* */*.[ch]*
+ $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@
+ $(RM) messages.po
+
+FRC:
diff --git a/usr/src/lib/libresolv2/cylink/Makefile.com b/usr/src/lib/libresolv2/cylink/Makefile.com
new file mode 100644
index 0000000000..427ca32947
--- /dev/null
+++ b/usr/src/lib/libresolv2/cylink/Makefile.com
@@ -0,0 +1,69 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/cylink/Makefile.com
+#
+
+LIBRARY= cylink.a
+VERS= .1
+
+DSTOBJS= cylink_link.o
+
+CYLINKOBJS= bits.o dss.o rand.o bn.o \
+ lbn00.o lbnmem.o sha.o bn00.o \
+ legal.o swap.o ctk_prime.o math.o
+
+OBJECTS= $(DSTOBJS) $(CYLINKOBJS)
+
+# include library definitions
+include ../../../Makefile.lib
+
+LIBNAME= $(LIBRARY:%.a=%)
+LIBS= $(DYNLIB)
+LDLIBS += -lresolv -lc
+
+MAPDIR = ../spec/$(TRANSMACH)
+SPECMAPFILE = $(MAPDIR)/mapfile
+SRCDIR= ../../common/cylink
+SRCS= $(DSTOBJS:%.o=../../common/dst/%.c) \
+ $(CYLINKOBJS:%.o=$(SRCDIR)/%.c)
+
+ROOTLIBDIR= $(ROOT)/usr/lib/dns
+ROOTLIBDIR64= $(ROOT)/usr/lib/dns/$(MACH64)
+
+# Local Libresolv definitions
+SOLCOMPAT = -Dgethostbyname=res_gethostbyname \
+ -Dgethostbyaddr=res_gethostbyaddr -Dgetnetbyname=res_getnetbyname \
+ -Dgethostbyname2=res_gethostbyname2\
+ -Dgetnetbyaddr=res_getnetbyaddr -Dsethostent=res_sethostent \
+ -Dendhostent=res_endhostent -Dgethostent=res_gethostent \
+ -Dsetnetent=res_setnetent -Dendnetent=res_endnetent \
+ -Dgetnetent=res_getnetent -Dsocket=_socket
+
+CRYPTINCL= -I../../common/cylink -I../../common/dnssafe
+CRYPTFLAGS= -DCYLINK_DSS -DHMAC_MD5 -DUSE_MD5 -DDNSSAFE \
+ -D__SUNW_DST_INIT_NODEFINE
+
+CPPFLAGS += $(CRYPTFLAGS) $(CRYPTINCL)
+CPPFLAGS += -D_SYS_STREAM_H -D_REENTRANT -DSVR4 -DSUNW_OPTIONS \
+ $(SOLCOMPAT) -I../../include
+
+REDLOC= $(ZREDLOCSYM)
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+$(ROOTLIBDIR) $(ROOTLIBDIR64):
+ $(INS.dir)
+
+include ../../../Makefile.targ
+
+pics/%.o: ../../common/dst/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
diff --git a/usr/src/lib/libresolv2/cylink/amd64/Makefile b/usr/src/lib/libresolv2/cylink/amd64/Makefile
new file mode 100644
index 0000000000..2b37434e6b
--- /dev/null
+++ b/usr/src/lib/libresolv2/cylink/amd64/Makefile
@@ -0,0 +1,15 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+MAPDIR= ../spec/amd64
+
+include ../Makefile.com
+include ../../../Makefile.lib.64
+
+all: $(LIBS)
+
+install: all $(ROOTLIBDIR64) .WAIT $(ROOTLIBS64)
diff --git a/usr/src/lib/libresolv2/cylink/i386/Makefile b/usr/src/lib/libresolv2/cylink/i386/Makefile
new file mode 100644
index 0000000000..ef5c431bf7
--- /dev/null
+++ b/usr/src/lib/libresolv2/cylink/i386/Makefile
@@ -0,0 +1,12 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/cylink/i386/Makefile
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBDIR) .WAIT $(ROOTLIBS)
diff --git a/usr/src/lib/libresolv2/cylink/sparc/Makefile b/usr/src/lib/libresolv2/cylink/sparc/Makefile
new file mode 100644
index 0000000000..5f69358368
--- /dev/null
+++ b/usr/src/lib/libresolv2/cylink/sparc/Makefile
@@ -0,0 +1,12 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/cylink/sparc/Makefile
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBDIR) .WAIT $(ROOTLIBS)
diff --git a/usr/src/lib/libresolv2/cylink/sparcv9/Makefile b/usr/src/lib/libresolv2/cylink/sparcv9/Makefile
new file mode 100644
index 0000000000..a99c57a229
--- /dev/null
+++ b/usr/src/lib/libresolv2/cylink/sparcv9/Makefile
@@ -0,0 +1,13 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/cylink/sparcv9/Makefile
+#
+
+include ../Makefile.com
+include ../../../Makefile.lib.64
+
+install: all $(ROOTLIBDIR64) .WAIT $(ROOTLIBS64)
diff --git a/usr/src/lib/libresolv2/cylink/spec/Makefile b/usr/src/lib/libresolv2/cylink/spec/Makefile
new file mode 100644
index 0000000000..335473f4cc
--- /dev/null
+++ b/usr/src/lib/libresolv2/cylink/spec/Makefile
@@ -0,0 +1,8 @@
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/cylink/spec/Makefile
+
+include $(SRC)/lib/Makefile.spec.arch
diff --git a/usr/src/lib/libresolv2/cylink/spec/Makefile.targ b/usr/src/lib/libresolv2/cylink/spec/Makefile.targ
new file mode 100644
index 0000000000..25ade9b830
--- /dev/null
+++ b/usr/src/lib/libresolv2/cylink/spec/Makefile.targ
@@ -0,0 +1,12 @@
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/cylink/spec/Makefile.targ
+
+LIBRARY = cylink.a
+VERS = .1
+
+OBJECTS = cylink.o
+
diff --git a/usr/src/lib/libresolv2/cylink/spec/amd64/Makefile b/usr/src/lib/libresolv2/cylink/spec/amd64/Makefile
new file mode 100644
index 0000000000..84ccf3ca89
--- /dev/null
+++ b/usr/src/lib/libresolv2/cylink/spec/amd64/Makefile
@@ -0,0 +1,26 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+
+# Uncomment the following if the linker complains
+#amd64_C_PICFLAGS = $(amd64_C_BIGPICFLAGS)
+
+include $(SRC)/lib/Makefile.spec
+
+# No public interface, so don't install spec libraries in the proto area
+INS.abilib=
+
+install: $(ROOTABILIB64)
diff --git a/usr/src/lib/libresolv2/cylink/spec/cylink.spec b/usr/src/lib/libresolv2/cylink/spec/cylink.spec
new file mode 100644
index 0000000000..aaa45150f4
--- /dev/null
+++ b/usr/src/lib/libresolv2/cylink/spec/cylink.spec
@@ -0,0 +1,11 @@
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/cylink/spec/cylink.spec
+
+function dst_cylink_init
+version SUNWprivate_1.1
+end
diff --git a/usr/src/lib/libresolv2/cylink/spec/i386/Makefile b/usr/src/lib/libresolv2/cylink/spec/i386/Makefile
new file mode 100644
index 0000000000..1c7d394c11
--- /dev/null
+++ b/usr/src/lib/libresolv2/cylink/spec/i386/Makefile
@@ -0,0 +1,26 @@
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/cylink/spec/i386/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+
+# Uncomment the following if the linker complains
+#sparc_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+# No public interface, so don't install spec libraries in the proto area
+INS.abilib=
+
+install: $(ROOTABILIB)
diff --git a/usr/src/lib/libresolv2/cylink/spec/sparc/Makefile b/usr/src/lib/libresolv2/cylink/spec/sparc/Makefile
new file mode 100644
index 0000000000..59d2b5cd6c
--- /dev/null
+++ b/usr/src/lib/libresolv2/cylink/spec/sparc/Makefile
@@ -0,0 +1,26 @@
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 2000 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/cylink/spec/sparc/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+
+# Uncomment the following if the linker complains
+#sparc_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+# No public interface, so don't install spec libraries in the proto area
+INS.abilib=
+
+install: $(ROOTABILIB)
diff --git a/usr/src/lib/libresolv2/cylink/spec/sparcv9/Makefile b/usr/src/lib/libresolv2/cylink/spec/sparcv9/Makefile
new file mode 100644
index 0000000000..311dcf33e4
--- /dev/null
+++ b/usr/src/lib/libresolv2/cylink/spec/sparcv9/Makefile
@@ -0,0 +1,27 @@
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/cylink/spec/sparcv9/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+
+# Uncomment the following if the linker complains
+#sparcv9_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+# No public interface, so don't install spec libraries in the proto area
+INS.abilib=
+
+install: $(ROOTABILIB64)
diff --git a/usr/src/lib/libresolv2/cylink/spec/versions b/usr/src/lib/libresolv2/cylink/spec/versions
new file mode 100644
index 0000000000..6a318d48a3
--- /dev/null
+++ b/usr/src/lib/libresolv2/cylink/spec/versions
@@ -0,0 +1,19 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+sparc {
+ SUNWprivate_1.1;
+}
+sparcv9 {
+ SUNWprivate_1.1;
+}
+i386 {
+ SUNWprivate_1.1;
+}
+amd64 {
+ SUNWprivate_1.1;
+}
diff --git a/usr/src/lib/libresolv2/dnssafe/Makefile b/usr/src/lib/libresolv2/dnssafe/Makefile
new file mode 100644
index 0000000000..03fb3d5f5b
--- /dev/null
+++ b/usr/src/lib/libresolv2/dnssafe/Makefile
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/dnssafe/Makefile
+
+include ../../../Makefile.master
+include ../../Makefile.lib
+
+SUBDIRS= spec $(MACH) $(BUILD64) $(MACH64)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+delete := TARGET= delete
+install := TARGET= install
+lint := TARGET= lint
+_msg := TARGET= _msg
+package := TARGET= package
+
+LIBRARY= dnssafe.a
+TEXT_DOMAIN= SUNW_OST_OSLIB
+XGETFLAGS= -a
+POFILE= $(LIBRARY:.a=.po)
+POFILES= generic.po
+
+SED= sed
+GREP= grep
+CP= cp
+
+.KEEP_STATE:
+
+all clean clobber delete install lint package: $(SUBDIRS)
+
+# install rule for install_h target
+$(ROOTHDRDIR)/%: %
+ $(INS.file)
+
+install_h: $(ROOTHDRS)
+
+check: $(CHECKHDRS)
+
+$(MACH) $(MACH64) spec: FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+_msg: $(MSGDOMAIN) $(POFILE)
+ $(RM) $(MSGDOMAIN)/$(POFILE)
+ $(CP) $(POFILE) $(MSGDOMAIN)
+
+$(POFILE): $(POFILES)
+ $(RM) $@
+ $(CAT) $(POFILES) > $@
+
+$(POFILES):
+ $(RM) messages.po
+ $(XGETTEXT) $(XGETFLAGS) *.[ch]* */*.[ch]*
+ $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@
+ $(RM) messages.po
+
+FRC:
diff --git a/usr/src/lib/libresolv2/dnssafe/Makefile.com b/usr/src/lib/libresolv2/dnssafe/Makefile.com
new file mode 100644
index 0000000000..1d85bdbc47
--- /dev/null
+++ b/usr/src/lib/libresolv2/dnssafe/Makefile.com
@@ -0,0 +1,88 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/dnssafe/Makefile.com
+#
+
+LIBRARY= dnssafe.a
+VERS= .1
+
+DSTOBJS= bsafe_link.o hmac_link.o rsaref_link.o eay_dss_link.o
+
+DNSSAFEOBJS= 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.o \
+ 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 \
+ md5rand.o prime.o random.o rsa.o \
+ rsakeygn.o seccbcd.o seccbce.o surrendr.o
+
+OBJECTS= $(DSTOBJS) $(DNSSAFEOBJS)
+
+include ../../../Makefile.lib
+
+LIBNAME= $(LIBRARY:%.a=%)
+LIBS= $(DYNLIB)
+LDLIBS += -lmd5 -lresolv -lc
+
+MAPDIR = ../spec/$(TRANSMACH)
+SPECMAPFILE = $(MAPDIR)/mapfile
+SRCDIR= ../../common/dnssafe
+SRCS= $(DSTOBJS:%.o=../../common/dst/%.c) \
+ $(DNSSAFEOBJS:%o=$(SRCDIR)/%.c)
+
+ROOTLIBDIR= $(ROOT)/usr/lib/dns
+ROOTLIBDIR64= $(ROOT)/usr/lib/dns/$(MACH64)
+
+
+# Local Libresolv definitions
+SOLCOMPAT = -Dgethostbyname=res_gethostbyname \
+ -Dgethostbyaddr=res_gethostbyaddr -Dgetnetbyname=res_getnetbyname \
+ -Dgethostbyname2=res_gethostbyname2\
+ -Dgetnetbyaddr=res_getnetbyaddr -Dsethostent=res_sethostent \
+ -Dendhostent=res_endhostent -Dgethostent=res_gethostent \
+ -Dsetnetent=res_setnetent -Dendnetent=res_endnetent \
+ -Dgetnetent=res_getnetent -Dsocket=_socket
+
+CRYPTINCL= -I../../common/cylink -I../../common/dnssafe
+CRYPTFLAGS= -DCYLINK_DSS -DHMAC_MD5 -DUSE_MD5 -DDNSSAFE \
+ -D__SUNW_DST_INIT_NODEFINE
+
+CPPFLAGS += $(CRYPTFLAGS) $(CRYPTINCL)
+CPPFLAGS += -D_SYS_STREAM_H -D_REENTRANT -DSVR4 -DSUNW_OPTIONS \
+ $(SOLCOMPAT) -I../../include
+
+REDLOC= $(ZREDLOCSYM)
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+$(ROOTLIBDIR) $(ROOTLIBDIR64):
+ $(INS.dir)
+
+include ../../../Makefile.targ
+
+pics/%.o: ../../common/dst/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
diff --git a/usr/src/lib/libresolv2/dnssafe/amd64/Makefile b/usr/src/lib/libresolv2/dnssafe/amd64/Makefile
new file mode 100644
index 0000000000..2b37434e6b
--- /dev/null
+++ b/usr/src/lib/libresolv2/dnssafe/amd64/Makefile
@@ -0,0 +1,15 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+MAPDIR= ../spec/amd64
+
+include ../Makefile.com
+include ../../../Makefile.lib.64
+
+all: $(LIBS)
+
+install: all $(ROOTLIBDIR64) .WAIT $(ROOTLIBS64)
diff --git a/usr/src/lib/libresolv2/dnssafe/i386/Makefile b/usr/src/lib/libresolv2/dnssafe/i386/Makefile
new file mode 100644
index 0000000000..5377e53c07
--- /dev/null
+++ b/usr/src/lib/libresolv2/dnssafe/i386/Makefile
@@ -0,0 +1,12 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/dnssafe/i386/Makefile
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBDIR) .WAIT $(ROOTLIBS)
diff --git a/usr/src/lib/libresolv2/dnssafe/sparc/Makefile b/usr/src/lib/libresolv2/dnssafe/sparc/Makefile
new file mode 100644
index 0000000000..f8244e9564
--- /dev/null
+++ b/usr/src/lib/libresolv2/dnssafe/sparc/Makefile
@@ -0,0 +1,12 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/dnssafe/sparc/Makefile
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBDIR) .WAIT $(ROOTLIBS)
diff --git a/usr/src/lib/libresolv2/dnssafe/sparcv9/Makefile b/usr/src/lib/libresolv2/dnssafe/sparcv9/Makefile
new file mode 100644
index 0000000000..2737e64129
--- /dev/null
+++ b/usr/src/lib/libresolv2/dnssafe/sparcv9/Makefile
@@ -0,0 +1,13 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/dnssafe/sparcv9/Makefile
+#
+
+include ../Makefile.com
+include ../../../Makefile.lib.64
+
+install: all $(ROOTLIBDIR64) .WAIT $(ROOTLIBS64)
diff --git a/usr/src/lib/libresolv2/dnssafe/spec/Makefile b/usr/src/lib/libresolv2/dnssafe/spec/Makefile
new file mode 100644
index 0000000000..8ad8521042
--- /dev/null
+++ b/usr/src/lib/libresolv2/dnssafe/spec/Makefile
@@ -0,0 +1,8 @@
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/dnssafe/spec/Makefile
+
+include $(SRC)/lib/Makefile.spec.arch
diff --git a/usr/src/lib/libresolv2/dnssafe/spec/Makefile.targ b/usr/src/lib/libresolv2/dnssafe/spec/Makefile.targ
new file mode 100644
index 0000000000..84dd50716e
--- /dev/null
+++ b/usr/src/lib/libresolv2/dnssafe/spec/Makefile.targ
@@ -0,0 +1,12 @@
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/dnssafe/spec/Makefile.targ
+
+LIBRARY = dnssafe.a
+VERS = .1
+
+OBJECTS = dnssafe.o
+
diff --git a/usr/src/lib/libresolv2/dnssafe/spec/amd64/Makefile b/usr/src/lib/libresolv2/dnssafe/spec/amd64/Makefile
new file mode 100644
index 0000000000..84ccf3ca89
--- /dev/null
+++ b/usr/src/lib/libresolv2/dnssafe/spec/amd64/Makefile
@@ -0,0 +1,26 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+
+# Uncomment the following if the linker complains
+#amd64_C_PICFLAGS = $(amd64_C_BIGPICFLAGS)
+
+include $(SRC)/lib/Makefile.spec
+
+# No public interface, so don't install spec libraries in the proto area
+INS.abilib=
+
+install: $(ROOTABILIB64)
diff --git a/usr/src/lib/libresolv2/dnssafe/spec/dnssafe.spec b/usr/src/lib/libresolv2/dnssafe/spec/dnssafe.spec
new file mode 100644
index 0000000000..55b7a26fe0
--- /dev/null
+++ b/usr/src/lib/libresolv2/dnssafe/spec/dnssafe.spec
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/dnssafe/spec/dnssafe.spec
+
+function dst_bsafe_init
+version SUNWprivate_1.1
+end
+
+function dst_eay_dss_init
+version SUNWprivate_1.1
+end
+
+function dst_md5_hmac_init
+version SUNWprivate_1.1
+end
+
+function dst_rsaref_init
+version SUNWprivate_1.1
+end
diff --git a/usr/src/lib/libresolv2/dnssafe/spec/i386/Makefile b/usr/src/lib/libresolv2/dnssafe/spec/i386/Makefile
new file mode 100644
index 0000000000..d60f7c85f9
--- /dev/null
+++ b/usr/src/lib/libresolv2/dnssafe/spec/i386/Makefile
@@ -0,0 +1,26 @@
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/dnssafe/spec/i386/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+
+# Uncomment the following if the linker complains
+#sparc_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+# No public interface, so don't install spec libraries in the proto area
+INS.abilib=
+
+install: $(ROOTABILIB)
diff --git a/usr/src/lib/libresolv2/dnssafe/spec/sparc/Makefile b/usr/src/lib/libresolv2/dnssafe/spec/sparc/Makefile
new file mode 100644
index 0000000000..6046f459ec
--- /dev/null
+++ b/usr/src/lib/libresolv2/dnssafe/spec/sparc/Makefile
@@ -0,0 +1,26 @@
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/dnssafe/spec/sparc/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+
+# Uncomment the following if the linker complains
+#sparc_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+# No public interface, so don't install spec libraries in the proto area
+INS.abilib=
+
+install: $(ROOTABILIB)
diff --git a/usr/src/lib/libresolv2/dnssafe/spec/sparcv9/Makefile b/usr/src/lib/libresolv2/dnssafe/spec/sparcv9/Makefile
new file mode 100644
index 0000000000..e405d11dc7
--- /dev/null
+++ b/usr/src/lib/libresolv2/dnssafe/spec/sparcv9/Makefile
@@ -0,0 +1,27 @@
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/dnssafe/spec/sparcv9/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+
+# Uncomment the following if the linker complains
+#sparcv9_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+# No public interface, so don't install spec libraries in the proto area
+INS.abilib=
+
+install: $(ROOTABILIB64)
diff --git a/usr/src/lib/libresolv2/dnssafe/spec/versions b/usr/src/lib/libresolv2/dnssafe/spec/versions
new file mode 100644
index 0000000000..6a318d48a3
--- /dev/null
+++ b/usr/src/lib/libresolv2/dnssafe/spec/versions
@@ -0,0 +1,19 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+sparc {
+ SUNWprivate_1.1;
+}
+sparcv9 {
+ SUNWprivate_1.1;
+}
+i386 {
+ SUNWprivate_1.1;
+}
+amd64 {
+ SUNWprivate_1.1;
+}
diff --git a/usr/src/lib/libresolv2/i386/Makefile b/usr/src/lib/libresolv2/i386/Makefile
new file mode 100644
index 0000000000..417285a02e
--- /dev/null
+++ b/usr/src/lib/libresolv2/i386/Makefile
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 1997-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/sparc/Makefile
+
+MAPDIR= ../spec/i386
+
+include ../Makefile.com
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libresolv2/include/Makefile b/usr/src/lib/libresolv2/include/Makefile
new file mode 100644
index 0000000000..65931f43f0
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/Makefile
@@ -0,0 +1,41 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../../../Makefile.master
+
+HDRS= os_version.h port_ipv6.h
+TMPHDRS= new_os_version.h new_port_ipv6.h
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+
+.KEEP_STATE:
+
+all lint: $(HDRS)
+
+install: all
+
+clean:
+ $(RM) $(HDRS) $(TMPHDRS)
+
+clobber: clean
+
+# os_version.h and port_ipv6.h should be rebuilt when you change OS
+# revision. Since that's not easily expressed as a dependency, we
+# rebuild them every time.
+
+os_version.h: make_os_version FRC
+ $(CHMOD) a+x make_os_version
+ ./make_os_version
+
+port_ipv6.h: probe_ipv6 FRC
+ $(CHMOD) a+x probe_ipv6
+ CC="$(CC)" ./probe_ipv6
+
+FRC:
diff --git a/usr/src/lib/libresolv2/include/conf/sunoptions.h b/usr/src/lib/libresolv2/include/conf/sunoptions.h
new file mode 100644
index 0000000000..9e4257b81d
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/conf/sunoptions.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SUNOPTIONS_H
+#define _SUNOPTIONS_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * The following options are PP flags available in the reference implementation
+ * but do not get compiled due to the elimination of the options.h file
+ * This section selectively reintroduces them
+ */
+
+#define HAVE_GETRUSAGE
+
+/*
+ * The following options are PP flags introduced as part of the Sun/Solaris
+ * port.
+ */
+
+/* We may have to pull this out */
+#define SUNW_LIBNSL /* conflicts for inet_addr, inet_ntoa */
+
+/* Additions for Solaris 2 */
+#define SUNW_NSSEARCH /* fix nslookup domain search */
+#define SUNW_AVOIDOVERFLOW /* Avoid buffer overflows */
+#define SUNW_INITCHKIF /* Check if any non-loopback interface is up */
+#define SUNW_DOMAINFROMNIS /* Default domain name from NIS/NIS+ */
+#define USELOOPBACK /* Resolver library defaults to 127.0.0.1 */
+#define SUNW_CONFCHECK /* Abort quickly if no /etc/resolv.conf or local */
+ /* named */
+#define SUNW_AREWEINNAMED /* Override _confcheck if proc is in.named */
+#define SUNW_OPENFDOFFSET /* Open non-stdio fd:s with offset */
+#define SUNW_POLL /* Use poll(2) instead of select(3) */
+#define SUNW_SYNONYMS /* Include synonyms.h (libresolv) */
+#define SUNW_HOSTS_FALLBACK /* Configurable /etc/hosts fallback */
+#define SUNW_LISTEN_BACKLOG /* Configurable listen(3N) backlog (named) */
+#define SUNW_REJECT_BOGUS_H_LENGTH /* (libresolv) */
+#define SUNW_HNOK_UNDERSCORE /* Allow underscore in hostnames (libresolv) */
+#define SUNW_MT_RESOLVER /* MT hot extensions (libresolv) */
+#define SUNW_QSTREAM_CLEANUP /* Avoid using free()d struct qstreams */
+#define SUNW_SETHERRNO /* ISC does not set h_errno in gethostbyname */
+#define SUNW_OVERRIDE_RETRY /* Allow NS switch to override res->retry */
+#define SUNW_CLOSEFROM /* closefrom(3C) per PSARC 2000/193 */
+#define SUNW_AVOIDSTDIO_FDLIMIT /* Avoid 256 file descriptor limit in stdio */
+#define SUNW_LIBMD5 /* Use md5(3EXT) instead of internal implementation */
+
+/* If compiling an MT warm libresolv, we also need reentrancy */
+#if defined(SUNW_MT_RESOLVER) && !defined(_REENTRANT)
+#define _REENTRANT
+#endif
+
+/* SUNW_AREWEINNAMED and SUNW_CONFCHECCK are mutually inclusive */
+#if defined(SUNW_AREWEINNAMED) && !defined(SUNW_CONFCHECK)
+#define SUNW_CONFCHECK
+#endif
+
+/* End additions for Solaris 2 */
+
+#endif /* _SUNOPTIONS_H */
diff --git a/usr/src/lib/libresolv2/include/err.h b/usr/src/lib/libresolv2/include/err.h
new file mode 100644
index 0000000000..45992ea336
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/err.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)err.h 8.1 (Berkeley) 6/2/93
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef _ERR_H_
+#define _ERR_H_
+
+#include <sys/cdefs.h>
+#include <stdarg.h>
+
+__BEGIN_DECLS
+__dead void err __P((int, const char *, ...)) __attribute__((__volatile));
+__dead void verr __P((int, const char *, va_list))
+ __attribute__((__volatile));
+__dead void errx __P((int, const char *, ...)) __attribute__((__volatile));
+__dead void verrx __P((int, const char *, va_list))
+ __attribute__((__volatile));
+void warn __P((const char *, ...));
+void vwarn __P((const char *, va_list));
+void warnx __P((const char *, ...));
+void vwarnx __P((const char *, va_list));
+__END_DECLS
+
+#endif /* !_ERR_H_ */
diff --git a/usr/src/lib/libresolv2/include/fd_setsize.h b/usr/src/lib/libresolv2/include/fd_setsize.h
new file mode 100644
index 0000000000..f6af1b2488
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/fd_setsize.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * No ISC copyright for this file.
+ */
+
+#ifndef _FD_SETSIZE_H
+#define _FD_SETSIZE_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * 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/usr/src/lib/libresolv2/include/hesiod.h b/usr/src/lib/libresolv2/include/hesiod.h
new file mode 100644
index 0000000000..5f113734c8
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/hesiod.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>.
+ */
+
+/*
+ * $Id: hesiod.h,v 1.7 1999/01/08 19:22:45 vixie 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/usr/src/lib/libresolv2/include/inet_private.h b/usr/src/lib/libresolv2/include/inet_private.h
new file mode 100644
index 0000000000..c9c03ab478
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/inet_private.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _INET_PRIVATE_H
+#define _INET_PRIVATE_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Functions defined by the ISC for BIND 8.2, but which do not appear
+ * in RFC 2553 (hence, aren't suitable for inclusion in <inet.h>).
+ */
+
+#ifdef __STDC__
+#ifndef __P
+#define __P(x) x
+#endif
+#else
+#ifndef __P
+#define __P(x) ()
+#endif
+#endif /* __STDC__ */
+
+char * inet_net_ntop __P((int, const void *, int, char *, size_t));
+int inet_net_pton __P((int, const char *, void *, size_t));
+u_int inet_nsap_addr __P((const char *, u_char *, int));
+char * inet_nsap_ntoa __P((int, const u_char *, char *));
+
+#endif /* _INET_PRIVATE_H */
diff --git a/usr/src/lib/libresolv2/include/irp.h b/usr/src/lib/libresolv2/include/irp.h
new file mode 100644
index 0000000000..76b7b23441
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/irp.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2003 by Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ */
+
+/*
+ * 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 8.4 2003/05/02 05:56:21 marka Exp $
+ */
+
+#ifndef _IRP_H_INCLUDED
+#define _IRP_H_INCLUDED
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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);
+#ifdef __GNUC__
+int irs_irp_send_command(struct irp_p *, const char *, ...)
+ __attribute__((__format__(__printf__, 2, 3)));
+#else
+int irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...);
+#endif
+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/usr/src/lib/libresolv2/include/irs.h b/usr/src/lib/libresolv2/include/irs.h
new file mode 100644
index 0000000000..d676136ac9
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/irs.h
@@ -0,0 +1,383 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * $Id: irs.h,v 8.9 2003/04/29 05:51:13 marka Exp $
+ */
+
+#ifndef _IRS_H_INCLUDED
+#define _IRS_H_INCLUDED
+
+#include <sys/types.h>
+
+#include <arpa/nameser.h>
+
+#include <grp.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <pwd.h>
+
+/*
+ * 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
+#ifdef ORIGINAL_ISC_CODE
+#define irs_destroy __irs_destroy
+#else
+#endif
+#define irs_dns_gr __irs_dns_gr
+#define irs_dns_ho __irs_dns_ho
+#define irs_dns_nw __irs_dns_nw
+#define irs_dns_pr __irs_dns_pr
+#define irs_dns_pw __irs_dns_pw
+#define irs_dns_sv __irs_dns_sv
+#define irs_gen_gr __irs_gen_gr
+#define irs_gen_ho __irs_gen_ho
+#define irs_gen_ng __irs_gen_ng
+#define irs_gen_nw __irs_gen_nw
+#define irs_gen_pr __irs_gen_pr
+#define irs_gen_pw __irs_gen_pw
+#define irs_gen_sv __irs_gen_sv
+#define irs_irp_get_full_response __irs_irp_get_full_response
+#define irs_irp_gr __irs_irp_gr
+#define irs_irp_ho __irs_irp_ho
+#define irs_irp_is_connected __irs_irp_is_connected
+#define irs_irp_ng __irs_irp_ng
+#define irs_irp_nw __irs_irp_nw
+#define irs_irp_pr __irs_irp_pr
+#define irs_irp_pw __irs_irp_pw
+#define irs_irp_read_line __irs_irp_read_line
+#define irs_irp_sv __irs_irp_sv
+#define irs_lcl_gr __irs_lcl_gr
+#define irs_lcl_ho __irs_lcl_ho
+#define irs_lcl_ng __irs_lcl_ng
+#define irs_lcl_nw __irs_lcl_nw
+#define irs_lcl_pr __irs_lcl_pr
+#define irs_lcl_pw __irs_lcl_pw
+#define irs_lcl_sv __irs_lcl_sv
+#define irs_nis_gr __irs_nis_gr
+#define irs_nis_ho __irs_nis_ho
+#define irs_nis_ng __irs_nis_ng
+#define irs_nis_nw __irs_nis_nw
+#define irs_nis_pr __irs_nis_pr
+#define irs_nis_pw __irs_nis_pw
+#define irs_nis_sv __irs_nis_sv
+#define net_data_create __net_data_create
+#define net_data_destroy __net_data_destroy
+#ifdef ORIGINAL_ISC_CODE
+#define net_data_minimize __net_data_minimize
+#else
+#endif
+
+/*
+ * 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/usr/src/lib/libresolv2/include/isc/assertions.h b/usr/src/lib/libresolv2/include/isc/assertions.h
new file mode 100644
index 0000000000..1f02d666ce
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/isc/assertions.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * $Id: assertions.h,v 8.4 2001/05/29 05:47:07 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/usr/src/lib/libresolv2/include/isc/ctl.h b/usr/src/lib/libresolv2/include/isc/ctl.h
new file mode 100644
index 0000000000..6b178c446a
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/isc/ctl.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2000-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef ISC_CTL_H
+#define ISC_CTL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * 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 8.11 2001/08/10 02:40:49 marka Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <isc/eventlib.h>
+
+/* 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
+
+#ifdef __GNUC__
+void ctl_logger(enum ctl_severity, const char *, ...)
+ __attribute__((__format__(__printf__, 2, 3)));
+#else
+void ctl_logger(enum ctl_severity, const char *, ...);
+#endif
+
+/* 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/usr/src/lib/libresolv2/include/isc/dst.h b/usr/src/lib/libresolv2/include/isc/dst.h
new file mode 100644
index 0000000000..4460cf63ae
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/isc/dst.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2003 by Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef DST_H
+#define DST_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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 */
+
+#ifdef ORIGINAL_ISC_CODE
+/*
+ * do not taint namespace
+ */
+#define dst_bsafe_init __dst_bsafe_init
+#define dst_buffer_to_key __dst_buffer_to_key
+#define dst_check_algorithm __dst_check_algorithm
+#define dst_compare_keys __dst_compare_keys
+#define dst_cylink_init __dst_cylink_init
+#define dst_dnskey_to_key __dst_dnskey_to_key
+#define dst_eay_dss_init __dst_eay_dss_init
+#define dst_free_key __dst_free_key
+#define dst_generate_key __dst_generate_key
+#define dst_hmac_md5_init __dst_hmac_md5_init
+#define dst_init __dst_init
+#define dst_key_to_buffer __dst_key_to_buffer
+#define dst_key_to_dnskey __dst_key_to_dnskey
+#define dst_random __dst_random
+#define dst_read_key __dst_read_key
+#define dst_rsaref_init __dst_rsaref_init
+#define dst_s_build_filename __dst_s_build_filename
+#define dst_s_calculate_bits __dst_s_calculate_bits
+#define dst_s_conv_bignum_b64_to_u8 __dst_s_conv_bignum_b64_to_u8
+#define dst_s_conv_bignum_u8_to_b64 __dst_s_conv_bignum_u8_to_b64
+#define dst_s_dns_key_id __dst_s_dns_key_id
+#define dst_s_dump __dst_s_dump
+#define dst_s_filename_length __dst_s_filename_length
+#define dst_s_fopen __dst_s_fopen
+#define dst_s_get_int16 __dst_s_get_int16
+#define dst_s_get_int32 __dst_s_get_int32
+#define dst_s_id_calc __dst_s_id_calc
+#define dst_s_put_int16 __dst_s_put_int16
+#define dst_s_put_int32 __dst_s_put_int32
+#define dst_s_quick_random __dst_s_quick_random
+#define dst_s_quick_random_set __dst_s_quick_random_set
+#define dst_s_random __dst_s_random
+#define dst_s_semi_random __dst_s_semi_random
+#define dst_s_verify_str __dst_s_verify_str
+#define dst_sig_size __dst_sig_size
+#define dst_sign_data __dst_sign_data
+#define dst_verify_data __dst_verify_data
+#define dst_write_key __dst_write_key
+#else
+#endif
+
+/*
+ * 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 /* initialize 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/usr/src/lib/libresolv2/include/isc/eventlib.h b/usr/src/lib/libresolv2/include/isc/eventlib.h
new file mode 100644
index 0000000000..92988f63ca
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/isc/eventlib.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.23 2001/05/29 05:47:09 marka Exp $
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef _EVENTLIB_H
+#define _EVENTLIB_H
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <stdio.h>
+
+#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));
+
+#ifdef SUNW_POLL
+extern void evPollfdAdd(evContext ctx, int pollfd_chunk_size, int fd,
+ short events);
+extern void evPollfdDel(evContext ctx, int fd);
+#endif /* SUNW_POLL */
+
+/* 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/usr/src/lib/libresolv2/include/isc/heap.h b/usr/src/lib/libresolv2/include/isc/heap.h
new file mode 100644
index 0000000000..46093f506d
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/isc/heap.h
@@ -0,0 +1,54 @@
+
+/*
+ * Copyright (c) 1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1997 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+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/usr/src/lib/libresolv2/include/isc/irpmarshall.h b/usr/src/lib/libresolv2/include/isc/irpmarshall.h
new file mode 100644
index 0000000000..9ef0f2e4e4
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/isc/irpmarshall.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2000-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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 8.2 2001/05/29 05:47:10 marka Exp $
+ */
+
+#ifndef _IRPMARSHALL_H_INCLUDED
+#define _IRPMARSHALL_H_INCLUDED
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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/usr/src/lib/libresolv2/include/isc/list.h b/usr/src/lib/libresolv2/include/isc/list.h
new file mode 100644
index 0000000000..dba0aad62d
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/isc/list.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 1998-2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef LIST_H
+#define LIST_H 1
+#include <isc/assertions.h>
+
+#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_TYPE(elt, link, type) \
+ do { \
+ (elt)->link.prev = (type *)(-1); \
+ (elt)->link.next = (type *)(-1); \
+ } while (0)
+#define INIT_LINK(elt, link) \
+ INIT_LINK_TYPE(elt, link, void)
+#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_TYPE(list, elt, link, type) \
+ 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_TYPE(elt, link, type); \
+ } while (0)
+#define UNLINK(list, elt, link) \
+ UNLINK_TYPE(list, elt, link, void)
+
+#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/usr/src/lib/libresolv2/include/isc/logging.h b/usr/src/lib/libresolv2/include/isc/logging.h
new file mode 100644
index 0000000000..99f0e40fea
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/isc/logging.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef LOGGING_H
+#define LOGGING_H
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#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
+#define log_close_debug_channels __log_close_debug_channels
+
+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);
+#ifdef __GNUC__
+void log_vwrite(log_context, int, int, const char *,
+ va_list args)
+ __attribute__((__format__(__printf__, 4, 0)));
+void log_write(log_context, int, int, const char *, ...)
+ __attribute__((__format__(__printf__, 4, 5)));
+#else
+void log_vwrite(log_context, int, int, const char *,
+ va_list args);
+void log_write(log_context, int, int, const char *, ...);
+#endif
+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, const 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);
+void log_close_debug_channels(log_context);
+
+#endif /* !LOGGING_H */
diff --git a/usr/src/lib/libresolv2/include/isc/memcluster.h b/usr/src/lib/libresolv2/include/isc/memcluster.h
new file mode 100644
index 0000000000..28e7c444a8
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/isc/memcluster.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 1998-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef MEMCLUSTER_H
+#define MEMCLUSTER_H
+
+#include <stdio.h>
+
+#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
+#define memactive __memactive
+
+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 *);
+int memactive(void);
+
+#endif /* MEMCLUSTER_H */
diff --git a/usr/src/lib/libresolv2/include/isc/misc.h b/usr/src/lib/libresolv2/include/isc/misc.h
new file mode 100644
index 0000000000..89afbc6c51
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/isc/misc.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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 8.5 2001/06/18 06:40:43 marka Exp $
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef _ISC_MISC_H
+#define _ISC_MISC_H
+
+#include <stdio.h>
+
+#define bitncmp __bitncmp
+
+extern int bitncmp(const void *l, const void *r, int n);
+
+extern int isc_gethexstring(unsigned char *, size_t, int, FILE *,
+ int *);
+extern void isc_puthexstring(FILE *, const unsigned char *, size_t,
+ size_t, size_t, const char *);
+extern void isc_tohex(const unsigned char *, size_t, char *);
+
+#endif /*_ISC_MISC_H*/
diff --git a/usr/src/lib/libresolv2/include/isc/tree.h b/usr/src/lib/libresolv2/include/isc/tree.h
new file mode 100644
index 0000000000..384832830c
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/isc/tree.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2003 by Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* 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 8.3 2002/12/03 05:26:48 marka Exp $
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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
+
+#ifdef ORIGINAL_ISC_CODE
+/*
+ * Do not taint namespace
+ */
+#define tree_add __tree_add
+#define tree_delete __tree_delete
+#define tree_init __tree_init
+#define tree_mung __tree_mung
+#define tree_srch __tree_srch
+#define tree_trav __tree_trav
+#else
+#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/usr/src/lib/libresolv2/include/make_os_version b/usr/src/lib/libresolv2/include/make_os_version
new file mode 100644
index 0000000000..3654490fee
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/make_os_version
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+UNAME_R=`/usr/bin/uname -r`
+
+OS_MAJOR=`echo $UNAME_R | /usr/bin/sed -e 's/^\([^.]*\).*/\1/'`
+OS_MINOR=`echo $UNAME_R | /usr/bin/sed -e 's/^[^.]*\.\([^.]*\).*/\1/'`
+OS_VERSION=`echo $UNAME_R | tr '.' '_'`
+
+cat <<EOF > new_os_version.h
+#ifndef OS_VERSION_H
+#define OS_VERSION_H
+
+#define SUNOS_$OS_VERSION
+#define OS_MAJOR $OS_MAJOR
+#define OS_MINOR $OS_MINOR
+
+#endif
+EOF
+
+if [ -f os_version.h ]; then
+ if /usr/bin/cmp -s new_os_version.h os_version.h; then
+ /usr/bin/rm -f new_os_version.h
+ else
+ /usr/bin/rm -f os_version.h
+ /usr/bin/mv new_os_version.h os_version.h
+ fi
+else
+ /usr/bin/mv new_os_version.h os_version.h
+fi
diff --git a/usr/src/lib/libresolv2/include/netdb_private.h b/usr/src/lib/libresolv2/include/netdb_private.h
new file mode 100644
index 0000000000..58a6c5905f
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/netdb_private.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 1999-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NETDB_PRIVATE_H
+#define _NETDB_PRIVATE_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Constants defined by the ISC for BIND 8.2, but which do not appear
+ * in RFC 2553 (hence, aren't suitable for inclusion in <netdb.h>).
+ */
+
+/*
+ * Error return codes from getaddrinfo()
+ */
+
+#define EAI_BADHINTS 12
+#define EAI_PROTOCOL 13
+#define EAI_MAX 14
+
+/*
+ * Flag values for getaddrinfo()
+ */
+
+#define AI_MASK 0x00000007
+
+/*
+ * Scope delimit character
+ */
+#define SCOPE_DELIMITER '%'
+
+/*
+ * XXX
+ * Various data types (hostent_data, netent_data, protoent_data, servent_data)
+ * only defined for __osf__ or __hpux => we don't need them ??
+ */
+
+#endif /* _NETDB_PRIVATE_H */
diff --git a/usr/src/lib/libresolv2/include/netgroup.h b/usr/src/lib/libresolv2/include/netgroup.h
new file mode 100644
index 0000000000..36cc9a742f
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/netgroup.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef ORIGINAL_ISC_CODE
+#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
+#endif /* ORIGINAL_ISC_CODE */
diff --git a/usr/src/lib/libresolv2/include/paths.h b/usr/src/lib/libresolv2/include/paths.h
new file mode 100644
index 0000000000..648c624e02
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/paths.h
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#define _PATH_DEVNULL "/dev/null"
+
diff --git a/usr/src/lib/libresolv2/include/port_after.h b/usr/src/lib/libresolv2/include/port_after.h
new file mode 100644
index 0000000000..2f449c0a7a
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/port_after.h
@@ -0,0 +1,294 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef PORT_AFTER_H
+#define PORT_AFTER_H
+#include "os_version.h"
+
+#undef HAVE_SA_LEN
+#define USE_POSIX
+#define POSIX_SIGNALS
+#define NETREAD_BROKEN
+#define USE_WAITPID
+#define HAVE_FCHMOD
+#define NEED_PSELECT
+#define SETGRENT_VOID
+#define SETPWENT_VOID
+#define SIOCGIFCONF_ADDR
+#define IP_OPT_BUF_SIZE 40
+#define HAVE_CHROOT
+#define CAN_CHANGE_ID
+#define POSIX_GETPWNAM_R
+#define POSIX_GETPWUID_R
+#define POSIX_GETGRGID_R
+#define POSIX_GETGRNAM_R
+#define NEED_SECURE_DIRECTORY
+#define HAVE_DEV_RANDOM
+#define NO_MSG_CONTROL
+
+#define PORT_NONBLOCK O_NONBLOCK
+#define PORT_WOULDBLK EWOULDBLOCK
+#define WAIT_T int
+#ifndef SUNW_LIBNSL
+#define INADDR_NONE 0xffffffff
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+#if (!defined(BSD)) || (BSD < 199306)
+#include <sys/bitypes.h>
+#endif
+#include <sys/time.h>
+
+#ifndef MIN
+#define MIN(x, y) ((x > y) ?y :x)
+#endif
+#ifndef MAX
+#define MAX(x, y) ((x > y) ?x :y)
+#endif
+
+/*
+ * We need to know the IPv6 address family number even on IPv4-only systems.
+ * Note that this is NOT a protocol constant, and that if the system has its
+ * own AF_INET6, different from ours below, all of BIND's libraries and
+ * executables will need to be recompiled after the system <sys/socket.h>
+ * has had this type added. The type number below is correct on most BSD-
+ * derived systems for which AF_INET6 is defined.
+ */
+#ifndef AF_INET6
+#define AF_INET6 24
+#endif
+
+#ifndef PF_INET6
+#define PF_INET6 AF_INET6
+#endif
+#include <port_ipv6.h>
+
+#ifndef HAS_INET6_STRUCTS
+/* Replace with structure from later rev of O/S if known. */
+struct in6_addr {
+ u_int8_t s6_addr[16];
+};
+
+/* Replace with structure from later rev of O/S if known. */
+struct sockaddr_in6 {
+#ifdef HAVE_SA_LEN
+ u_int8_t sin6_len; /* length of this struct */
+ u_int8_t sin6_family; /* AF_INET6 */
+#else
+ u_int16_t sin6_family; /* AF_INET6 */
+#endif
+ u_int16_t sin6_port; /* transport layer port # */
+ u_int32_t sin6_flowinfo; /* IPv6 flow information */
+ struct in6_addr sin6_addr; /* IPv6 address */
+ u_int32_t sin6_scope_id; /* set of interfaces for a scope */
+};
+
+#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
+#endif /* HAS_INET6_STRUCTS */
+
+#if defined(NEED_SOCKADDR_STORAGE) || !defined(HAS_INET6_STRUCTS)
+#define __SS_MAXSIZE 128
+#define __SS_ALLIGSIZE (sizeof (long))
+
+struct sockaddr_storage {
+#ifdef HAVE_SA_LEN
+ u_int8_t ss_len; /* address length */
+ u_int8_t ss_family; /* address family */
+ char __ss_pad1[__SS_ALLIGSIZE - 2 * sizeof (u_int8_t)];
+ long __ss_align;
+ char __ss_pad2[__SS_MAXSIZE - 2 * __SS_ALLIGSIZE];
+#else
+ u_int16_t ss_family; /* address family */
+ char __ss_pad1[__SS_ALLIGSIZE - sizeof (u_int16_t)];
+ long __ss_align;
+ char __ss_pad2[__SS_MAXSIZE - 2 * __SS_ALLIGSIZE];
+#endif
+};
+#endif
+
+
+#if !defined(HAS_INET6_STRUCTS) || defined(NEED_IN6ADDR_ANY)
+#define in6addr_any isc_in6addr_any
+extern const struct in6_addr in6addr_any;
+#endif
+
+#ifndef IN6_ARE_ADDR_EQUAL
+#define IN6_ARE_ADDR_EQUAL(a, b) \
+ (memcmp(&(a)->s6_addr[0], &(b)->s6_addr[0], sizeof (struct in6_addr)) == 0)
+#endif
+
+#ifndef IN6_IS_ADDR_UNSPECIFIED
+#define IN6_IS_ADDR_UNSPECIFIED(a) \
+ IN6_ARE_ADDR_EQUAL(a, &in6addr_any)
+#endif
+
+#ifndef IN6_IS_ADDR_LOOPBACK
+extern const struct in6_addr isc_in6addr_loopback;
+#define IN6_IS_ADDR_LOOPBACK(a) \
+ IN6_ARE_ADDR_EQUAL(a, &isc_in6addr_loopback)
+#endif
+
+#ifndef IN6_IS_ADDR_V4COMPAT
+#define IN6_IS_ADDR_V4COMPAT(a) \
+ ((a)->s6_addr[0] == 0x00 && (a)->s6_addr[1] == 0x00 && \
+ (a)->s6_addr[2] == 0x00 && (a)->s6_addr[3] == 0x00 && \
+ (a)->s6_addr[4] == 0x00 && (a)->s6_addr[5] == 0x00 && \
+ (a)->s6_addr[6] == 0x00 && (a)->s6_addr[7] == 0x00 && \
+ (a)->s6_addr[8] == 0x00 && (a)->s6_addr[9] == 0x00 && \
+ (a)->s6_addr[10] == 0x00 && (a)->s6_addr[11] == 0x00 && \
+ ((a)->s6_addr[12] != 0x00 || (a)->s6_addr[13] != 0x00 || \
+ (a)->s6_addr[14] != 0x00 || \
+ ((a)->s6_addr[15] != 0x00 && (a)->s6_addr[15] != 1)))
+#endif
+
+#ifndef IN6_IS_ADDR_V4MAPPED
+#define IN6_IS_ADDR_V4MAPPED(a) \
+ ((a)->s6_addr[0] == 0x00 && (a)->s6_addr[1] == 0x00 && \
+ (a)->s6_addr[2] == 0x00 && (a)->s6_addr[3] == 0x00 && \
+ (a)->s6_addr[4] == 0x00 && (a)->s6_addr[5] == 0x00 && \
+ (a)->s6_addr[6] == 0x00 && (a)->s6_addr[7] == 0x00 && \
+ (a)->s6_addr[8] == 0x00 && (a)->s6_addr[9] == 0x00 && \
+ (a)->s6_addr[10] == 0xff && (a)->s6_addr[11] == 0xff)
+#endif
+
+#ifndef IN6_IS_ADDR_SITELOCAL
+#define IN6_IS_ADDR_SITELOCAL(a) \
+ (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0))
+#endif
+
+#ifndef IN6_IS_ADDR_LINKLOCAL
+#define IN6_IS_ADDR_LINKLOCAL(a) \
+ (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0x80))
+#endif
+
+#ifndef IN6_IS_ADDR_MULTICAST
+#define IN6_IS_ADDR_MULTICAST(a) ((a)->s6_addr[0] == 0xff)
+#endif
+
+#ifndef __IPV6_ADDR_MC_SCOPE
+#define __IPV6_ADDR_MC_SCOPE(a) ((a)->s6_addr[1] & 0x0f)
+#endif
+
+#ifndef __IPV6_ADDR_SCOPE_SITELOCAL
+#define __IPV6_ADDR_SCOPE_SITELOCAL 0x05
+#endif
+
+#ifndef __IPV6_ADDR_SCOPE_ORGLOCAL
+#define __IPV6_ADDR_SCOPE_ORGLOCAL 0x08
+#endif
+
+#ifndef IN6_IS_ADDR_MC_SITELOCAL
+#define IN6_IS_ADDR_MC_SITELOCAL(a) \
+ (IN6_IS_ADDR_MULTICAST(a) && \
+ (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL))
+#endif
+
+#ifndef IN6_IS_ADDR_MC_ORGLOCAL
+#define IN6_IS_ADDR_MC_ORGLOCAL(a) \
+ (IN6_IS_ADDR_MULTICAST(a) && \
+ (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL))
+#endif
+
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 46
+#endif
+
+/*
+ * Prior to 2.6, Solaris needs a prototype for gethostname().
+ */
+#if (OS_MAJOR == 5 && OS_MINOR < 6)
+extern int gethostname(char *, size_t);
+#endif
+/*
+ * gethostid() was not available until 2.5
+ * setsockopt(SO_REUSEADDR) fails on unix domain sockets before 2.5
+ * use ioctl(FIONBIO) rather than fcntl() calls to set/clear non-blocking i/o.
+ */
+#if (OS_MAJOR == 5 && OS_MINOR < 5)
+#define GET_HOST_ID_MISSING
+#define NO_UNIX_REUSEADDR
+#define USE_FIONBIO_IOCTL
+#endif
+
+#define NEED_STRSEP
+extern char *strsep(char **, const char *);
+
+#define NEED_DAEMON
+int daemon(int nochdir, int noclose);
+
+/*
+ * Solaris defines this in <netdb.h> instead of in <sys/param.h>. We don't
+ * define it in our <netdb.h>, so we define it here.
+ */
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 256
+#endif
+
+/*
+ * Solaris 2.5 and later have getrlimit(), setrlimit() and getrusage().
+ */
+#if (OS_MAJOR > 5 || (OS_MAJOR == 5 && OS_MINOR >= 5))
+#include <sys/resource.h>
+#define HAVE_GETRUSAGE
+#define RLIMIT_TYPE rlim_t
+#define RLIMIT_FILE_INFINITY
+#endif
+
+#include <resolv_mt.h>
+#include <netdb_private.h>
+#include <inet_private.h>
+#include <ctype.h>
+#include <sunw_dst_init.h>
+#include <sunw_irs_init.h>
+
+#ifdef ORIGINAL_ISC_CODE
+const char *isc_strerror(int errnum);
+#define strerror isc_strerror
+#endif
+
+#ifndef ISC_FACILITY
+#define ISC_FACILITY LOG_DAEMON
+#endif
+
+/* res_mkquery.c refers explicitly to __putlong and __putshort */
+#define __putlong putlong
+#define __putshort putshort
+
+/*
+ * If one wanted to use isc__gettimeofday for Solaris, they would
+ * need to define NEED_GETTIMEOFDAY (common/bsd/gettimeofday.c),
+ * which is not defined for Solaris. Hence there is no reason to
+ * change the current definition of gettimeofday which currently
+ * comes from libc and we comment the following out.
+ */
+#ifdef ORIGINAL_ISC_CODE
+int isc__gettimeofday(struct timeval *, struct timezone *);
+#define gettimeofday isc__gettimeofday
+#endif
+
+/*
+ * Solaris 8 has if_nametoindex().
+ */
+#if (OS_MAJOR > 5 || (OS_MAJOR == 5 && OS_MINOR >= 8))
+#define USE_IFNAMELINKID
+#endif
+
+#define UNUSED(x) (x) = (x)
+#define DE_CONST(konst, var) \
+ do { \
+ union { const void *k; void *v; } _u; \
+ _u.k = konst; \
+ var = _u.v; \
+ } while (0)
+#endif /* ! PORT_AFTER_H */
diff --git a/usr/src/lib/libresolv2/include/port_before.h b/usr/src/lib/libresolv2/include/port_before.h
new file mode 100644
index 0000000000..32595ef5e0
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/port_before.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef SUNW_OPTIONS
+#include "conf/sunoptions.h"
+#endif
+
+#define __EXTENSIONS__
+/* #define SVR4 */
+#ifdef WANT_IRS_NIS
+#undef WANT_IRS_NIS
+#endif
+#undef WANT_IRS_PW
+#undef WANT_IRS_GR
+#define SIG_FN void
+#define ISC_SOCKLEN_T int
+#include "os_version.h"
+#if (OS_MAJOR == 5 && OS_MINOR < 5)
+#undef HAS_PTHREADS
+#else
+#define HAS_PTHREADS
+#endif
+
+#if defined(HAS_PTHREADS) && defined(_REENTRANT)
+#define DO_PTHREADS
+#endif
+
+#define GROUP_R_RETURN struct group *
+#define GROUP_R_SET_RETURN void
+#undef GROUP_R_SET_RESULT /*empty*/
+#define GROUP_R_END_RETURN void
+#undef GROUP_R_END_RESULT /*empty*/
+#define GROUP_R_ARGS char *buf, int buflen
+#undef GROUP_R_ENT_ARGS /*empty*/
+#define GROUP_R_OK gptr
+#define GROUP_R_BAD NULL
+#define GETGROUPLIST_ARGS const char *name, gid_t basegid, gid_t *groups, \
+ int *ngroups
+
+#define HOST_R_RETURN struct hostent *
+#define HOST_R_SET_RETURN void
+#undef HOST_R_SET_RESULT /*empty*/
+#define HOST_R_END_RETURN void
+#define HOST_R_END_RESULT(x) /*empty*/
+#define HOST_R_ARGS char *buf, int buflen, int *h_errnop
+#undef HOST_R_ENT_ARGS /*empty*/
+#define HOST_R_COPY buf, buflen
+#define HOST_R_COPY_ARGS char *buf, int buflen
+#define HOST_R_ERRNO *h_errnop = h_errno
+#define HOST_R_OK hptr
+#define HOST_R_BAD NULL
+
+#define NET_R_RETURN struct netent *
+#define NET_R_SET_RETURN void
+#undef NET_R_SET_RESULT /*empty*/
+#define NET_R_END_RETURN void
+#define NET_R_END_RESULT(x) /*empty*/
+#define NET_R_ARGS char *buf, int buflen
+#undef NET_R_ENT_ARGS /*empty*/
+#define NET_R_COPY buf, buflen
+#define NET_R_COPY_ARGS NET_R_ARGS
+#define NET_R_OK nptr
+#define NET_R_BAD NULL
+
+#define NGR_R_RETURN int
+#define NGR_R_SET_RETURN void
+#undef NGR_R_SET_RESULT /*empty*/
+#define NGR_R_END_RETURN void
+#ifdef ORIGINAL_ISC_CODE
+#undef NGR_R_END_RESULT /*empty*/
+#else
+#define NGR_R_END_RESULT(x) /*empty*/
+#endif
+#define NGR_R_ARGS char *buf, int buflen
+#undef NGR_R_ENT_ARGS /*empty*/
+#define NGR_R_COPY buf, buflen
+#define NGR_R_COPY_ARGS NGR_R_ARGS
+#define NGR_R_OK 1
+#define NGR_R_BAD (0)
+
+#define PROTO_R_RETURN struct protoent *
+#define PROTO_R_SET_RETURN void
+#undef PROTO_R_SET_RESULT /*empty*/
+#define PROTO_R_END_RETURN void
+#define PROTO_R_END_RESULT(x) /*empty*/
+#define PROTO_R_ARGS char *buf, int buflen
+#undef PROTO_R_ENT_ARGS /*empty*/
+#define PROTO_R_COPY buf, buflen
+#define PROTO_R_COPY_ARGS PROTO_R_ARGS
+#define PROTO_R_OK pptr
+#define PROTO_R_BAD NULL
+
+#define PASS_R_RETURN struct passwd *
+#define PASS_R_SET_RETURN void
+#undef PASS_R_SET_RESULT /*empty*/
+#define PASS_R_END_RETURN void
+#undef PASS_R_END_RESULT /*empty*/
+#define PASS_R_ARGS char *buf, int buflen
+#undef PASS_R_ENT_ARGS /*empty*/
+#define PASS_R_COPY buf, buflen
+#define PASS_R_COPY_ARGS PASS_R_ARGS
+#define PASS_R_OK pwptr
+#define PASS_R_BAD NULL
+
+#define SERV_R_RETURN struct servent *
+#define SERV_R_SET_RETURN void
+#undef SERV_R_SET_RESULT /*empty*/
+#define SERV_R_END_RETURN void
+#define SERV_R_END_RESULT(x) /*empty*/
+#define SERV_R_ARGS char *buf, int buflen
+#undef SERV_R_ENT_ARGS /*empty*/
+#define SERV_R_COPY buf, buflen
+#define SERV_R_COPY_ARGS SERV_R_ARGS
+#define SERV_R_OK sptr
+#define SERV_R_BAD NULL
+
+/* make #include <sys/ioctl.h> also #include <sys/sockio.h> */
+#define BSD_COMP
+
+#include <limits.h> /* _POSIX_PATH_MAX */
+
+#ifdef __GNUC__
+#define ISC_FORMAT_PRINTF(fmt, args) \
+ __attribute__((__format__(__printf__, fmt, args)))
+#else
+#define ISC_FORMAT_PRINTF(fmt, args)
+#endif
+
+/*
+ * Several files in the ISC distribution use an ALIGN macro which doesn't
+ * appear to be defined anywhere. From the context, it's intended to round
+ * up its argument to the nearest suitable boundary. We'll guess that eight
+ * byte alignment is sufficient.
+ */
+#define ALIGN(p) (uint64_t)(((uintptr_t)(p) + (sizeof (uint64_t) - 1)) \
+ & ~(sizeof (uint64_t) - 1))
+
+#ifdef SUNW_SYNONYMS
+#include "synonyms.h"
+#endif
+
+/*
+ * Remove compiler warnings without modifying ISC source by including
+ * various headers here, mostly to get function prototypes.
+ */
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include "sys/bitypes.h"
+#include "sys/cdefs.h"
+
+#define HAS_INET6_STRUCTS
+#define H_ERRNO_IS_FUNCTION
diff --git a/usr/src/lib/libresolv2/include/prand_conf.h b/usr/src/lib/libresolv2/include/prand_conf.h
new file mode 100644
index 0000000000..89aa78295c
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/prand_conf.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * No ISC copyright for this file.
+ */
+
+#ifndef _PRAND_CMD_H_
+#define _PRAND_CMD_H_
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+static const char *cmds[] = {
+ "/bin/ps -ef 2>&1",
+ "/usr/ucb/netstat -an 2>&1",
+ "/bin/df 2>&1",
+ "/usr/bin/dig com. soa +ti=1 +retry=0 2>&1",
+ "/usr/ucb/uptime 2>&1",
+ "/usr/ucb/netstat -an 2>&1",
+ "/bin/iostat 2>&1",
+ NULL
+};
+
+static const char *dirs[] = {
+ "/tmp",
+ "/var/tmp",
+ ".",
+ "/",
+ "/var/spool",
+ "/var/adm",
+ "/dev",
+ "/var/mail",
+ "/home",
+ NULL
+};
+
+static const char *files[] = {
+ "/proc/self/status",
+ "/var/adm/messages",
+ "/var/adm/wtmp",
+ "/var/adm/lastlog",
+ NULL
+};
+
+#endif /* _PRAND_CMD_H_ */
diff --git a/usr/src/lib/libresolv2/include/probe_ipv6 b/usr/src/lib/libresolv2/include/probe_ipv6
new file mode 100644
index 0000000000..371ac96c55
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/probe_ipv6
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+# Copyright 2003 by Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+set -e
+PATH=/bin:/usr/bin:$PATH; export PATH
+trap "rm -f tmp$$[abc].[oc]" 0
+target=port_ipv6
+new=new_${target}.h
+old=${target}.h
+
+cat > tmp$$a.c <<EOF
+#include <sys/types.h>
+#include <netinet/in.h>
+struct sockaddr_in6 xx;
+EOF
+
+cat > tmp$$b.c <<EOF
+#include <sys/types.h>
+#include <netinet/in.h>
+struct in6_addr xx;
+EOF
+
+cat > tmp$$c.c <<EOF
+#include <sys/types.h>
+#include <netinet/in.h>
+struct sockaddr_in6 xx;
+main() { xx.sin6_scope_id = 0; }
+EOF
+
+cat > ${new} <<EOF
+
+/* This file is automatically generated. Do Not Edit. */
+
+#ifndef ${target}_h
+#define ${target}_h
+
+EOF
+
+if ${CC} -c tmp$$a.c > /dev/null 2>&1
+then
+ echo "#define HAS_INET6_STRUCTS" >> ${new}
+ if ${CC} -c tmp$$b.c > /dev/null 2>&1
+ then
+ :
+ else
+ echo "#define in6_addr in_addr6" >> ${new}
+ fi
+ if ${CC} -c tmp$$c.c > /dev/null 2>&1
+ then
+ echo "#define HAVE_SIN6_SCOPE_ID" >> ${new}
+ else
+ echo "#undef HAVE_SIN6_SCOPE_ID" >> ${new}
+ fi
+else
+ echo "#undef HAS_INET6_STRUCTS" >> ${new}
+fi
+echo >> ${new}
+echo "#endif" >> ${new}
+if [ -f ${old} ]; then
+ if cmp -s ${new} ${old} ; then
+ rm -f ${new}
+ else
+ rm -f ${old}
+ mv ${new} ${old}
+ fi
+else
+ mv ${new} ${old}
+fi
+exit 0
diff --git a/usr/src/lib/libresolv2/include/res_update.h b/usr/src/lib/libresolv2/include/res_update.h
new file mode 100644
index 0000000000..e2eb9c651f
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/res_update.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * 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 8.1 1999/10/07 08:24:13 vixie Exp $
+ */
+
+#ifndef __RES_UPDATE_H
+#define __RES_UPDATE_H
+
+#include <sys/types.h>
+#include <sys/bitypes.h>
+#include <arpa/nameser.h>
+#include <isc/list.h>
+#include <resolv.h>
+
+#ifdef ORIGINAL_ISC_CODE
+#else
+/*
+ * ISC changed the ns_updrec structure. However, it's a public interface
+ * in Solaris, so it's time to break out that old #define magic.
+ */
+#define ns_updrec __ISC_ns_updrec
+#endif /* ORIGINAL_ISC_CODE */
+/*
+ * 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;
+
+#ifdef ORIGINAL_ISC_CODE
+#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
+#else
+/*
+ * For BIND 8.2.2, ISC removed the dynamic update functions, and the
+ * definition of the ns_updrec structure, from the public include files
+ * (<resolv.h>, <arpa/nameser.h>. However, res_update(), res_mkupdate(),
+ * and res_mkupdrec() are in the public libresolv interface in Solaris,
+ * so we can't easily remove them. Thus, ISC's new versions of res_mkupdate()
+ * etc. can't be exposed under their original names.
+ *
+ * res_nmkupdate() and res_nupdate are new. We could either change them
+ * to accept the <arpa/nameser.h> ns_updrec, or leave them unchanged and
+ * undocumented. Since ISC may change ns_updrec again, we pick the latter
+ * solution for now.
+ */
+#define res_mkupdate __ISC_res_mkupdate
+#define res_update __ISC_res_update
+#define res_mkupdrec __ISC_res_mkupdrec
+#define res_freeupdrec __ISC_res_freeupdrec
+#define res_nmkupdate __ISC_res_nmkupdate
+#define res_nupdate __ISC_res_nupdate
+#endif /* ORIGINAL_ISC_CODE */
+
+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/usr/src/lib/libresolv2/include/resolv_mt.h b/usr/src/lib/libresolv2/include/resolv_mt.h
new file mode 100644
index 0000000000..e26fd18f02
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/resolv_mt.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1998-1999 by Sun Microsystems, Inc.
+ */
+
+#ifndef _RESOLV_MT_H
+#define _RESOLV_MT_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef SUNW_MT_RESOLVER
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+/* Access functions for the libresolv private interface */
+
+int __res_enable_mt(void);
+int __res_disable_mt(void);
+
+/* Per-thread context */
+
+typedef struct {
+#ifdef SUNW_HOSTS_FALLBACK
+ int no_hosts_fallback_private;
+#endif /* SUNW_HOSTS_FALLBACK */
+#ifdef SUNW_OVERRIDE_RETRY
+ int retry_save;
+ int retry_private;
+#endif /* SUNW_OVERRIDE_RETRY */
+ char inet_nsap_ntoa_tmpbuf[255*3];
+ char sym_ntos_unname[20];
+ char sym_ntop_unname[20];
+ char p_option_nbuf[40];
+ char p_time_nbuf[40];
+ char precsize_ntoa_retbuf[sizeof "90000000.00"];
+ char loc_ntoa_tmpbuf[sizeof
+"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
+ char p_secstodate_output[15];
+} mtctxres_t;
+
+/* Thread-specific data (TSD) */
+
+extern mtctxres_t *___mtctxres();
+#define mtctxres (___mtctxres())
+
+/* Various static data that should be TSD */
+
+#define sym_ntos_unname (mtctxres->sym_ntos_unname)
+#define sym_ntop_unname (mtctxres->sym_ntop_unname)
+#define inet_nsap_ntoa_tmpbuf (mtctxres->inet_nsap_ntoa_tmpbuf)
+#define p_option_nbuf (mtctxres->p_option_nbuf)
+#define p_time_nbuf (mtctxres->p_time_nbuf)
+#define precsize_ntoa_retbuf (mtctxres->precsize_ntoa_retbuf)
+#define loc_ntoa_tmpbuf (mtctxres->loc_ntoa_tmpbuf)
+#define p_secstodate_output (mtctxres->p_secstodate_output)
+
+#endif /* SUNW_MT_RESOLVER */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RESOLV_MT_H */
diff --git a/usr/src/lib/libresolv2/include/sunw_dst_init.h b/usr/src/lib/libresolv2/include/sunw_dst_init.h
new file mode 100644
index 0000000000..72a93e3d70
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/sunw_dst_init.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef _SUNW_DST_INIT_H
+#define _SUNW_DST_INIT_H
+
+extern int sunw_dst_bsafe_init(void);
+extern int sunw_dst_rsaref_init(void);
+extern int sunw_dst_hmac_md5_init(void);
+extern int sunw_dst_eay_dss_init(void);
+extern int sunw_dst_cylink_init(void);
+
+#ifndef __SUNW_DST_INIT_NODEFINE
+
+#define dst_bsafe_init sunw_dst_bsafe_init
+#define dst_rsaref_init sunw_dst_rsaref_init
+#define dst_hmac_md5_init sunw_dst_hmac_md5_init
+#define dst_eay_dss_init sunw_dst_eay_dss_init
+#define dst_cylink_init sunw_dst_cylink_init
+
+#endif /* __SUNW_DST_INIT_NODEFINE */
+
+#endif /* _SUNW_DST_INIT_H */
diff --git a/usr/src/lib/libresolv2/include/sunw_irs_init.h b/usr/src/lib/libresolv2/include/sunw_irs_init.h
new file mode 100644
index 0000000000..d249a0f7e6
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/sunw_irs_init.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef _SUNW_IRS_INIT_H
+#define _SUNW_IRS_INIT_H
+
+extern struct irs_acc *sunw_irs_nis_acc(const char *);
+extern struct irs_acc *sunw_irs_irp_acc(const char *);
+
+#ifndef __SUNW_IRS_INIT_NODEFINE
+
+#define __irs_nis_acc sunw_irs_nis_acc
+#define __irs_irp_acc sunw_irs_irp_acc
+
+#endif /* __SUNW_IRS_INIT_NODEFINE */
+
+#endif /* _SUNW_IRS_INIT_H */
diff --git a/usr/src/lib/libresolv2/include/synonyms.h b/usr/src/lib/libresolv2/include/synonyms.h
new file mode 100644
index 0000000000..a1a17fb7d4
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/synonyms.h
@@ -0,0 +1,564 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+#ifndef _SYNONYMS_H
+#define _SYNONYMS_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__STDC__)
+
+/* external data */
+#define altzone _altzone
+#define daylight _daylight
+#define lone _lone
+#define lten _lten
+#define lzero _lzero
+#define timezone _timezone
+#define tzname _tzname
+
+/* functions */
+#define Msgdb _Msgdb
+#define a64l _a64l
+#define access _access
+#define acct _acct
+#define acl _acl
+#define addseverity _addseverity
+#define adjtime _adjtime
+#define alarm _alarm
+#define ascftime _ascftime
+#define basename _basename
+#define brk _brk
+#define brkbase _brkbase
+#define bsd_signal _bsd_signal
+#define catclose _catclose
+#define catgets _catgets
+#define catopen _catopen
+#define cfgetispeed _cfgetispeed
+#define cfgetospeed _cfgetospeed
+#define cfree _cfree
+#define cfsetispeed _cfsetispeed
+#define cfsetospeed _cfsetospeed
+#define cftime _cftime
+#define chdir _chdir
+#define chmod _chmod
+#define chown _chown
+#define chroot _chroot
+#define close _close
+#define closedir _closedir
+#define closelog _closelog
+#define countbase _countbase
+#define creat _creat
+#define crypt _crypt
+#define ctermid _ctermid
+#define cuserid _cuserid
+#define dial _dial
+#define dirname _dirname
+#define door_bind _door_bind
+#define door_call _door_call
+#define door_create _door_create
+#define door_cred _door_cred
+#define door_getparam _door_getparam
+#define door_info _door_info
+#define door_return _door_return
+#define door_revoke _door_revoke
+#define door_setparam _door_setparam
+#define door_server_create _door_server_create
+#define door_ucred _door_ucred
+#define door_unbind _door_unbind
+#define drand48 _drand48
+#define dup _dup
+#define dup2 _dup2
+#define ecvt _ecvt
+#define edata _edata
+#define encrypt _encrypt
+#define end _end
+#define endgrent _endgrent
+#define endpwent _endpwent
+#define endspent _endspent
+#define endutent _endutent
+#define endutxent _endutxent
+#define environ _environ
+#define erand48 _erand48
+#define etext _etext
+#define execl _execl
+#define execle _execle
+#define execlp _execlp
+#define execv _execv
+#define execve _execve
+#define execvp _execvp
+#define exportfs _exportfs
+#define facl _facl
+#define fattach _fattach
+#define fchdir _fchdir
+#define fchmod _fchmod
+#define fchown _fchown
+#define fchroot _fchroot
+#define fcntl _fcntl
+#define fcvt _fcvt
+#define fdetach _fdetach
+#define fdopen _fdopen
+#define ffs _ffs
+#define fgetgrent _fgetgrent
+#define fgetgrent_r _fgetgrent_r
+#define fgetpwent _fgetpwent
+#define fgetpwent_r _fgetpwent_r
+#define fgetspent _fgetspent
+#define fgetspent_r _fgetspent_r
+#define finite _finite
+#define fmtmsg _fmtmsg
+#define fork _fork
+#define fork1 _fork1
+#define fpathconf _fpathconf
+#define fpclass _fpclass
+#define fpgetmask _fpgetmask
+#define fpgetround _fpgetround
+#define fpgetsticky _fpgetsticky
+#define fprintf _fprintf
+#define fpsetmask _fpsetmask
+#define fpsetround _fpsetround
+#define fpsetsticky _fpsetsticky
+#define fstat _fstat
+#define fstatfs _fstatfs
+#define fstatvfs _fstatvfs
+#define fsync _fsync
+/* #define ftell _ftell */
+#define ftello _ftello
+/* #define fseek _fseek */
+#define fseeko _fseeko
+#define ftok _ftok
+#define ftruncate _ftruncate
+#define gcvt _gcvt
+#define getcontext _getcontext
+#define getcwd _getcwd
+#define getdate _getdate
+#if !defined(_REENTRANT)
+#define getdate_err _getdate_err
+#else /* defined(_REENTRANT) */
+#define _getdate_err getdate_err
+#endif /* !defined(_REENTRANT) */
+#define getdents _getdents
+#define getegid _getegid
+#define geteuid _geteuid
+#define getgid _getgid
+#define getgrent _getgrent
+#define getgrent_r _getgrent_r
+#define getgrgid _getgrgid
+#define getgrgid_r _getgrgid_r
+#define getgrnam _getgrnam
+#define getgrnam_r _getgrnam_r
+#define getgroups _getgroups
+#define gethz _gethz
+#define getitimer _getitimer
+#define getlogin _getlogin
+#define getmntany _getmntany
+#define getmntent _getmntent
+#define getmsg _getmsg
+#define getopt _getopt
+#define getpass _getpass
+#define getpassphrase _getpassphrase
+#define getpgid _getpgid
+#define getpgrp _getpgrp
+#define getpid _getpid
+#define getpmsg _getpmsg
+#define getppid _getppid
+#define getpw _getpw
+#define getpwent _getpwent
+#define getpwent_r _getpwent_r
+#define getpwnam _getpwnam
+#define getpwnam_r _getpwnam_r
+#define getpwuid _getpwuid
+#define getpwuid_r _getpwuid_r
+#define getrlimit _getrlimit
+#define getsid _getsid
+#define getspent _getspent
+#define getspent_r _getspent_r
+#define getspnam _getspnam
+#define getspnam_r _getspnam_r
+#define getsubopt _getsubopt
+#define gettimeofday _gettimeofday
+#define gettxt _gettxt
+#define getuid _getuid
+#define getutent _getutent
+#define getutid _getutid
+#define getutline _getutline
+#define getutmp _getutmp
+#define getutmpx _getutmpx
+#define getutxent _getutxent
+#define getutxid _getutxid
+#define getutxline _getutxline
+#define getvfsany _getvfsany
+#define getvfsent _getvfsent
+#define getvfsfile _getvfsfile
+#define getvfsspec _getvfsspec
+#define getw _getw
+#define grantpt _grantpt
+#define gsignal _gsignal
+#define gtty _gtty
+#define hasmntopt _hasmntopt
+#define hcreate _hcreate
+#define hdestroy _hdestroy
+#define hsearch _hsearch
+#define id2str _id2str
+#define initgroups _initgroups
+#define insque _insque
+#define install_utrap _install_utrap
+#define ioctl _ioctl
+#define isastream _isastream
+#define isatty _isatty
+#define jrand48 _jrand48
+#define kaio _kaio
+#define kill _kill
+#define l64a _l64a
+#define ladd _ladd
+#define lchown _lchown
+#define lckpwdf _lckpwdf
+#define lcong48 _lcong48
+#define ldivide _ldivide
+#define lexp10 _lexp10
+#define lfind _lfind
+#define link _link
+#define llog10 _llog10
+#define llseek _llseek
+#define lmul _lmul
+#define lockf _lockf
+#define longjmp _longjmp
+#define lrand48 _lrand48
+#define lsearch _lsearch
+#define lseek _lseek
+#define lshiftl _lshiftl
+#define lsign _lsign
+#define lstat _lstat
+#define lsub _lsub
+#define ltol3 _ltol3
+#define madvise _madvise
+#define makecontext _makecontext
+#define makeut _makeut
+#define makeutx _makeutx
+#define memalign _memalign
+#define memccpy _memccpy
+#define memcntl _memcntl
+#define memcmp _memcmp
+#define memcpy _memcpy
+#define memmove _memmove
+#define memset _memset
+#define mincore _mincore
+#define mkdir _mkdir
+#define mkfifo _mkfifo
+#define mknod _mknod
+#define mktemp _mktemp
+#define mkstemp _mkstemp
+#define mlock _mlock
+#define mlockall _mlockall
+#define mmap _mmap
+#define modut _modut
+#define modutx _modutx
+#define monitor _monitor
+#define mount _mount
+#define mprotect _mprotect
+#define mrand48 _mrand48
+#define msgctl _msgctl
+#define msgget _msgget
+#define msgrcv _msgrcv
+#define msgsnd _msgsnd
+#define msync _msync
+#define munlock _munlock
+#define munlockall _munlockall
+#define munmap _munmap
+#define nfs_getfh _nfs_getfh
+#define nfssvc _nfssvc
+#define nftw _nftw
+#define nice _nice
+#define nrand48 _nrand48
+#define nss_delete _nss_delete
+#define nss_endent _nss_endent
+#define nss_getent _nss_getent
+#define nss_search _nss_search
+#define nss_setent _nss_setent
+#define open _open
+#define opendir _opendir
+#define openlog _openlog
+#define pathconf _pathconf
+#define pause _pause
+#define pclose _pclose
+#define pipe _pipe
+#define plock _plock
+#define poll _poll
+#define popen _popen
+#define pread _pread
+#define pset_create _pset_create
+#define pset_destroy _pset_destroy
+#define pset_assign _pset_assign
+#define pset_info _pset_info
+#define pset_bind _pset_bind
+#define profil _profil
+#define psiginfo _psiginfo
+#define psignal _psignal
+#define ptrace _ptrace
+#define ptsname _ptsname
+#define pwrite _pwrite
+#define putenv _putenv
+#define putmsg _putmsg
+#define putpmsg _putpmsg
+#define putpwent _putpwent
+#define putspent _putspent
+#define pututline _pututline
+#define pututxline _pututxline
+#define putw _putw
+#define read _read
+#define readdir _readdir
+#define readdir_r _readdir_r
+#define readlink _readlink
+#define readv _readv
+#define realpath _realpath
+#define regcmp _regcmp
+#define regex _regex
+#define remque _remque
+#define rmdir _rmdir
+#define sbrk _sbrk
+#define seed48 _seed48
+#define seekdir _seekdir
+#define select _select
+#define semctl _semctl
+#define semget _semget
+#define semop _semop
+#define setcontext _setcontext
+#define setegid _setegid
+#define seteuid _seteuid
+#define setgid _setgid
+#define setgrent _setgrent
+#define setgroups _setgroups
+#define setitimer _setitimer
+#define setjmp _setjmp
+#define setkey _setkey
+#define setlocale _setlocale
+#define setlogmask _setlogmask
+#define setpgid _setpgid
+#define setpgrp _setpgrp
+#define setpwent _setpwent
+#define setregid _setregid
+#define setreuid _setreuid
+#define setrlimit _setrlimit
+#define setsid _setsid
+#define setspent _setspent
+#define settimeofday _settimeofday
+#define setuid _setuid
+#define setutent _setutent
+#define setutxent _setutxent
+#define shmat _shmat
+#define shmctl _shmctl
+#define shmdt _shmdt
+#define shmget _shmget
+#define sig2str _sig2str
+#define sigaction _sigaction
+#define sigaddset _sigaddset
+#define sigaltstack _sigaltstack
+#define sigdelset _sigdelset
+#define sigemptyset _sigemptyset
+#define sigfillset _sigfillset
+#define sigflag _sigflag
+#define sigfpe _sigfpe
+#define sighold _sighold
+#define sigignore _sigignore
+#define siginterrupt _siginterrupt
+#define sigismember _sigismember
+#define siglongjmp _siglongjmp
+#define sigpause _sigpause
+#define sigpending _sigpending
+#define sigprocmask _sigprocmask
+#define sigrelse _sigrelse
+#define sigsend _sigsend
+#define sigsendset _sigsendset
+#define sigset _sigset
+#define signal _signal
+#define sigsetjmp _sigsetjmp
+#define sigsuspend _sigsuspend
+#define sigwait _sigwait
+#define sleep _sleep
+#define srand48 _srand48
+#define ssignal _ssignal
+#define stat _stat
+#define statfs _statfs
+#define statvfs _statvfs
+#define stime _stime
+#define str2id _str2id
+#define str2sig _str2sig
+#define strdup _strdup
+#define stty _stty
+#define swab _swab
+#define swapcontext _swapcontext
+#define swapctl _swapctl
+#define symlink _symlink
+#define sync _sync
+#define synchutmp _synchutmp
+#if defined(__ppc)
+#define sysppc _sysppc
+#else
+#define syssun _syssun
+#endif
+#define sys_errlist _sys_errlist
+#define sys_nerr _sys_nerr
+#define syscall _syscall
+#define sysconf _sysconf
+#define sysfs _sysfs
+#define sysinfo _sysinfo
+#define syslog _syslog
+#define tcdrain _tcdrain
+#define tcflow _tcflow
+#define tcflush _tcflush
+#define tcgetattr _tcgetattr
+#define tcgetpgrp _tcgetpgrp
+#define tcgetsid _tcgetsid
+#define tcsendbreak _tcsendbreak
+#define tcsetattr _tcsetattr
+#define tcsetpgrp _tcsetpgrp
+#define tdelete _tdelete
+#define tell _tell
+#define telldir _telldir
+#define tempnam _tempnam
+#define tfind _tfind
+#define time _time
+#define times _times
+#define truncate _truncate
+#define tsearch _tsearch
+#define ttyname _ttyname
+#define ttyslot _ttyslot
+#define twalk _twalk
+#define tzname _tzname
+#define tzset _tzset
+#define uadmin _uadmin
+#define ulckpwdf _ulckpwdf
+#define ulimit _ulimit
+#define umask _umask
+#define umount _umount
+#define uname _uname
+#define undial _undial
+#define unlink _unlink
+#define unlockpt _unlockpt
+#define unordered _unordered
+#define updutfile _updutfile
+#define updutxfile _updutxfile
+#define updutmp _updutmp
+#define updutmpx _updutmpx
+#define updwtmp _updwtmp
+#define updwtmpx _updwtmpx
+#define ustat _ustat
+#define utime _utime
+#define utimes _utimes
+#define utmpname _utmpname
+#define utmpxname _utmpxname
+#define utssys _utssys
+#define valloc _valloc
+#define vfork _vfork
+#define vhangup _vhangup
+#define vsyslog _vsyslog
+#define wait _wait
+#define waitid _waitid
+#define waitpid _waitpid
+#define write _write
+#define writev _writev
+#define yield _yield
+#define _assert __assert
+#define _ctype __ctype
+#define _filbuf __filbuf
+#define _flsbuf __flsbuf
+#define _iob __iob
+
+/* fp and ll functions */
+#define decimal_to_double _decimal_to_double
+#define decimal_to_extended _decimal_to_extended
+#define decimal_to_quadruple _decimal_to_quadruple
+#define decimal_to_single _decimal_to_single
+#define double_to_decimal _double_to_decimal
+#define econvert _econvert
+#define extended_to_decimal _extended_to_decimal
+#define fconvert _fconvert
+#define file_to_decimal _file_to_decimal
+#define func_to_decimal _func_to_decimal
+#define gconvert _gconvert
+#define qeconvert _qeconvert
+#define qecvt _qecvt
+#define qfconvert _qfconvert
+#define qfcvt _qfcvt
+#define qgconvert _qgconvert
+#define qgcvt _qgcvt
+#define quadruple_to_decimal _quadruple_to_decimal
+#define seconvert _seconvert
+#define sfconvert _sfconvert
+#define sgconvert _sgconvert
+#define single_to_decimal _single_to_decimal
+#define string_to_decimal _string_to_decimal
+#define atoll _atoll
+#define llabs _llabs
+#define lldiv _lldiv
+#define lltostr _lltostr
+#define strtoll _strtoll
+#define strtoull _strtoull
+#define ulltostr _ulltostr
+
+#if !defined(_LP64)
+/* transitional large file interfaces */
+#define creat64 _creat64
+#define ftello64 _ftello64
+#define fseeko64 _fseeko64
+#define fstat64 _fstat64
+#define ftw64 _ftw64
+#define fstatvfs64 _fstatvfs64
+#define ftruncate64 _ftruncate64
+#define getdents64 _getdents64
+#define getrlimit64 _getrlimit64
+#define lockf64 _lockf64
+#define lseek64 _lseek64
+#define lstat64 _lstat64
+#define mkstemp64 _mkstemp64
+#define mmap64 _mmap64
+#define nftw64 _nftw64
+#define open64 _open64
+#define pread64 _pread64
+#define pwrite64 _pwrite64
+#define readdir64 _readdir64
+#define readdir64_r _readdir64_r
+#define seekdir64 _seekdir64
+#define telldir64 _telldir64
+#define setrlimit64 _setrlimit64
+#define stat64 _stat64
+#define statvfs64 _statvfs64
+#define truncate64 _truncate64
+#endif /* !_LP64 */
+
+#define thr_setspecific _thr_setspecific
+#define thr_getspecific _thr_getspecific
+#define thr_keycreate _thr_keycreate
+
+#ifdef SUNW_LIBNSL
+#define inet_aton _inet_aton
+#endif
+
+#else /* !defined(__STDC__) */
+
+#if !defined(_ASM)
+#define const
+
+#if !defined(_SIZE_T)
+#define _SIZE_T
+typedef unsigned int size_t;
+#endif /* !defined(_SIZE_T) */
+#endif /* !defined(_ASM) */
+
+#endif /* defined(__STDC__) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYNONYMS_H */
diff --git a/usr/src/lib/libresolv2/include/sys/bitypes.h b/usr/src/lib/libresolv2/include/sys/bitypes.h
new file mode 100644
index 0000000000..5228129f3b
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/sys/bitypes.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef __BIT_TYPES_DEFINED__
+#define __BIT_TYPES_DEFINED__
+
+ /*
+ * Basic integral types. Omit the typedef if
+ * not possible for a machine/compiler combination.
+ */
+#ifndef _SYS_INT_TYPES_H
+ typedef /*signed*/ char int8_t;
+ typedef short int16_t;
+ typedef int int32_t;
+#endif /* _SYS_INT_TYPES_H */
+ typedef unsigned char u_int8_t;
+ typedef unsigned short u_int16_t;
+ typedef unsigned int u_int32_t;
+
+# if 0 /* don't fight with these unless you need them */
+ typedef long long int64_t;
+ typedef unsigned long long u_int64_t;
+# endif
+
+#endif /* __BIT_TYPES_DEFINED__ */
diff --git a/usr/src/lib/libresolv2/include/sys/cdefs.h b/usr/src/lib/libresolv2/include/sys/cdefs.h
new file mode 100644
index 0000000000..9738c69582
--- /dev/null
+++ b/usr/src/lib/libresolv2/include/sys/cdefs.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * ++Copyright++ 1991, 1993
+ * -
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * 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--
+ */
+
+/*
+ * @(#)cdefs.h 8.1 (Berkeley) 6/2/93
+ * $Id: cdefs.h,v 1.1 1996/11/22 02:20:19 vixie Exp $
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef _CDEFS_H_
+#define _CDEFS_H_
+
+#if defined(__cplusplus)
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS };
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+
+/*
+ * The __CONCAT macro is used to concatenate parts of symbol names, e.g.
+ * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
+ * The __CONCAT macro is a bit tricky -- make sure you don't put spaces
+ * in between its arguments. __CONCAT can also concatenate double-quoted
+ * strings produced by the __STRING macro, but this only works with ANSI C.
+ */
+#if defined(__STDC__) || defined(__cplusplus)
+#define __P(protos) protos /* full-blown ANSI C */
+#define __CONCAT(x,y) x ## y
+#define __STRING(x) #x
+
+#define __const const /* define reserved names to standard */
+#define __signed signed
+#define __volatile volatile
+#if defined(__cplusplus)
+#define __inline inline /* convert to C++ keyword */
+#else
+#ifndef __GNUC__
+#define __inline /* delete GCC keyword */
+#endif /* !__GNUC__ */
+#endif /* !__cplusplus */
+
+#else /* !(__STDC__ || __cplusplus) */
+#define __P(protos) () /* traditional C preprocessor */
+#define __CONCAT(x,y) x/**/y
+#define __STRING(x) "x"
+
+#ifndef __GNUC__
+#define __const /* delete pseudo-ANSI C keywords */
+#define __inline
+#define __signed
+#define __volatile
+/*
+ * In non-ANSI C environments, new programs will want ANSI-only C keywords
+ * deleted from the program and old programs will want them left alone.
+ * When using a compiler other than gcc, programs using the ANSI C keywords
+ * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
+ * When using "gcc -traditional", we assume that this is the intent; if
+ * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
+ */
+#ifndef NO_ANSI_KEYWORDS
+#define const /* delete ANSI C keywords */
+#define inline
+#define signed
+#define volatile
+#endif
+#endif /* !__GNUC__ */
+#endif /* !(__STDC__ || __cplusplus) */
+
+/*
+ * GCC1 and some versions of GCC2 declare dead (non-returning) and
+ * pure (no side effects) functions using "volatile" and "const";
+ * unfortunately, these then cause warnings under "-ansi -pedantic".
+ * GCC2 uses a new, peculiar __attribute__((attrs)) style. All of
+ * these work for GNU C++ (modulo a slight glitch in the C++ grammar
+ * in the distribution version of 2.5.5).
+ */
+#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC_MINOR__ < 5
+#define __attribute__(x) /* delete __attribute__ if non-gcc or gcc1 */
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+#define __dead __volatile
+#define __pure __const
+#endif
+#endif
+
+/* Delete pseudo-keywords wherever they are not available or needed. */
+#ifndef __dead
+#define __dead
+#define __pure
+#endif
+
+#endif /* !_CDEFS_H_ */
diff --git a/usr/src/lib/libresolv2/irs/Makefile b/usr/src/lib/libresolv2/irs/Makefile
new file mode 100644
index 0000000000..42a540092b
--- /dev/null
+++ b/usr/src/lib/libresolv2/irs/Makefile
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/irs/Makefile
+
+include ../../../Makefile.master
+include ../../Makefile.lib
+
+SUBDIRS= spec $(MACH) $(BUILD64) $(MACH64)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+delete := TARGET= delete
+install := TARGET= install
+lint := TARGET= lint
+_msg := TARGET= _msg
+package := TARGET= package
+
+LIBRARY= irs.a
+TEXT_DOMAIN= SUNW_OST_OSLIB
+XGETFLAGS= -a
+POFILE= $(LIBRARY:.a=.po)
+POFILES= generic.po
+
+SED= sed
+GREP= grep
+CP= cp
+
+.KEEP_STATE:
+
+all clean clobber delete install lint package: $(SUBDIRS)
+
+# install rule for install_h target
+$(ROOTHDRDIR)/%: %
+ $(INS.file)
+
+install_h: $(ROOTHDRS)
+
+check: $(CHECKHDRS)
+
+$(MACH) $(MACH64) spec: FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+_msg: $(MSGDOMAIN) $(POFILE)
+ $(RM) $(MSGDOMAIN)/$(POFILE)
+ $(CP) $(POFILE) $(MSGDOMAIN)
+
+$(POFILE): $(POFILES)
+ $(RM) $@
+ $(CAT) $(POFILES) > $@
+
+$(POFILES):
+ $(RM) messages.po
+ $(XGETTEXT) $(XGETFLAGS) *.[ch]* */*.[ch]*
+ $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@
+ $(RM) messages.po
+
+FRC:
diff --git a/usr/src/lib/libresolv2/irs/Makefile.com b/usr/src/lib/libresolv2/irs/Makefile.com
new file mode 100644
index 0000000000..d99eb7f828
--- /dev/null
+++ b/usr/src/lib/libresolv2/irs/Makefile.com
@@ -0,0 +1,70 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/irs/Makefile.com
+#
+
+LIBRARY= irs.a
+VERS= .1
+
+IRSDYNOBJS= nis_nw.o nis_pr.o nis_pw.o nis_sv.o \
+ nis.o nis_gr.o nis_ho.o nis_ng.o \
+ irp.o irpmarshall.o irp_ho.o irp_nw.o \
+ irp_pr.o irp_sv.o irp_gr.o irp_ng.o \
+ irp_pw.o getnetent.o getpwent_r.o getgrent_r.o \
+ getservent_r.o getnetent_r.o getnetgrent_r.o getgrent.o \
+ getnetgrent.o getprotoent.o getpwent.o getservent.o \
+ getprotoent_r.o getnameinfo.o gai_strerror.o
+
+SUNWOBJS= sunw_irs_nis_acc.o
+
+OBJECTS= $(IRSDYNOBJS) $(SUNWOBJS)
+
+include ../../../Makefile.lib
+
+LIBNAME= $(LIBRARY:%.a=%)
+LIBS= $(DYNLIB)
+LDLIBS += -lresolv -lnsl -lsocket -lc
+
+MAPDIR = ../spec/$(TRANSMACH)
+SPECMAPFILE = $(MAPDIR)/mapfile
+SRCDIR= ../../common/irs
+SRCS= $(IRSDYNOBJS:%.$(SRCDIR)/%.c) \
+ $(SUNWOBJS:%.o=../../common/sunw/%.c)
+
+ROOTLIBDIR= $(ROOT)/usr/lib/dns
+ROOTLIBDIR64= $(ROOT)/usr/lib/dns/$(MACH64)
+
+# Local Libresolv definitions
+SOLCOMPAT = -Dgethostbyname=res_gethostbyname \
+ -Dgethostbyaddr=res_gethostbyaddr -Dgetnetbyname=res_getnetbyname \
+ -Dgethostbyname2=res_gethostbyname2\
+ -Dgetnetbyaddr=res_getnetbyaddr -Dsethostent=res_sethostent \
+ -Dendhostent=res_endhostent -Dgethostent=res_gethostent \
+ -Dsetnetent=res_setnetent -Dendnetent=res_endnetent \
+ -Dgetnetent=res_getnetent -Dsocket=_socket
+
+CRYPTINCL= -I../../common/cylink -I../../common/dnssafe
+CRYPTFLAGS= -DCYLINK_DSS -DHMAC_MD5 -DUSE_MD5 -DDNSSAFE
+
+CPPFLAGS += $(CRYPTFLAGS) $(CRYPTINCL)
+CPPFLAGS += -D_SYS_STREAM_H -D_REENTRANT -DSVR4 -DSUNW_OPTIONS \
+ -D__SUNW_IRS_INIT_NODEFINE $(SOLCOMPAT) -I../../include
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+$(ROOTLIBDIR) $(ROOTLIBDIR64):
+ $(INS.dir)
+
+include ../../../Makefile.targ
+
+pics/%.o: ../../common/sunw/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
diff --git a/usr/src/lib/libresolv2/irs/amd64/Makefile b/usr/src/lib/libresolv2/irs/amd64/Makefile
new file mode 100644
index 0000000000..2b37434e6b
--- /dev/null
+++ b/usr/src/lib/libresolv2/irs/amd64/Makefile
@@ -0,0 +1,15 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+MAPDIR= ../spec/amd64
+
+include ../Makefile.com
+include ../../../Makefile.lib.64
+
+all: $(LIBS)
+
+install: all $(ROOTLIBDIR64) .WAIT $(ROOTLIBS64)
diff --git a/usr/src/lib/libresolv2/irs/i386/Makefile b/usr/src/lib/libresolv2/irs/i386/Makefile
new file mode 100644
index 0000000000..009d72b5eb
--- /dev/null
+++ b/usr/src/lib/libresolv2/irs/i386/Makefile
@@ -0,0 +1,12 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/irs/i386/Makefile
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBDIR) .WAIT $(ROOTLIBS)
diff --git a/usr/src/lib/libresolv2/irs/sparc/Makefile b/usr/src/lib/libresolv2/irs/sparc/Makefile
new file mode 100644
index 0000000000..8dd442702e
--- /dev/null
+++ b/usr/src/lib/libresolv2/irs/sparc/Makefile
@@ -0,0 +1,12 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/irs/sparc/Makefile
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBDIR) .WAIT $(ROOTLIBS)
diff --git a/usr/src/lib/libresolv2/irs/sparcv9/Makefile b/usr/src/lib/libresolv2/irs/sparcv9/Makefile
new file mode 100644
index 0000000000..51ec6b8a9d
--- /dev/null
+++ b/usr/src/lib/libresolv2/irs/sparcv9/Makefile
@@ -0,0 +1,13 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/irs/sparcv9/Makefile
+#
+
+include ../Makefile.com
+include ../../../Makefile.lib.64
+
+install: all $(ROOTLIBDIR64) .WAIT $(ROOTLIBS64)
diff --git a/usr/src/lib/libresolv2/irs/spec/Makefile b/usr/src/lib/libresolv2/irs/spec/Makefile
new file mode 100644
index 0000000000..1928a002a5
--- /dev/null
+++ b/usr/src/lib/libresolv2/irs/spec/Makefile
@@ -0,0 +1,8 @@
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/irs/spec/Makefile
+
+include $(SRC)/lib/Makefile.spec.arch
diff --git a/usr/src/lib/libresolv2/irs/spec/Makefile.targ b/usr/src/lib/libresolv2/irs/spec/Makefile.targ
new file mode 100644
index 0000000000..fe57106695
--- /dev/null
+++ b/usr/src/lib/libresolv2/irs/spec/Makefile.targ
@@ -0,0 +1,12 @@
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/irs/spec/Makefile.targ
+
+LIBRARY = irs.a
+VERS = .1
+
+OBJECTS = irs.o
+
diff --git a/usr/src/lib/libresolv2/irs/spec/amd64/Makefile b/usr/src/lib/libresolv2/irs/spec/amd64/Makefile
new file mode 100644
index 0000000000..84ccf3ca89
--- /dev/null
+++ b/usr/src/lib/libresolv2/irs/spec/amd64/Makefile
@@ -0,0 +1,26 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+
+# Uncomment the following if the linker complains
+#amd64_C_PICFLAGS = $(amd64_C_BIGPICFLAGS)
+
+include $(SRC)/lib/Makefile.spec
+
+# No public interface, so don't install spec libraries in the proto area
+INS.abilib=
+
+install: $(ROOTABILIB64)
diff --git a/usr/src/lib/libresolv2/irs/spec/i386/Makefile b/usr/src/lib/libresolv2/irs/spec/i386/Makefile
new file mode 100644
index 0000000000..b399d8191c
--- /dev/null
+++ b/usr/src/lib/libresolv2/irs/spec/i386/Makefile
@@ -0,0 +1,26 @@
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/irs/spec/i386/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+
+# Uncomment the following if the linker complains
+#sparc_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+# No public interface, so don't install spec libraries in the proto area
+INS.abilib=
+
+install: $(ROOTABILIB)
diff --git a/usr/src/lib/libresolv2/irs/spec/irs.spec b/usr/src/lib/libresolv2/irs/spec/irs.spec
new file mode 100644
index 0000000000..9b08d54093
--- /dev/null
+++ b/usr/src/lib/libresolv2/irs/spec/irs.spec
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/irs/spec/irs.spec
+
+function __irs_nis_acc
+version SUNWprivate_1.1
+end
+
+function __irs_irp_acc
+version SUNWprivate_1.1
+end
diff --git a/usr/src/lib/libresolv2/irs/spec/sparc/Makefile b/usr/src/lib/libresolv2/irs/spec/sparc/Makefile
new file mode 100644
index 0000000000..0440fdd8c6
--- /dev/null
+++ b/usr/src/lib/libresolv2/irs/spec/sparc/Makefile
@@ -0,0 +1,26 @@
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/irs/spec/sparc/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+
+# Uncomment the following if the linker complains
+#sparc_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+# No public interface, so don't install spec libraries in the proto area
+INS.abilib=
+
+install: $(ROOTABILIB)
diff --git a/usr/src/lib/libresolv2/irs/spec/sparcv9/Makefile b/usr/src/lib/libresolv2/irs/spec/sparcv9/Makefile
new file mode 100644
index 0000000000..63a2917247
--- /dev/null
+++ b/usr/src/lib/libresolv2/irs/spec/sparcv9/Makefile
@@ -0,0 +1,27 @@
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/irs/spec/sparcv9/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+
+# Uncomment the following if the linker complains
+#sparcv9_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+# No public interface, so don't install spec libraries in the proto area
+INS.abilib=
+
+install: $(ROOTABILIB64)
diff --git a/usr/src/lib/libresolv2/irs/spec/versions b/usr/src/lib/libresolv2/irs/spec/versions
new file mode 100644
index 0000000000..6a318d48a3
--- /dev/null
+++ b/usr/src/lib/libresolv2/irs/spec/versions
@@ -0,0 +1,19 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+sparc {
+ SUNWprivate_1.1;
+}
+sparcv9 {
+ SUNWprivate_1.1;
+}
+i386 {
+ SUNWprivate_1.1;
+}
+amd64 {
+ SUNWprivate_1.1;
+}
diff --git a/usr/src/lib/libresolv2/req.flg b/usr/src/lib/libresolv2/req.flg
new file mode 100644
index 0000000000..9ca59f35c3
--- /dev/null
+++ b/usr/src/lib/libresolv2/req.flg
@@ -0,0 +1,9 @@
+#!/bin/sh
+#
+# Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+echo_file usr/src/lib/libnsl/include/nsl_stdio_prv.h
diff --git a/usr/src/lib/libresolv2/sparc/Makefile b/usr/src/lib/libresolv2/sparc/Makefile
new file mode 100644
index 0000000000..490d924db5
--- /dev/null
+++ b/usr/src/lib/libresolv2/sparc/Makefile
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 1997-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/sparc/Makefile
+
+MAPDIR= ../spec/sparc
+
+include ../Makefile.com
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libresolv2/sparcv9/Makefile b/usr/src/lib/libresolv2/sparcv9/Makefile
new file mode 100644
index 0000000000..72aa5e4563
--- /dev/null
+++ b/usr/src/lib/libresolv2/sparcv9/Makefile
@@ -0,0 +1,27 @@
+#
+# Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/sparcv9/Makefile
+
+MAPDIR= ../spec/sparcv9
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+# With the adition of BIND 8.3.3, the symbol table for 64 bit went over
+# the limit for Kpic, so we've added -KPIC here, for just the 64 bit
+# library. This avoids compiling the 32-bit library with PIC unnecessarily.
+
+sparcv9_C_PICFLAGS = -K PIC
+sparcv9_CC_PICFLAGS = -KPIC
+
+LIBS = $(DYNLIB) $(LINTLIB)
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/libresolv2/spec/Makefile b/usr/src/lib/libresolv2/spec/Makefile
new file mode 100644
index 0000000000..bc844c2654
--- /dev/null
+++ b/usr/src/lib/libresolv2/spec/Makefile
@@ -0,0 +1,8 @@
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1998-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/spec/Makefile
+
+include $(SRC)/lib/Makefile.spec.arch
diff --git a/usr/src/lib/libresolv2/spec/Makefile.targ b/usr/src/lib/libresolv2/spec/Makefile.targ
new file mode 100644
index 0000000000..16385fb51f
--- /dev/null
+++ b/usr/src/lib/libresolv2/spec/Makefile.targ
@@ -0,0 +1,12 @@
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1998-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/spec/Makefile.targ
+
+LIBRARY = libresolv.a
+VERS = .2
+
+OBJECTS = resolv2.o
+
diff --git a/usr/src/lib/libresolv2/spec/amd64/Makefile b/usr/src/lib/libresolv2/spec/amd64/Makefile
new file mode 100644
index 0000000000..96bda57a49
--- /dev/null
+++ b/usr/src/lib/libresolv2/spec/amd64/Makefile
@@ -0,0 +1,23 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+
+# Uncomment the following if the linker complains
+#amd64_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB64)
diff --git a/usr/src/lib/libresolv2/spec/i386/Makefile b/usr/src/lib/libresolv2/spec/i386/Makefile
new file mode 100644
index 0000000000..9d0faf35d0
--- /dev/null
+++ b/usr/src/lib/libresolv2/spec/i386/Makefile
@@ -0,0 +1,23 @@
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1998-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/spec/i386/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+
+# Uncomment the following if the linker complains
+#i386_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB)
diff --git a/usr/src/lib/libresolv2/spec/resolv2.spec b/usr/src/lib/libresolv2/spec/resolv2.spec
new file mode 100644
index 0000000000..ef489c41ff
--- /dev/null
+++ b/usr/src/lib/libresolv2/spec/resolv2.spec
@@ -0,0 +1,1096 @@
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libresolv2/spec/resolv2.spec
+
+function b64_ntop
+version SUNWprivate_2.1
+end
+
+function __b64_ntop
+version SUNWprivate_2.1
+end
+
+function b64_pton
+version SUNWprivate_2.1
+end
+
+function __b64_pton
+version SUNWprivate_2.1
+end
+
+function dn_count_labels
+version SUNWprivate_2.1
+end
+
+function __dn_count_labels
+version SUNWprivate_2.1
+end
+
+function dn_skipname
+version SUNWprivate_2.1
+end
+
+function __dn_skipname
+version SUNW_2.1
+end
+
+function __evAddTime
+version SUNWprivate_2.1
+end
+
+function __evCancelConn
+version SUNWprivate_2.1
+end
+
+function __evCancelRW
+version SUNWprivate_2.1
+end
+
+function __evClearTimer
+version SUNWprivate_2.1
+end
+
+function __evConnect
+version SUNWprivate_2.1
+end
+
+function __evConsIovec
+version SUNWprivate_2.1
+end
+
+function __evConsTime
+version SUNWprivate_2.1
+end
+
+function __evCreate
+version SUNWprivate_2.1
+end
+
+function __evDeselectFD
+version SUNWprivate_2.1
+end
+
+function __evDispatch
+version SUNWprivate_2.1
+end
+
+function __evDo
+version SUNWprivate_2.1
+end
+
+function __evGetNext
+version SUNWprivate_2.1
+end
+
+function __evListen
+version SUNWprivate_2.1
+end
+
+function __evNowTime
+version SUNWprivate_2.1
+end
+
+function __evRead
+version SUNWprivate_2.1
+end
+
+function __evResetTimer
+version SUNWprivate_2.1
+end
+
+function __evSelectFD
+version SUNWprivate_2.1
+end
+
+function __evSetDebug
+version SUNWprivate_2.1
+end
+
+function __evSetTimer
+version SUNWprivate_2.1
+end
+
+function __evWaitFor
+version SUNWprivate_2.1
+end
+
+function fp_nquery
+version SUNWprivate_2.1
+end
+
+function __fp_nquery
+version SUNWprivate_2.1
+end
+
+function fp_query
+version SUNWprivate_2.1
+end
+
+function __fp_query
+version SUNW_2.1
+end
+
+function fp_resstat
+version SUNW_2.2
+end
+
+function __fp_resstat
+version SUNWprivate_2.1
+end
+
+function __hostalias
+version SUNW_2.1
+end
+
+function res_hostalias
+version SUNW_2.2
+end
+
+function hostalias
+version SUNWprivate_2.1
+end
+
+function loc_aton
+version SUNWprivate_2.1
+end
+
+function __loc_aton
+version SUNWprivate_2.1
+end
+
+function loc_ntoa
+version SUNWprivate_2.1
+end
+
+function __loc_ntoa
+version SUNWprivate_2.1
+end
+
+function __log_add_channel
+version SUNWprivate_2.1
+end
+
+function __log_category_is_active
+version SUNWprivate_2.1
+end
+
+function __log_close_stream
+version SUNWprivate_2.1
+end
+
+function __log_free_context
+version SUNWprivate_2.1
+end
+
+function __log_get_stream
+version SUNWprivate_2.1
+end
+
+function __log_inc_references
+version SUNWprivate_2.1
+end
+
+function __log_new_context
+version SUNWprivate_2.1
+end
+
+function __log_new_file_channel
+version SUNWprivate_2.1
+end
+
+function __log_new_null_channel
+version SUNWprivate_2.1
+end
+
+function __log_set_file_owner
+version SUNWprivate_2.1
+end
+
+function __log_new_syslog_channel
+version SUNWprivate_2.1
+end
+
+function __log_open_stream
+version SUNWprivate_2.1
+end
+
+function __log_option
+version SUNWprivate_2.1
+end
+
+function __log_vwrite
+version SUNWprivate_2.1
+end
+
+function __log_write
+version SUNWprivate_2.1
+end
+
+function __ns_get16
+version SUNWprivate_2.1
+end
+
+function __ns_get32
+version SUNWprivate_2.1
+end
+
+function __ns_initparse
+version SUNWprivate_2.1
+end
+
+function __ns_name_ntop
+version SUNWprivate_2.1
+end
+
+function __ns_name_pton
+version SUNWprivate_2.1
+end
+
+function __ns_name_rollback
+version SUNWprivate_2.1
+end
+
+function __ns_name_unpack
+version SUNWprivate_2.1
+end
+
+function __ns_parse_ttl
+version SUNWprivate_2.1
+end
+
+function __ns_parserr
+version SUNWprivate_2.1
+end
+
+function __ns_put16
+version SUNWprivate_2.1
+end
+
+function __ns_sprintrr
+version SUNWprivate_2.1
+end
+
+function __ns_sprintrrf
+version SUNWprivate_2.1
+end
+
+function p_cdname
+version SUNWprivate_2.1
+end
+
+function __p_cdname
+version SUNW_2.1
+end
+
+function p_class
+version SUNWprivate_2.1
+end
+
+function __p_class
+version SUNW_2.1
+end
+
+function __p_class_syms
+version SUNWprivate_2.1
+end
+
+function __p_query
+version SUNW_2.1
+end
+
+function p_secstodate
+version SUNWprivate_2.1
+end
+
+function __p_secstodate
+version SUNWprivate_2.1
+end
+
+function p_section
+version SUNWprivate_2.1
+end
+
+function __p_section
+version SUNWprivate_2.1
+end
+
+function p_time
+version SUNWprivate_2.1
+end
+
+function __p_time
+version SUNW_2.1
+end
+
+function p_type
+version SUNWprivate_2.1
+end
+
+function __p_type
+version SUNW_2.1
+end
+
+function __p_type_syms
+version SUNWprivate_2.1
+end
+
+function p_fqnname
+version SUNWprivate_2.1
+end
+
+function putlong
+version SUNWprivate_2.1
+end
+
+function __putlong
+version SUNW_2.1
+end
+
+function putshort
+version SUNWprivate_2.1
+end
+
+function __putshort
+version SUNWprivate_2.1
+end
+
+function res_dnok
+version SUNWprivate_2.1
+end
+
+function __res_dnok
+version SUNWprivate_2.1
+end
+
+function res_hnok
+version SUNWprivate_2.1
+end
+
+function __res_hnok
+version SUNWprivate_2.1
+end
+
+function res_mailok
+version SUNWprivate_2.1
+end
+
+function __res_mailok
+version SUNWprivate_2.1
+end
+
+function res_nameinquery
+version SUNWprivate_2.1
+end
+
+function __res_nameinquery
+version SUNWprivate_2.1
+end
+
+function res_ownok
+version SUNWprivate_2.1
+end
+
+function __res_ownok
+version SUNWprivate_2.1
+end
+
+function res_randomid
+version SUNWprivate_2.1
+end
+
+function __res_randomid
+version SUNWprivate_2.1
+end
+
+function sym_ntop
+version SUNWprivate_2.1
+end
+
+function __sym_ntop
+version SUNWprivate_2.1
+end
+
+function sym_ntos
+version SUNWprivate_2.1
+end
+
+function __sym_ntos
+version SUNWprivate_2.1
+end
+
+function sym_ston
+version SUNWprivate_2.1
+end
+
+function __sym_ston
+version SUNWprivate_2.1
+end
+
+function _getlong
+version SUNW_2.1
+end
+
+function _getshort
+version SUNW_2.1
+end
+
+function _ns_flagdata
+version SUNWprivate_2.1
+end
+
+function _res
+version SUNW_2.1
+end
+
+function _res_opcodes
+version SUNWprivate_2.1
+end
+
+function daemon
+version SUNWprivate_2.1
+end
+
+function dn_comp
+include <sys/types.h>, <netinet/in.h>, <arpa/nameser.h>, <resolv.h>
+declaration int dn_comp(const char *exp_dn, uchar_t *comp_dn, int length, \
+ uchar_t **dnptrs, uchar_t **lastdnptr)
+version SUNW_2.1
+exception $return == -1
+end
+
+function dn_expand
+include <sys/types.h>, <netinet/in.h>, <arpa/nameser.h>, <resolv.h>
+declaration int dn_expand(const uchar_t *msg, const uchar_t *eomorig, \
+ const uchar_t *comp_dn, char *exp_dn, int length)
+version SUNW_2.1
+exception $return == -1
+end
+
+function h_errlist
+version SUNWprivate_2.1
+end
+
+# h_errno moved to explicit mapfile definition to provide correct type and size.
+
+function herror
+version SUNW_2.2
+end
+
+function hstrerror
+version SUNW_2.1
+end
+
+function inet_aton
+version SUNW_2.3
+filter libnsl.so.1
+end
+
+function inet_nsap_addr
+version SUNWprivate_2.1
+end
+
+function inet_nsap_ntoa
+version SUNWprivate_2.1
+end
+
+function res_endhostent
+version SUNWprivate_2.1
+end
+
+function res_gethostbyaddr
+version SUNWprivate_2.1
+end
+
+function res_gethostbyname
+version SUNWprivate_2.1
+end
+
+function res_gethostbyname2
+version SUNWprivate_2.2
+end
+
+function res_gethostent
+version SUNWprivate_2.1
+end
+
+function res_getipnodebyname
+version SUNWprivate_2.1
+end
+
+function res_getipnodebyaddr
+version SUNWprivate_2.1
+end
+
+function res_freehostent
+version SUNWprivate_2.1
+end
+
+function res_init
+include <sys/types.h>, <netinet/in.h>, <arpa/nameser.h>, <resolv.h>
+declaration int res_init(void)
+version SUNW_2.1
+end
+
+function res_mkquery
+include <sys/types.h>, <netinet/in.h>, <arpa/nameser.h>, <resolv.h>
+declaration int res_mkquery(int op, const char *dname, int class, \
+ int type, const uchar_t *data, int datalen, \
+ const uchar_t *newrr, uchar_t *buf, int buflen)
+version SUNW_2.1
+exception $return == -1
+end
+
+function res_mkupdrec
+version SUNWprivate_2.1
+end
+
+function res_queriesmatch
+version SUNWprivate_2.1
+end
+
+function __res_queriesmatch
+version SUNWprivate_2.1
+end
+
+function res_query
+include <sys/types.h>, <netinet/in.h>, <arpa/nameser.h>, <resolv.h>
+declaration int res_query(const char *dname, int class, int type, \
+ uchar_t *answer, int anslen)
+version SUNW_2.1
+end
+
+function res_querydomain
+version SUNW_2.1
+end
+
+function res_search
+include <sys/types.h>, <netinet/in.h>, <arpa/nameser.h>, <resolv.h>
+declaration int res_search(const char *dname, int class, int type, \
+ uchar_t *answer, int anslen)
+version SUNW_2.1
+end
+
+function res_send
+include <sys/types.h>, <netinet/in.h>, <arpa/nameser.h>, <resolv.h>
+declaration int res_send(const uchar_t *msg, int msglen, uchar_t *answer, \
+ int anslen)
+version SUNW_2.1
+exception $return == -1
+end
+
+function res_sethostent
+version SUNWprivate_2.1
+end
+
+function res_update
+version SUNW_2.1
+end
+
+function res_close
+version SUNWprivate_2.1
+end
+
+function tree_add
+version SUNWprivate_2.1
+end
+
+function tree_init
+version SUNWprivate_2.1
+end
+
+function tree_srch
+version SUNWprivate_2.1
+end
+
+function tree_trav
+version SUNWprivate_2.1
+end
+
+function __assertion_failed
+version SUNWprivate_2.1
+end
+
+function __evDestroy
+version SUNWprivate_2.1
+end
+
+function __evUnwait
+version SUNWprivate_2.1
+end
+
+function __log_free_channel
+version SUNWprivate_2.1
+end
+
+function __log_get_channel_type
+version SUNWprivate_2.1
+end
+
+function __memget
+version SUNWprivate_2.1
+end
+
+function __memput
+version SUNWprivate_2.1
+end
+
+function __memstats
+version SUNWprivate_2.1
+end
+
+function __res_disable_mt
+version SUNWprivate_2.1
+end
+
+function __res_enable_mt
+version SUNWprivate_2.1
+end
+
+function __res_get_res
+version SUNWprivate_2.1
+end
+
+function __res_get_h_errno
+version SUNWprivate_2.1
+end
+
+function __res_set_no_hosts_fallback
+version SUNWprivate_2.1
+end
+
+function __res_unset_no_hosts_fallback
+version SUNWprivate_2.1
+end
+
+function __res_override_retry
+version SUNWprivate_2.1
+end
+
+function assertion_type_to_text
+version SUNWprivate_2.1
+end
+
+function set_assertion_failure_callback
+version SUNWprivate_2.1
+end
+
+function tree_mung
+version SUNWprivate_2.1
+end
+
+function res_ninit
+version SUNW_2.2
+end
+
+function res_nquery
+version SUNW_2.2
+end
+
+function p_query
+version SUNWprivate_2.1
+end
+
+function res_nsearch
+version SUNW_2.2
+end
+
+function res_nquerydomain
+version SUNW_2.2
+end
+
+function res_nmkquery
+version SUNW_2.2
+end
+
+function res_nsend
+version SUNW_2.2
+end
+
+function res_nsendsigned
+version SUNW_2.2
+end
+
+function res_findzonecut
+version SUNWprivate_2.1
+end
+
+function __ISC_res_nupdate
+version SUNWprivate_2.1
+end
+
+function __ISC_res_nmkupdate
+version SUNWprivate_2.1
+end
+
+function res_nclose
+version SUNW_2.2
+end
+
+function res_nsendsigned
+version SUNW_2.2
+end
+
+function res_nisourserver
+version SUNWprivate_2.1
+end
+
+function res_isourserver
+version SUNWprivate_2.1
+end
+
+function res_mkupdate
+version SUNWprivate_2.1
+end
+
+function res_sendsigned
+version SUNWprivate_2.1
+end
+
+function p_rcode
+version SUNWprivate_2.1
+end
+
+function __res_state
+version SUNWprivate_2.1
+end
+
+function res_freeupdrec
+version SUNWprivate_2.1
+end
+
+function dst_init
+version SUNWprivate_2.1
+end
+
+function dst_check_algorithm
+version SUNWprivate_2.1
+end
+
+function dst_generate_key
+version SUNWprivate_2.1
+end
+
+function dst_write_key
+version SUNWprivate_2.1
+end
+
+function res_pquery
+version SUNWprivate_2.1
+end
+
+function __h_errno
+version SUNWprivate_2.1
+end
+
+function __ctl_command
+version SUNWprivate_2.1
+end
+
+function __ctl_endclient
+version SUNWprivate_2.1
+end
+
+function __ctl_client
+version SUNWprivate_2.1
+end
+
+function __ctl_getcsctx
+version SUNWprivate_2.1
+end
+
+function __log_check
+version SUNWprivate_2.1
+end
+
+function __ctl_response
+version SUNWprivate_2.1
+end
+
+function __p_cert_syms
+version SUNWprivate_2.1
+end
+
+function __ns_name_ntol
+version SUNWprivate_2.1
+end
+
+function dst_buffer_to_key
+version SUNWprivate_2.1
+end
+
+function __ctl_setcsctx
+version SUNWprivate_2.1
+end
+
+function __ctl_server
+version SUNWprivate_2.1
+end
+
+function __evHighestFD
+version SUNWprivate_2.1
+end
+
+function dst_verify_data
+version SUNWprivate_2.1
+end
+
+function __ctl_sendhelp
+version SUNWprivate_2.1
+end
+
+function __ns_skiprr
+version SUNWprivate_2.1
+end
+
+function __ns_verify
+version SUNWprivate_2.1
+end
+
+function __p_key_syms
+version SUNWprivate_2.1
+end
+
+function __evTimeVal
+version SUNWprivate_2.1
+end
+
+function __ns_datetosecs
+version SUNWprivate_2.1
+end
+
+function dst_key_to_buffer
+version SUNWprivate_2.1
+end
+
+function dst_free_key
+version SUNWprivate_2.1
+end
+
+function __ctl_endserver
+version SUNWprivate_2.1
+end
+
+function dst_dnskey_to_key
+version SUNWprivate_2.1
+end
+
+function __ns_find_tsig
+version SUNWprivate_2.1
+end
+
+function __ns_verify_tcp
+version SUNWprivate_2.1
+end
+
+function __ns_verify_tcp_init
+version SUNWprivate_2.1
+end
+
+function key_file_fmt_str
+version SUNWprivate_2.1
+end
+
+function dst_s_id_calc
+version SUNWprivate_2.1
+end
+
+function dst_s_conv_bignum_u8_to_b64
+version SUNWprivate_2.1
+end
+
+function dst_random
+version SUNWprivate_2.1
+end
+
+
+function dst_s_verify_str
+version SUNWprivate_2.1
+end
+
+function dst_t_func
+version SUNWprivate_2.1
+end
+
+function dst_s_conv_bignum_b64_to_u8
+version SUNWprivate_2.1
+end
+
+function dst_s_get_int16
+version SUNWprivate_2.1
+end
+
+function dst_s_calculate_bits
+version SUNWprivate_2.1
+end
+
+function dst_s_put_int16
+version SUNWprivate_2.1
+end
+
+function inet_net_pton
+version SUNWprivate_2.1
+end
+
+function inet_net_ntop
+version SUNWprivate_2.1
+end
+
+function net_data_minimize
+version SUNWprivate_2.1
+end
+
+function __h_errno_set
+version SUNWprivate_2.1
+end
+
+function __net_data_init
+version SUNWprivate_2.1
+end
+
+# BIND 8.2 adds the various ns_sign*() functions for TSIG. Until the
+# interface has seen some actual use and has stabilized, we'll leave
+# those functions undocumented and in the private interface.
+
+function __ns_sign
+version SUNWprivate_2.1
+end
+
+function __ns_sign2
+version SUNWprivate_2.1
+end
+
+function __ns_sign_tcp
+version SUNWprivate_2.1
+end
+
+function __ns_sign_tcp2
+version SUNWprivate_2.1
+end
+
+function __ns_sign_tcp_init
+version SUNWprivate_2.1
+end
+
+function __ns_verify
+version SUNWprivate_2.1
+end
+
+function __ns_verify_tcp
+version SUNWprivate_2.1
+end
+
+function __ns_verify_tcp_init
+version SUNWprivate_2.1
+end
+
+function __ns_find_tsig
+version SUNWprivate_2.1
+end
+
+function __ISC_res_freeupdrec
+version SUNWprivate_2.1
+end
+
+function __ISC_res_mkupdrec
+version SUNWprivate_2.1
+end
+
+function __ISC_res_update
+version SUNWprivate_2.1
+end
+
+function __ISC_res_mkupdate
+version SUNWprivate_2.1
+end
+
+function irs_destroy
+version SUNWprivate_2.1
+end
+
+function __ns_samedomain
+version SUNWprivate_2.1
+end
+
+function __ns_samename
+version SUNWprivate_2.1
+end
+
+function __ns_makecanon
+version SUNWprivate_2.1
+end
+
+function __ns_msg_getflag
+version SUNWprivate_2.1
+end
+
+function __memget_record
+version SUNWprivate_2.1
+end
+
+function __memput_record
+version SUNWprivate_2.1
+end
+
+function dst_read_key
+version SUNWprivate_2.1
+end
+
+function dst_sign_data
+version SUNWprivate_2.1
+end
+
+function dst_s_dns_key_id
+version SUNWprivate_2.1
+end
+
+function __ns_format_ttl
+version SUNWprivate_2.1
+end
+
+function __areweinnamed
+version SUNWprivate_2.1
+end
+
+function __log_close_debug_channels
+version SUNWprivate_2.2
+end
+
+function res_getservers
+version SUNWprivate_2.2
+end
+
+function res_setservers
+version SUNWprivate_2.2
+end
+
+function res_nametotype
+version SUNWprivate_2.2
+end
+
+function res_nametoclass
+version SUNWprivate_2.2
+end
+
+function res_nopt
+version SUNWprivate_2.2
+end
+
+function isc_puthexstring
+version SUNWprivate_2.2
+end
+
+function isc_gethexstring
+version SUNWprivate_2.2
+end
+
+function __memactive
+version SUNWprivate_2.2
+end
+
+function p_sockun
+version SUNWprivate_2.2
+end
diff --git a/usr/src/lib/libresolv2/spec/sparc/Makefile b/usr/src/lib/libresolv2/spec/sparc/Makefile
new file mode 100644
index 0000000000..ee76178462
--- /dev/null
+++ b/usr/src/lib/libresolv2/spec/sparc/Makefile
@@ -0,0 +1,23 @@
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1998-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/spec/sparc/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+
+# Uncomment the following if the linker complains
+#sparc_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB)
diff --git a/usr/src/lib/libresolv2/spec/sparcv9/Makefile b/usr/src/lib/libresolv2/spec/sparcv9/Makefile
new file mode 100644
index 0000000000..a6ebe9c847
--- /dev/null
+++ b/usr/src/lib/libresolv2/spec/sparcv9/Makefile
@@ -0,0 +1,24 @@
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1998-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libresolv2/spec/sparcv9/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+
+# Uncomment the following if the linker complains
+#sparcv9_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB64)
diff --git a/usr/src/lib/libresolv2/spec/versions b/usr/src/lib/libresolv2/spec/versions
new file mode 100644
index 0000000000..90e69aa7fb
--- /dev/null
+++ b/usr/src/lib/libresolv2/spec/versions
@@ -0,0 +1,35 @@
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+sparc {
+ SUNW_2.3: {SUNW_2.2};
+ SUNW_2.2: {SUNW_2.1};
+ SUNW_2.1;
+ SUNWprivate_2.2: {SUNWprivate_2.1};
+ SUNWprivate_2.1;
+}
+sparcv9 {
+ SUNW_2.3: {SUNW_2.2};
+ SUNW_2.2: {SUNW_2.1};
+ SUNW_2.1;
+ SUNWprivate_2.2: {SUNWprivate_2.1};
+ SUNWprivate_2.1;
+}
+i386 {
+ SUNW_2.3: {SUNW_2.2};
+ SUNW_2.2: {SUNW_2.1};
+ SUNW_2.1;
+ SUNWprivate_2.2: {SUNWprivate_2.1};
+ SUNWprivate_2.1;
+}
+amd64 {
+ SUNW_2.3: {SUNW_2.2};
+ SUNW_2.2: {SUNW_2.1};
+ SUNW_2.1;
+ SUNWprivate_2.2: {SUNWprivate_2.1};
+ SUNWprivate_2.1;
+}